Annotation of Amaya/amaya/AHTBridge.c, revision 1.94

1.9       cvs         1: /*
                      2:  *
1.93      vatton      3:  *  (c) COPYRIGHT INRIA and W3C, 1996-2004
1.9       cvs         4:  *  Please first read the full copyright statement in file COPYRIGHT.
                      5:  *
                      6:  */
1.75      cvs         7:   
1.14      cvs         8: /*
                      9:  * AHTBridge.c : This module implements the callback setup and
                     10:  * handlers between the Xt, libwww, and Amaya procedures. It's responsible
                     11:  * for assigning, modifying, and supressing Xt events to the active
                     12:  * requests.
                     13:  *
                     14:  * Author: J Kahan
1.67      cvs        15:  *         J. K./R. Guetari. Windows NT/95 routines
1.79      cvs        16:  *         J. K./S. Gully GTK routines
1.14      cvs        17:  *
                     18:  */
1.94    ! gully      19: 
        !            20: #if defined(_GTK)
1.85      gully      21:   #include <glib.h>
1.68      cvs        22: #endif /* _GTK */
                     23: 
1.94    ! gully      24: #ifdef _WX
        !            25:   #include "wxAmayaTimer.h"
        !            26:   #include "wxAmayaSocketEvent.h"
        !            27: #endif /* _WX */
        !            28: 
1.16      cvs        29: #define THOT_EXPORT extern
1.4       cvs        30: #include "amaya.h"
1.10      cvs        31: #include "AHTBridge_f.h"
                     32: #include "AHTFWrite_f.h"
                     33: #include "query_f.h"
                     34: #include "answer_f.h"
1.64      cvs        35: #include "HTEvtLst.h"
1.4       cvs        36: 
1.58      cvs        37: #if 0
                     38: #define DEBUG_LIBWWW
                     39: #define THD_TRACE 1
                     40: #endif
                     41: 
1.85      gully      42: #ifdef _MOTIF
                     43:   /* Amaya's X appcontext */
                     44:   extern ThotAppContext app_cont;
                     45: #endif /* #ifdef _MOTIF */
                     46: 
1.94    ! gully      47: #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI)
1.85      gully      48:   /* Private functions */
                     49:   static void         RequestRegisterReadXtevent (SOCKET);
                     50:   static void         RequestKillReadXtevent (SOCKET);
                     51:   static void         RequestRegisterWriteXtevent ( SOCKET);
                     52:   static void         RequestKillWriteXtevent (SOCKET);
                     53:   static void         RequestRegisterExceptXtevent ( SOCKET);
                     54:   static void         RequestKillExceptXtevent (SOCKET);
                     55: #endif /* #if defined(_MOTIF) || defined(_GTK) */
1.24      cvs        56: 
1.32      cvs        57: /* Private variables */
1.4       cvs        58: 
                     59: /*
1.58      cvs        60:  * this set of HTEventType map our WinSock "socket event HTEventType" into 
1.4       cvs        61:  * our read and write sets. Note that under the canonical Unix model,
                     62:  * a non-blocking socket passed to an accept() call will appear as readable, 
                     63:  * whilst a non-blocking call to connect() will appear as writeable. In add.
                     64:  * if the connection has been closed, the socket will appear readable under
                     65:  * BSD Unix semantics 
                     66:  */
1.32      cvs        67: 
1.91      gully      68: static const HTEventType ReadBits = (HTEventType)(HTEvent_READ | HTEvent_ACCEPT | HTEvent_CLOSE);
                     69: static const HTEventType WriteBits = (HTEventType)(HTEvent_WRITE | HTEvent_CONNECT);
                     70: static const HTEventType ExceptBits = (HTEventType)HTEvent_OOB;
1.58      cvs        71: 
1.85      gully      72: #ifdef _MOTIF
                     73:   typedef struct sStatus {
                     74:     XtInputId read;             /* the different Xt Id's */
                     75:     XtInputId write;
                     76:     XtInputId except;
                     77:   } SocketStatus;
                     78: #endif /*! #ifdef _MOTIF */
1.79      cvs        79: 
1.94    ! gully      80: #if defined(_GTK)
1.85      gully      81:   typedef struct sStatus {
                     82:     gint read;             /* the different GTK Id's */
                     83:     gint write;
                     84:     gint except;
                     85:   } SocketStatus;
1.79      cvs        86: #endif /* _GTK */
1.4       cvs        87: 
1.94    ! gully      88: #if defined(_WX)
        !            89: typedef struct sStatus {
        !            90:   int read;
        !            91:   int write;
        !            92:   int except;
        !            93: } SocketStatus;
        !            94: #endif /* _WX */
        !            95: 
        !            96: #if defined(_NOGUI)
1.85      gully      97:   typedef struct sStatus {
                     98:     int read;
                     99:     int write;
                    100:     int except;
                    101:   } SocketStatus;
1.88      cvs       102: #endif /* #ifdef _NOGUI */
1.85      gully     103: 
1.94    ! gully     104: #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI)
1.89      cvs       105:   #define SOCK_TABLE_SIZE 67
                    106:   #define HASH(s) ((s) % SOCK_TABLE_SIZE)
                    107:   static SocketStatus persSockets[SOCK_TABLE_SIZE];
