/[dtapublic]/sf_code/esrgpcpj/shared/tk_base/tkerror.c
ViewVC logotype

Annotation of /sf_code/esrgpcpj/shared/tk_base/tkerror.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (hide annotations) (download)
Sat Oct 8 06:43:03 2016 UTC (7 years, 9 months ago) by dashley
File MIME type: text/plain
File size: 10273 byte(s)
Initial commit.
1 dashley 25 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkerror.c,v 1.1.1.1 2001/06/13 05:00:00 dtashley Exp $ */
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    
312     /* $History: tkError.c $
313     *
314     * ***************** Version 1 *****************
315     * User: Dtashley Date: 1/02/01 Time: 2:50a
316     * Created in $/IjuScripter, IjuConsole/Source/Tk Base
317     * Initial check-in.
318     */
319    
320     /* End of TKERROR.C */

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25