|
|
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/param.h>
1.1.1.2 ! root 35: #include <sys/timeb.h>
! 36: #undef FD_SET
! 37: #undef FD_ISSET
! 38: #undef FD_CLR
1.1 root 39: #include "fd.h"
40: /*
41: * Private definitions
42: */
43:
44: static struct timer_interval {
1.1.1.2 ! root 45: struct timeb ti_interval;
! 46: struct timeb ti_value;
1.1 root 47: };
48:
49:
50:
51: static struct Timer_event {
52: struct timer_interval Te_tim;
53: struct Timer_event *Te_next;
54: Display *Te_dpy;
55: Window Te_wID;
56: caddr_t Te_cookie;
57: };
58:
59: static struct Select_event {
60: Window Se_wID;
61: struct Select_event *Se_next;
62: XClientMessageEvent Se_event;
63: struct Select_event *Se_oq;
64: };
65:
66:
67: /*
68: * Private data
69: */
70:
71: static struct Timer_event *Timer_queue = NULL;
72: static struct Select_event *Select_rqueue[NOFILE], *Select_wqueue[NOFILE],
73: *Select_equeue[NOFILE];
1.1.1.2 ! root 74: static struct timeb Timer_next;
1.1 root 75: static struct Select_event *outstanding_queue = NULL;
76: static struct
77: {
78: Fd_set rmask;
79: Fd_set wmask;
80: Fd_set emask;
81: int nfds;
82: } composite;
83:
84:
85:
86:
87: /*
88: * Private routines
89: */
90:
91: #define TIMEADD(dest, src1, src2) { \
1.1.1.2 ! root 92: if(((dest)->millitm = (src1)->millitm + (src2)->millitm) >= 1000) {\
! 93: (dest)->millitm -= 1000;\
! 94: (dest)->time = (src1)->time + (src2)->time + 1 ; \
! 95: } else { (dest)->time = (src1)->time + (src2)->time ; \
! 96: if(((dest)->time >= 1) && (((dest)->millitm <0))) { \
! 97: (dest)->time --;(dest)->millitm += 1000; } } }
1.1 root 98:
99:
100: #define TIMEDELTA(dest, src1, src2) { \
1.1.1.2 ! root 101: if(((dest)->millitm = (src1)->millitm - (src2)->millitm) < 0) {\
! 102: (dest)->millitm += 1000;\
! 103: (dest)->time = (src1)->time - (src2)->time - 1;\
! 104: } else (dest)->time = (src1)->time - (src2)->time; }
! 105: #define ISAFTER(t1, t2) (((t2)->time > (t1)->time) ||(((t2)->time == (t1)->time)&& ((t2)->millitm > (t1)->millitm)))
1.1 root 106:
107: static void ReQueueTimerEvent(ptr)
108: struct Timer_event *ptr;
109: {
110: register struct Timer_event *tptr, *lptr;
1.1.1.2 ! root 111: struct timeb cur_time, when, *inter;
1.1 root 112:
1.1.1.2 ! root 113: (void) ftime(&cur_time);
1.1 root 114:
115: ptr->Te_tim.ti_value = ptr->Te_tim.ti_interval;
116: inter = &(ptr->Te_tim.ti_value);
117: TIMEADD(&when, &cur_time, inter);
118: ptr->Te_tim.ti_value = when;
119: if(Timer_queue == NULL)
120: {
121: TIMEADD(&Timer_next, inter, &cur_time)
122: Timer_next = when;
123: Timer_queue = ptr;
124: return;
125: }
126: if (ISAFTER(&when, &Timer_next))
127: {
128: /* This goes on the front */
129: ptr -> Te_next = Timer_queue;
130: Timer_next = when;
131: Timer_queue = ptr;
132: return;
133: }
134:
135: for(tptr = Timer_queue ; tptr ; tptr=tptr->Te_next )
136: {
137: if(ISAFTER( &(tptr->Te_tim.ti_value), &when)) {
138: lptr = tptr;
139: } else {
140: ptr->Te_next = tptr;
141: lptr->Te_next = ptr;
142: return;
143: }
144: }
145: lptr->Te_next = ptr;
146: }
147:
148: /*
149: * Public Routines
150: */
151:
152: void XtSetTimeOut(wID, cookie, interval)
153: Window wID;
154: caddr_t cookie;
155: int interval;
156: {
157: struct Timer_event *tptr;
158:
159: tptr = (struct Timer_event *)XtMalloc(sizeof (*tptr));
160: tptr->Te_next = NULL;
1.1.1.2 ! root 161: tptr->Te_tim.ti_interval.time = interval/1000;
! 162: tptr->Te_tim.ti_interval.millitm = (interval%1000);
1.1 root 163: tptr->Te_wID = wID;
164: tptr->Te_cookie = cookie;
165: ReQueueTimerEvent(tptr);
166: }
167:
168: int XtGetTimeOut(wID, cookie)
169: Window wID;
170: caddr_t cookie;
171: {
1.1.1.2 ! root 172: struct timeb sum, cur_time;
1.1 root 173: register struct Timer_event *tptr;
174:
1.1.1.2 ! root 175: (void) ftime(&cur_time);
1.1 root 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);
1.1.1.2 ! root 181: return((sum.time*1000)+(sum.millitm));
1.1 root 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;
1.1.1.2 ! root 355: struct timeb cur_time;
1.1 root 356: Fd_set rmaskfd, wmaskfd, emaskfd;
357: int nfound, i;
1.1.1.2 ! root 358: struct timeb wait_time;
! 359: int milli;
1.1 root 360: int Claims_X_is_pending = 0;
361: XClientMessageEvent *ev = (XClientMessageEvent *)event;
362: extern void perror(), exit();
363: extern int errno;
364:
365: for(;;) {
366: if(XPending(dpy) || Claims_X_is_pending) {
367: XNextEvent(dpy, event);
368: return;
369: }
370: if((se_ptr = outstanding_queue) != NULL) {
371: *event = *((XEvent *)&se_ptr->Se_event);
372: outstanding_queue = se_ptr->Se_oq;
373: return;
374: }
1.1.1.2 ! root 375: (void) ftime(&cur_time);
1.1 root 376: if(Timer_queue) /* check timeout queue */
377: {
378: if (ISAFTER(&Timer_next, &cur_time)){
379: /* timer has expired */
380: ev->type = ClientMessage;
381: ev->display = dpy;
382: ev->window = Timer_queue->Te_wID;
383: ev->message_type = XtTimerExpired;
384: ev->format = 32;
385: ev->data.l[0] = (int)Timer_queue->Te_cookie;
386: te_ptr = Timer_queue;
387: Timer_queue = Timer_queue->Te_next;
388: te_ptr->Te_next = NULL;
389: if(Timer_queue) /* set up next time out time */
390: Timer_next = Timer_queue->Te_tim.ti_value;
391: ReQueueTimerEvent(te_ptr);
392: return;
393: }
394: }/* No timers ready time to wait */
395: /* should be done only once */
396: if(ConnectionNumber(dpy) +1 > composite.nfds)
397: composite.nfds = ConnectionNumber(dpy) + 1;
398: while(1) {
399: FD_SET(ConnectionNumber(dpy),&composite.rmask);
400: if (Timer_queue) {
401: TIMEDELTA(&wait_time, &Timer_next, &cur_time);
1.1.1.2 ! root 402: milli = wait_time.time * 1000 + wait_time.millitm;
1.1 root 403: } else
1.1.1.2 ! root 404: milli = 0x6fffffff;
1.1 root 405: rmaskfd = composite.rmask;
406: wmaskfd = composite.wmask;
407: if((nfound=select(composite.nfds,
408: (int *)&rmaskfd,(int *)&wmaskfd,
1.1.1.2 ! root 409: milli)) == -1) {
1.1 root 410: if(errno == EINTR)
411: continue;
412: }
413: if(nfound == -1) {
414: perror("select:");
415: exit(-1);
416: }
417: break;
418:
419: }
420: if(nfound == 0)
421: continue;
422: for(i = 0; i < composite.nfds && nfound > 0;i++) {
423: if(FD_ISSET(i,&rmaskfd)) {
424: if(i == ConnectionNumber(dpy)){
425: Claims_X_is_pending= 1;
426: nfound--;
427: } else {
428: Select_rqueue[i] -> Se_oq = outstanding_queue;
429: outstanding_queue = Select_rqueue[i];
430: nfound--;
431: }
432: }
433: if(FD_ISSET(i,&wmaskfd)) {
434: Select_rqueue[i] -> Se_oq = outstanding_queue;
435: outstanding_queue = Select_rqueue[i];
436: nfound--;
437: }
438: }
439: }
440: }
441:
442:
443: XtPending(dpy)
444: Display *dpy;
445: {
446: Fd_set rmask, wmask, emask;
1.1.1.2 ! root 447: struct timeb cur_time;
1.1 root 448: int ret;
449: Fd_set *compositeRmask = &composite.rmask;
450:
1.1.1.2 ! root 451: (void) ftime(&cur_time);
1.1 root 452:
453: if(ret = XPending(dpy))
454: return(ret);
455:
456: if(outstanding_queue)
457: return(1);
458:
459: if(ISAFTER(&cur_time, &(Timer_queue->Te_tim.ti_value)))
460: return(1);
461:
462: FD_SET(ConnectionNumber(dpy),compositeRmask); /*should be done only once */
463: if(ConnectionNumber(dpy) +1 > composite.nfds)
464: composite.nfds = ConnectionNumber(dpy) + 1;
465: rmask = composite.rmask;
466: wmask = composite.wmask;
467: emask = composite.emask;
1.1.1.2 ! root 468: if(select(composite.nfds,(int *)&rmask,(int *)&wmask,0) > 0)
1.1 root 469: return(1);
470:
471: return(0);
472: }
473:
474: XtPeekEvent(dpy, event)
475: Display *dpy;
476: XEvent *event;
477: {
478: Fd_set rmask, wmask, emask;
1.1.1.2 ! root 479: int milli;
1.1 root 480: int nfound, i;
1.1.1.2 ! root 481: struct timeb cur_time, wait_time;
1.1 root 482: int Claims_X_is_pending = 0;
483: XClientMessageEvent *ev = (XClientMessageEvent *)event;
484: Fd_set *compositeRmask = &composite.rmask;
485:
486: if(XPending(dpy)){
487: XPeekEvent(dpy, event); /* Xevents */
488: return(1);
489: }
490: if(outstanding_queue){
491: *event = *((XEvent *)&outstanding_queue->Se_event);
492: return(1);
493: }
1.1.1.2 ! root 494: (void) ftime(&cur_time);
1.1 root 495: if(ISAFTER(&cur_time, &(Timer_queue->Te_tim.ti_value))) {
496: ev->type = ClientMessage;
497: ev->display = dpy;
498: ev->window = Timer_queue->Te_wID;
499: ev->format = 32;
500: ev->message_type = XtTimerExpired;
501: ev->format = 32;
502: ev->data.l[0] = (int)Timer_queue->Te_cookie;
503: return(1);
504: }
505:
506: FD_SET(ConnectionNumber(dpy),compositeRmask);/* should be done only once */
507: if(ConnectionNumber(dpy) +1 > composite.nfds)
508: composite.nfds = ConnectionNumber(dpy) + 1;
509: TIMEDELTA(&wait_time, &Timer_next, &cur_time);
1.1.1.2 ! root 510: milli = wait_time.time * 1000 + wait_time.millitm;
1.1 root 511: rmask = composite.rmask;
512: wmask = composite.wmask;
1.1.1.2 ! root 513: nfound=select(composite.nfds,(int *)&rmask,(int *)&wmask,milli);
1.1 root 514:
515: for(i = 0; i < composite.nfds && nfound > 0;i++) {
516: if(FD_ISSET(i,&rmask)) {
517: if(i == ConnectionNumber(dpy)) {
518: Claims_X_is_pending= 1;
519: } else {
520: Select_rqueue[i] -> Se_oq = outstanding_queue;
521: outstanding_queue = Select_rqueue[i];
522: nfound--;
523: }
524: }
525: if(FD_ISSET(i,&wmask)) {
526: Select_rqueue[i] -> Se_oq = outstanding_queue;
527: outstanding_queue = Select_rqueue[i];
528: nfound--;
529: }
530:
531: }
532: if(Claims_X_is_pending && XPending(dpy)) {
533: XPeekEvent(dpy, event);
534: return(1);
535: }
536:
537: if(outstanding_queue){
538: *event = *((XEvent *)&outstanding_queue->Se_event);
539: return(1);
540: }
541: return(0);
542: }
543:
544:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.