Annotation of researchv9/X11/src/X.V11R1/lib/Xtk/NextEvent.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char rcsid[] = "$Header: NextEvent.c,v 1.8 87/09/12 16:12:50 swick Exp $";
                      3: #endif lint
                      4: 
                      5: /*
                      6:  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
                      7:  * 
                      8:  *                         All Rights Reserved
                      9:  * 
                     10:  * Permission to use, copy, modify, and distribute this software and its 
                     11:  * documentation for any purpose and without fee is hereby granted, 
                     12:  * provided that the above copyright notice appear in all copies and that
                     13:  * both that copyright notice and this permission notice appear in 
                     14:  * supporting documentation, and that the name of Digital Equipment
                     15:  * Corporation not be used in advertising or publicity pertaining to
                     16:  * distribution of the software without specific, written prior permission.  
                     17:  * 
                     18:  * 
                     19:  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
                     20:  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
                     21:  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
                     22:  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
                     23:  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
                     24:  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                     25:  * SOFTWARE.
                     26:  */
                     27: #include <stdio.h>
                     28: #include <errno.h>
                     29: #include <X11/Xlib.h>
                     30: #include "Intrinsic.h"
                     31: #include <nlist.h>
                     32: #include <sys/time.h>
                     33: #include <sys/file.h>
                     34: #include <sys/param.h>
                     35: #include "fd.h"
                     36: 
                     37: extern int errno;
                     38: extern void CallCallbacks(); /* gotten from Intrinsic.c, should be in .h ||| */
                     39: extern void RemoveAllCallbacks(); /* from Intrinsic.c, should be in .h ||| */
                     40: 
                     41: /*
                     42:  * Private definitions
                     43:  */
                     44: 
                     45: static struct timer_interval {
                     46:        struct timeval  ti_interval;
                     47:        struct timeval  ti_value;
                     48: };
                     49: 
                     50: 
                     51:        
                     52: static struct Timer_event {
                     53:        struct timer_interval Te_tim;
                     54:        struct Timer_event *Te_next;
                     55:        Display *Te_dpy;
                     56:        Widget   Te_wID;
                     57:        XtIntervalId Te_id;
                     58: };
                     59: 
                     60: static struct Select_event {
                     61:        Widget  Se_wID;
                     62:        struct  Select_event    *Se_next;
                     63:        XClientMessageEvent     Se_event;
                     64:        struct  Select_event    *Se_oq;
                     65: };
                     66: 
                     67: 
                     68: /*
                     69:  * Private data
                     70:  */
                     71: 
                     72: static struct Timer_event *Timer_queue = NULL;
                     73: static struct Select_event *Select_rqueue[NOFILE], *Select_wqueue[NOFILE],
                     74:   *Select_equeue[NOFILE];
                     75: static struct timeval Timer_next = {0};
                     76: static struct  Select_event *outstanding_queue = NULL;
                     77: static struct 
                     78: {
                     79:        Fd_set rmask;
                     80:        Fd_set wmask;
                     81:        Fd_set emask;
                     82:        int     nfds;
                     83: } composite;
                     84: 
                     85: 
                     86:   
                     87: 
                     88: /*
                     89:  * Private routines
                     90:  */
                     91: 
                     92: #define TIMEADD(dest, src1, src2) { \
                     93:        if(((dest)->tv_usec = (src1)->tv_usec + (src2)->tv_usec) >= 1000000) {\
                     94:              (dest)->tv_usec -= 1000000;\
                     95:              (dest)->tv_sec = (src1)->tv_sec + (src2)->tv_sec + 1 ; \
                     96:        } else { (dest)->tv_sec = (src1)->tv_sec + (src2)->tv_sec ; \
                     97:           if(((dest)->tv_sec >= 1) && (((dest)->tv_usec <0))) { \
                     98:            (dest)->tv_sec --;(dest)->tv_usec += 1000000; } } }
                     99: 
                    100: 
                    101: #define TIMEDELTA(dest, src1, src2) { \
                    102:        if(((dest)->tv_usec = (src1)->tv_usec - (src2)->tv_usec) < 0) {\
                    103:              (dest)->tv_usec += 1000000;\
                    104:              (dest)->tv_sec = (src1)->tv_sec - (src2)->tv_sec - 1;\
                    105:        } else  (dest)->tv_sec = (src1)->tv_sec - (src2)->tv_sec;  }
                    106: #define ISAFTER(t1, t2) (((t2)->tv_sec > (t1)->tv_sec) ||(((t2)->tv_sec == (t1)->tv_sec)&& ((t2)->tv_usec > (t1)->tv_usec)))
                    107: 
                    108: static void ReQueueTimerEvent(ptr)
                    109: struct Timer_event *ptr;
                    110: {
                    111:        register struct Timer_event *tptr, *lptr;
                    112:        struct timeval cur_time, when, *inter;
                    113:        struct timezone curzone;
                    114:        
                    115:        (void) gettimeofday(&cur_time, &curzone);
                    116: 
                    117:        ptr->Te_tim.ti_value = ptr->Te_tim.ti_interval;
                    118:        inter = &(ptr->Te_tim.ti_value);
                    119:        TIMEADD(&when, &cur_time, inter);
                    120:        ptr->Te_tim.ti_value = when;
                    121:        if(Timer_queue == NULL)
                    122:          {
                    123:                  TIMEADD(&Timer_next, inter, &cur_time)
                    124:                  Timer_next = when;
                    125:                  Timer_queue = ptr;
                    126:                  return;
                    127:          }
                    128:        if (ISAFTER(&when, &Timer_next)) 
                    129:          {
                    130:                /* This goes on the front */
                    131:                  ptr -> Te_next = Timer_queue;
                    132:                  Timer_next = when;
                    133:                  Timer_queue = ptr;
                    134:                  return;
                    135:          }
                    136:        
                    137:        for(tptr = Timer_queue ; tptr ; tptr=tptr->Te_next )
                    138:          {
                    139:                  if(ISAFTER( &(tptr->Te_tim.ti_value), &when)) {
                    140:                          lptr = tptr;
                    141:                  } else {
                    142:                          ptr->Te_next = tptr;
                    143:                          lptr->Te_next = ptr;
                    144:                          return;
                    145:                  }
                    146:          }
                    147:        lptr->Te_next = ptr;
                    148: }     
                    149: 
                    150: /*
                    151:  * Public Routines
                    152:  */
                    153: 
                    154: XtIntervalId
                    155: XtAddTimeOut(wID, interval)
                    156: Widget wID;
                    157: int interval;
                    158: {
                    159:        struct Timer_event *tptr;
                    160:        
                    161:        tptr = (struct Timer_event *)XtMalloc(sizeof (*tptr));
                    162:        tptr->Te_next = NULL;
                    163:        tptr->Te_tim.ti_interval.tv_sec = interval/1000;
                    164:        tptr->Te_tim.ti_interval.tv_usec = (interval%1000)*1000;
                    165:        tptr->Te_wID = wID;
                    166:        tptr->Te_id = (XtIntervalId) tptr;
                    167: 
                    168:        ReQueueTimerEvent(tptr);
                    169:        return(tptr->Te_id);
                    170: }
                    171: 
                    172: /* this is obsolete */
                    173: 
                    174: unsigned long 
                    175: XtGetTimeOut(timer)
                    176: XtIntervalId timer;
                    177: {
                    178:        struct timeval sum, cur_time;
                    179:        struct timezone curzone;
                    180:        register struct Timer_event *tptr = (struct Timer_event *) timer;
                    181: 
                    182:        (void) gettimeofday(&cur_time, &curzone);
                    183:        
                    184:        if(tptr != (struct Timer_event *) tptr->Te_id) {
                    185:                XtError("Internal event timer botch.");
                    186:        }
                    187:        TIMEDELTA(&sum, &(tptr->Te_tim.ti_value), &cur_time);
                    188:        return((sum.tv_sec*1000)+(sum.tv_usec/1000));
                    189: }
                    190: 
                    191: void
                    192: XtRemoveTimeOut(iD)
                    193: XtIntervalId iD;
                    194: {
                    195:        register struct Timer_event *tptr,*lptr;
                    196:        lptr = NULL;
                    197:        
                    198:        for(tptr = Timer_queue ;tptr != NULL;tptr = tptr->Te_next) 
                    199:          {     
                    200:                  if((struct Timer_event *) iD != tptr)
                    201:                    {
                    202:                            lptr = tptr;
                    203:                            continue;
                    204:                    }
                    205:                  else{
                    206:                    if(lptr)
                    207:                      lptr->Te_next = tptr->Te_next;
                    208: 
                    209:                    else 
                    210:                      Timer_queue = tptr->Te_next;
                    211: 
                    212:                    XtFree((char *) tptr);
                    213:                  }
                    214:          }
                    215: }
                    216: 
                    217: void 
                    218: XtAddInput(widget,source,condition)
                    219: Widget widget;
                    220: int source;
                    221: int condition;
                    222: {
                    223:        struct Select_event *sptr;
                    224:        
                    225:        if(((int)condition &(XtInputReadMask|XtInputWriteMask|XtInputExceptMask))==0) {
                    226:          return; /* error */ /* XXX */
                    227:        }
                    228:        if(condition&XtInputReadMask){
                    229:            sptr = (struct Select_event *)XtMalloc(sizeof (*sptr));
                    230:            sptr->Se_wID = widget;
                    231:            sptr->Se_next = Select_rqueue[source];
                    232:            Select_rqueue[source] = sptr;
                    233:            FD_SET(source, &composite.rmask);
                    234:            sptr->Se_event.type = ClientMessage;
                    235:            sptr->Se_event.display = XtDisplay(widget);
                    236:            sptr->Se_event.window = widget->core.window;
                    237:            sptr->Se_event.message_type = XtHasInput;
                    238:            sptr->Se_event.format = 32;
                    239:            sptr->Se_event.data.l[0] = (int)source;
                    240:            sptr->Se_event.data.l[1] = XtInputReadMask;
                    241:        }
                    242:        
                    243:        if(condition&XtInputWriteMask) {
                    244:            sptr = (struct Select_event *) XtMalloc(sizeof (*sptr));
                    245:            sptr->Se_wID = widget;
                    246:            sptr->Se_next = Select_wqueue[source];
                    247:            Select_wqueue[source] = sptr;
                    248:            FD_SET(source, &composite.wmask);
                    249:            sptr->Se_event.type = ClientMessage;
                    250:            sptr->Se_event.display = XtDisplay(widget);
                    251:            sptr->Se_event.window = widget->core.window;
                    252:            sptr->Se_event.message_type = XtHasInput;
                    253:            sptr->Se_event.format = 32;
                    254:            sptr->Se_event.data.l[0] = (int)source;
                    255:            sptr->Se_event.data.l[1] = XtInputWriteMask;
                    256:        }
                    257:        
                    258:        if(condition&XtInputExceptMask) {
                    259:            sptr = (struct Select_event *) XtMalloc(sizeof (*sptr));
                    260:            sptr->Se_wID = widget;
                    261:            sptr->Se_next = Select_equeue[source];
                    262:            Select_equeue[source] = sptr;
                    263:            FD_SET(source, &composite.emask);
                    264:            sptr->Se_event.type = ClientMessage;
                    265:            sptr->Se_event.display = XtDisplay(widget);
                    266:            sptr->Se_event.window = widget->core.window;
                    267:            sptr->Se_event.message_type = XtHasInput;
                    268:            sptr->Se_event.format = 32;
                    269:            sptr->Se_event.data.l[0] = (int)source;
                    270:            sptr->Se_event.data.l[1] = XtInputExceptMask;
                    271:        }
                    272:        if (composite.nfds < (source+1))
                    273:            composite.nfds = source+1;
                    274: }
                    275: 
                    276: void XtRemoveInput(wID, source, condition)
                    277: Widget wID;
                    278: int source;
                    279: int condition;
                    280: {
                    281:        register struct Select_event *sptr, *lptr;
                    282: 
                    283:        if(((int)condition &(XtInputReadMask|XtInputWriteMask|XtInputExceptMask))==0) {
                    284:            return; /* error */ /* XXX */
                    285:        }
                    286:        if(condition&XtInputReadMask){
                    287:            if((sptr = Select_rqueue[source]) == NULL)
                    288:              return; /* error */ /* XXX */
                    289:            for(lptr = NULL;sptr; sptr = sptr->Se_next){
                    290:                if(sptr->Se_wID == wID) {
                    291:                    if(lptr == NULL) {
                    292:                        Select_rqueue[source] = sptr->Se_next;
                    293:                        FD_CLR(source, &composite.rmask);
                    294:                    } else {
                    295:                        lptr->Se_next = sptr->Se_next;
                    296:                    }
                    297:                    XtFree((char *) sptr);
                    298:                    return;
                    299:                }
                    300:                lptr = sptr;          
                    301:            }
                    302:        }
                    303:        if(condition&XtInputWriteMask){
                    304:            if((sptr = Select_wqueue[source]) == NULL)
                    305:              return; /* error */ /* XXX */
                    306:            for(lptr = NULL;sptr; sptr = sptr->Se_next){
                    307:                if(sptr->Se_wID == wID) {
                    308:                    if(lptr == NULL){
                    309:                        Select_wqueue[source] = sptr->Se_next;
                    310:                        FD_CLR(source, &composite.wmask);
                    311:                    }else {
                    312:                        lptr->Se_next = sptr->Se_next;
                    313:                    }
                    314:                    XtFree((char *) sptr);
                    315:                    return;
                    316:                }
                    317:                lptr = sptr;
                    318:            }
                    319:            
                    320:        }
                    321:        if(condition&XtInputExceptMask){
                    322:            if((sptr = Select_equeue[source]) == NULL)
                    323:              return; /* error */ /* XXX */
                    324:            for(lptr = NULL;sptr; sptr = sptr->Se_next){
                    325:                if(sptr->Se_wID == wID) {
                    326:                    if(lptr == NULL){
                    327:                        Select_equeue[source] = sptr->Se_next;
                    328:                        FD_CLR(source, &composite.emask);
                    329:                    }else {
                    330:                        lptr->Se_next = sptr->Se_next;
                    331:                    }
                    332:                    XtFree((char *) sptr);
                    333:                    return;
                    334:                }
                    335:                lptr = sptr;
                    336:            }
                    337:            
                    338:        }
                    339:        return;
                    340:         /* error */
                    341: }
                    342: 
                    343: 
                    344:      
                    345: /*
                    346:  * XtNextEvent()
                    347:  * return next event;
                    348:  */
                    349: 
                    350: void XtNextEvent(event)
                    351: XEvent *event;
                    352: {
                    353:        struct Select_event *se_ptr;
                    354:        struct Timer_event *te_ptr;
                    355:        struct timeval cur_time;
                    356:        struct timezone cur_timezone;
                    357:        Fd_set rmaskfd, wmaskfd, emaskfd;
                    358:        int  nfound, i;
                    359:        struct timeval wait_time;
                    360:        struct timeval *wait_time_ptr;
                    361:        int Claims_X_is_pending = 0;
                    362:        XClientMessageEvent *ev = (XClientMessageEvent *)event;
                    363:        extern void perror(), exit();
                    364:        
                    365:     if (DestroyList != NULL) {
                    366:         CallCallbacks(&DestroyList, (Opaque)NULL);
                    367:         RemoveAllCallbacks(&DestroyList);
                    368:     }
                    369: 
                    370:     for(;;) {
                    371:         if(XPending(toplevelDisplay) || Claims_X_is_pending) {
                    372:            XNextEvent(toplevelDisplay, event);
                    373:            return;
                    374:        }
                    375:        if((se_ptr = outstanding_queue) != NULL) {
                    376:            *event = *((XEvent *)&se_ptr->Se_event);
                    377:            outstanding_queue = se_ptr->Se_oq;
                    378:            return;
                    379:        }
                    380:        (void) gettimeofday(&cur_time, &cur_timezone);
                    381:        if(Timer_queue)  /* check timeout queue */
                    382:          {
                    383:              if (ISAFTER(&Timer_next, &cur_time)){
                    384:                  /* timer has expired */
                    385:                  ev->type = ClientMessage;
                    386:                  ev->display = toplevelDisplay;
                    387:                  ev->window =  Timer_queue->Te_wID->core.window;
                    388:                  ev->message_type = XtTimerExpired;
                    389:                  ev->format = 32;
                    390:                  ev->data.l[0] = (int)Timer_queue->Te_id;
                    391:                  te_ptr = Timer_queue;
                    392:                  Timer_queue = Timer_queue->Te_next;
                    393:                  te_ptr->Te_next = NULL;
                    394:                  if(Timer_queue) /* set up next time out time */
                    395:                    Timer_next = Timer_queue->Te_tim.ti_value;
                    396:                  ReQueueTimerEvent(te_ptr);
                    397:                  return;
                    398:              }
                    399:       }/* No timers ready time to wait */
                    400:                /* should be done only once */
                    401:        if(ConnectionNumber(toplevelDisplay) +1 > composite.nfds) 
                    402:          composite.nfds = ConnectionNumber(toplevelDisplay) + 1;
                    403:        while(1) {
                    404:                FD_SET(ConnectionNumber(toplevelDisplay),&composite.rmask);
                    405:                if (Timer_queue) {
                    406:                        TIMEDELTA(&wait_time, &Timer_next, &cur_time);
                    407:                        wait_time_ptr = &wait_time;
                    408:                } else 
                    409:                  wait_time_ptr = (struct timeval *)0;
                    410:                rmaskfd = composite.rmask;
                    411:                wmaskfd = composite.wmask;
                    412:                emaskfd = composite.emask;
                    413:                if((nfound=select(composite.nfds,
                    414:                                  (int *)&rmaskfd,(int *)&wmaskfd,
                    415:                                  (int *)&emaskfd,wait_time_ptr)) == -1) {
                    416:                        if(errno == EINTR)
                    417:                          continue;
                    418:                }
                    419:                if(nfound == -1) {
                    420:                        perror("select:");
                    421:                        exit(-1);
                    422:                }
                    423:                break;
                    424: 
                    425:        }
                    426:        if(nfound == 0)
                    427:          continue;
                    428:        for(i = 0; i < composite.nfds && nfound > 0;i++) {
                    429:            if(FD_ISSET(i,&rmaskfd)) {
                    430:              if(i == ConnectionNumber(toplevelDisplay)){
                    431:                Claims_X_is_pending= 1;
                    432:                nfound--;
                    433:              } else {
                    434:                Select_rqueue[i] -> Se_oq = outstanding_queue;
                    435:                outstanding_queue = Select_rqueue[i];
                    436:                nfound--;
                    437:              }
                    438:            }
                    439:            if(FD_ISSET(i,&wmaskfd)) {
                    440:              Select_rqueue[i] -> Se_oq = outstanding_queue;
                    441:              outstanding_queue = Select_rqueue[i];
                    442:              nfound--;
                    443:            }
                    444:            if(FD_ISSET(i,&emaskfd)) {
                    445:              Select_rqueue[i] -> Se_oq = outstanding_queue;
                    446:              outstanding_queue = Select_rqueue[i];
                    447:              nfound--;
                    448:            }
                    449:         }
                    450:     }
                    451: }
                    452: 
                    453: 
                    454: Boolean XtPending()
                    455: {
                    456:     Fd_set rmask, wmask, emask;
                    457:     struct timeval cur_time, wait_time;
                    458:     struct timezone curzone;
                    459:     Boolean ret;
                    460: 
                    461:     (void) gettimeofday(&cur_time, &curzone);
                    462:     
                    463:     if(ret = (Boolean) XPending(toplevelDisplay))
                    464:       return(ret);
                    465: 
                    466:     if(outstanding_queue)
                    467:       return TRUE;
                    468:     
                    469:     if(ISAFTER(&cur_time, &(Timer_queue->Te_tim.ti_value)))
                    470:        return TRUE;
                    471: 
                    472:     FD_SET(ConnectionNumber(toplevelDisplay),&composite.rmask); /*should be done only once */
                    473:     if(ConnectionNumber(toplevelDisplay) +1 > composite.nfds) 
                    474:       composite.nfds = ConnectionNumber(toplevelDisplay) + 1;
                    475:     wait_time.tv_sec = 0;
                    476:     wait_time.tv_usec = 0;
                    477:     rmask = composite.rmask;
                    478:     wmask = composite.wmask;
                    479:     emask = composite.emask;
                    480:     if(select(composite.nfds,(int *)&rmask,(int *)&wmask,(int*)&emask,&wait_time) > 0)
                    481:        return TRUE;
                    482:       
                    483:     return FALSE;  
                    484: }      
                    485: 
                    486: XtPeekEvent(event)
                    487: XEvent *event;
                    488: {
                    489:     Fd_set rmask, wmask, emask;
                    490:     int nfound, i;
                    491:     struct timeval cur_time, wait_time;
                    492:     struct timezone curzone;
                    493:     int Claims_X_is_pending = 0;
                    494:     XClientMessageEvent *ev = (XClientMessageEvent *)event;
                    495: 
                    496:     if(XPending(toplevelDisplay)){
                    497:        XPeekEvent(toplevelDisplay, event); /* Xevents */
                    498:        return(1);
                    499:     }
                    500:     if(outstanding_queue){
                    501:        *event = *((XEvent *)&outstanding_queue->Se_event);
                    502:        return(1);
                    503:     }
                    504:     (void) gettimeofday(&cur_time, &curzone);
                    505:     if(ISAFTER(&cur_time, &(Timer_queue->Te_tim.ti_value))) {
                    506:        ev->type = ClientMessage;
                    507:        ev->display = toplevelDisplay;
                    508:        ev->window =  Timer_queue->Te_wID->core.window;
                    509:                  ev->format = 32;
                    510:        ev->message_type = XtTimerExpired;
                    511:        ev->format = 32;
                    512:        ev->data.l[0] = (int)Timer_queue->Te_id;
                    513:        return(1);
                    514:     }
                    515:     
                    516:     FD_SET(ConnectionNumber(toplevelDisplay),&composite.rmask);/* should be done only once */
                    517:     if(ConnectionNumber(toplevelDisplay) +1 > composite.nfds) 
                    518:       composite.nfds = ConnectionNumber(toplevelDisplay) + 1;
                    519:     TIMEDELTA(&wait_time, &Timer_next, &cur_time);
                    520:     rmask = composite.rmask;
                    521:     wmask = composite.wmask;
                    522:     emask = composite.emask;
                    523:     nfound=select(composite.nfds,(int *)&rmask,(int *)&wmask,(int *)&emask,&wait_time);
                    524:     
                    525:     for(i = 0; i < composite.nfds && nfound > 0;i++) {
                    526:        if(FD_ISSET(i,&rmask)) {
                    527:            if(i == ConnectionNumber(toplevelDisplay)) {
                    528:                Claims_X_is_pending= 1;
                    529:              } else {
                    530:                Select_rqueue[i] -> Se_oq = outstanding_queue;
                    531:                outstanding_queue = Select_rqueue[i];
                    532:                nfound--;
                    533:              }
                    534:        }
                    535:        if(FD_ISSET(i,&wmask)) {
                    536:            Select_rqueue[i] -> Se_oq = outstanding_queue;
                    537:            outstanding_queue = Select_rqueue[i];
                    538:            nfound--;
                    539:        }
                    540:        if(FD_ISSET(i,&emask)) {
                    541:            Select_rqueue[i] -> Se_oq = outstanding_queue;
                    542:            outstanding_queue = Select_rqueue[i];
                    543:            nfound--;
                    544:        }
                    545: 
                    546:       }
                    547:     if(Claims_X_is_pending && XPending(toplevelDisplay)) {
                    548:       XPeekEvent(toplevelDisplay, event);
                    549:       return(1);
                    550:     }
                    551: 
                    552:     if(outstanding_queue){
                    553:        *event = *((XEvent *)&outstanding_queue->Se_event);
                    554:        return(1);
                    555:     }
                    556:     return(0);
                    557: }      
                    558:          
                    559:        

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.