/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkerror.c
ViewVC logotype

Contents of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkerror.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 71 - (show annotations) (download)
Sat Nov 5 11:07:06 2016 UTC (7 years, 4 months ago) by dashley
File MIME type: text/plain
File size: 9642 byte(s)
Set EOL properties appropriately to facilitate simultaneous Linux and Windows development.
1 /* $Header$ */
2
3 /*
4 * tkError.c --
5 *
6 * This file provides a high-performance mechanism for
7 * selectively dealing with errors that occur in talking
8 * to the X server. This is useful, for example, when
9 * communicating with a window that may not exist.
10 *
11 * Copyright (c) 1990-1994 The Regents of the University of California.
12 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
13 *
14 * See the file "license.terms" for information on usage and redistribution
15 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16 *
17 * RCS: @(#) $Id: tkerror.c,v 1.1.1.1 2001/06/13 05:00:00 dtashley Exp $
18 */
19
20 #include "tkPort.h"
21 #include "tkInt.h"
22
23 /*
24 * The default X error handler gets saved here, so that it can
25 * be invoked if an error occurs that we can't handle.
26 */
27
28 static int (*defaultHandler) _ANSI_ARGS_((Display *display,
29 XErrorEvent *eventPtr)) = NULL;
30
31
32 /*
33 * Forward references to procedures declared later in this file:
34 */
35
36 static int ErrorProc _ANSI_ARGS_((Display *display,
37 XErrorEvent *errEventPtr));
38
39 /*
40 *--------------------------------------------------------------
41 *
42 * Tk_CreateErrorHandler --
43 *
44 * Arrange for all a given procedure to be invoked whenever
45 * certain errors occur.
46 *
47 * Results:
48 * The return value is a token identifying the handler;
49 * it must be passed to Tk_DeleteErrorHandler to delete the
50 * handler.
51 *
52 * Side effects:
53 * If an X error occurs that matches the error, request,
54 * and minor arguments, then errorProc will be invoked.
55 * ErrorProc should have the following structure:
56 *
57 * int
58 * errorProc(clientData, errorEventPtr)
59 * caddr_t clientData;
60 * XErrorEvent *errorEventPtr;
61 * {
62 * }
63 *
64 * The clientData argument will be the same as the clientData
65 * argument to this procedure, and errorEvent will describe
66 * the error. If errorProc returns 0, it means that it
67 * completely "handled" the error: no further processing
68 * should be done. If errorProc returns 1, it means that it
69 * didn't know how to deal with the error, so we should look
70 * for other error handlers, or invoke the default error
71 * handler if no other handler returns zero. Handlers are
72 * invoked in order of age: youngest handler first.
73 *
74 * Note: errorProc will only be called for errors associated
75 * with X requests made AFTER this call, but BEFORE the handler
76 * is deleted by calling Tk_DeleteErrorHandler.
77 *
78 *--------------------------------------------------------------
79 */
80
81 Tk_ErrorHandler
82 Tk_CreateErrorHandler(display, error, request, minorCode, errorProc, clientData)
83 Display *display; /* Display for which to handle
84 * errors. */
85 int error; /* Consider only errors with this
86 * error_code (-1 means consider
87 * all errors). */
88 int request; /* Consider only errors with this
89 * major request code (-1 means
90 * consider all major codes). */
91 int minorCode; /* Consider only errors with this
92 * minor request code (-1 means
93 * consider all minor codes). */
94 Tk_ErrorProc *errorProc; /* Procedure to invoke when a
95 * matching error occurs. NULL means
96 * just ignore matching errors. */
97 ClientData clientData; /* Arbitrary value to pass to
98 * errorProc. */
99 {
100 register TkErrorHandler *errorPtr;
101 register TkDisplay *dispPtr;
102
103 /*
104 * Find the display. If Tk doesn't know about this display then
105 * it's an error: panic.
106 */
107
108 dispPtr = TkGetDisplay(display);
109 if (dispPtr == NULL) {
110 panic("Unknown display passed to Tk_CreateErrorHandler");
111 }
112
113 /*
114 * Make sure that X calls us whenever errors occur.
115 */
116
117 if (defaultHandler == NULL) {
118 defaultHandler = XSetErrorHandler(ErrorProc);
119 }
120
121 /*
122 * Create the handler record.
123 */
124
125 errorPtr = (TkErrorHandler *) ckalloc(sizeof(TkErrorHandler));
126 errorPtr->dispPtr = dispPtr;
127 errorPtr->firstRequest = NextRequest(display);
128 errorPtr->lastRequest = (unsigned) -1;
129 errorPtr->error = error;
130 errorPtr->request = request;
131 errorPtr->minorCode = minorCode;
132 errorPtr->errorProc = errorProc;
133 errorPtr->clientData = clientData;
134 errorPtr->nextPtr = dispPtr->errorPtr;
135 dispPtr->errorPtr = errorPtr;
136
137 return (Tk_ErrorHandler) errorPtr;
138 }
139
140 /*
141 *--------------------------------------------------------------
142 *
143 * Tk_DeleteErrorHandler --
144 *
145 * Do not use an error handler anymore.
146 *
147 * Results:
148 * None.
149 *
150 * Side effects:
151 * The handler denoted by the "handler" argument will not
152 * be invoked for any X errors associated with requests
153 * made after this call. However, if errors arrive later
154 * for requests made BEFORE this call, then the handler
155 * will still be invoked. Call XSync if you want to be
156 * sure that all outstanding errors have been received
157 * and processed.
158 *
159 *--------------------------------------------------------------
160 */
161
162 void
163 Tk_DeleteErrorHandler(handler)
164 Tk_ErrorHandler handler; /* Token for handler to delete;
165 * was previous return value from
166 * Tk_CreateErrorHandler. */
167 {
168 register TkErrorHandler *errorPtr = (TkErrorHandler *) handler;
169 register TkDisplay *dispPtr = errorPtr->dispPtr;
170
171 errorPtr->lastRequest = NextRequest(dispPtr->display) - 1;
172
173 /*
174 * Every once-in-a-while, cleanup handlers that are no longer
175 * active. We probably won't be able to free the handler that
176 * was just deleted (need to wait for any outstanding requests to
177 * be processed by server), but there may be previously-deleted
178 * handlers that are now ready for garbage collection. To reduce
179 * the cost of the cleanup, let a few dead handlers pile up, then
180 * clean them all at once. This adds a bit of overhead to errors
181 * that might occur while the dead handlers are hanging around,
182 * but reduces the overhead of scanning the list to clean up
183 * (particularly if there are many handlers that stay around
184 * forever).
185 */
186
187 dispPtr->deleteCount += 1;
188 if (dispPtr->deleteCount >= 10) {
189 register TkErrorHandler *prevPtr;
190 TkErrorHandler *nextPtr;
191 int lastSerial;
192
193 dispPtr->deleteCount = 0;
194 lastSerial = LastKnownRequestProcessed(dispPtr->display);
195 errorPtr = dispPtr->errorPtr;
196 for (prevPtr = NULL; errorPtr != NULL; errorPtr = nextPtr) {
197 nextPtr = errorPtr->nextPtr;
198 if ((errorPtr->lastRequest != (unsigned long) -1)
199 && (errorPtr->lastRequest <= (unsigned long) lastSerial)) {
200 if (prevPtr == NULL) {
201 dispPtr->errorPtr = nextPtr;
202 } else {
203 prevPtr->nextPtr = nextPtr;
204 }
205 ckfree((char *) errorPtr);
206 continue;
207 }
208 prevPtr = errorPtr;
209 }
210 }
211 }
212
213 /*
214 *--------------------------------------------------------------
215 *
216 * ErrorProc --
217 *
218 * This procedure is invoked by the X system when error
219 * events arrive.
220 *
221 * Results:
222 * If it returns, the return value is zero. However,
223 * it is possible that one of the error handlers may
224 * just exit.
225 *
226 * Side effects:
227 * This procedure does two things. First, it uses the
228 * serial # in the error event to eliminate handlers whose
229 * expiration serials are now in the past. Second, it
230 * invokes any handlers that want to deal with the error.
231 *
232 *--------------------------------------------------------------
233 */
234
235 static int
236 ErrorProc(display, errEventPtr)
237 Display *display; /* Display for which error
238 * occurred. */
239 register XErrorEvent *errEventPtr; /* Information about error. */
240 {
241 register TkDisplay *dispPtr;
242 register TkErrorHandler *errorPtr;
243
244 /*
245 * See if we know anything about the display. If not, then
246 * invoke the default error handler.
247 */
248
249 dispPtr = TkGetDisplay(display);
250 if (dispPtr == NULL) {
251 goto couldntHandle;
252 }
253
254 /*
255 * Otherwise invoke any relevant handlers for the error, in order.
256 */
257
258 for (errorPtr = dispPtr->errorPtr; errorPtr != NULL;
259 errorPtr = errorPtr->nextPtr) {
260 if ((errorPtr->firstRequest > errEventPtr->serial)
261 || ((errorPtr->error != -1)
262 && (errorPtr->error != errEventPtr->error_code))
263 || ((errorPtr->request != -1)
264 && (errorPtr->request != errEventPtr->request_code))
265 || ((errorPtr->minorCode != -1)
266 && (errorPtr->minorCode != errEventPtr->minor_code))
267 || ((errorPtr->lastRequest != (unsigned long) -1)
268 && (errorPtr->lastRequest < errEventPtr->serial))) {
269 continue;
270 }
271 if (errorPtr->errorProc == NULL) {
272 return 0;
273 } else {
274 if ((*errorPtr->errorProc)(errorPtr->clientData,
275 errEventPtr) == 0) {
276 return 0;
277 }
278 }
279 }
280
281 /*
282 * See if the error is a BadWindow error. If so, and it refers
283 * to a window that still exists in our window table, then ignore
284 * the error. Errors like this can occur if a window owned by us
285 * is deleted by someone externally, like a window manager. We'll
286 * ignore the errors at least long enough to clean up internally and
287 * remove the entry from the window table.
288 *
289 * NOTE: For embedding, we must also check whether the window was
290 * recently deleted. If so, it may be that Tk generated operations on
291 * windows that were deleted by the container. Now we are getting
292 * the errors (BadWindow) after Tk already deleted the window itself.
293 */
294
295 if ((errEventPtr->error_code == BadWindow) &&
296 ((Tk_IdToWindow(display, (Window) errEventPtr->resourceid) !=
297 NULL) ||
298 (TkpWindowWasRecentlyDeleted((Window) errEventPtr->resourceid,
299 dispPtr)))) {
300 return 0;
301 }
302
303 /*
304 * We couldn't handle the error. Use the default handler.
305 */
306
307 couldntHandle:
308 return (*defaultHandler)(display, errEventPtr);
309 }
310
311 /* End of tkerror.c */

Properties

Name Value
svn:eol-style native
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25