1.94    ! gully     108: #endif /* #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI) */
1.4       cvs       109: 
1.10      cvs       110: /*--------------------------------------------------------------------
                    111:   AHTCallback_bridge
1.11      cvs       112:   this function acts as a bridge between Xt and libwww. From the Xt
                    113:   point of view, this function is the callback handler whenever there's
                    114:   any activity on the sockets associated with the active requests. From
                    115:   the libwww point of view, this is the function that takes the initiative
                    116:   to invoke the callback function associated with an active request,
                    117:   whenever there's an activity in the socket associated to it.
                    118:   In this latter  aspect, this function is similar to the library's
                    119:   own __DoCallback()  function.
                    120:   Upon activation, the function looks up the request associated with the
                    121:   active socket and then looks up the cbf associated with that request.
                    122:   Upon completion of the execution of the request's cbf, it verifies
                    123:   the state of the request and, if it's an asynchronous request, deletes
                    124:   the memory allocated to it.
1.10      cvs       125:   -------------------------------------------------------------------*/
1.80      kahan     126: void *AHTCallback_bridge (caddr_t cd, int *s, XtInputId * id)
1.4       cvs       127: {
1.86      gully     128: #ifdef _MOTIF
1.11      cvs       129:    int                 status;  /* the status result of the libwwww call */
1.58      cvs       130:    HTEventType         type  = HTEvent_ALL;    
1.38      cvs       131:    int                 v;
1.40      cvs       132:    int                        socket = *s;
1.58      cvs       133:    ms_t                now = HTGetTimeInMillis();
                    134:    
                    135:    v = HASH (socket);
1.4       cvs       136: 
1.58      cvs       137:    /* convert the FD into an HTEventType which will allow us to find the
                    138:       request associated with the socket */
1.47      cvs       139: 
1.58      cvs       140:    /* I could send some other data here, like the event itself, right */
                    141:    switch ((XtInputId) cd) 
1.47      cvs       142:      {
1.58      cvs       143:      case XtInputReadMask:
                    144:        type = HTEvent_READ;
                    145:        break;
                    146:      case XtInputWriteMask:
                    147:        type = HTEvent_WRITE;
                    148:        break;
                    149:      case XtInputExceptMask:
                    150:        type = HTEvent_OOB;
                    151:        break;
                    152:      default:
                    153:        type = HTEvent_ALL; 
                    154:        break;
                    155:      } /* switch */
1.47      cvs       156:    
1.32      cvs       157:    /* Invokes the callback associated to the requests */
                    158:    
1.66      cvs       159:    /**   CanDoStop_set (FALSE); **/
1.58      cvs       160:    if ((status = HTEventList_dispatch (socket, type, now)) != HT_OK)
                    161:      {
1.36      cvs       162: #ifdef DEBUG_LIBWWW
1.58      cvs       163:      HTTrace ("Callback.... returned a value != HT_OK");
1.36      cvs       164: #endif
1.58      cvs       165:      }
1.41      cvs       166: 
1.66      cvs       167:    /***   CanDoStop_set (TRUE); **/
1.86      gully     168: #endif /* _MOTIF */
                    169:    
1.7       cvs       170:    return (0);
1.4       cvs       171: }
1.85      gully     172: 
1.94    ! gully     173: #if defined(_GTK)
1.79      cvs       174: static void AHTCallback_bridgeGTK (gpointer data,  gint source, GdkInputCondition condition)
                    175: {
                    176:    int                 status;  /* the status result of the libwwww call */
                    177:    HTEventType         type  = HTEvent_ALL;    
                    178:    int                 v;
                    179:    int                        socket;
                    180:    ms_t                now = HTGetTimeInMillis();
                    181:    
                    182:    socket = (SOCKET) data;
                    183:    v = HASH (socket);
                    184: 
                    185:    /* convert the FD into an HTEventType which will allow us to find the
                    186:       request associated with the socket */
                    187: 
                    188:    /* I could send some other data here, like the event itself, right */
                    189:    switch (condition) 
                    190:      {
                    191:      case GDK_INPUT_READ:
                    192:        type = HTEvent_READ;
                    193:        break;
                    194:      case GDK_INPUT_WRITE:
                    195:        type = HTEvent_WRITE;
                    196:        break;
                    197:      case GDK_INPUT_EXCEPTION:
                    198:        type = HTEvent_OOB;
                    199:        break;
                    200:      default:
                    201:        type = HTEvent_ALL; 
                    202:        break;
                    203:      } /* switch */
                    204:    
                    205:    /* Invokes the callback associated to the requests */
                    206:    
                    207:    /**   CanDoStop_set (FALSE); **/
                    208:    if ((status = HTEventList_dispatch (socket, type, now)) != HT_OK)
                    209:      {
                    210: #ifdef DEBUG_LIBWWW
                    211:      HTTrace ("Callback.... returned a value != HT_OK");
                    212: #endif
                    213:      }
                    214:    /***   CanDoStop_set (TRUE); **/
                    215: }
1.94    ! gully     216: #endif /* _GTK  */
        !           217: 
        !           218: 
        !           219: #if defined(_WX)
        !           220: static void AHTCallback_bridgeWX ( int register_id,  int socket, wxAmayaSocketCondition condition)
        !           221: {
        !           222:   int                 status;  /* the status result of the libwwww call */
        !           223:   HTEventType         type  = HTEvent_ALL;     
        !           224:   int                 v;
        !           225:   ms_t                now = HTGetTimeInMillis();
        !           226:    
        !           227:   v = HASH (socket);
        !           228: 
        !           229:   /* convert the FD into an HTEventType which will allow us to find the
        !           230:      request associated with the socket */
        !           231: 
        !           232:   /* I could send some other data here, like the event itself, right */
        !           233:   switch (condition) 
        !           234:     {
        !           235:     case WXAMAYASOCKET_READ:
        !           236:       type = HTEvent_READ;
        !           237:       break;
        !           238:     case WXAMAYASOCKET_WRITE:
        !           239:       type = HTEvent_WRITE;
        !           240:       break;
        !           241:     case WXAMAYASOCKET_EXCEPTION:
        !           242:       type = HTEvent_OOB;
        !           243:       break;
        !           244:     default:
        !           245:       type = HTEvent_ALL; 
        !           246:       break;
        !           247:     } /* switch */
        !           248:    
        !           249:    /* Invokes the callback associated to the requests */
        !           250:    
        !           251:    /**   CanDoStop_set (FALSE); **/
        !           252:    if ((status = HTEventList_dispatch (socket, type, now)) != HT_OK)
        !           253:      {
        !           254: #ifdef DEBUG_LIBWWW
        !           255:      HTTrace ("Callback.... returned a value != HT_OK");
        !           256: #endif
        !           257:      }
        !           258:    /***   CanDoStop_set (TRUE); **/
        !           259: }
        !           260: #endif /* _WX  */
1.41      cvs       261: 
                    262: /*--------------------------------------------------------------------
                    263:   ProcessTerminateRequest
                    264:   This function is called whenever a request has ended. If the requested
                    265:   ended normally, the function will call any callback associated to the
                    266:   request. Otherwise, it will just mark the request as over.
                    267:   -------------------------------------------------------------------*/
