comparison lib/dispatch.c @ 0:92745d501b9a

initial import from kinput2-v3.1
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 08 Mar 2010 04:44:30 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:92745d501b9a
1 #ifndef lint
2 static char *rcsid = "$Id: dispatch.c,v 1.14 1994/05/31 07:48:42 ishisone Rel $";
3 #endif
4
5 /*
6 * a very simple event dispatch library for non-widget windows
7 *
8 * 'non-widget window' means windows that have no associated widget,
9 * e.g. windows created by Xlib directly.
10 */
11
12 /*
13 * Copyright (c) 1990 Software Research Associates, Inc.
14 *
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted, provided
17 * that the above copyright notice appear in all copies and that both that
18 * copyright notice and this permission notice appear in supporting
19 * documentation, and that the name of Software Research Associates not be
20 * used in advertising or publicity pertaining to distribution of the
21 * software without specific, written prior permission. Software Research
22 * Associates makes no representations about the suitability of this software
23 * for any purpose. It is provided "as is" without express or implied
24 * warranty.
25 *
26 * Author: Makoto Ishisone, Software Research Associates, Inc., Japan
27 */
28
29 #include <X11/Intrinsic.h>
30 #include "MyDispatch.h"
31 #include "AsyncErr.h"
32
33 #define DEBUG_VAR debug_dispatch
34 #include "DebugPrint.h"
35
36 typedef struct _handler_ {
37 int type; /* event type */
38 unsigned long mask; /* event mask */
39 void (*handler)();
40 XtPointer data;
41 struct _handler_ *next;
42 } HandlerRec;
43
44 typedef struct {
45 Boolean dispatching; /* now dispatching */
46 Boolean toberemoved; /* this list is to be removed later */
47 unsigned long mask; /* event mask */
48 HandlerRec *handlers;
49 } WindowRec;
50
51 static int Initialized = 0;
52 static XContext Context;
53
54 static void
55 initialize()
56 {
57 Context = XUniqueContext();
58 Initialized = 1;
59 }
60
61 static void
62 resetEventMask(dpy, window, wp)
63 Display *dpy;
64 Window window;
65 WindowRec *wp;
66 {
67 register HandlerRec *hp = wp->handlers;
68 register unsigned long mask = 0L;
69
70 while (hp != NULL) {
71 mask |= hp->mask;
72 hp = hp->next;
73 }
74
75 if (mask != wp->mask) {
76 XAEHandle h = XAESetIgnoreErrors(dpy); /* keep the operation safe */
77 XSelectInput(dpy, window, mask);
78 XAEUnset(h);
79 wp->mask = mask;
80 }
81 }
82
83 static void
84 removeAll(dpy, window, wp)
85 Display *dpy;
86 Window window;
87 WindowRec *wp;
88 {
89 register HandlerRec *hp = wp->handlers;
90
91 while (hp != NULL) {
92 register HandlerRec *hp0 = hp;
93 hp = hp->next;
94 XtFree((char *)hp0);
95 }
96
97 if (wp->mask != 0L) {
98 XAEHandle h = XAESetIgnoreErrors(dpy);
99
100 /* keep it safe (because the window might not exist any more) */
101 XSelectInput(dpy, window, 0L);
102 XAEUnset(h);
103 }
104
105 XtFree((char *)wp);
106 (void)XDeleteContext(dpy, window, Context);
107 }
108
109 static void
110 doDispatch(event, list)
111 XEvent *event;
112 register HandlerRec *list;
113 {
114 void (*handler)();
115 XtPointer data;
116 register int type = event->type;
117
118 /*
119 * we must be careful here. the invoked handler might remove
120 * itself, or remove other handler to be invoked next.
121 * so we use this somewhat strange recursive call.
122 */
123 while (list != NULL) {
124 if (list->type == type) {
125 handler = list->handler;
126 data = list->data;
127 doDispatch(event, list->next);
128 (*handler)(event, data);
129 return;
130 }
131 list = list->next;
132 }
133 }
134
135 void
136 MyDispatchEvent(event)
137 XEvent *event;
138 {
139 caddr_t data;
140
141 if (!Initialized) initialize();
142
143 if (!XFindContext(event->xany.display, event->xany.window,
144 Context, &data)) {
145 WindowRec *wrec = (WindowRec *)data;
146
147 wrec->dispatching = True;
148 wrec->toberemoved = False;
149
150 doDispatch(event, wrec->handlers);
151
152 wrec->dispatching = False;
153 if (wrec->toberemoved) {
154 removeAll(event->xany.display, event->xany.window, wrec);
155 }
156 }
157 }
158
159 void
160 MyAddEventHandler(dpy, window, type, mask, func, data)
161 Display *dpy;
162 Window window;
163 int type;
164 unsigned long mask;
165 void (*func)();
166 XtPointer data;
167 {
168 WindowRec *wp;
169 HandlerRec *hp;
170 caddr_t cdata;
171
172 TRACE(("MyAddEventHandler(window=%08lx,type=%d)\n", window, type));
173 if (!Initialized) initialize();
174
175 hp = XtNew(HandlerRec);
176 hp->type = type;
177 hp->mask = mask;
178 hp->handler = func;
179 hp->data = data;
180 hp->next = NULL;
181
182 if (!XFindContext(dpy, window, Context, &cdata)) {
183 wp = (WindowRec *)cdata;
184 hp->next = wp->handlers;
185 wp->handlers = hp;
186 } else {
187 wp = XtNew(WindowRec);
188 wp->mask = 0L;
189 wp->dispatching = False;
190 wp->handlers = hp;
191 (void)XSaveContext(dpy, window, Context, (caddr_t)wp);
192 }
193 resetEventMask(dpy, window, wp);
194 }
195
196 void
197 MyRemoveEventHandler(dpy, window, type, func, data)
198 Display *dpy;
199 Window window;
200 int type;
201 void (*func)();
202 XtPointer data;
203 {
204 caddr_t cdata;
205 WindowRec *wp;
206 HandlerRec *hp, *hp0;
207
208 TRACE(("MyRemoveEventHandler(window=%08lx,type=%d)\n", window, type));
209 if (!Initialized) initialize();
210 if (XFindContext(dpy, window, Context, &cdata) || cdata == NULL) return;
211
212 wp = (WindowRec *)cdata;
213 hp0 = NULL;
214 hp = wp->handlers;
215
216 while (hp != NULL) {
217 if (hp->type == type && hp->handler == func && hp->data == data) {
218 HandlerRec *tmp = hp;
219
220 hp = hp->next;
221 if (hp0 == NULL) {
222 wp->handlers = hp;
223 } else {
224 hp0->next = hp;
225 }
226 XtFree((char *)tmp);
227 } else {
228 hp0 = hp;
229 hp = hp->next;
230 }
231 }
232
233 resetEventMask(dpy, window, wp);
234
235 if (wp->handlers == NULL) {
236 if (wp->dispatching) {
237 /* now dispatching. we just mark it to be removed later. */
238 wp->toberemoved = True;
239 } else {
240 XtFree((char *)wp);
241 (void)XDeleteContext(dpy, window, Context);
242 }
243 }
244 }
245
246 void
247 MyRemoveAllEventHandler(dpy, window)
248 Display *dpy;
249 Window window;
250 {
251 caddr_t cdata;
252 WindowRec *wp;
253
254 TRACE(("MyRemoveAllEventHandler(window=%08lx)\n", window));
255 if (!Initialized) initialize();
256
257 if (XFindContext(dpy, window, Context, &cdata) || cdata == NULL) return;
258
259 wp = (WindowRec *)cdata;
260
261 if (wp->dispatching) {
262 /* now dispatching. we just mark it to be removed later. */
263 wp->toberemoved = True;
264 return;
265 } else {
266 removeAll(dpy, window, wp);
267 }
268 }