comparison lib/asyncerr.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: asyncerr.c,v 1.6 1994/08/08 01:20:52 ishisone Exp $";
3 #endif
4 /*
5 * Copyright (C) 1992, 1994 Software Research Associates, Inc.
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation for any purpose and without fee is hereby granted, provided
9 * that the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Software Research Associates not be
12 * used in advertising or publicity pertaining to distribution of the
13 * software without specific, written prior permission. Software Research
14 * Associates makes no representations about the suitability of this software
15 * for any purpose. It is provided "as is" without express or implied
16 * warranty.
17 *
18 * Author: Makoto Ishisone, Software Research Associates, Inc., Japan
19 */
20
21 /*
22 * X asyncronous error handler
23 */
24
25 #include <X11/Xlib.h>
26 #include <X11/Xfuncproto.h>
27 #include "AsyncErr.h"
28
29 #ifdef __STDC__
30 #include <stdlib.h>
31 #else
32 extern char *malloc();
33 #endif
34
35 #ifndef NULL
36 #define NULL 0
37 #endif
38
39 #undef XSetErrorHandler
40
41 typedef struct fe_errdesc_ {
42 struct fe_errdesc_ *prev;
43 struct fe_errdesc_ *next;
44 Display *dpy;
45 unsigned long from; /* range of the sequence numbers */
46 unsigned long to; /* which this handler covers */
47 int (*handler)(); /* async handler */
48 void (*destroy)();
49 XPointer client_data;
50 } ErrDesc;
51
52 static ErrDesc esentinel = {
53 &esentinel,
54 &esentinel,
55 };
56
57 #define EHEAD (esentinel.next)
58 #define ETAIL (esentinel.prev)
59 #define EEND(p) ((p) == &esentinel)
60
61 static int (*original_handler)();
62
63 /*
64 * Some useful handlers
65 */
66
67 /* ARGSUSED */
68 static int
69 ignoreErrors(dpy, eev, cldata)
70 Display *dpy;
71 XErrorEvent *eev;
72 XPointer cldata;
73 {
74 /*
75 * Just ignore any errors.
76 */
77 return 0;
78 }
79
80 /* ARGSUSED */
81 static int
82 recordErrors(dpy, eev, cldata)
83 Display *dpy;
84 XErrorEvent *eev;
85 XPointer cldata;
86 {
87 /*
88 * Record the type of the error.
89 * It assumes that the client data is a pointer to
90 * an unsigned long int. If error occurs, it does:
91 * + if the error code is less than 32, set the 'error code'th bit.
92 * + otherwise (i.e. extension defined error) set the bit 0.
93 */
94 unsigned long *errorbitsp = (unsigned long *)cldata;
95
96 if (eev->error_code < 32) {
97 *errorbitsp |= (1 << eev->error_code);
98 } else {
99 /* other errors */
100 *errorbitsp |= 1;
101 }
102
103 /* don't invoke global handler */
104 return 0;
105 }
106
107 static ErrDesc *
108 newErrDesc()
109 {
110 return (ErrDesc *)malloc(sizeof(ErrDesc));
111 }
112
113 static void
114 eremove(edp)
115 ErrDesc *edp;
116 {
117 edp->prev->next = edp->next;
118 edp->next->prev = edp->prev;
119 }
120
121 static void
122 eappend(edp)
123 ErrDesc *edp;
124 {
125 edp->prev = esentinel.prev;
126 edp->next = &esentinel;
127 (esentinel.prev)->next = edp;
128 esentinel.prev = edp;
129 }
130
131 static void
132 removeHandler(edp)
133 ErrDesc *edp;
134 {
135 if (edp->destroy != NULL) (*edp->destroy)(edp->dpy, edp->client_data);
136 eremove(edp);
137 (void)free((char *)edp);
138 }
139
140 static int
141 callHandlers(dpy, eev)
142 Display *dpy;
143 XErrorEvent *eev;
144 {
145 ErrDesc *edp = EHEAD;
146 int found = 0;
147 int call_original = 0;
148
149 while (!EEND(edp)) {
150 if (edp->dpy == dpy && edp->from <= eev->serial &&
151 (eev->serial < edp->to || edp->from == edp->to)) {
152 found = 1;
153 if ((*edp->handler)(dpy, eev, edp->client_data)) call_original = 1;
154 }
155 edp = edp->next;
156 }
157 return !found || call_original;
158 }
159
160 static void
161 removeHandlers(dpy)
162 Display *dpy;
163 {
164 /*
165 * Remove obsolete (out of date) handlers.
166 */
167 ErrDesc *edp = EHEAD;
168 unsigned long last = LastKnownRequestProcessed(dpy);
169
170 while (!EEND(edp)) {
171 ErrDesc *next = edp->next;
172
173 if (edp->dpy == dpy && edp->to <= last && edp->from != edp->to) {
174 removeHandler(edp);
175 }
176 edp = next;
177 }
178 }
179
180 /*
181 * public functions
182 */
183
184 int
185 XAEHandler(dpy, eev)
186 Display *dpy;
187 XErrorEvent *eev;
188 {
189 if (callHandlers(dpy, eev) && original_handler != NULL) {
190 (void)original_handler(dpy, eev);
191 }
192 removeHandlers(dpy);
193 return 0; /* for lint */
194 }
195
196 void
197 XAEInit()
198 {
199 int (*oldhandler)() = XSetErrorHandler(XAEHandler);
200
201 if (oldhandler != XAEHandler) original_handler = oldhandler;
202 }
203
204 XErrorHandler
205 XAESetErrorHandler(handler)
206 XErrorHandler handler;
207 {
208 int (*oldhandler)();
209
210 oldhandler = original_handler;
211 original_handler = handler;
212 return oldhandler;
213 }
214
215 XAEHandle
216 XAESet(dpy, handler, destroy, client_data)
217 Display *dpy;
218 int (*handler)();
219 void (*destroy)();
220 XPointer client_data;
221 {
222 ErrDesc *e;
223
224 /*
225 * First, remove out-of-date handlers.
226 */
227 removeHandlers(dpy);
228
229 /*
230 * Allocate new ErrDesc structure.
231 */
232 e = newErrDesc();
233 if (e == NULL) return NULL;
234
235 e->dpy = dpy;
236 e->from = NextRequest(dpy);
237 e->to = e->from;
238 e->handler = handler;
239 e->destroy = destroy;
240 e->client_data = client_data;
241
242 eappend(e);
243
244 return e;
245 }
246
247 void
248 XAEUnset(handle)
249 XAEHandle handle;
250 {
251 Display *dpy = handle->dpy;
252
253 if (handle != NULL && handle->from == handle->to) {
254 handle->to = NextRequest(dpy);
255 if (handle->to <= handle->from) removeHandler(handle);
256 }
257 removeHandlers(dpy);
258 }
259
260 XAEHandle
261 XAESetIgnoreErrors(dpy)
262 Display *dpy;
263 {
264 return XAESet(dpy, ignoreErrors, (void (*)())NULL, (XPointer)NULL);
265 }
266
267 XAEHandle
268 XAESetRecordErrors(dpy, errorbitsp)
269 Display *dpy;
270 unsigned long *errorbitsp;
271 {
272 *errorbitsp = 0L; /* clear all bits */
273 return XAESet(dpy, recordErrors,
274 (void (*)())NULL, (XPointer)errorbitsp);
275 }