1.82      vatton    268: void  ProcessTerminateRequest (HTRequest *request, HTResponse *response,
                    269:                               void *param, int status)
1.41      cvs       270: {   
1.91      gully     271:   AHTReqContext *me = (AHTReqContext *)HTRequest_context (request);
1.56      cvs       272: 
1.58      cvs       273:   /* choose a correct treatment in function of the request's
1.41      cvs       274:      being associated with an error, with an interruption, or with a
                    275:      succesful completion */
1.64      cvs       276: 
                    277: #ifdef DEBUG_LIBWWW  
                    278:   if (THD_TRACE)
1.82      vatton    279:     fprintf (stderr,"ProcessTerminateRequest: processing req %p, url %s,\
                    280:  status %d\n", me, me->urlName, me->reqStatus);  
1.64      cvs       281: #endif /* DEBUG_LIBWWW */
1.83      kahan     282:   if (me->reqStatus == HT_END)
1.41      cvs       283:     {
1.58      cvs       284:       if (AmayaIsAlive ()  && me->terminate_cbf)
1.82      vatton    285:        (*me->terminate_cbf) (me->docid, 0, me->urlName, me->outputfile,
                    286:                              &(me->http_headers), me->context_tcbf);
1.58      cvs       287: 
1.41      cvs       288:     }
1.42      cvs       289:   else if (me->reqStatus == HT_ABORT)
1.41      cvs       290:     /* either the application ended or the user pressed the stop 
                    291:        button. We erase the incoming file, if it exists */
                    292:     {
1.52      cvs       293:       if (AmayaIsAlive () && me->terminate_cbf)
1.82      vatton    294:        (*me->terminate_cbf) (me->docid, -1, me->urlName, me->outputfile,
                    295:                              &(me->http_headers), me->context_tcbf);
1.78      cvs       296:       if (me->outputfile && me->outputfile[0] != EOS)
1.41      cvs       297:        {
1.70      cvs       298:          TtaFileUnlink (me->outputfile);
1.78      cvs       299:          me->outputfile[0] = EOS; 
1.70      cvs       300:        } 
1.41      cvs       301:     }
1.83      kahan     302:   else if (me->reqStatus == HT_ERR)
1.41      cvs       303:     {
                    304:       /* there was an error */
1.90      gully     305:       if (AmayaIsAlive () && me->terminate_cbf)
1.82      vatton    306:        (*me->terminate_cbf) (me->docid, -2, me->urlName, me->outputfile,
                    307:                              &(me->http_headers), me->context_tcbf);
1.41      cvs       308:       
1.78      cvs       309:       if (me->outputfile && me->outputfile[0] != EOS)
1.41      cvs       310:        {
1.70      cvs       311:          TtaFileUnlink (me->outputfile);
1.78      cvs       312:          me->outputfile[0] = EOS;
1.41      cvs       313:        }
                    314:     }
1.58      cvs       315: 
1.41      cvs       316:    /* we erase the context if we're dealing with an asynchronous request */
1.61      cvs       317:   if ((me->mode & AMAYA_ASYNC)
                    318:       || (me->mode & AMAYA_IASYNC))
1.58      cvs       319:     {
1.63      cvs       320:       Document doc = me->docid;
1.58      cvs       321:       me->reqStatus = HT_END;
                    322:       /*** @@@ do we need this? yes!! **/
                    323:       AHTLoadTerminate_handler (request, response, param, status);
                    324:       AHTReqContext_delete (me);
1.63      cvs       325:       AHTPrintPendingRequestStatus (doc, YES);
1.58      cvs       326:     }
                    327: }
1.4       cvs       328: 
1.92      cvs       329: #ifdef _WINGUI
1.29      cvs       330: /*----------------------------------------------------------------
1.32      cvs       331:   WIN_Activate_Request
1.29      cvs       332:   when there are more open requests than available sockets, the 
                    333:   requests are put in a "pending state." When a socket becomes
                    334:   available, libwww associates it with a pending request and then
                    335:   calls this callback function. This function is responsible for
                    336:   opening the temporary file where the GET and POST  results
                    337:   will be stored. The function is also responsible for 
                    338:   registering the socket with the Xt event loop.
                    339:   Consult the libwww manual for more details on the signature
                    340:   of this function.
                    341:   ----------------------------------------------------------------*/
1.79      cvs       342: int WIN_Activate_Request (HTRequest * request, HTAlertOpcode op, int msgnum, const char *dfault, void *input, HTAlertPar * reply)
1.29      cvs       343: {
                    344:    AHTReqContext      *me = HTRequest_context (request);
                    345: 
1.58      cvs       346:    if (me->reqStatus == HT_NEW) 
                    347:      {
                    348:        if (!(me->output)
                    349:           && (me->output != stdout) 
                    350:           && me->outputfile
1.78      cvs       351:           &&  (me->output = fopen (me->outputfile, "wb")) == NULL) {
1.58      cvs       352:         /* the request is associated with a file */
1.78      cvs       353:         me->outputfile[0] = EOS;       /* file could not be opened */
1.70      cvs       354:         TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_CREATE_FILE), me->outputfile);
1.58      cvs       355:         me->reqStatus = HT_ERR;
                    356: 
                    357:         if (me->error_html)
                    358:           DocNetworkStatus[me->docid] |= AMAYA_NET_ERROR; /* so we can show the error message */
                    359:        } 
                    360:        else
                    361:         {
                    362: #ifdef DEBUG_LIBWWW
                    363:           if (THD_TRACE)
                    364:             fprintf (stderr, "WIN_Activate_Request: Activating pending %s. "
                    365:                      "Open fd %d\n", me->urlName, (int) me->output);
                    366: #endif /* DEBUG_LIBWWW */
                    367:           HTRequest_setOutputStream (me->request, AHTFWriter_new (me->request, me->output, YES));    
                    368:           /*change the status of the request */
                    369:           me->reqStatus = HT_WAITING;
                    370:         }
                    371:      } 
                    372:    else if (me->reqStatus == HT_WAITING)
                    373:      {
                    374:        /*change the status of the request */
                    375:        rewind (me->output);
                    376:        if (HTRequest_outputStream (me->request) == NULL)
                    377:         HTRequest_setOutputStream (me->request, AHTFWriter_new (me->request, me->output, YES));
                    378:      } 
