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