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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

to_be_filed/sf_code/esrgpcpj/shared/tk_base/tkerror.c revision 29 by dashley, Sat Oct 8 07:08:47 2016 UTC projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkerror.c revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkerror.c,v 1.1.1.1 2001/06/13 05:00:00 dtashley Exp $ */  
   
 /*  
  * tkError.c --  
  *  
  *      This file provides a high-performance mechanism for  
  *      selectively dealing with errors that occur in talking  
  *      to the X server.  This is useful, for example, when  
  *      communicating with a window that may not exist.  
  *  
  * Copyright (c) 1990-1994 The Regents of the University of California.  
  * Copyright (c) 1994-1995 Sun Microsystems, Inc.  
  *  
  * See the file "license.terms" for information on usage and redistribution  
  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.  
  *  
  * RCS: @(#) $Id: tkerror.c,v 1.1.1.1 2001/06/13 05:00:00 dtashley Exp $  
  */  
   
 #include "tkPort.h"  
 #include "tkInt.h"  
   
 /*  
  * The default X error handler gets saved here, so that it can  
  * be invoked if an error occurs that we can't handle.  
  */  
   
 static int      (*defaultHandler) _ANSI_ARGS_((Display *display,  
                     XErrorEvent *eventPtr)) = NULL;  
   
   
 /*  
  * Forward references to procedures declared later in this file:  
  */  
   
 static int      ErrorProc _ANSI_ARGS_((Display *display,  
                     XErrorEvent *errEventPtr));  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * Tk_CreateErrorHandler --  
  *  
  *      Arrange for all a given procedure to be invoked whenever  
  *      certain errors occur.  
  *  
  * Results:  
  *      The return value is a token identifying the handler;  
  *      it must be passed to Tk_DeleteErrorHandler to delete the  
  *      handler.  
  *  
  * Side effects:  
  *      If an X error occurs that matches the error, request,  
  *      and minor arguments, then errorProc will be invoked.  
  *      ErrorProc should have the following structure:  
  *  
  *      int  
  *      errorProc(clientData, errorEventPtr)  
  *          caddr_t clientData;  
  *          XErrorEvent *errorEventPtr;  
  *      {  
  *      }  
  *  
  *      The clientData argument will be the same as the clientData  
  *      argument to this procedure, and errorEvent will describe  
  *      the error.  If errorProc returns 0, it means that it  
  *      completely "handled" the error:  no further processing  
  *      should be done.  If errorProc returns 1, it means that it  
  *      didn't know how to deal with the error, so we should look  
  *      for other error handlers, or invoke the default error  
  *      handler if no other handler returns zero.  Handlers are  
  *      invoked in order of age:  youngest handler first.  
  *  
  *      Note:  errorProc will only be called for errors associated  
  *      with X requests made AFTER this call, but BEFORE the handler  
  *      is deleted by calling Tk_DeleteErrorHandler.  
  *  
  *--------------------------------------------------------------  
  */  
   
 Tk_ErrorHandler  
 Tk_CreateErrorHandler(display, error, request, minorCode, errorProc, clientData)  
     Display *display;           /* Display for which to handle  
                                  * errors. */  
     int error;                  /* Consider only errors with this  
                                  * error_code (-1 means consider  
                                  * all errors). */  
     int request;                /* Consider only errors with this  
                                  * major request code (-1 means  
                                  * consider all major codes). */  
     int minorCode;              /* Consider only errors with this  
                                  * minor request code (-1 means  
                                  * consider all minor codes). */  
     Tk_ErrorProc *errorProc;    /* Procedure to invoke when a  
                                  * matching error occurs.  NULL means  
                                  * just ignore matching errors. */  
     ClientData clientData;      /* Arbitrary value to pass to  
                                  * errorProc. */  
 {  
     register TkErrorHandler *errorPtr;  
     register TkDisplay *dispPtr;  
   
     /*  
      * Find the display.  If Tk doesn't know about this display then  
      * it's an error:  panic.  
      */  
   
     dispPtr = TkGetDisplay(display);  
     if (dispPtr == NULL) {  
         panic("Unknown display passed to Tk_CreateErrorHandler");  
     }  
   
     /*  
      * Make sure that X calls us whenever errors occur.  
      */  
   
     if (defaultHandler == NULL) {  
         defaultHandler = XSetErrorHandler(ErrorProc);  
     }  
   
     /*  
      * Create the handler record.  
      */  
   
     errorPtr = (TkErrorHandler *) ckalloc(sizeof(TkErrorHandler));  
     errorPtr->dispPtr = dispPtr;  
     errorPtr->firstRequest = NextRequest(display);  
     errorPtr->lastRequest = (unsigned) -1;  
     errorPtr->error = error;  
     errorPtr->request = request;  
     errorPtr->minorCode = minorCode;  
     errorPtr->errorProc = errorProc;  
     errorPtr->clientData = clientData;  
     errorPtr->nextPtr = dispPtr->errorPtr;  
     dispPtr->errorPtr = errorPtr;  
   
     return (Tk_ErrorHandler) errorPtr;  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * Tk_DeleteErrorHandler --  
  *  
  *      Do not use an error handler anymore.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The handler denoted by the "handler" argument will not  
  *      be invoked for any X errors associated with requests  
  *      made after this call.  However, if errors arrive later  
  *      for requests made BEFORE this call, then the handler  
  *      will still be invoked.  Call XSync if you want to be  
  *      sure that all outstanding errors have been received  
  *      and processed.  
  *  
  *--------------------------------------------------------------  
  */  
   
 void  
 Tk_DeleteErrorHandler(handler)  
     Tk_ErrorHandler handler;    /* Token for handler to delete;  
                                  * was previous return value from  
                                  * Tk_CreateErrorHandler. */  
 {  
     register TkErrorHandler *errorPtr = (TkErrorHandler *) handler;  
     register TkDisplay *dispPtr = errorPtr->dispPtr;  
   
     errorPtr->lastRequest = NextRequest(dispPtr->display) - 1;  
   
     /*  
      * Every once-in-a-while, cleanup handlers that are no longer  
      * active.  We probably won't be able to free the handler that  
      * was just deleted (need to wait for any outstanding requests to  
      * be processed by server), but there may be previously-deleted  
      * handlers that are now ready for garbage collection.  To reduce  
      * the cost of the cleanup, let a few dead handlers pile up, then  
      * clean them all at once.  This adds a bit of overhead to errors  
      * that might occur while the dead handlers are hanging around,  
      * but reduces the overhead of scanning the list to clean up  
      * (particularly if there are many handlers that stay around  
      * forever).  
      */  
   
     dispPtr->deleteCount += 1;  
     if (dispPtr->deleteCount >= 10) {  
         register TkErrorHandler *prevPtr;  
         TkErrorHandler *nextPtr;  
         int lastSerial;  
   
         dispPtr->deleteCount = 0;  
         lastSerial = LastKnownRequestProcessed(dispPtr->display);  
         errorPtr = dispPtr->errorPtr;  
         for (prevPtr = NULL; errorPtr != NULL; errorPtr = nextPtr) {  
             nextPtr = errorPtr->nextPtr;  
             if ((errorPtr->lastRequest != (unsigned long) -1)  
                     && (errorPtr->lastRequest <= (unsigned long) lastSerial)) {  
                 if (prevPtr == NULL) {  
                     dispPtr->errorPtr = nextPtr;  
                 } else {  
                     prevPtr->nextPtr = nextPtr;  
                 }  
                 ckfree((char *) errorPtr);  
                 continue;  
             }  
             prevPtr = errorPtr;  
         }  
     }  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * ErrorProc --  
  *  
  *      This procedure is invoked by the X system when error  
  *      events arrive.  
  *  
  * Results:  
  *      If it returns, the return value is zero.  However,  
  *      it is possible that one of the error handlers may  
  *      just exit.  
  *  
  * Side effects:  
  *      This procedure does two things.  First, it uses the  
  *      serial #  in the error event to eliminate handlers whose  
  *      expiration serials are now in the past.  Second, it  
  *      invokes any handlers that want to deal with the error.  
  *  
  *--------------------------------------------------------------  
  */  
   
 static int  
 ErrorProc(display, errEventPtr)  
     Display *display;                   /* Display for which error  
                                          * occurred. */  
     register XErrorEvent *errEventPtr;  /* Information about error. */  
 {  
     register TkDisplay *dispPtr;  
     register TkErrorHandler *errorPtr;  
   
     /*  
      * See if we know anything about the display.  If not, then  
      * invoke the default error handler.  
      */  
   
     dispPtr = TkGetDisplay(display);  
     if (dispPtr == NULL) {  
         goto couldntHandle;  
     }  
   
     /*  
      * Otherwise invoke any relevant handlers for the error, in order.  
      */  
   
     for (errorPtr = dispPtr->errorPtr; errorPtr != NULL;  
             errorPtr = errorPtr->nextPtr) {  
         if ((errorPtr->firstRequest > errEventPtr->serial)  
                 || ((errorPtr->error != -1)  
                     && (errorPtr->error != errEventPtr->error_code))  
                 || ((errorPtr->request != -1)  
                     && (errorPtr->request != errEventPtr->request_code))  
                 || ((errorPtr->minorCode != -1)  
                     && (errorPtr->minorCode != errEventPtr->minor_code))  
                 || ((errorPtr->lastRequest != (unsigned long) -1)  
                     && (errorPtr->lastRequest < errEventPtr->serial))) {  
             continue;  
         }  
         if (errorPtr->errorProc == NULL) {  
             return 0;  
         } else {  
             if ((*errorPtr->errorProc)(errorPtr->clientData,  
                     errEventPtr) == 0) {  
                 return 0;  
             }  
         }  
     }  
   
     /*  
      * See if the error is a BadWindow error.  If so, and it refers  
      * to a window that still exists in our window table, then ignore  
      * the error.  Errors like this can occur if a window owned by us  
      * is deleted by someone externally, like a window manager.  We'll  
      * ignore the errors at least long enough to clean up internally and  
      * remove the entry from the window table.  
      *  
      * NOTE: For embedding, we must also check whether the window was  
      * recently deleted. If so, it may be that Tk generated operations on  
      * windows that were deleted by the container. Now we are getting  
      * the errors (BadWindow) after Tk already deleted the window itself.  
      */  
   
     if ((errEventPtr->error_code == BadWindow) &&  
             ((Tk_IdToWindow(display, (Window) errEventPtr->resourceid) !=  
                     NULL) ||  
                 (TkpWindowWasRecentlyDeleted((Window) errEventPtr->resourceid,  
                         dispPtr)))) {  
         return 0;  
     }  
   
     /*  
      * We couldn't handle the error.  Use the default handler.  
      */  
   
     couldntHandle:  
     return (*defaultHandler)(display, errEventPtr);  
 }  
   
   
 /* $History: tkError.c $  
  *  
  * *****************  Version 1  *****************  
  * User: Dtashley     Date: 1/02/01    Time: 2:50a  
  * Created in $/IjuScripter, IjuConsole/Source/Tk Base  
  * Initial check-in.  
  */  
   
 /* End of TKERROR.C */  
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 */

Legend:
Removed from v.29  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25