1.32      cvs       379:    else {
1.36      cvs       380:      me->reqStatus = HT_ERR;
1.32      cvs       381:    }
                    382:    
1.36      cvs       383:    return ((me->reqStatus != HT_ERR) ? HT_OK : HT_ERROR);
1.32      cvs       384: }
                    385: 
1.92      cvs       386: #endif /* _WINGUI */
1.60      cvs       387: 
1.11      cvs       388: /*----------------------------------------------------------------------
                    389:   AHTEvent_register
                    390:   callback called by libwww whenever a socket is open and associated
                    391:   to a request. It sets the pertinent Xt events so that the Xt Event
                    392:   loops gets an interruption whenever there's action of the socket. 
                    393:   In addition, it registers the request with libwww.
                    394:   ----------------------------------------------------------------------*/
1.58      cvs       395: int AHTEvent_register (SOCKET sock, HTEventType type, HTEvent *event)
1.4       cvs       396: {
1.85      gully     397:   int  status = 0;
1.7       cvs       398: 
1.40      cvs       399:   if (sock == INVSOC)
                    400:     {
1.36      cvs       401: #ifdef DEBUG_LIBWWW
1.58      cvs       402:       fprintf(stderr, "AHTEvent_register: sock = INVSOC\n");
1.37      cvs       403: #endif /* DEBUG_LIBWWW */
1.58      cvs       404:       return (0);
                    405:     }
1.43      cvs       406: 
1.94    ! gully     407: #if defined(_MOTIF) || defined(_GTK) || defined(_WX)
        !           408:   /* need something special for HTEvent_CLOSE */
1.58      cvs       409:   if (type & ReadBits)
                    410:     RequestRegisterReadXtevent (sock);
                    411:   
                    412:   if (type & WriteBits)
                    413:     RequestRegisterWriteXtevent (sock);
                    414:   
                    415:   if (type & ExceptBits)
                    416:     RequestRegisterExceptXtevent (sock);
1.94    ! gully     417: #endif  /* #if defined(_MOTIF) || defined(_GTK) || defined(_WX) */
1.58      cvs       418:   
1.94    ! gully     419: #ifdef _WINDOWS
1.50      cvs       420:   /* under windows, libwww requires an explicit FD_CLOSE registration 
1.58      cvs       421:      to detect HTTP responses not having a Content-Length header */
                    422:   status = HTEventList_register (sock, type | HTEvent_CLOSE , event);
1.94    ! gully     423: #endif /* _WINDOWS */
1.85      gully     424: 
1.94    ! gully     425: #if defined(_UNIX)
1.58      cvs       426:   status = HTEventList_register (sock, type, event);
1.94    ! gully     427: #endif /* #if defined(_UNIX) */
1.58      cvs       428:   
                    429:   return (status);
                    430: }
1.50      cvs       431: 
1.34      cvs       432: /*----------------------------------------------------------------------
                    433:   AHTEvent_unregister
                    434:   callback called by libwww each time a request is unregistered. This
                    435:   function takes care of unregistering the pertinent Xt events
                    436:   associated with the request's socket. In addition, it unregisters
                    437:   the request from libwww.
                    438:   ----------------------------------------------------------------------*/
1.58      cvs       439: int AHTEvent_unregister (SOCKET sock, HTEventType type)
1.34      cvs       440: {
1.58      cvs       441:   int    status;
1.76      kahan     442:   
                    443:   if (sock == INVSOC)
                    444:     return HT_OK;
1.38      cvs       445: 
1.94    ! gully     446: #if defined(_MOTIF) || defined(_GTK) || defined(_WX)
1.58      cvs       447:    /* remove the Xt event hooks */
                    448:    if (type & ReadBits) 
                    449:      RequestKillReadXtevent (sock);
                    450:    
                    451:    if (type & WriteBits)
                    452:      RequestKillWriteXtevent (sock);
                    453:    
                    454:    if (type & ExceptBits) 
                    455:      RequestKillExceptXtevent (sock);
1.94    ! gully     456: #endif /* #if defined(_MOTIF) || defined(_GTK) || defined(_WX) */
1.35      cvs       457: 
1.58      cvs       458:    /* @@@ if this is the default for windows, no need to have AHTEvent_..
                    459:       in windows!! */
1.35      cvs       460: 
1.58      cvs       461:    /* call libwww's default routine */
                    462:    status = HTEventList_unregister (sock, type);
                    463:    
1.7       cvs       464:    return (status);
1.4       cvs       465: }
1.35      cvs       466: 
1.58      cvs       467: /* Private functions */
                    468: 
1.11      cvs       469: /*----------------------------------------------------------------------
                    470:   RequestKillAllXtevents
                    471:   front-end for kill all Xt events associated with the request pointed
                    472:   to by "me".
                    473:   ----------------------------------------------------------------------*/
1.79      cvs       474: void RequestKillAllXtevents (AHTReqContext * me)
1.4       cvs       475: {
1.94    ! gully     476: #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI)
1.58      cvs       477:   int sock = INVSOC;
                    478: 
                    479:   return;
                    480: 
                    481:   /* @@@ what to do with this one? @@@ */
                    482:   if (me->read_sock != INVSOC)
                    483:     sock = me->read_sock;
                    484:   else
                    485:     if (me->write_sock != INVSOC)
                    486:           sock = me->write_sock;
                    487:   else
                    488:     if (me->except_sock != INVSOC)
                    489:           sock = me->except_sock;
                    490: 
                    491: #ifdef DEBUG_LIBWWW
1.7       cvs       492:    if (THD_TRACE)
1.58      cvs       493:       fprintf (stderr, "RequestKillAllXtEvents: Clearing XtInputs\n");
                    494: #endif /* DEBUG_LIBWWW */
1.4       cvs       495: 
1.58      cvs       496: 
                    497:    RequestKillReadXtevent (sock);
                    498:    RequestKillWriteXtevent (sock);
                    499:    RequestKillExceptXtevent (sock);
1.94    ! gully     500: #endif /* #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI) */   
1.4       cvs       501: }
                    502: 
