Annotation of micropolis/src/tk/tkerror.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.