home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / Xt / NextEvent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  24.2 KB  |  937 lines

  1. /* $XConsortium: NextEvent.c,v 1.110 93/02/10 15:47:39 converse Exp $ */
  2.  
  3. /***********************************************************
  4. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
  5. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  6.  
  7.                         All Rights Reserved
  8.  
  9. Permission to use, copy, modify, and distribute this software and its 
  10. documentation for any purpose and without fee is hereby granted, 
  11. provided that the above copyright notice appear in all copies and that
  12. both that copyright notice and this permission notice appear in 
  13. supporting documentation, and that the names of Digital or MIT not be
  14. used in advertising or publicity pertaining to distribution of the
  15. software without specific, written prior permission.  
  16.  
  17. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  18. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  19. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  20. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  22. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  23. SOFTWARE.
  24.  
  25. ******************************************************************/
  26.  
  27. #include "IntrinsicI.h"
  28. #include <stdio.h>
  29. #include <errno.h>
  30.  
  31. extern int errno;
  32.  
  33. static TimerEventRec* freeTimerRecs;
  34. static WorkProcRec* freeWorkRecs;
  35.  
  36. /* Some systems running NTP daemons are known to return strange usec
  37.  * values from gettimeofday.  At present (3/90) this has only been
  38.  * reported on SunOS...
  39.  */
  40.  
  41. #ifndef NEEDS_NTPD_FIXUP
  42. # if defined(sun) || defined(MOTOROLA)
  43. #  define NEEDS_NTPD_FIXUP 1
  44. # else
  45. #  define NEEDS_NTPD_FIXUP 0
  46. # endif
  47. #endif
  48.  
  49. #if NEEDS_NTPD_FIXUP
  50. #define FIXUP_TIMEVAL(t) { \
  51.     while ((t).tv_usec >= 1000000) { \
  52.         (t).tv_usec -= 1000000; \
  53.         (t).tv_sec++; \
  54.     } \
  55.     while ((t).tv_usec < 0) { \
  56.         if ((t).tv_sec > 0) { \
  57.         (t).tv_usec += 1000000; \
  58.         (t).tv_sec--; \
  59.         } else { \
  60.         (t).tv_usec = 0; \
  61.         break; \
  62.         } \
  63.     }}
  64. #else
  65. #define FIXUP_TIMEVAL(t)
  66. #endif /*NEEDS_NTPD_FIXUP*/
  67.  
  68.  
  69.  
  70. /*
  71.  * Private routines
  72.  */
  73. #define ADD_TIME(dest, src1, src2) { \
  74.     if(((dest).tv_usec = (src1).tv_usec + (src2).tv_usec) >= 1000000) {\
  75.           (dest).tv_usec -= 1000000;\
  76.           (dest).tv_sec = (src1).tv_sec + (src2).tv_sec + 1 ; \
  77.     } else { (dest).tv_sec = (src1).tv_sec + (src2).tv_sec ; \
  78.        if(((dest).tv_sec >= 1) && (((dest).tv_usec <0))) { \
  79.         (dest).tv_sec --;(dest).tv_usec += 1000000; } } }
  80.  
  81.  
  82. #define TIMEDELTA(dest, src1, src2) { \
  83.     if(((dest).tv_usec = (src1).tv_usec - (src2).tv_usec) < 0) {\
  84.           (dest).tv_usec += 1000000;\
  85.           (dest).tv_sec = (src1).tv_sec - (src2).tv_sec - 1;\
  86.     } else     (dest).tv_sec = (src1).tv_sec - (src2).tv_sec;  }
  87.  
  88. #define IS_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \
  89.     || (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec > (t1).tv_usec)))
  90.  
  91. #define IS_AT_OR_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \
  92.     || (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec >= (t1).tv_usec)))
  93.  
  94. static void QueueTimerEvent(app, ptr)
  95.     XtAppContext app;
  96.     TimerEventRec *ptr;
  97. {
  98.         TimerEventRec *t,**tt;
  99.         tt = &app->timerQueue;
  100.         t  = *tt;
  101.         while (t != NULL &&
  102.                 IS_AFTER(t->te_timer_value, ptr->te_timer_value)) {
  103.           tt = &t->te_next;
  104.           t  = *tt;
  105.          }
  106.          ptr->te_next = t;
  107.          *tt = ptr;
  108. }
  109.  
  110. /* 
  111.  * Routine to block in the toolkit.  This should be the only call to select.
  112.  *
  113.  * This routine returns when there is something to be done.
  114.  *
  115.  * Before calling this with ignoreInputs==False, app->outstandingQueue should
  116.  * be checked; this routine will not verify that an alternate input source
  117.  * has not already been enqueued.
  118.  *
  119.  *
  120.  * _XtwaitForSomething( ignoreTimers, ignoreInputs, ignoreEvents,
  121.  *            block, howlong, appContext)
  122.  * Boolean ignoreTimers;     (Don't return if a timer would fire
  123.  *                Also implies forget timers exist)
  124.  *
  125.  * Boolean ignoreInputs;     (Ditto for input callbacks )
  126.  *
  127.  * Boolean ignoreEvents;     (Ditto for X events)
  128.  *
  129.  * Boolean block;         (Okay to block)
  130.  * TimeVal howlong;         (howlong to wait for if blocking and not
  131.  *                doing Timers... Null mean forever.
  132.  *                Maybe should mean shortest of both)
  133.  * XtAppContext app;         (Displays to check wait on)
  134.  * Returns display for which input is available, if any
  135.  * and if ignoreEvents==False, else returns -1
  136.  *
  137.  * if ignoring everything && block=True && howlong=NULL, you'll have
  138.  * lots of time for coffee; better not try it!  In fact, it probably
  139.  * makes little sense to do this regardless of the value of howlong
  140.  * (bottom line is, we don't bother checking here).
  141.  */
  142. #if NeedFunctionPrototypes
  143. int _XtwaitForSomething(
  144.     _XtBoolean ignoreTimers,
  145.     _XtBoolean ignoreInputs,
  146.     _XtBoolean ignoreEvents,
  147.     _XtBoolean block,
  148.     unsigned long *howlong,
  149.     XtAppContext app
  150.         )
  151. #else
  152. int _XtwaitForSomething(ignoreTimers, ignoreInputs, ignoreEvents,
  153.             block, howlong, app)
  154.     Boolean ignoreTimers;
  155.     Boolean ignoreInputs;
  156.     Boolean ignoreEvents;
  157.     Boolean block;
  158.     unsigned long *howlong;
  159.     XtAppContext app;
  160. #endif
  161. {
  162.     struct timeval  cur_time;
  163.     struct timeval  start_time;
  164.     struct timeval  wait_time;
  165.     struct timeval  new_time;
  166.     struct timeval  time_spent;
  167.     struct timeval    max_wait_time;
  168.     static struct timeval  zero_time = { 0 , 0};
  169.     register struct timeval *wait_time_ptr;
  170.     Fd_set rmaskfd, wmaskfd, emaskfd;
  171.     static Fd_set zero_fd = { 0 };
  172.     int nfound, i, d;
  173.     
  174.      if (block) {
  175.         (void) gettimeofday (&cur_time, NULL);
  176.         FIXUP_TIMEVAL(cur_time);
  177.         start_time = cur_time;
  178.         if(howlong == NULL) { /* special case for ever */
  179.             wait_time_ptr = 0;
  180.         } else { /* block until at most */
  181.             max_wait_time.tv_sec = *howlong/1000;
  182.             max_wait_time.tv_usec = (*howlong %1000)*1000;
  183.             wait_time_ptr = &max_wait_time;
  184.         }
  185.     } else {  /* don't block */
  186.         max_wait_time = zero_time;
  187.         wait_time_ptr = &max_wait_time;
  188.     }
  189.  
  190.       WaitLoop:
  191.     while (1) {
  192.         if (app->timerQueue != NULL && !ignoreTimers && block) {
  193.             if(IS_AFTER(cur_time, app->timerQueue->te_timer_value)) {
  194.             TIMEDELTA (wait_time, app->timerQueue->te_timer_value, 
  195.                    cur_time);
  196.             if(howlong==NULL || IS_AFTER(wait_time,max_wait_time)){
  197.                 wait_time_ptr = &wait_time;
  198.             } else {
  199.                 wait_time_ptr = &max_wait_time;
  200.             }
  201.             } else wait_time_ptr = &zero_time;
  202.         } 
  203.         if( !ignoreInputs ) {
  204.             rmaskfd = app->fds.rmask;
  205.             wmaskfd = app->fds.wmask;
  206.             emaskfd = app->fds.emask;
  207.         } else {
  208.             rmaskfd = zero_fd;
  209.             wmaskfd = zero_fd;
  210.             emaskfd = zero_fd;
  211.         }
  212.         if (!ignoreEvents) {
  213.             for (d = 0; d < app->count; d++) {
  214.             FD_SET (ConnectionNumber(app->list[d]), &rmaskfd);
  215.             }
  216.         }
  217.         nfound = select (app->fds.nfds, (int *) &rmaskfd,
  218.             (int *) &wmaskfd, (int *) &emaskfd, wait_time_ptr);
  219.         if (nfound == -1) {
  220.             /*
  221.              *  interrupt occured recalculate time value and select
  222.              *  again.
  223.              */
  224.             if (errno == EINTR) {
  225.                 errno = 0;  /* errno is not self reseting */
  226.                 if (block) {
  227.                 if (wait_time_ptr == NULL) /*howlong == NULL*/
  228.                     continue;
  229.                 (void)gettimeofday (&new_time, NULL);
  230.                 FIXUP_TIMEVAL(new_time);
  231.                 TIMEDELTA(time_spent, new_time, cur_time);
  232.                 cur_time = new_time;
  233.                 if(IS_AFTER(time_spent, *wait_time_ptr)) {
  234.                     TIMEDELTA(wait_time, *wait_time_ptr,
  235.                           time_spent);
  236.                     wait_time_ptr = &wait_time;
  237.                     continue;
  238.                 } else {
  239.                     /* time is up anyway */
  240.                     nfound = 0;
  241.                 }
  242.                 }
  243.             } else {
  244.                 char Errno[12];
  245.                 String param = Errno;
  246.                 Cardinal param_count = 1;
  247.  
  248.                 if (!ignoreEvents) {
  249.                 /* get Xlib to detect a bad connection */
  250.                 for (d = 0; d < app->count; d++) {
  251.                     if (XEventsQueued(app->list[d],
  252.                               QueuedAfterReading))
  253.                     return d;
  254.                 }
  255.                 }
  256.                 sprintf( Errno, "%d", errno);
  257.                 XtAppWarningMsg(app, "communicationError","select",
  258.                    XtCXtToolkitError,"Select failed; error code %s",
  259.                    ¶m, ¶m_count);
  260.                 continue;
  261.             }
  262.         } /* timed out or input available */
  263.         break;
  264.     }
  265.     
  266.     if (nfound == 0) {
  267.         if(howlong) *howlong = (unsigned long)0;  /* Timed out */
  268.         return -1;
  269.     }
  270.     if(block && howlong != NULL) { /* adjust howlong */
  271.         (void) gettimeofday (&new_time, NULL);
  272.         FIXUP_TIMEVAL(new_time);
  273.         TIMEDELTA(time_spent, new_time, start_time);
  274.         if(*howlong <= (time_spent.tv_sec*1000+time_spent.tv_usec/1000))
  275.         *howlong = (unsigned long)0;  /* Timed out */
  276.         else
  277.         *howlong -= (time_spent.tv_sec*1000+time_spent.tv_usec/1000);
  278.     }
  279.     if(ignoreInputs) {
  280.         if (ignoreEvents) return -1; /* then only doing timers */
  281.         for (d = 0; d < app->count; d++) {
  282.         if (FD_ISSET(ConnectionNumber(app->list[d]), &rmaskfd)) {
  283.             if (XEventsQueued( app->list[d], QueuedAfterReading ))
  284.             return d;
  285.             /*
  286.              * An error event could have arrived
  287.              * without any real events, or events
  288.              * could have been swallowed by Xlib,
  289.              * or the connection may be broken.
  290.              * We can't tell the difference, so
  291.              * ssume Xlib will eventually discover
  292.              * a broken connection.
  293.              */
  294.         }
  295.         }
  296.         goto WaitLoop;    /* must have been only error events */
  297.         }
  298.     {
  299.     int ret = -1;
  300.     Boolean found_input = False;
  301.  
  302.     for (i = 0; i < app->fds.nfds && nfound > 0; i++) {
  303.         XtInputMask condition = 0;
  304.         if (FD_ISSET (i, &rmaskfd)) {
  305.         nfound--;
  306.         if (!ignoreEvents) {
  307.             for (d = 0; d < app->count; d++) {
  308.             if (i == ConnectionNumber(app->list[d])) {
  309.                 if (ret == -1) {
  310.                 if (XEventsQueued( app->list[d],
  311.                            QueuedAfterReading ))
  312.                     ret = d;
  313.                 /*
  314.                  * An error event could have arrived
  315.                  * without any real events, or events
  316.                  * could have been swallowed by Xlib,
  317.                  * or the connection may be broken.
  318.                  * We can't tell the difference, so
  319.                  * assume Xlib will eventually discover
  320.                  * a broken connection.
  321.                  */
  322.                 }
  323.                 goto ENDILOOP;
  324.             }
  325.             }
  326.         }
  327.         condition = XtInputReadMask;
  328.         }
  329.         if (FD_ISSET (i, &wmaskfd)) {
  330.         condition |= XtInputWriteMask;
  331.         nfound--;
  332.         }
  333.         if (FD_ISSET (i, &emaskfd)) {
  334.         condition |= XtInputExceptMask;
  335.         nfound--;
  336.         }
  337.         if (condition) {
  338.         InputEvent *ep;
  339.         for (ep = app->input_list[i]; ep; ep = ep->ie_next) {
  340.             if (condition & ep->ie_condition) {
  341.             ep->ie_oq = app->outstandingQueue;
  342.             app->outstandingQueue = ep;
  343.             }
  344.         }
  345.         found_input = True;
  346.         }
  347. ENDILOOP:   ;
  348.     } /* endfor */
  349.     if (ret >= 0 || found_input)
  350.         return ret;
  351.     goto WaitLoop;        /* must have been only error events */
  352.     }
  353. }
  354.  
  355. #define IeCallProc(ptr) \
  356.     (*ptr->ie_proc) (ptr->ie_closure, &ptr->ie_source, (XtInputId*)&ptr);
  357.  
  358. #define TeCallProc(ptr) \
  359.     (*ptr->te_proc) (ptr->te_closure, (XtIntervalId*)&ptr);
  360.  
  361. /*
  362.  * Public Routines
  363.  */
  364.  
  365. XtIntervalId XtAddTimeOut(interval, proc, closure)
  366.     unsigned long interval;
  367.     XtTimerCallbackProc proc;
  368.     XtPointer closure;
  369. {
  370.     return XtAppAddTimeOut(_XtDefaultAppContext(), 
  371.         interval, proc, closure); 
  372. }
  373.  
  374.  
  375. XtIntervalId XtAppAddTimeOut(app, interval, proc, closure)
  376.     XtAppContext app;
  377.     unsigned long interval;
  378.     XtTimerCallbackProc proc;
  379.     XtPointer closure;
  380. {
  381.     TimerEventRec *tptr;
  382.         struct timeval current_time;
  383.  
  384.     if (freeTimerRecs) {
  385.         tptr = freeTimerRecs;
  386.         freeTimerRecs = tptr->te_next;
  387.     }
  388.     else tptr = XtNew(TimerEventRec);
  389.  
  390.     tptr->te_next = NULL;
  391.     tptr->te_closure = closure;
  392.     tptr->te_proc = proc;
  393.     tptr->app = app;
  394.     tptr->te_timer_value.tv_sec = interval/1000;
  395.     tptr->te_timer_value.tv_usec = (interval%1000)*1000;
  396.         (void) gettimeofday(¤t_time, NULL);
  397.     FIXUP_TIMEVAL(current_time);
  398.         ADD_TIME(tptr->te_timer_value,tptr->te_timer_value,current_time);
  399.     QueueTimerEvent(app, tptr);
  400.     return( (XtIntervalId) tptr);
  401. }
  402.  
  403. void  XtRemoveTimeOut(id)
  404.     XtIntervalId id;
  405. {
  406.    TimerEventRec *t, *last, *tid = (TimerEventRec *) id;
  407.  
  408.    /* find it */
  409.  
  410.    for(t = tid->app->timerQueue, last = NULL;
  411.        t != NULL && t != tid;
  412.        t = t->te_next) last = t;
  413.  
  414.    if (t == NULL) return; /* couldn't find it */
  415.    if(last == NULL) { /* first one on the list */
  416.        t->app->timerQueue = t->te_next;
  417.    } else last->te_next = t->te_next;
  418.  
  419.    t->te_next = freeTimerRecs;
  420.    freeTimerRecs = t;
  421.    return;
  422. }
  423.  
  424. XtWorkProcId XtAddWorkProc(proc, closure)
  425.     XtWorkProc proc;
  426.     XtPointer closure;
  427. {
  428.     return XtAppAddWorkProc(_XtDefaultAppContext(), proc, closure);
  429. }
  430.  
  431. XtWorkProcId XtAppAddWorkProc(app, proc, closure)
  432.     XtAppContext app;
  433.     XtWorkProc proc;
  434.     XtPointer closure;
  435. {
  436.     WorkProcRec *wptr;
  437.  
  438.     if (freeWorkRecs) {
  439.         wptr = freeWorkRecs;
  440.         freeWorkRecs = wptr->next;
  441.     } else wptr = XtNew(WorkProcRec);
  442.  
  443.     wptr->next = app->workQueue;
  444.     wptr->closure = closure;
  445.     wptr->proc = proc;
  446.     wptr->app = app;
  447.     app->workQueue = wptr;
  448.  
  449.     return (XtWorkProcId) wptr;
  450. }
  451.  
  452. void  XtRemoveWorkProc(id)
  453.     XtWorkProcId id;
  454. {
  455.     WorkProcRec *wid= (WorkProcRec *) id, *w, *last;
  456.  
  457.     /* find it */
  458.     for(w = wid->app->workQueue, last = NULL; w != NULL && w != wid; w = w->next) last = w;
  459.  
  460.     if (w == NULL) return; /* couldn't find it */
  461.  
  462.     if(last == NULL) wid->app->workQueue = w->next;
  463.     else last->next = w->next;
  464.  
  465.     w->next = freeWorkRecs;
  466.     freeWorkRecs = w;
  467. }
  468.  
  469. XtInputId XtAddInput( source, Condition, proc, closure)
  470.     int source;
  471.     XtPointer Condition;
  472.     XtInputCallbackProc proc;
  473.     XtPointer closure;
  474. {
  475.     return XtAppAddInput(_XtDefaultAppContext(),
  476.         source, Condition, proc, closure);
  477. }
  478.  
  479. XtInputId XtAppAddInput(app, source, Condition, proc, closure)
  480.     XtAppContext app;
  481.     int source;
  482.     XtPointer Condition;
  483.     XtInputCallbackProc proc;
  484.     XtPointer closure;
  485. {
  486.     InputEvent* sptr;
  487.     XtInputMask condition = (XtInputMask) Condition;
  488.     
  489.     if (!condition ||
  490.         condition & ~(XtInputReadMask|XtInputWriteMask|XtInputExceptMask))
  491.         XtAppErrorMsg(app,"invalidParameter","xtAddInput",XtCXtToolkitError,
  492.               "invalid condition passed to XtAppAddInput",
  493.               (String *)NULL, (Cardinal *)NULL);
  494.  
  495.     if (app->input_max <= source) {
  496.         Cardinal n = source + 1;
  497.         app->input_list = (InputEvent**)XtRealloc((char*) app->input_list,
  498.                               n * sizeof(InputEvent*));
  499.         bzero((char *) &app->input_list[app->input_max],
  500.           (unsigned) (n - app->input_max) * sizeof(InputEvent*));
  501.         app->input_max = n;
  502.     }
  503.     sptr = XtNew(InputEvent);
  504.     sptr->ie_proc = proc;
  505.     sptr->ie_closure = closure;
  506.     sptr->app = app;
  507.     sptr->ie_oq = NULL;
  508.     sptr->ie_source = source;
  509.     sptr->ie_condition = condition;
  510.     sptr->ie_next = app->input_list[source];
  511.     app->input_list[source] = sptr;
  512.  
  513.     if (condition & XtInputReadMask)   FD_SET(source, &app->fds.rmask);
  514.     if (condition & XtInputWriteMask)  FD_SET(source, &app->fds.wmask);
  515.     if (condition & XtInputExceptMask) FD_SET(source, &app->fds.emask);
  516.  
  517.     if (app->fds.nfds < (source+1)) app->fds.nfds = source+1;
  518.     app->fds.count++;
  519.     return((XtInputId)sptr);
  520.  
  521. }
  522.  
  523. void XtRemoveInput( id )
  524.     register XtInputId  id;
  525. {
  526.       register InputEvent *sptr, *lptr;
  527.     XtAppContext app = ((InputEvent *)id)->app;
  528.     register int source = ((InputEvent *)id)->ie_source;
  529.     Boolean found = False;
  530.  
  531.     sptr = app->outstandingQueue;
  532.     lptr = NULL;
  533.     for (; sptr != NULL; sptr = sptr->ie_oq) {
  534.         if (sptr == (InputEvent *)id) {
  535.         if (lptr == NULL) app->outstandingQueue = sptr->ie_oq;
  536.         else lptr->ie_oq = sptr->ie_oq;
  537.         }
  538.         lptr = sptr;
  539.     }
  540.  
  541.     if(app->input_list && (sptr = app->input_list[source]) != NULL) {
  542.         for( lptr = NULL ; sptr; sptr = sptr->ie_next ){
  543.             if(sptr == (InputEvent *) id) {
  544.                 XtInputMask condition = 0;
  545.                 if(lptr == NULL) {
  546.                     app->input_list[source] = sptr->ie_next;
  547.                 } else {
  548.                     lptr->ie_next = sptr->ie_next;
  549.                 }
  550.                 for (lptr = app->input_list[source];
  551.                      lptr; lptr = lptr->ie_next)
  552.                     condition |= lptr->ie_condition;
  553.                 if ((sptr->ie_condition & XtInputReadMask) &&
  554.                     !(condition & XtInputReadMask))
  555.                    FD_CLR(source, &app->fds.rmask);
  556.                 if ((sptr->ie_condition & XtInputWriteMask) &&
  557.                     !(condition & XtInputWriteMask))
  558.                    FD_CLR(source, &app->fds.wmask);
  559.                 if ((sptr->ie_condition & XtInputExceptMask) &&
  560.                     !(condition & XtInputExceptMask))
  561.                    FD_CLR(source, &app->fds.emask);
  562.                 XtFree((char *) sptr);
  563.                 found = True;
  564.                 break;
  565.             }
  566.             lptr = sptr;          
  567.         }
  568.     }
  569.  
  570.     if (found)
  571.     app->fds.count--;
  572.     else
  573.     XtAppWarningMsg(app, "invalidProcedure","inputHandler",XtCXtToolkitError,
  574.                    "XtRemoveInput: Input handler not found",
  575.            (String *)NULL, (Cardinal *)NULL);
  576. }
  577.  
  578. void _XtRemoveAllInputs(app)
  579.     XtAppContext app;
  580. {
  581.     int i;
  582.     for (i = 0; i < app->input_max; i++) {
  583.     InputEvent* ep = app->input_list[i];
  584.     while (ep) {
  585.         InputEvent *next = ep->ie_next;
  586.         XtFree( (char*)ep );
  587.         ep = next;
  588.     }
  589.     }
  590.     XtFree((char *) app->input_list);
  591. }
  592.  
  593. /* Do alternate input and timer callbacks if there are any */
  594.  
  595. static void DoOtherSources(app)
  596.     XtAppContext app;
  597. {
  598.     TimerEventRec *te_ptr;
  599.     InputEvent *ie_ptr;
  600.     struct timeval  cur_time;
  601.  
  602. #define DrainQueue() \
  603.     for (ie_ptr = app->outstandingQueue; ie_ptr != NULL;) { \
  604.         app->outstandingQueue = ie_ptr->ie_oq;        \
  605.         ie_ptr ->ie_oq = NULL;                \
  606.         IeCallProc(ie_ptr);                    \
  607.         ie_ptr = app->outstandingQueue;            \
  608.     }
  609. /*enddef*/
  610.     DrainQueue();
  611.     if (app->fds.count > 0) {
  612.         /* Call _XtwaitForSomething to get input queued up */
  613.         (void) _XtwaitForSomething(TRUE, FALSE, TRUE, FALSE,
  614.         (unsigned long *)NULL, app);
  615.         DrainQueue();
  616.     }
  617.     if (app->timerQueue != NULL) {    /* check timeout queue */
  618.         (void) gettimeofday (&cur_time, NULL);
  619.         FIXUP_TIMEVAL(cur_time);
  620.         while(IS_AT_OR_AFTER (app->timerQueue->te_timer_value, cur_time)) {
  621.         te_ptr = app->timerQueue;
  622.         app->timerQueue = te_ptr->te_next;
  623.         te_ptr->te_next = NULL;
  624.         if (te_ptr->te_proc != NULL)
  625.             TeCallProc(te_ptr);
  626.         te_ptr->te_next = freeTimerRecs;
  627.         freeTimerRecs = te_ptr;
  628.               if (app->timerQueue == NULL) break;
  629.         }
  630.     }
  631. #undef DrainQueue
  632. }
  633.  
  634. /* If there are any work procs, call them.  Return whether we did so */
  635.  
  636. static Boolean CallWorkProc(app)
  637.     XtAppContext app;
  638. {
  639.     register WorkProcRec *w = app->workQueue;
  640.     Boolean delete;
  641.  
  642.     if (w == NULL) return FALSE;
  643.  
  644.     app->workQueue = w->next;
  645.  
  646.     delete = (*(w->proc)) (w->closure);
  647.  
  648.     if (delete) {
  649.         w->next = freeWorkRecs;
  650.         freeWorkRecs = w;
  651.     }
  652.     else {
  653.         w->next = app->workQueue;
  654.         app->workQueue = w;
  655.     }
  656.     return TRUE;
  657. }
  658.  
  659. /*
  660.  * XtNextEvent()
  661.  * return next event;
  662.  */
  663.  
  664. void XtNextEvent(event)
  665.     XEvent *event;
  666. {
  667.     XtAppNextEvent(_XtDefaultAppContext(), event);
  668. }
  669.  
  670. void _XtRefreshMapping(event, dispatch)
  671.     XEvent *event;
  672.     Boolean dispatch;
  673. {
  674.     XtPerDisplay pd = _XtGetPerDisplay(event->xmapping.display);
  675.  
  676.     if (event->xmapping.request != MappingPointer &&
  677.     pd && pd->keysyms && (event->xmapping.serial >= pd->keysyms_serial))
  678.     _XtBuildKeysymTables( event->xmapping.display, pd );
  679.     XRefreshKeyboardMapping(&event->xmapping);
  680.     if (dispatch && pd && pd->mapping_callbacks)
  681.     XtCallCallbackList((Widget) NULL,
  682.                (XtCallbackList)pd->mapping_callbacks,
  683.                (XtPointer)event );
  684. }
  685.  
  686. void XtAppNextEvent(app, event)
  687.     XtAppContext app;
  688.     XEvent *event;
  689. {
  690.     int i, d;
  691.  
  692.     for (;;) {
  693.     if (app->count == 0)
  694.         DoOtherSources(app);
  695.     else {
  696.         for (i = 1; i <= app->count; i++) {
  697.         d = (i + app->last) % app->count;
  698.         if (d == 0) DoOtherSources(app);
  699.         if (XEventsQueued(app->list[d], QueuedAfterReading))
  700.             goto GotEvent;
  701.         }
  702.         for (i = 1; i <= app->count; i++) {
  703.         d = (i + app->last) % app->count;
  704.         if (XEventsQueued(app->list[d], QueuedAfterFlush))
  705.             goto GotEvent;
  706.         }
  707.     }
  708.  
  709.     /* We're ready to wait...if there is a work proc, call it */
  710.     if (CallWorkProc(app)) continue;
  711.  
  712.     d = _XtwaitForSomething(FALSE, FALSE, FALSE, TRUE,
  713.                 (unsigned long *) NULL, app);
  714.  
  715.     if (d != -1) {
  716.       GotEvent:
  717.         XNextEvent (app->list[d], event);
  718.         app->last = d;
  719.         if (event->xany.type == MappingNotify)
  720.         _XtRefreshMapping(event, False);
  721.         return;
  722.     } 
  723.  
  724.     } /* for */
  725. }
  726.     
  727. void XtProcessEvent(mask)
  728.     XtInputMask mask;
  729. {
  730.     XtAppProcessEvent(_XtDefaultAppContext(), mask);
  731. }
  732.  
  733. void XtAppProcessEvent(app, mask)
  734.     XtAppContext app;
  735.     XtInputMask mask;
  736. {
  737.     int i, d;
  738.     XEvent event;
  739.     struct timeval cur_time;
  740.  
  741.     if (mask == 0) return;
  742.  
  743.     for (;;) {
  744.         if (mask & XtIMTimer && app->timerQueue != NULL) {
  745.         (void) gettimeofday (&cur_time, NULL);
  746.         FIXUP_TIMEVAL(cur_time);
  747.         if (IS_AT_OR_AFTER(app->timerQueue->te_timer_value, cur_time)){
  748.             TimerEventRec *te_ptr = app->timerQueue;
  749.             app->timerQueue = app->timerQueue->te_next;
  750.             te_ptr->te_next = NULL;
  751.                     if (te_ptr->te_proc != NULL)
  752.                 TeCallProc(te_ptr);
  753.             te_ptr->te_next = freeTimerRecs;
  754.             freeTimerRecs = te_ptr;
  755.             return;
  756.         }
  757.         }
  758.     
  759.         if (mask & XtIMAlternateInput) {
  760.         if (app->fds.count > 0 && app->outstandingQueue == NULL) {
  761.             /* Call _XtwaitForSomething to get input queued up */
  762.             (void) _XtwaitForSomething(TRUE, FALSE, TRUE, FALSE,
  763.                 (unsigned long *)NULL, app);
  764.         }
  765.         if (app->outstandingQueue != NULL) {
  766.             InputEvent *ie_ptr = app->outstandingQueue;
  767.             app->outstandingQueue = ie_ptr->ie_oq;
  768.             ie_ptr->ie_oq = NULL;
  769.             IeCallProc(ie_ptr);
  770.             return;
  771.         }
  772.         }
  773.     
  774.         if (mask & XtIMXEvent) {
  775.         for (i = 1; i <= app->count; i++) {
  776.             d = (i + app->last) % app->count;
  777.             if (XEventsQueued(app->list[d], QueuedAfterReading))
  778.             goto GotEvent;
  779.         }
  780.         for (i = 1; i <= app->count; i++) {
  781.             d = (i + app->last) % app->count;
  782.             if (XEventsQueued(app->list[d], QueuedAfterFlush))
  783.             goto GotEvent;
  784.         }
  785.         }
  786.  
  787.         /* Nothing to do...wait for something */
  788.  
  789.         if (CallWorkProc(app)) continue;
  790.  
  791.         d = _XtwaitForSomething(
  792.                     (mask & XtIMTimer ? FALSE : TRUE),
  793.                     (mask & XtIMAlternateInput ? FALSE : TRUE),
  794.                     (mask & XtIMXEvent ? FALSE : TRUE),
  795.                     TRUE,
  796.                     (unsigned long *) NULL, app);
  797.  
  798.         if (mask & XtIMXEvent && d != -1) {
  799.           GotEvent:
  800.         XNextEvent(app->list[d], &event);
  801.         app->last = d;
  802.         if (event.xany.type == MappingNotify) {
  803.             _XtRefreshMapping(&event, False);
  804.         }
  805.         XtDispatchEvent(&event);
  806.         return;
  807.         } 
  808.     
  809.     }    
  810. }
  811.  
  812. XtInputMask XtPending()
  813. {
  814.     return XtAppPending(_XtDefaultAppContext());
  815. }
  816.  
  817. XtInputMask XtAppPending(app)
  818.     XtAppContext app;
  819. {
  820.     struct timeval cur_time;
  821.     int d;
  822.     XtInputMask ret = 0;
  823.  
  824. /*
  825.  * Check for pending X events
  826.  */
  827.     for (d = 0; d < app->count; d++) {
  828.         if (XEventsQueued(app->list[d], QueuedAfterReading)) {
  829.         ret = XtIMXEvent;
  830.         break;
  831.         }
  832.     }
  833.     if (ret == 0) {
  834.         for (d = 0; d < app->count; d++) {
  835.         if (XEventsQueued(app->list[d], QueuedAfterFlush)) {
  836.             ret = XtIMXEvent;
  837.             break;
  838.         }
  839.         }
  840.     }
  841.  
  842. /*
  843.  * Check for pending alternate input
  844.  */
  845.     if (app->timerQueue != NULL) {    /* check timeout queue */ 
  846.         (void) gettimeofday (&cur_time, NULL);
  847.         FIXUP_TIMEVAL(cur_time);
  848.         if ((IS_AT_OR_AFTER(app->timerQueue->te_timer_value, cur_time))  &&
  849.                 (app->timerQueue->te_proc != 0)) {
  850.         ret |= XtIMTimer;
  851.         }
  852.     }
  853.  
  854.     if (app->outstandingQueue != NULL) ret |= XtIMAlternateInput;
  855.     else {
  856.         /* This won't cause a wait, but will enqueue any input */
  857.  
  858.         if(_XtwaitForSomething(TRUE, FALSE, FALSE, FALSE, (unsigned long *) NULL,
  859.             app) != -1) ret |= XtIMXEvent;
  860.         if (app->outstandingQueue != NULL) ret |= XtIMAlternateInput;
  861.     }
  862.     return ret;
  863. }
  864.  
  865. /* Peek at alternate input and timer callbacks if there are any */
  866.  
  867. static Boolean PeekOtherSources(app)
  868.     XtAppContext app;
  869. {
  870.     struct timeval  cur_time;
  871.  
  872.     if (app->outstandingQueue != NULL) return TRUE;
  873.  
  874.     if (app->fds.count > 0) {
  875.         /* Call _XtwaitForSomething to get input queued up */
  876.         (void) _XtwaitForSomething(TRUE, FALSE, TRUE, FALSE,
  877.             (unsigned long *)NULL, app);
  878.         if (app->outstandingQueue != NULL) return TRUE;
  879.     }
  880.  
  881.     if (app->timerQueue != NULL) {    /* check timeout queue */
  882.         (void) gettimeofday (&cur_time, NULL);
  883.         FIXUP_TIMEVAL(cur_time);
  884.         if (IS_AT_OR_AFTER (app->timerQueue->te_timer_value, cur_time))
  885.         return TRUE;
  886.     }
  887.  
  888.     return FALSE;
  889. }
  890.  
  891. Boolean XtPeekEvent(event)
  892.     XEvent *event;
  893. {
  894.     return XtAppPeekEvent(_XtDefaultAppContext(), event);
  895. }
  896.  
  897. Boolean XtAppPeekEvent(app, event)
  898.     XtAppContext app;
  899.     XEvent *event;
  900. {
  901.     int i, d;
  902.     Boolean foundCall = FALSE;
  903.     
  904.     for (i = 1; i <= app->count; i++) {
  905.         d = (i + app->last) % app->count;
  906.         if (d == 0) foundCall = PeekOtherSources(app);
  907.         if (XEventsQueued(app->list[d], QueuedAfterReading))
  908.         goto GotEvent;
  909.     }
  910.     for (i = 1; i <= app->count; i++) {
  911.         d = (i + app->last) % app->count;
  912.         if (XEventsQueued(app->list[d], QueuedAfterFlush))
  913.         goto GotEvent;
  914.     }
  915.     
  916.     if (foundCall) {
  917.         event->xany.type = 0;
  918.         event->xany.display = NULL;
  919.         event->xany.window = 0;
  920.         return FALSE;
  921.     }
  922.     
  923.     d = _XtwaitForSomething(FALSE, FALSE, FALSE, TRUE,
  924.                 (unsigned long *) NULL, app);
  925.     
  926.     if (d != -1) {
  927.       GotEvent:
  928.         XPeekEvent(app->list[d], event);
  929.         app->last = (d == 0 ? app->count : d) - 1;
  930.         return TRUE;
  931.     }
  932.     event->xany.type = 0;    /* Something else must be ready */
  933.     event->xany.display = NULL;
  934.     event->xany.window = 0;
  935.     return FALSE;
  936. }    
  937.