1.11      cvs       503: /*----------------------------------------------------------------------
1.18      cvs       504:   RequestRegisterReadXtevent
                    505:   Registers with Xt the read events associated with socket sock
                    506:   ----------------------------------------------------------------------*/
1.79      cvs       507: static void RequestRegisterReadXtevent (SOCKET sock)
1.18      cvs       508: {
1.94    ! gully     509: #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI)
1.58      cvs       510:   int v;
                    511: 
                    512:   v = HASH (sock);
                    513: 
                    514:   if (!persSockets[v].read)
1.18      cvs       515:     {
1.85      gully     516:       
                    517: #ifdef _MOTIF
1.58      cvs       518:       persSockets[v].read  =
                    519:        XtAppAddInput (app_cont,
                    520:                       sock,
                    521:                       (XtPointer) XtInputReadMask,
                    522:                       (XtInputCallbackProc) AHTCallback_bridge,
                    523:                       (XtPointer) XtInputReadMask);
1.85      gully     524: #endif /* _MOTIF */
                    525:       
1.94    ! gully     526: #if defined(_GTK)
1.79      cvs       527:      persSockets[v].read  =
                    528:        gdk_input_add ((gint) sock,
                    529:                      GDK_INPUT_READ,
                    530:                      AHTCallback_bridgeGTK,
                    531:                      (gpointer) sock);
1.94    ! gully     532: #endif /* _GTK */
        !           533: 
        !           534: #if defined(_WX)
        !           535:      persSockets[v].read  =
        !           536:        wxAmayaSocketEvent::RegisterSocket( sock,
        !           537:                                           WXAMAYASOCKET_READ,
        !           538:                                           AHTCallback_bridgeWX );
        !           539: #endif /* _WX */
1.79      cvs       540: 
1.58      cvs       541: #ifdef DEBUG_LIBWWW
1.18      cvs       542:       if (THD_TRACE)
1.58      cvs       543:        fprintf (stderr, "RegisterReadXtEvent: adding XtInput %lu Socket %d\n",
                    544:                 persSockets[v].read, sock);
                    545: #endif /* DEBUG_LIBWWW */
1.18      cvs       546:     }
1.94    ! gully     547: #endif /* #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI) */
1.18      cvs       548: }
                    549: 
                    550: /*----------------------------------------------------------------------
1.11      cvs       551:   RequestKillReadXtevent
                    552:   kills any read Xt event associated with the request pointed to by "me".
                    553:   ----------------------------------------------------------------------*/
1.79      cvs       554: static void RequestKillReadXtevent (SOCKET sock)
1.4       cvs       555: {
1.94    ! gully     556: #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI)
1.58      cvs       557:   int v;
                    558: 
                    559:   v = HASH (sock);
                    560: 
                    561:   if (persSockets[v].read)
                    562:     {
                    563: #ifdef DEBUG_LIBWWW
                    564:       if (THD_TRACE)
                    565:        fprintf (stderr, "UnregisterReadXtEvent: Clearing XtInput %lu\n",
                    566:                 persSockets[v].read);
                    567: #endif /* DEBUG_LIBWWW */
1.85      gully     568: 
                    569: #ifdef _MOTIF
1.58      cvs       570:       XtRemoveInput (persSockets[v].read);
                    571:       persSockets[v].read = (XtInputId) NULL;
1.85      gully     572: #endif /* _MOTIF */
                    573:       
1.94    ! gully     574: #if defined(_GTK)
1.79      cvs       575:       gdk_input_remove (persSockets[v].read);
                    576:       persSockets[v].read = (gint) 0;
                    577: #endif /* !_GTK */
1.85      gully     578: 
1.94    ! gully     579: #if defined(_WX)
        !           580:       wxAmayaSocketEvent::UnregisterSocket( persSockets[v].read );
        !           581:       persSockets[v].read = 0;
        !           582: #endif /* _WX */
        !           583: 
1.58      cvs       584:     }
1.94    ! gully     585: #endif /* #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI) */  
1.18      cvs       586: }
                    587: 
                    588: /*----------------------------------------------------------------------
                    589:   RequestRegisterWriteXtevent
                    590:   Registers with Xt the write events associated with socket sock
                    591:   ----------------------------------------------------------------------*/
1.79      cvs       592: static void RequestRegisterWriteXtevent (SOCKET sock)
1.18      cvs       593: {
1.94    ! gully     594: #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI)
1.58      cvs       595:   int v;
                    596:   v = HASH (sock);
1.18      cvs       597: 
1.58      cvs       598:   if (!persSockets[v].write)
                    599:     {   
1.85      gully     600: #ifdef _MOTIF
1.58      cvs       601:       persSockets[v].write =
                    602:        XtAppAddInput (app_cont,
                    603:                       sock,
1.18      cvs       604:                   (XtPointer) XtInputWriteMask,
                    605:                   (XtInputCallbackProc) AHTCallback_bridge,
                    606:                   (XtPointer) XtInputWriteMask);
1.85      gully     607: #endif /* _MOTIF */
                    608:       
1.94    ! gully     609: #if defined(_GTK) 
1.79      cvs       610:      persSockets[v].write  =
                    611:        gdk_input_add ((gint) sock,
                    612:                      GDK_INPUT_WRITE,
                    613:                      AHTCallback_bridgeGTK,
                    614:                      (gpointer) sock);
1.94    ! gully     615: #endif /* _GTK  */
        !           616: 
        !           617: #if defined(_WX)
        !           618:      persSockets[v].write  =
        !           619:        wxAmayaSocketEvent::RegisterSocket( sock,
        !           620:                                           WXAMAYASOCKET_WRITE,
        !           621:                                           AHTCallback_bridgeWX );
        !           622: #endif /* _WX */
1.79      cvs       623: 
1.58      cvs       624: #ifdef DEBUG_LIBWWW   
1.18      cvs       625:   if (THD_TRACE)
1.58      cvs       626:     fprintf (stderr, "RegisterWriteXtEvent: Adding XtInput %lu Socket %d\n",
                    627:             persSockets[v].write, sock);
                    628: #endif /* DEBUG_LIBWWW */
                    629:   
                    630:     }
1.94    ! gully     631: #endif /* #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI) */  
1.4       cvs       632: }
                    633: 
