/[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

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

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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25