Mercurial > kinput2.yaz
diff lib/asyncerr.c @ 0:92745d501b9a
initial import from kinput2-v3.1
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Mon, 08 Mar 2010 04:44:30 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/asyncerr.c Mon Mar 08 04:44:30 2010 +0900 @@ -0,0 +1,275 @@ +#ifndef lint +static char *rcsid = "$Id: asyncerr.c,v 1.6 1994/08/08 01:20:52 ishisone Exp $"; +#endif +/* + * Copyright (C) 1992, 1994 Software Research Associates, Inc. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Software Research Associates not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Software Research + * Associates makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * Author: Makoto Ishisone, Software Research Associates, Inc., Japan + */ + +/* + * X asyncronous error handler + */ + +#include <X11/Xlib.h> +#include <X11/Xfuncproto.h> +#include "AsyncErr.h" + +#ifdef __STDC__ +#include <stdlib.h> +#else +extern char *malloc(); +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#undef XSetErrorHandler + +typedef struct fe_errdesc_ { + struct fe_errdesc_ *prev; + struct fe_errdesc_ *next; + Display *dpy; + unsigned long from; /* range of the sequence numbers */ + unsigned long to; /* which this handler covers */ + int (*handler)(); /* async handler */ + void (*destroy)(); + XPointer client_data; +} ErrDesc; + +static ErrDesc esentinel = { + &esentinel, + &esentinel, +}; + +#define EHEAD (esentinel.next) +#define ETAIL (esentinel.prev) +#define EEND(p) ((p) == &esentinel) + +static int (*original_handler)(); + +/* + * Some useful handlers + */ + +/* ARGSUSED */ +static int +ignoreErrors(dpy, eev, cldata) +Display *dpy; +XErrorEvent *eev; +XPointer cldata; +{ + /* + * Just ignore any errors. + */ + return 0; +} + +/* ARGSUSED */ +static int +recordErrors(dpy, eev, cldata) +Display *dpy; +XErrorEvent *eev; +XPointer cldata; +{ + /* + * Record the type of the error. + * It assumes that the client data is a pointer to + * an unsigned long int. If error occurs, it does: + * + if the error code is less than 32, set the 'error code'th bit. + * + otherwise (i.e. extension defined error) set the bit 0. + */ + unsigned long *errorbitsp = (unsigned long *)cldata; + + if (eev->error_code < 32) { + *errorbitsp |= (1 << eev->error_code); + } else { + /* other errors */ + *errorbitsp |= 1; + } + + /* don't invoke global handler */ + return 0; +} + +static ErrDesc * +newErrDesc() +{ + return (ErrDesc *)malloc(sizeof(ErrDesc)); +} + +static void +eremove(edp) +ErrDesc *edp; +{ + edp->prev->next = edp->next; + edp->next->prev = edp->prev; +} + +static void +eappend(edp) +ErrDesc *edp; +{ + edp->prev = esentinel.prev; + edp->next = &esentinel; + (esentinel.prev)->next = edp; + esentinel.prev = edp; +} + +static void +removeHandler(edp) +ErrDesc *edp; +{ + if (edp->destroy != NULL) (*edp->destroy)(edp->dpy, edp->client_data); + eremove(edp); + (void)free((char *)edp); +} + +static int +callHandlers(dpy, eev) +Display *dpy; +XErrorEvent *eev; +{ + ErrDesc *edp = EHEAD; + int found = 0; + int call_original = 0; + + while (!EEND(edp)) { + if (edp->dpy == dpy && edp->from <= eev->serial && + (eev->serial < edp->to || edp->from == edp->to)) { + found = 1; + if ((*edp->handler)(dpy, eev, edp->client_data)) call_original = 1; + } + edp = edp->next; + } + return !found || call_original; +} + +static void +removeHandlers(dpy) +Display *dpy; +{ + /* + * Remove obsolete (out of date) handlers. + */ + ErrDesc *edp = EHEAD; + unsigned long last = LastKnownRequestProcessed(dpy); + + while (!EEND(edp)) { + ErrDesc *next = edp->next; + + if (edp->dpy == dpy && edp->to <= last && edp->from != edp->to) { + removeHandler(edp); + } + edp = next; + } +} + +/* + * public functions + */ + +int +XAEHandler(dpy, eev) +Display *dpy; +XErrorEvent *eev; +{ + if (callHandlers(dpy, eev) && original_handler != NULL) { + (void)original_handler(dpy, eev); + } + removeHandlers(dpy); + return 0; /* for lint */ +} + +void +XAEInit() +{ + int (*oldhandler)() = XSetErrorHandler(XAEHandler); + + if (oldhandler != XAEHandler) original_handler = oldhandler; +} + +XErrorHandler +XAESetErrorHandler(handler) +XErrorHandler handler; +{ + int (*oldhandler)(); + + oldhandler = original_handler; + original_handler = handler; + return oldhandler; +} + +XAEHandle +XAESet(dpy, handler, destroy, client_data) +Display *dpy; +int (*handler)(); +void (*destroy)(); +XPointer client_data; +{ + ErrDesc *e; + + /* + * First, remove out-of-date handlers. + */ + removeHandlers(dpy); + + /* + * Allocate new ErrDesc structure. + */ + e = newErrDesc(); + if (e == NULL) return NULL; + + e->dpy = dpy; + e->from = NextRequest(dpy); + e->to = e->from; + e->handler = handler; + e->destroy = destroy; + e->client_data = client_data; + + eappend(e); + + return e; +} + +void +XAEUnset(handle) +XAEHandle handle; +{ + Display *dpy = handle->dpy; + + if (handle != NULL && handle->from == handle->to) { + handle->to = NextRequest(dpy); + if (handle->to <= handle->from) removeHandler(handle); + } + removeHandlers(dpy); +} + +XAEHandle +XAESetIgnoreErrors(dpy) +Display *dpy; +{ + return XAESet(dpy, ignoreErrors, (void (*)())NULL, (XPointer)NULL); +} + +XAEHandle +XAESetRecordErrors(dpy, errorbitsp) +Display *dpy; +unsigned long *errorbitsp; +{ + *errorbitsp = 0L; /* clear all bits */ + return XAESet(dpy, recordErrors, + (void (*)())NULL, (XPointer)errorbitsp); +}