|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.