Mercurial > kinput2.yaz
diff lib/dispatch.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/dispatch.c Mon Mar 08 04:44:30 2010 +0900 @@ -0,0 +1,268 @@ +#ifndef lint +static char *rcsid = "$Id: dispatch.c,v 1.14 1994/05/31 07:48:42 ishisone Rel $"; +#endif + +/* + * a very simple event dispatch library for non-widget windows + * + * 'non-widget window' means windows that have no associated widget, + * e.g. windows created by Xlib directly. + */ + +/* + * Copyright (c) 1990 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 + */ + +#include <X11/Intrinsic.h> +#include "MyDispatch.h" +#include "AsyncErr.h" + +#define DEBUG_VAR debug_dispatch +#include "DebugPrint.h" + +typedef struct _handler_ { + int type; /* event type */ + unsigned long mask; /* event mask */ + void (*handler)(); + XtPointer data; + struct _handler_ *next; +} HandlerRec; + +typedef struct { + Boolean dispatching; /* now dispatching */ + Boolean toberemoved; /* this list is to be removed later */ + unsigned long mask; /* event mask */ + HandlerRec *handlers; +} WindowRec; + +static int Initialized = 0; +static XContext Context; + +static void +initialize() +{ + Context = XUniqueContext(); + Initialized = 1; +} + +static void +resetEventMask(dpy, window, wp) +Display *dpy; +Window window; +WindowRec *wp; +{ + register HandlerRec *hp = wp->handlers; + register unsigned long mask = 0L; + + while (hp != NULL) { + mask |= hp->mask; + hp = hp->next; + } + + if (mask != wp->mask) { + XAEHandle h = XAESetIgnoreErrors(dpy); /* keep the operation safe */ + XSelectInput(dpy, window, mask); + XAEUnset(h); + wp->mask = mask; + } +} + +static void +removeAll(dpy, window, wp) +Display *dpy; +Window window; +WindowRec *wp; +{ + register HandlerRec *hp = wp->handlers; + + while (hp != NULL) { + register HandlerRec *hp0 = hp; + hp = hp->next; + XtFree((char *)hp0); + } + + if (wp->mask != 0L) { + XAEHandle h = XAESetIgnoreErrors(dpy); + + /* keep it safe (because the window might not exist any more) */ + XSelectInput(dpy, window, 0L); + XAEUnset(h); + } + + XtFree((char *)wp); + (void)XDeleteContext(dpy, window, Context); +} + +static void +doDispatch(event, list) +XEvent *event; +register HandlerRec *list; +{ + void (*handler)(); + XtPointer data; + register int type = event->type; + + /* + * we must be careful here. the invoked handler might remove + * itself, or remove other handler to be invoked next. + * so we use this somewhat strange recursive call. + */ + while (list != NULL) { + if (list->type == type) { + handler = list->handler; + data = list->data; + doDispatch(event, list->next); + (*handler)(event, data); + return; + } + list = list->next; + } +} + +void +MyDispatchEvent(event) +XEvent *event; +{ + caddr_t data; + + if (!Initialized) initialize(); + + if (!XFindContext(event->xany.display, event->xany.window, + Context, &data)) { + WindowRec *wrec = (WindowRec *)data; + + wrec->dispatching = True; + wrec->toberemoved = False; + + doDispatch(event, wrec->handlers); + + wrec->dispatching = False; + if (wrec->toberemoved) { + removeAll(event->xany.display, event->xany.window, wrec); + } + } +} + +void +MyAddEventHandler(dpy, window, type, mask, func, data) +Display *dpy; +Window window; +int type; +unsigned long mask; +void (*func)(); +XtPointer data; +{ + WindowRec *wp; + HandlerRec *hp; + caddr_t cdata; + + TRACE(("MyAddEventHandler(window=%08lx,type=%d)\n", window, type)); + if (!Initialized) initialize(); + + hp = XtNew(HandlerRec); + hp->type = type; + hp->mask = mask; + hp->handler = func; + hp->data = data; + hp->next = NULL; + + if (!XFindContext(dpy, window, Context, &cdata)) { + wp = (WindowRec *)cdata; + hp->next = wp->handlers; + wp->handlers = hp; + } else { + wp = XtNew(WindowRec); + wp->mask = 0L; + wp->dispatching = False; + wp->handlers = hp; + (void)XSaveContext(dpy, window, Context, (caddr_t)wp); + } + resetEventMask(dpy, window, wp); +} + +void +MyRemoveEventHandler(dpy, window, type, func, data) +Display *dpy; +Window window; +int type; +void (*func)(); +XtPointer data; +{ + caddr_t cdata; + WindowRec *wp; + HandlerRec *hp, *hp0; + + TRACE(("MyRemoveEventHandler(window=%08lx,type=%d)\n", window, type)); + if (!Initialized) initialize(); + if (XFindContext(dpy, window, Context, &cdata) || cdata == NULL) return; + + wp = (WindowRec *)cdata; + hp0 = NULL; + hp = wp->handlers; + + while (hp != NULL) { + if (hp->type == type && hp->handler == func && hp->data == data) { + HandlerRec *tmp = hp; + + hp = hp->next; + if (hp0 == NULL) { + wp->handlers = hp; + } else { + hp0->next = hp; + } + XtFree((char *)tmp); + } else { + hp0 = hp; + hp = hp->next; + } + } + + resetEventMask(dpy, window, wp); + + if (wp->handlers == NULL) { + if (wp->dispatching) { + /* now dispatching. we just mark it to be removed later. */ + wp->toberemoved = True; + } else { + XtFree((char *)wp); + (void)XDeleteContext(dpy, window, Context); + } + } +} + +void +MyRemoveAllEventHandler(dpy, window) +Display *dpy; +Window window; +{ + caddr_t cdata; + WindowRec *wp; + + TRACE(("MyRemoveAllEventHandler(window=%08lx)\n", window)); + if (!Initialized) initialize(); + + if (XFindContext(dpy, window, Context, &cdata) || cdata == NULL) return; + + wp = (WindowRec *)cdata; + + if (wp->dispatching) { + /* now dispatching. we just mark it to be removed later. */ + wp->toberemoved = True; + return; + } else { + removeAll(dpy, window, wp); + } +}