1.11      cvs       634: /*----------------------------------------------------------------------
                    635:   RequestKillWriteXtevent
                    636:   kills any write Xt event associated with the request pointed to
                    637:   by "me".
                    638:   ----------------------------------------------------------------------*/
1.79      cvs       639: static void RequestKillWriteXtevent (SOCKET sock)
1.4       cvs       640: {
1.94    ! gully     641: #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI)
1.58      cvs       642:   int v;
                    643: 
                    644:   v = HASH (sock);
                    645: 
                    646:   if (persSockets[v].write)
                    647:     {
                    648: #ifdef DEBUG_LIBWWW   
                    649:       if (THD_TRACE)
                    650:        fprintf (stderr, "UnRegisterWriteXtEvent: Clearing Write XtInputs "
                    651:                 "%lu\n",
                    652:                 persSockets[v].write);
                    653: #endif /* DEBUG_LIBWWW */
1.85      gully     654:       
                    655: #ifdef _MOTIF
1.58      cvs       656:       XtRemoveInput (persSockets[v].write);
                    657:       persSockets[v].write =  (XtInputId) NULL;
1.85      gully     658: #endif /* _MOTIF */
                    659:       
1.94    ! gully     660: #if defined(_GTK)
1.79      cvs       661:       gdk_input_remove (persSockets[v].write);
                    662:       persSockets[v].write = (gint) 0;
1.85      gully     663: #endif /* _GTK */
                    664: 
1.94    ! gully     665: #if defined(_WX)
        !           666:       wxAmayaSocketEvent::UnregisterSocket( persSockets[v].write );
        !           667:       persSockets[v].write = 0;
        !           668: #endif /* _WX */
        !           669: 
1.58      cvs       670:     }
1.94    ! gully     671: #endif /* #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI) */  
1.18      cvs       672: }
                    673: 
                    674: /*----------------------------------------------------------------------
                    675:   RequestRegisterExceptXtevent
                    676:   Registers with Xt the except events associated with socket sock
                    677:   ----------------------------------------------------------------------*/
1.79      cvs       678: static void RequestRegisterExceptXtevent (SOCKET sock)
1.18      cvs       679: {
1.94    ! gully     680: #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI)
1.58      cvs       681:   int v;
                    682: 
                    683:   v = HASH (sock);
                    684: 
                    685:    if (!persSockets[v].except)
1.18      cvs       686:      {
1.85      gully     687: #ifdef _MOTIF
1.58      cvs       688:        persSockets[v].except =
                    689:         XtAppAddInput (app_cont,
                    690:                        sock,
                    691:                        (XtPointer) XtInputExceptMask,
                    692:                        (XtInputCallbackProc) AHTCallback_bridge,
                    693:                        (XtPointer) XtInputExceptMask);
1.85      gully     694: #endif /* _MOTIF */
                    695:        
1.94    ! gully     696: #if defined(_GTK)
1.79      cvs       697:      persSockets[v].except  =
                    698:        gdk_input_add ((gint) sock,
                    699:                      GDK_INPUT_EXCEPTION,
                    700:                      AHTCallback_bridgeGTK,
                    701:                      (gpointer) sock);
1.85      gully     702: #endif /* _GTK */
1.94    ! gully     703: 
        !           704: #if defined(_WX)
        !           705:      persSockets[v].except =
        !           706:        wxAmayaSocketEvent::RegisterSocket( sock,
        !           707:                                           WXAMAYASOCKET_EXCEPTION,
        !           708:                                           AHTCallback_bridgeWX );
        !           709: #endif /* _WX */
        !           710: 
        !           711: #ifdef DEBUG_LIBWWW
1.58      cvs       712:    if (THD_TRACE)
                    713:      fprintf (stderr, "RegisterExceptXtEvent: adding XtInput %lu Socket %d\n",
                    714:              persSockets[v].except, sock);
                    715: #endif /* DEBUG_LIBWWW */
1.18      cvs       716:      }
1.94    ! gully     717: #endif /* #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI) */   
1.4       cvs       718: }
                    719: 
1.11      cvs       720: /*----------------------------------------------------------------------
                    721:   RequestKillExceptXtevent
                    722:   kills any exception Xt event associated with the request pointed to
                    723:   by "me".
                    724:   ----------------------------------------------------------------------*/
