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