|
|
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.