1.79      cvs       725: static void RequestKillExceptXtevent (SOCKET sock)
1.4       cvs       726: {
1.94    ! gully     727: #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI)
1.58      cvs       728:   int v;
                    729: 
                    730:   v = HASH (sock);
                    731:   if (persSockets[v].except)
                    732:     {
                    733: #ifdef DEBUG_LIBWWW   
                    734:       if (THD_TRACE)
                    735:        fprintf (stderr, "UnregisterExceptXtEvent: Clearing Except XtInputs "
                    736:                 "%lu\n", persSockets[v].except);
                    737: #endif /* DEBUG_LIBWWW */
1.85      gully     738: 
                    739: #ifdef _MOTIF
1.58      cvs       740:       XtRemoveInput (persSockets[v].except);
                    741:       persSockets[v].except = (XtInputId) NULL;
1.85      gully     742: #endif /* _MOTIF */
                    743:       
1.94    ! gully     744: #if defined(_GTK)
1.79      cvs       745:       gdk_input_remove (persSockets[v].except);
                    746:       persSockets[v].except = (gint) 0;
1.85      gully     747: #endif /* _GTK */
1.94    ! gully     748: 
        !           749: #if defined(_WX)
        !           750:       wxAmayaSocketEvent::UnregisterSocket( persSockets[v].except );
        !           751:       persSockets[v].except = 0;
        !           752: #endif /* _WX */
1.85      gully     753:       
1.58      cvs       754:     }
1.94    ! gully     755: #endif /* #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI) */
1.58      cvs       756: }
                    757: 
                    758: /*----------------------------------------------------------------------
                    759:   Xt Timer functions 
                    760:   ----------------------------------------------------------------------*/
                    761: 
                    762: struct _HTTimer {
                    763:     ms_t        millis;         /* Relative value in millis */
                    764:     ms_t        expires;        /* Absolute value in millis */
                    765:     BOOL        relative;
                    766:     BOOL        repetitive;
                    767:     void *      param;          /* Client supplied context */
                    768:     HTTimerCallback * cbf;
                    769: };
                    770: 
                    771: struct _AmayaTimer {
                    772:   HTTimer *libwww_timer;
1.85      gully     773: 
                    774: #ifdef _MOTIF
1.58      cvs       775:   XtIntervalId xt_timer;
1.85      gully     776: #endif /* _MOTIF */
                    777:   
                    778: #ifdef _GTK
1.79      cvs       779:   guint  xt_timer;
1.85      gully     780: #endif /* _GTK */
                    781: 
1.94    ! gully     782: #ifdef _WX
        !           783:   wxAmayaTimer * xt_timer;
        !           784: #endif /* _WX */
        !           785: 
1.85      gully     786: #ifdef _NOGUI
                    787:   unsigned int xt_timer;
                    788: #endif /* #ifdef _NOGUI */  
                    789:   
1.58      cvs       790: };
                    791: 
                    792: typedef struct _AmayaTimer AmayaTimer;
                    793: 
                    794: static HTList *Timers = NULL;
                    795: 
                    796: /*----------------------------------------------------------------------
1.79      cvs       797:   TimerCallback
                    798:   called by the system event loop. Timers shouldn't be restarted
                    799:   on exiting.
1.58      cvs       800:   ----------------------------------------------------------------------*/
                    801: void *TimerCallback (XtPointer cdata, XtIntervalId *id)
                    802: {
1.86      gully     803: #ifdef _MOTIF
1.58      cvs       804:   HTList *cur, *last;
                    805:   AmayaTimer *me;
                    806:   HTTimer *libwww_timer;
                    807: 
                    808:   if (!AmayaIsAlive () 
                    809:       || Timers == NULL)
                    810:     return (0);
                    811: 
                    812:   /* find the timer from the uid */
                    813:   last = cur = Timers;
                    814:   while ((me = (AmayaTimer * ) HTList_nextObject (cur)))
                    815:     {
                    816:       if (me->xt_timer == *id)
                    817:        break;
                    818:       last = cur;
                    819:     }
                    820: 
                    821:   if (me)
                    822:     {
                    823:       libwww_timer = me->libwww_timer;
                    824:       /* remove the element from the list @@@ can be optimized later */
                    825:       HTList_quickRemoveElement(cur, last);
                    826:       TtaFreeMemory (me);
                    827:       HTTimer_dispatch (libwww_timer);
                    828:     }
1.86      gully     829: #endif /* _MOTIF */
                    830:   
1.58      cvs       831:   return (0);
1.86      gully     832:   
1.58      cvs       833: }
1.86      gully     834: 
1.85      gully     835: #ifdef _GTK
1.79      cvs       836: /*----------------------------------------------------------------------
                    837:   TimerCallbackGTK
1.81      kahan     838:   The callback returns FALSE to destroy the timer that called it.
1.79      cvs       839:   ----------------------------------------------------------------------*/
                    840: gboolean TimerCallbackGTK (gpointer id)
                    841: {
                    842:   HTList *cur, *last;
                    843:   AmayaTimer *me;
                    844:   HTTimer *libwww_timer;
                    845:   AmayaTimer *data;
                    846: 
                    847:   data = (AmayaTimer *) id;
                    848: 
                    849:   if (!AmayaIsAlive () 
                    850:       || Timers == NULL)
1.81      kahan     851:     return (FALSE);
1.79      cvs       852: 
                    853:   /* find the timer from the uid */
                    854:   last = cur = Timers;
                    855:   while ((me = (AmayaTimer * ) HTList_nextObject (cur)))
                    856:     {
                    857:       if (me == data)
                    858:        break;
                    859:       last = cur;
                    860:     }
                    861: 
                    862:   if (me)
                    863:     {
                    864:       libwww_timer = me->libwww_timer;
                    865:       /* remove the element from the list @@@ can be optimized later */
                    866:       HTList_quickRemoveElement(cur, last);
                    867:       TtaFreeMemory (me);
                    868:       HTTimer_dispatch (libwww_timer);
                    869:     }
                    870:   return (FALSE);
                    871: }
1.85      gully     872: #endif /* _GTK */
1.79      cvs       873: 
1.58      cvs       874: /*----------------------------------------------------------------------
1.94    ! gully     875:   TimerCallbackWX
        !           876:   called when a timer is throw
        !           877:   ----------------------------------------------------------------------*/
        !           878: void TimerCallbackWX( void * p_context )
        !           879: {
        !           880: #ifdef _WX
        !           881:   HTList *cur, *last;
        !           882:   AmayaTimer *me;
        !           883:   HTTimer *libwww_timer;
        !           884:   AmayaTimer *data;
        !           885: 
        !           886:   data = (AmayaTimer *)p_context;
        !           887: 
        !           888:   if (!AmayaIsAlive () 
        !           889:       || Timers == NULL)
        !           890:     return;
        !           891: 
        !           892:   /* find the timer from the uid */
        !           893:   last = cur = Timers;
        !           894:   while ((me = (AmayaTimer * ) HTList_nextObject (cur)))
        !           895:     {
        !           896:       if (me == data)
        !           897:        break;
        !           898:       last = cur;
        !           899:     }
        !           900: 
        !           901:   if (me)
        !           902:     {
        !           903:       libwww_timer = me->libwww_timer;
        !           904:       /* remove the element from the list @@@ can be optimized later */
        !           905:       HTList_quickRemoveElement(cur, last);
        !           906: 
        !           907:       /* delete explicitely the AmayaTimer */
        !           908:       delete wxDynamicCast(me->xt_timer, wxAmayaTimer);
        !           909: 
        !           910:       TtaFreeMemory (me);
        !           911:       HTTimer_dispatch (libwww_timer);
        !           912:     }
        !           913: #endif /* _WX */
        !           914: }
        !           915: 
        !           916: /*----------------------------------------------------------------------
1.59      cvs       917:   KillAllTimers
1.58      cvs       918:   ----------------------------------------------------------------------*/
1.59      cvs       919: void KillAllTimers (void)
1.58      cvs       920: {
1.94    ! gully     921: #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI)
1.58      cvs       922:   /* @@@ maybe add something else to kill the Xt things */
                    923:   if (Timers)
                    924:     HTList_delete (Timers);
1.65      cvs       925:   Timers = NULL;
1.94    ! gully     926: #endif /* #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI) */
1.58      cvs       927: }
                    928: 
                    929: /*----------------------------------------------------------------------
1.59      cvs       930:  AMAYA_SetTimer
                    931:  ----------------------------------------------------------------------*/
                    932: void AMAYA_SetTimer (HTTimer *libwww_timer)
1.58      cvs       933: {
1.94    ! gully     934: #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI)
1.58      cvs       935:   HTList *cur, *last;
                    936:   AmayaTimer *me;
                    937: 
1.90      gully     938:   if (!AmayaIsAlive () 
1.58      cvs       939:       || libwww_timer == NULL
                    940:       || libwww_timer->expires == 0)
                    941:     return;
                    942: 
                    943:   if (Timers == NULL)
                    944:     Timers = HTList_new ();
                    945: 
                    946:   /* see if this timer existed already */
                    947:   last = cur = Timers;
                    948:   while ((me = (AmayaTimer * ) HTList_nextObject (cur)))
                    949:     {
                    950:       if (me->libwww_timer == libwww_timer)
                    951:        break;
                    952:       last = cur;
                    953:     }
                    954: 
                    955:   if (me)
                    956:     {
                    957:     /* remove the old timer */
                    958:       if (me->xt_timer) 
                    959:        {
1.85      gully     960: #ifdef _MOTIF
1.58      cvs       961:          XtRemoveTimeOut (me->xt_timer);
1.59      cvs       962:          me->xt_timer = (XtIntervalId) NULL;
1.85      gully     963: #endif /* _MOTIF */
                    964: 
                    965: #ifdef _GTK
1.79      cvs       966:          gtk_timeout_remove (me->xt_timer);
                    967:          me->xt_timer = (guint) 0;
                    968: #endif /* !_GTK */
1.85      gully     969: 
1.94    ! gully     970: #ifdef _WX
        !           971:          delete wxDynamicCast(me->xt_timer, wxTimer);
        !           972:          me->xt_timer = NULL;
        !           973: #endif /* _WX */
        !           974:        }
1.58      cvs       975:     }
                    976:   else
                    977:     {
                    978:       /* create a new element */
1.91      gully     979:       me = (AmayaTimer*)TtaGetMemory (sizeof (AmayaTimer));
1.58      cvs       980:       /* and add it to the list */
                    981:       HTList_addObject(last, (void *) me);
                    982:       me->libwww_timer = libwww_timer;
                    983:     }
                    984: 
                    985:   /* add a new time out */
1.85      gully     986: #ifdef _MOTIF
1.58      cvs       987:   me->xt_timer = XtAppAddTimeOut (app_cont,
                    988:                                 me->libwww_timer->millis,
                    989:                                 (XtTimerCallbackProc) TimerCallback,
                    990:                                 (XtPointer *) (void *) me);
1.85      gully     991: #endif /* _MOTIF */
                    992:   
                    993: #ifdef _GTK
1.79      cvs       994:   me->xt_timer = gtk_timeout_add ((guint32) me->libwww_timer->millis,
                    995:                                  (GtkFunction) TimerCallbackGTK,
                    996:                                  (gpointer) me);
1.85      gully     997: #endif /* _GTK */
1.94    ! gully     998: 
        !           999: #ifdef _WX
        !          1000:   me->xt_timer = new wxAmayaTimer( TimerCallbackWX, me);
        !          1001:   /* start a one shot timer */
        !          1002:   me->xt_timer->Start( me->libwww_timer->millis, TRUE );
        !          1003: #endif /* _WX */
        !          1004: 
        !          1005: #endif /* #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI) */  
1.58      cvs      1006: }
                   1007: 
                   1008: /*----------------------------------------------------------------------
1.59      cvs      1009:   AMAYA_DeleteTimer
1.58      cvs      1010:   ----------------------------------------------------------------------*/
1.59      cvs      1011: void AMAYA_DeleteTimer (HTTimer *libwww_timer)
1.58      cvs      1012: {
1.94    ! gully    1013: #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI)
1.58      cvs      1014:   HTList *cur, *last;
                   1015:   AmayaTimer *me;
                   1016: 
1.59      cvs      1017:   if (Timers == NULL || libwww_timer == NULL)
1.58      cvs      1018:     return;
                   1019: 
                   1020:   /* find the id */
                   1021:   last = cur = Timers;
                   1022:   while ((me = (AmayaTimer * ) HTList_nextObject (cur)))
                   1023:     {
1.59      cvs      1024:       if (me->libwww_timer == libwww_timer)
1.58      cvs      1025:        break;
                   1026:       last = cur;
                   1027:     }
                   1028: 
                   1029:   if (me)
                   1030:     {
                   1031:       /* remove the Xt timer */
1.85      gully    1032: #ifdef _MOTIF
1.58      cvs      1033:       XtRemoveTimeOut (me->xt_timer);
1.85      gully    1034: #endif /* _MOTIF */
                   1035:       
                   1036: #ifdef _GTK
1.79      cvs      1037:       gtk_timeout_remove (me->xt_timer);
1.85      gully    1038: #endif /* _GTK */
1.94    ! gully    1039: 
        !          1040: #ifdef _WX
        !          1041:       delete wxDynamicCast(me->xt_timer, wxTimer);
        !          1042: #endif /* _WX */
        !          1043: 
1.58      cvs      1044:       /* and the element from the list */
1.65      cvs      1045:       HTList_removeObject (Timers, me);
1.58      cvs      1046:       TtaFreeMemory (me);
                   1047:     }
1.94    ! gully    1048: #endif /* #if defined(_MOTIF) || defined(_GTK) || defined(_WX) || defined(_NOGUI) */
1.31      cvs      1049: }
1.86      gully    1050: 

Webmaster