Event.c revision 444c061a
1444c061aSmrg/* $Xorg: Event.c,v 1.5 2001/02/09 02:03:54 xorgcvs Exp $ */
2444c061aSmrg
3444c061aSmrg/***********************************************************
4444c061aSmrgCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
5444c061aSmrgCopyright 1993 by Sun Microsystems, Inc. Mountain View, CA.
6444c061aSmrg
7444c061aSmrg                        All Rights Reserved
8444c061aSmrg
9444c061aSmrgPermission to use, copy, modify, and distribute this software and its
10444c061aSmrgdocumentation for any purpose and without fee is hereby granted,
11444c061aSmrgprovided that the above copyright notice appear in all copies and that
12444c061aSmrgboth that copyright notice and this permission notice appear in
13444c061aSmrgsupporting documentation, and that the names of Digital or Sun not be
14444c061aSmrgused in advertising or publicity pertaining to distribution of the
15444c061aSmrgsoftware without specific, written prior permission.
16444c061aSmrg
17444c061aSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
18444c061aSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
19444c061aSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
20444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21444c061aSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22444c061aSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23444c061aSmrgSOFTWARE.
24444c061aSmrg
25444c061aSmrgSUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
26444c061aSmrgINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
27444c061aSmrgNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
28444c061aSmrgABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
29444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
30444c061aSmrgPROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
31444c061aSmrgOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
32444c061aSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
33444c061aSmrg
34444c061aSmrg******************************************************************/
35444c061aSmrg
36444c061aSmrg/*
37444c061aSmrg
38444c061aSmrgCopyright 1987, 1988, 1998  The Open Group
39444c061aSmrg
40444c061aSmrgPermission to use, copy, modify, distribute, and sell this software and its
41444c061aSmrgdocumentation for any purpose is hereby granted without fee, provided that
42444c061aSmrgthe above copyright notice appear in all copies and that both that
43444c061aSmrgcopyright notice and this permission notice appear in supporting
44444c061aSmrgdocumentation.
45444c061aSmrg
46444c061aSmrgThe above copyright notice and this permission notice shall be included in
47444c061aSmrgall copies or substantial portions of the Software.
48444c061aSmrg
49444c061aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50444c061aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51444c061aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
52444c061aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
53444c061aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
54444c061aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
55444c061aSmrg
56444c061aSmrgExcept as contained in this notice, the name of The Open Group shall not be
57444c061aSmrgused in advertising or otherwise to promote the sale, use or other dealings
58444c061aSmrgin this Software without prior written authorization from The Open Group.
59444c061aSmrg
60444c061aSmrg*/
61444c061aSmrg/* $XFree86: xc/lib/Xt/Event.c,v 3.10 2001/12/14 19:56:11 dawes Exp $ */
62444c061aSmrg
63444c061aSmrg#ifdef HAVE_CONFIG_H
64444c061aSmrg#include <config.h>
65444c061aSmrg#endif
66444c061aSmrg#include "IntrinsicI.h"
67444c061aSmrg#include "Shell.h"
68444c061aSmrg#include "StringDefs.h"
69444c061aSmrg
70444c061aSmrgtypedef struct _XtEventRecExt {
71444c061aSmrg    int type;
72444c061aSmrg    XtPointer select_data[1]; /* actual dimension is [mask] */
73444c061aSmrg} XtEventRecExt;
74444c061aSmrg
75444c061aSmrg#define EXT_TYPE(p) (((XtEventRecExt*) ((p)+1))->type)
76444c061aSmrg#define EXT_SELECT_DATA(p,n) (((XtEventRecExt*) ((p)+1))->select_data[n])
77444c061aSmrg
78444c061aSmrg#define NonMaskableMask ((EventMask)0x80000000L)
79444c061aSmrg
80444c061aSmrg/*
81444c061aSmrg * These are definitions to make the code that handles exposure compresssion
82444c061aSmrg * easier to read.
83444c061aSmrg *
84444c061aSmrg * COMP_EXPOSE      - The compression exposure field of "widget"
85444c061aSmrg * COMP_EXPOSE_TYPE - The type of compression (lower 4 bits of COMP_EXPOSE.
86444c061aSmrg * GRAPHICS_EXPOSE  - TRUE if the widget wants graphics expose events
87444c061aSmrg *                    dispatched.
88444c061aSmrg * NO_EXPOSE        - TRUE if the widget wants No expose events dispatched.
89444c061aSmrg */
90444c061aSmrg
91444c061aSmrg#define COMP_EXPOSE   (widget->core.widget_class->core_class.compress_exposure)
92444c061aSmrg#define COMP_EXPOSE_TYPE (COMP_EXPOSE & 0x0f)
93444c061aSmrg#define GRAPHICS_EXPOSE  ((XtExposeGraphicsExpose & COMP_EXPOSE) || \
94444c061aSmrg			  (XtExposeGraphicsExposeMerged & COMP_EXPOSE))
95444c061aSmrg#define NO_EXPOSE        (XtExposeNoExpose & COMP_EXPOSE)
96444c061aSmrg
97444c061aSmrgEventMask XtBuildEventMask(
98444c061aSmrg    Widget widget)
99444c061aSmrg{
100444c061aSmrg    XtEventTable ev;
101444c061aSmrg    EventMask	mask = 0L;
102444c061aSmrg    WIDGET_TO_APPCON(widget);
103444c061aSmrg
104444c061aSmrg    LOCK_APP(app);
105444c061aSmrg    for (ev = widget->core.event_table; ev != NULL; ev = ev->next)
106444c061aSmrg	if (ev->select) {
107444c061aSmrg	    if (!ev->has_type_specifier)
108444c061aSmrg		mask |= ev->mask;
109444c061aSmrg	    else {
110444c061aSmrg		if (EXT_TYPE(ev) < LASTEvent) {
111444c061aSmrg		    Cardinal i;
112444c061aSmrg		    for (i = 0; i < ev->mask; i++)
113444c061aSmrg			if (EXT_SELECT_DATA(ev, i))
114444c061aSmrg			    mask |= *(EventMask*)EXT_SELECT_DATA(ev, i);
115444c061aSmrg		}
116444c061aSmrg	    }
117444c061aSmrg	}
118444c061aSmrg    LOCK_PROCESS;
119444c061aSmrg    if (widget->core.widget_class->core_class.expose != NULL)
120444c061aSmrg	mask |= ExposureMask;
121444c061aSmrg    if (widget->core.widget_class->core_class.visible_interest)
122444c061aSmrg	mask |= VisibilityChangeMask;
123444c061aSmrg    UNLOCK_PROCESS;
124444c061aSmrg    if (widget->core.tm.translations)
125444c061aSmrg	mask |= widget->core.tm.translations->eventMask;
126444c061aSmrg
127444c061aSmrg    mask =  mask & ~NonMaskableMask;
128444c061aSmrg    UNLOCK_APP(app);
129444c061aSmrg    return mask;
130444c061aSmrg}
131444c061aSmrg
132444c061aSmrgstatic void CallExtensionSelector(
133444c061aSmrg    Widget widget,
134444c061aSmrg    ExtSelectRec* rec,
135444c061aSmrg    Boolean forceCall)
136444c061aSmrg{
137444c061aSmrg    XtEventRec* p;
138444c061aSmrg    XtPointer* data;
139444c061aSmrg    int* types;
140444c061aSmrg    Cardinal i, count = 0;
141444c061aSmrg
142444c061aSmrg    for (p = widget->core.event_table; p != NULL; p = p->next)
143444c061aSmrg	if (p->has_type_specifier &&
144444c061aSmrg	    EXT_TYPE(p) >= rec->min && EXT_TYPE(p) <= rec->max)
145444c061aSmrg	    count += p->mask;
146444c061aSmrg
147444c061aSmrg    if (count == 0 && !forceCall) return;
148444c061aSmrg
149444c061aSmrg    data = (XtPointer *) ALLOCATE_LOCAL(count * sizeof (XtPointer));
150444c061aSmrg    types = (int *) ALLOCATE_LOCAL(count * sizeof (int));
151444c061aSmrg    count = 0;
152444c061aSmrg
153444c061aSmrg    for (p = widget->core.event_table; p != NULL; p = p->next)
154444c061aSmrg	if (p->has_type_specifier &&
155444c061aSmrg	    EXT_TYPE(p) >= rec->min && EXT_TYPE(p) <= rec->max)
156444c061aSmrg	    for (i =0; i < p->mask; i++) {
157444c061aSmrg		types[count] = EXT_TYPE(p);
158444c061aSmrg		data[count++] = EXT_SELECT_DATA(p, i);
159444c061aSmrg	    }
160444c061aSmrg
161444c061aSmrg    (*rec->proc)(widget, types, data, count, rec->client_data);
162444c061aSmrg    DEALLOCATE_LOCAL((char*) types);
163444c061aSmrg    DEALLOCATE_LOCAL((char*) data);
164444c061aSmrg}
165444c061aSmrg
166444c061aSmrgstatic void
167444c061aSmrgRemoveEventHandler(
168444c061aSmrg    Widget widget,
169444c061aSmrg    XtPointer select_data,
170444c061aSmrg    int type,
171444c061aSmrg    Boolean has_type_specifier,
172444c061aSmrg    Boolean other,
173444c061aSmrg    XtEventHandler proc,
174444c061aSmrg    XtPointer closure,
175444c061aSmrg    Boolean raw)
176444c061aSmrg{
177444c061aSmrg    XtEventRec *p, **pp;
178444c061aSmrg    EventMask eventMask, oldMask = XtBuildEventMask(widget);
179444c061aSmrg
180444c061aSmrg    if (raw) raw = 1;
181444c061aSmrg    pp = &widget->core.event_table;
182444c061aSmrg    while ((p = *pp) &&
183444c061aSmrg	   (p->proc != proc || p->closure != closure || p->select == raw ||
184444c061aSmrg	    has_type_specifier != p->has_type_specifier ||
185444c061aSmrg	    (has_type_specifier && EXT_TYPE(p) != type)))
186444c061aSmrg	pp = &p->next;
187444c061aSmrg    if (!p) return;
188444c061aSmrg
189444c061aSmrg    /* un-register it */
190444c061aSmrg    if (!has_type_specifier) {
191444c061aSmrg	eventMask = *(EventMask*)select_data;
192444c061aSmrg	eventMask &= ~NonMaskableMask;
193444c061aSmrg	if (other)
194444c061aSmrg	    eventMask |= NonMaskableMask;
195444c061aSmrg	p->mask &= ~eventMask;
196444c061aSmrg    } else {
197444c061aSmrg	Cardinal i;
198444c061aSmrg	/* p->mask specifies count of EXT_SELECT_DATA(p,i)
199444c061aSmrg	 * search through the list of selection data, if not found
200444c061aSmrg	 * dont remove this handler
201444c061aSmrg	 */
202444c061aSmrg	for (i = 0; i < p->mask && select_data != EXT_SELECT_DATA(p,i);) i++;
203444c061aSmrg	if (i == p->mask) return;
204444c061aSmrg	if (p->mask == 1) p->mask = 0;
205444c061aSmrg	else {
206444c061aSmrg	    p->mask--;
207444c061aSmrg	    while (i < p->mask) {
208444c061aSmrg		EXT_SELECT_DATA(p,i) = EXT_SELECT_DATA(p, i+1);
209444c061aSmrg		i++;
210444c061aSmrg	    }
211444c061aSmrg	}
212444c061aSmrg    }
213444c061aSmrg
214444c061aSmrg    if (!p->mask) {        /* delete it entirely */
215444c061aSmrg        *pp = p->next;
216444c061aSmrg	XtFree((char *)p);
217444c061aSmrg    }
218444c061aSmrg
219444c061aSmrg    /* Reset select mask if realized and not raw. */
220444c061aSmrg    if ( !raw && XtIsRealized(widget) && !widget->core.being_destroyed) {
221444c061aSmrg	EventMask mask = XtBuildEventMask(widget);
222444c061aSmrg	Display* dpy = XtDisplay (widget);
223444c061aSmrg
224444c061aSmrg	if (oldMask != mask)
225444c061aSmrg	    XSelectInput(dpy, XtWindow(widget), mask);
226444c061aSmrg
227444c061aSmrg	if (has_type_specifier) {
228444c061aSmrg	    XtPerDisplay pd = _XtGetPerDisplay(dpy);
229444c061aSmrg	    int i;
230444c061aSmrg	    for (i = 0; i < pd->ext_select_count; i++) {
231444c061aSmrg		if (type >= pd->ext_select_list[i].min &&
232444c061aSmrg		    type <= pd->ext_select_list[i].max) {
233444c061aSmrg		    CallExtensionSelector(widget, pd->ext_select_list+i, TRUE);
234444c061aSmrg		    break;
235444c061aSmrg		}
236444c061aSmrg		if (type < pd->ext_select_list[i].min) break;
237444c061aSmrg	    }
238444c061aSmrg	}
239444c061aSmrg    }
240444c061aSmrg}
241444c061aSmrg
242444c061aSmrg/*	Function Name: AddEventHandler
243444c061aSmrg *	Description: An Internal routine that does the actual work of
244444c061aSmrg *                   adding the event handlers.
245444c061aSmrg *	Arguments: widget - widget to register an event handler for.
246444c061aSmrg *                 eventMask - events to mask for.
247444c061aSmrg *                 other - pass non maskable events to this proceedure.
248444c061aSmrg *                 proc - proceedure to register.
249444c061aSmrg *                 closure - data to pass to the event hander.
250444c061aSmrg *                 position - where to add this event handler.
251444c061aSmrg *                 force_new_position - If the element is already in the
252444c061aSmrg *                                      list, this will force it to the
253444c061aSmrg *                                      beginning or end depending on position.
254444c061aSmrg *                 raw - If FALSE call XSelectInput for events in mask.
255444c061aSmrg *	Returns: none
256444c061aSmrg */
257444c061aSmrg
258444c061aSmrgstatic void
259444c061aSmrgAddEventHandler(
260444c061aSmrg    Widget widget,
261444c061aSmrg    XtPointer select_data,
262444c061aSmrg    int type,
263444c061aSmrg    Boolean         has_type_specifier,
264444c061aSmrg    Boolean         other,
265444c061aSmrg    XtEventHandler  proc,
266444c061aSmrg    XtPointer	closure,
267444c061aSmrg    XtListPosition  position,
268444c061aSmrg    Boolean         force_new_position,
269444c061aSmrg    Boolean         raw)
270444c061aSmrg{
271444c061aSmrg    register XtEventRec *p, **pp;
272444c061aSmrg    EventMask oldMask = 0, eventMask = 0;
273444c061aSmrg
274444c061aSmrg    if (!has_type_specifier) {
275444c061aSmrg	eventMask = *(EventMask*)select_data & ~NonMaskableMask;
276444c061aSmrg	if (other) eventMask |= NonMaskableMask;
277444c061aSmrg	if (!eventMask) return;
278444c061aSmrg    } else if (!type) return;
279444c061aSmrg
280444c061aSmrg    if (XtIsRealized(widget) && !raw) oldMask = XtBuildEventMask(widget);
281444c061aSmrg
282444c061aSmrg    if (raw) raw = 1;
283444c061aSmrg    pp = &widget->core.event_table;
284444c061aSmrg    while ((p = *pp) &&
285444c061aSmrg	   (p->proc != proc || p->closure != closure || p->select == raw ||
286444c061aSmrg	    has_type_specifier != p->has_type_specifier ||
287444c061aSmrg	    (has_type_specifier && EXT_TYPE(p) != type)))
288444c061aSmrg	pp = &p->next;
289444c061aSmrg
290444c061aSmrg    if (!p) {		                /* New proc to add to list */
291444c061aSmrg	if (has_type_specifier) {
292444c061aSmrg	    p = (XtEventRec*) __XtMalloc(sizeof(XtEventRec) +
293444c061aSmrg				       sizeof(XtEventRecExt));
294444c061aSmrg	    EXT_TYPE(p) = type;
295444c061aSmrg	    EXT_SELECT_DATA(p,0) = select_data;
296444c061aSmrg	    p->mask = 1;
297444c061aSmrg	    p->has_type_specifier = True;
298444c061aSmrg	} else {
299444c061aSmrg	    p = (XtEventRec*) __XtMalloc(sizeof(XtEventRec));
300444c061aSmrg	    p->mask = eventMask;
301444c061aSmrg	    p->has_type_specifier = False;
302444c061aSmrg	}
303444c061aSmrg	p->proc = proc;
304444c061aSmrg	p->closure = closure;
305444c061aSmrg	p->select = ! raw;
306444c061aSmrg
307444c061aSmrg	if (position == XtListHead) {
308444c061aSmrg	    p->next = widget->core.event_table;
309444c061aSmrg	    widget->core.event_table = p;
310444c061aSmrg	    pp = &widget->core.event_table;
311444c061aSmrg	} else {
312444c061aSmrg	    *pp = p;
313444c061aSmrg	    p->next = NULL;
314444c061aSmrg	}
315444c061aSmrg    }
316444c061aSmrg    else {
317444c061aSmrg	if (force_new_position) {
318444c061aSmrg	    *pp = p->next;
319444c061aSmrg
320444c061aSmrg	    if (position == XtListHead) {
321444c061aSmrg		p->next = widget->core.event_table;
322444c061aSmrg		widget->core.event_table = p;
323444c061aSmrg	    } else {
324444c061aSmrg	       	/*
325444c061aSmrg		 * Find the last element in the list.
326444c061aSmrg		 */
327444c061aSmrg		while (*pp)
328444c061aSmrg		    pp = &(*pp)->next;
329444c061aSmrg		*pp = p;
330444c061aSmrg		p->next = NULL;
331444c061aSmrg	    }
332444c061aSmrg	}
333444c061aSmrg
334444c061aSmrg	if (!has_type_specifier)
335444c061aSmrg	    p->mask |= eventMask;
336444c061aSmrg	else {
337444c061aSmrg	    Cardinal i;
338444c061aSmrg	    /* p->mask specifies count of EXT_SELECT_DATA(p,i) */
339444c061aSmrg	    for (i = 0; i < p->mask && select_data != EXT_SELECT_DATA(p,i); )
340444c061aSmrg		i++;
341444c061aSmrg	    if (i == p->mask) {
342444c061aSmrg		p = (XtEventRec*) XtRealloc((char*)p,
343444c061aSmrg					    sizeof(XtEventRec) +
344444c061aSmrg					    sizeof(XtEventRecExt) +
345444c061aSmrg					    p->mask * sizeof(XtPointer));
346444c061aSmrg		EXT_SELECT_DATA(p,i) = select_data;
347444c061aSmrg		p->mask++;
348444c061aSmrg		*pp = p;
349444c061aSmrg	    }
350444c061aSmrg	}
351444c061aSmrg    }
352444c061aSmrg
353444c061aSmrg    if (XtIsRealized(widget) && !raw) {
354444c061aSmrg	EventMask mask = XtBuildEventMask(widget);
355444c061aSmrg	Display* dpy = XtDisplay (widget);
356444c061aSmrg
357444c061aSmrg	if (oldMask != mask)
358444c061aSmrg	    XSelectInput(dpy, XtWindow(widget), mask);
359444c061aSmrg
360444c061aSmrg	if (has_type_specifier) {
361444c061aSmrg	    XtPerDisplay pd = _XtGetPerDisplay (dpy);
362444c061aSmrg	    int i;
363444c061aSmrg	    for (i = 0; i < pd->ext_select_count; i++) {
364444c061aSmrg		if (type >= pd->ext_select_list[i].min &&
365444c061aSmrg		    type <= pd->ext_select_list[i].max) {
366444c061aSmrg		    CallExtensionSelector(widget, pd->ext_select_list+i, FALSE);
367444c061aSmrg		    break;
368444c061aSmrg		}
369444c061aSmrg		if (type < pd->ext_select_list[i].min) break;
370444c061aSmrg	    }
371444c061aSmrg	}
372444c061aSmrg    }
373444c061aSmrg}
374444c061aSmrg
375444c061aSmrgvoid XtRemoveEventHandler(
376444c061aSmrg    Widget	    widget,
377444c061aSmrg    EventMask       eventMask,
378444c061aSmrg    _XtBoolean	    other,
379444c061aSmrg    XtEventHandler  proc,
380444c061aSmrg    XtPointer	    closure)
381444c061aSmrg{
382444c061aSmrg    WIDGET_TO_APPCON(widget);
383444c061aSmrg    LOCK_APP(app);
384444c061aSmrg    RemoveEventHandler(widget, (XtPointer) &eventMask, 0, FALSE,
385444c061aSmrg		       other, proc, closure, FALSE);
386444c061aSmrg    UNLOCK_APP(app);
387444c061aSmrg}
388444c061aSmrg
389444c061aSmrgvoid XtAddEventHandler(
390444c061aSmrg    Widget	    widget,
391444c061aSmrg    EventMask       eventMask,
392444c061aSmrg    _XtBoolean      other,
393444c061aSmrg    XtEventHandler  proc,
394444c061aSmrg    XtPointer	    closure)
395444c061aSmrg{
396444c061aSmrg    WIDGET_TO_APPCON(widget);
397444c061aSmrg    LOCK_APP(app);
398444c061aSmrg    AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
399444c061aSmrg		    proc, closure, XtListTail, FALSE, FALSE);
400444c061aSmrg    UNLOCK_APP(app);
401444c061aSmrg}
402444c061aSmrg
403444c061aSmrgvoid XtInsertEventHandler(
404444c061aSmrg    Widget	    widget,
405444c061aSmrg    EventMask       eventMask,
406444c061aSmrg    _XtBoolean      other,
407444c061aSmrg    XtEventHandler  proc,
408444c061aSmrg    XtPointer	    closure,
409444c061aSmrg    XtListPosition  position)
410444c061aSmrg{
411444c061aSmrg    WIDGET_TO_APPCON(widget);
412444c061aSmrg    LOCK_APP(app);
413444c061aSmrg    AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
414444c061aSmrg		    proc, closure, position, TRUE, FALSE);
415444c061aSmrg    UNLOCK_APP(app);
416444c061aSmrg}
417444c061aSmrg
418444c061aSmrgvoid XtRemoveRawEventHandler(
419444c061aSmrg    Widget	    widget,
420444c061aSmrg    EventMask       eventMask,
421444c061aSmrg    _XtBoolean	    other,
422444c061aSmrg    XtEventHandler  proc,
423444c061aSmrg    XtPointer	    closure)
424444c061aSmrg{
425444c061aSmrg    WIDGET_TO_APPCON(widget);
426444c061aSmrg    LOCK_APP(app);
427444c061aSmrg    RemoveEventHandler(widget, (XtPointer) &eventMask, 0, FALSE,
428444c061aSmrg		       other, proc, closure, TRUE);
429444c061aSmrg    UNLOCK_APP(app);
430444c061aSmrg}
431444c061aSmrg
432444c061aSmrgvoid XtInsertRawEventHandler(
433444c061aSmrg    Widget	    widget,
434444c061aSmrg    EventMask       eventMask,
435444c061aSmrg    _XtBoolean	    other,
436444c061aSmrg    XtEventHandler  proc,
437444c061aSmrg    XtPointer	    closure,
438444c061aSmrg    XtListPosition  position)
439444c061aSmrg{
440444c061aSmrg    WIDGET_TO_APPCON(widget);
441444c061aSmrg    LOCK_APP(app);
442444c061aSmrg    AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
443444c061aSmrg		    proc, closure, position, TRUE, TRUE);
444444c061aSmrg    UNLOCK_APP(app);
445444c061aSmrg}
446444c061aSmrg
447444c061aSmrgvoid XtAddRawEventHandler(
448444c061aSmrg    Widget	    widget,
449444c061aSmrg    EventMask       eventMask,
450444c061aSmrg    _XtBoolean      other,
451444c061aSmrg    XtEventHandler  proc,
452444c061aSmrg    XtPointer	    closure)
453444c061aSmrg{
454444c061aSmrg    WIDGET_TO_APPCON(widget);
455444c061aSmrg    LOCK_APP(app);
456444c061aSmrg    AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
457444c061aSmrg		    proc, closure, XtListTail, FALSE, TRUE);
458444c061aSmrg    UNLOCK_APP(app);
459444c061aSmrg}
460444c061aSmrg
461444c061aSmrgvoid XtRemoveEventTypeHandler(
462444c061aSmrg    Widget	    widget,
463444c061aSmrg    int		    type,
464444c061aSmrg    XtPointer	    select_data,
465444c061aSmrg    XtEventHandler  proc,
466444c061aSmrg    XtPointer	    closure)
467444c061aSmrg{
468444c061aSmrg    WIDGET_TO_APPCON(widget);
469444c061aSmrg    LOCK_APP(app);
470444c061aSmrg    RemoveEventHandler(widget, select_data, type, TRUE,
471444c061aSmrg		       FALSE, proc, closure, FALSE);
472444c061aSmrg    UNLOCK_APP(app);
473444c061aSmrg}
474444c061aSmrg
475444c061aSmrgvoid XtInsertEventTypeHandler(
476444c061aSmrg    Widget	    widget,
477444c061aSmrg    int		    type,
478444c061aSmrg    XtPointer	    select_data,
479444c061aSmrg    XtEventHandler  proc,
480444c061aSmrg    XtPointer	    closure,
481444c061aSmrg    XtListPosition  position)
482444c061aSmrg{
483444c061aSmrg    WIDGET_TO_APPCON(widget);
484444c061aSmrg    LOCK_APP(app);
485444c061aSmrg    AddEventHandler(widget, select_data, type, TRUE, FALSE,
486444c061aSmrg		    proc, closure, position, TRUE, FALSE);
487444c061aSmrg    UNLOCK_APP(app);
488444c061aSmrg}
489444c061aSmrg
490444c061aSmrgtypedef struct _WWPair {
491444c061aSmrg    struct _WWPair *next;
492444c061aSmrg    Window window;
493444c061aSmrg    Widget widget;
494444c061aSmrg} *WWPair;
495444c061aSmrg
496444c061aSmrgtypedef struct _WWTable {
497444c061aSmrg    unsigned int mask;		/* size of hash table - 1 */
498444c061aSmrg    unsigned int rehash;	/* mask - 2 */
499444c061aSmrg    unsigned int occupied;	/* number of occupied entries */
500444c061aSmrg    unsigned int fakes;		/* number occupied by WWfake */
501444c061aSmrg    Widget *entries;		/* the entries */
502444c061aSmrg    WWPair pairs;		/* bogus entries */
503444c061aSmrg} *WWTable;
504444c061aSmrg
505444c061aSmrgstatic const WidgetRec WWfake;	/* placeholder for deletions */
506444c061aSmrg
507444c061aSmrg#define WWHASH(tab,win) ((win) & tab->mask)
508444c061aSmrg#define WWREHASHVAL(tab,win) ((((win) % tab->rehash) + 2) | 1)
509444c061aSmrg#define WWREHASH(tab,idx,rehash) ((idx + rehash) & tab->mask)
510444c061aSmrg#define WWTABLE(display) (_XtGetPerDisplay(display)->WWtable)
511444c061aSmrg
512444c061aSmrgstatic void ExpandWWTable(WWTable);
513444c061aSmrg
514444c061aSmrgvoid XtRegisterDrawable(
515444c061aSmrg    Display* display,
516444c061aSmrg    Drawable drawable,
517444c061aSmrg    Widget widget)
518444c061aSmrg{
519444c061aSmrg    WWTable tab;
520444c061aSmrg    int idx, rehash;
521444c061aSmrg    Widget entry;
522444c061aSmrg    Window window = (Window) drawable;
523444c061aSmrg    WIDGET_TO_APPCON(widget);
524444c061aSmrg
525444c061aSmrg    LOCK_APP(app);
526444c061aSmrg    LOCK_PROCESS;
527444c061aSmrg    tab = WWTABLE(display);
528444c061aSmrg    if (window != XtWindow(widget)) {
529444c061aSmrg	WWPair pair;
530444c061aSmrg	pair = XtNew(struct _WWPair);
531444c061aSmrg	pair->next = tab->pairs;
532444c061aSmrg	pair->window = window;
533444c061aSmrg	pair->widget = widget;
534444c061aSmrg	tab->pairs = pair;
535444c061aSmrg	UNLOCK_PROCESS;
536444c061aSmrg	UNLOCK_APP(app);
537444c061aSmrg	return;
538444c061aSmrg    }
539444c061aSmrg    if ((tab->occupied + (tab->occupied >> 2)) > tab->mask)
540444c061aSmrg	ExpandWWTable(tab);
541444c061aSmrg
542444c061aSmrg    idx = WWHASH(tab, window);
543444c061aSmrg    if ((entry = tab->entries[idx]) && entry != &WWfake) {
544444c061aSmrg	rehash = WWREHASHVAL(tab, window);
545444c061aSmrg	do {
546444c061aSmrg	    idx = WWREHASH(tab, idx, rehash);
547444c061aSmrg	} while ((entry = tab->entries[idx]) && entry != &WWfake);
548444c061aSmrg    }
549444c061aSmrg    if (!entry)
550444c061aSmrg	tab->occupied++;
551444c061aSmrg    else if (entry == &WWfake)
552444c061aSmrg	tab->fakes--;
553444c061aSmrg    tab->entries[idx] = widget;
554444c061aSmrg    UNLOCK_PROCESS;
555444c061aSmrg    UNLOCK_APP(app);
556444c061aSmrg}
557444c061aSmrg
558444c061aSmrgvoid XtUnregisterDrawable(
559444c061aSmrg    Display* display,
560444c061aSmrg    Drawable drawable)
561444c061aSmrg{
562444c061aSmrg    WWTable tab;
563444c061aSmrg    int idx, rehash;
564444c061aSmrg    Widget entry;
565444c061aSmrg    Window window = (Window) drawable;
566444c061aSmrg    Widget widget = XtWindowToWidget (display, window);
567444c061aSmrg    DPY_TO_APPCON(display);
568444c061aSmrg
569444c061aSmrg    if (widget == NULL) return;
570444c061aSmrg
571444c061aSmrg    LOCK_APP(app);
572444c061aSmrg    LOCK_PROCESS;
573444c061aSmrg    tab = WWTABLE(display);
574444c061aSmrg    if (window != XtWindow(widget)) {
575444c061aSmrg	WWPair *prev, pair;
576444c061aSmrg
577444c061aSmrg	prev = &tab->pairs;
578444c061aSmrg	while ((pair = *prev) && pair->window != window)
579444c061aSmrg	    prev = &pair->next;
580444c061aSmrg	if (pair) {
581444c061aSmrg	    *prev = pair->next;
582444c061aSmrg	    XtFree((char *)pair);
583444c061aSmrg	}
584444c061aSmrg	UNLOCK_PROCESS;
585444c061aSmrg	UNLOCK_APP(app);
586444c061aSmrg	return;
587444c061aSmrg    }
588444c061aSmrg    idx = WWHASH(tab, window);
589444c061aSmrg    if ((entry = tab->entries[idx])) {
590444c061aSmrg	if (entry != widget) {
591444c061aSmrg	    rehash = WWREHASHVAL(tab, window);
592444c061aSmrg	    do {
593444c061aSmrg		idx = WWREHASH(tab, idx, rehash);
594444c061aSmrg		if (!(entry = tab->entries[idx])) {
595444c061aSmrg		    UNLOCK_PROCESS;
596444c061aSmrg		    UNLOCK_APP(app);
597444c061aSmrg		    return;
598444c061aSmrg		}
599444c061aSmrg	    } while (entry != widget);
600444c061aSmrg	}
601444c061aSmrg	tab->entries[idx] = (Widget)&WWfake;
602444c061aSmrg	tab->fakes++;
603444c061aSmrg    }
604444c061aSmrg    UNLOCK_PROCESS;
605444c061aSmrg    UNLOCK_APP(app);
606444c061aSmrg}
607444c061aSmrg
608444c061aSmrgstatic void ExpandWWTable(
609444c061aSmrg    register WWTable tab)
610444c061aSmrg{
611444c061aSmrg    unsigned int oldmask;
612444c061aSmrg    register Widget *oldentries, *entries;
613444c061aSmrg    register Cardinal oldidx, newidx, rehash;
614444c061aSmrg    register Widget entry;
615444c061aSmrg
616444c061aSmrg    LOCK_PROCESS;
617444c061aSmrg    oldmask = tab->mask;
618444c061aSmrg    oldentries = tab->entries;
619444c061aSmrg    tab->occupied -= tab->fakes;
620444c061aSmrg    tab->fakes = 0;
621444c061aSmrg    if ((tab->occupied + (tab->occupied >> 2)) > tab->mask) {
622444c061aSmrg	tab->mask = (tab->mask << 1) + 1;
623444c061aSmrg	tab->rehash = tab->mask - 2;
624444c061aSmrg    }
625444c061aSmrg    entries = tab->entries = (Widget *) __XtCalloc(tab->mask+1, sizeof(Widget));
626444c061aSmrg    for (oldidx = 0; oldidx <= oldmask; oldidx++) {
627444c061aSmrg	if ((entry = oldentries[oldidx]) && entry != &WWfake) {
628444c061aSmrg	    newidx = WWHASH(tab, XtWindow(entry));
629444c061aSmrg	    if (entries[newidx]) {
630444c061aSmrg		rehash = WWREHASHVAL(tab, XtWindow(entry));
631444c061aSmrg		do {
632444c061aSmrg		    newidx = WWREHASH(tab, newidx, rehash);
633444c061aSmrg		} while (entries[newidx]);
634444c061aSmrg	    }
635444c061aSmrg	    entries[newidx] = entry;
636444c061aSmrg	}
637444c061aSmrg    }
638444c061aSmrg    XtFree((char *)oldentries);
639444c061aSmrg    UNLOCK_PROCESS;
640444c061aSmrg}
641444c061aSmrg
642444c061aSmrgWidget XtWindowToWidget(
643444c061aSmrg    register Display *display,
644444c061aSmrg    register Window window)
645444c061aSmrg{
646444c061aSmrg    register WWTable tab;
647444c061aSmrg    register int idx, rehash;
648444c061aSmrg    register Widget entry;
649444c061aSmrg    WWPair pair;
650444c061aSmrg    DPY_TO_APPCON(display);
651444c061aSmrg
652444c061aSmrg    if (!window) return NULL;
653444c061aSmrg
654444c061aSmrg    LOCK_APP(app);
655444c061aSmrg    LOCK_PROCESS;
656444c061aSmrg    tab = WWTABLE(display);
657444c061aSmrg    idx = WWHASH(tab, window);
658444c061aSmrg    if ((entry = tab->entries[idx]) && XtWindow(entry) != window) {
659444c061aSmrg	rehash = WWREHASHVAL(tab, window);
660444c061aSmrg	do {
661444c061aSmrg	    idx = WWREHASH(tab, idx, rehash);
662444c061aSmrg	} while ((entry = tab->entries[idx]) && XtWindow(entry) != window);
663444c061aSmrg    }
664444c061aSmrg    if (entry) {
665444c061aSmrg    	UNLOCK_PROCESS;
666444c061aSmrg    	UNLOCK_APP(app);
667444c061aSmrg	return entry;
668444c061aSmrg    }
669444c061aSmrg    for (pair = tab->pairs; pair; pair = pair->next) {
670444c061aSmrg	if (pair->window == window) {
671444c061aSmrg	    entry = pair->widget;
672444c061aSmrg	    UNLOCK_PROCESS;
673444c061aSmrg    	    UNLOCK_APP(app);
674444c061aSmrg	    return entry;
675444c061aSmrg	}
676444c061aSmrg    }
677444c061aSmrg    UNLOCK_PROCESS;
678444c061aSmrg    UNLOCK_APP(app);
679444c061aSmrg    return NULL;
680444c061aSmrg}
681444c061aSmrg
682444c061aSmrgvoid _XtAllocWWTable(
683444c061aSmrg    XtPerDisplay pd)
684444c061aSmrg{
685444c061aSmrg    register WWTable tab;
686444c061aSmrg
687444c061aSmrg    tab = (WWTable) __XtMalloc(sizeof(struct _WWTable));
688444c061aSmrg    tab->mask = 0x7f;
689444c061aSmrg    tab->rehash = tab->mask - 2;
690444c061aSmrg    tab->entries = (Widget *) __XtCalloc(tab->mask+1, sizeof(Widget));
691444c061aSmrg    tab->occupied = 0;
692444c061aSmrg    tab->fakes = 0;
693444c061aSmrg    tab->pairs = NULL;
694444c061aSmrg    pd->WWtable = tab;
695444c061aSmrg}
696444c061aSmrg
697444c061aSmrgvoid _XtFreeWWTable(
698444c061aSmrg    register XtPerDisplay pd)
699444c061aSmrg{
700444c061aSmrg    register WWPair pair, next;
701444c061aSmrg
702444c061aSmrg    for (pair = pd->WWtable->pairs; pair; pair = next) {
703444c061aSmrg	next = pair->next;
704444c061aSmrg	XtFree((char *)pair);
705444c061aSmrg    }
706444c061aSmrg    XtFree((char *)pd->WWtable->entries);
707444c061aSmrg    XtFree((char *)pd->WWtable);
708444c061aSmrg}
709444c061aSmrg
710444c061aSmrg#define EHMAXSIZE 25 /* do not make whopping big */
711444c061aSmrg
712444c061aSmrgstatic Boolean CallEventHandlers(
713444c061aSmrg    Widget     widget,
714444c061aSmrg    XEvent    *event,
715444c061aSmrg    EventMask  mask)
716444c061aSmrg{
717444c061aSmrg    register XtEventRec *p;
718444c061aSmrg    XtEventHandler *proc;
719444c061aSmrg    XtPointer *closure;
720444c061aSmrg    XtEventHandler procs[EHMAXSIZE];
721444c061aSmrg    XtPointer closures[EHMAXSIZE];
722444c061aSmrg    Boolean cont_to_disp = True;
723444c061aSmrg    int i, numprocs;
724444c061aSmrg
725444c061aSmrg    /* Have to copy the procs into an array, because one of them might
726444c061aSmrg     * call XtRemoveEventHandler, which would break our linked list. */
727444c061aSmrg
728444c061aSmrg    numprocs = 0;
729444c061aSmrg    for (p=widget->core.event_table; p; p = p->next) {
730444c061aSmrg	if ((!p->has_type_specifier && (mask & p->mask)) ||
731444c061aSmrg	    (p->has_type_specifier && event->type == EXT_TYPE(p)))
732444c061aSmrg	    numprocs++;
733444c061aSmrg    }
734444c061aSmrg    if (numprocs > EHMAXSIZE) {
735444c061aSmrg	proc = (XtEventHandler *)__XtMalloc(numprocs * (sizeof(XtEventHandler) +
736444c061aSmrg						      sizeof(XtPointer)));
737444c061aSmrg	closure = (XtPointer *)(proc + numprocs);
738444c061aSmrg    } else {
739444c061aSmrg	proc = procs;
740444c061aSmrg	closure = closures;
741444c061aSmrg    }
742444c061aSmrg    numprocs = 0;
743444c061aSmrg    for (p=widget->core.event_table; p; p = p->next) {
744444c061aSmrg	if ((!p->has_type_specifier && (mask & p->mask)) ||
745444c061aSmrg	    (p->has_type_specifier && event->type == EXT_TYPE(p))) {
746444c061aSmrg	    proc[numprocs] = p->proc;
747444c061aSmrg	    closure[numprocs] = p->closure;
748444c061aSmrg	    numprocs++;
749444c061aSmrg	}
750444c061aSmrg    }
751444c061aSmrg/* FUNCTIONS CALLED THROUGH POINTER proc:
752444c061aSmrg		Selection.c:ReqCleanup,
753444c061aSmrg		"Shell.c":EventHandler,
754444c061aSmrg		PassivGrab.c:ActiveHandler,
755444c061aSmrg		PassivGrab.c:RealizeHandler,
756444c061aSmrg		Keyboard.c:QueryEventMask,
757444c061aSmrg		_XtHandleFocus,
758444c061aSmrg		Selection.c:HandleSelectionReplies,
759444c061aSmrg		Selection.c:HandleGetIncrement,
760444c061aSmrg		Selection.c:HandleIncremental,
761444c061aSmrg		Selection.c:HandlePropertyGone,
762444c061aSmrg		Selection.c:HandleSelectionEvents
763444c061aSmrg		*/
764444c061aSmrg    for (i = 0; i < numprocs && cont_to_disp; i++)
765444c061aSmrg	(*(proc[i]))(widget, closure[i], event, &cont_to_disp);
766444c061aSmrg    if (numprocs > EHMAXSIZE)
767444c061aSmrg	XtFree((char *)proc);
768444c061aSmrg    return cont_to_disp;
769444c061aSmrg}
770444c061aSmrg
771444c061aSmrgstatic void CompressExposures(XEvent *, Widget);
772444c061aSmrg
773444c061aSmrg#define KnownButtons (Button1MotionMask|Button2MotionMask|Button3MotionMask|\
774444c061aSmrg		      Button4MotionMask|Button5MotionMask)
775444c061aSmrg
776444c061aSmrg/* keep this SMALL to avoid blowing stack cache! */
777444c061aSmrg/* because some compilers allocate all local locals on procedure entry */
778444c061aSmrg#define EHSIZE 4
779444c061aSmrg
780444c061aSmrgBoolean XtDispatchEventToWidget(
781444c061aSmrg    Widget widget,
782444c061aSmrg    XEvent* event)
783444c061aSmrg{
784444c061aSmrg    register XtEventRec *p;
785444c061aSmrg    Boolean was_dispatched = False;
786444c061aSmrg    Boolean call_tm = False;
787444c061aSmrg    Boolean cont_to_disp;
788444c061aSmrg    EventMask mask;
789444c061aSmrg    WIDGET_TO_APPCON(widget);
790444c061aSmrg
791444c061aSmrg    LOCK_APP(app);
792444c061aSmrg
793444c061aSmrg    mask = _XtConvertTypeToMask(event->type);
794444c061aSmrg    if (event->type == MotionNotify)
795444c061aSmrg	mask |= (event->xmotion.state & KnownButtons);
796444c061aSmrg
797444c061aSmrg    LOCK_PROCESS;
798444c061aSmrg    if ( (mask == ExposureMask) ||
799444c061aSmrg	 ((event->type == NoExpose) && NO_EXPOSE) ||
800444c061aSmrg	 ((event->type == GraphicsExpose) && GRAPHICS_EXPOSE) ) {
801444c061aSmrg
802444c061aSmrg	if (widget->core.widget_class->core_class.expose != NULL ) {
803444c061aSmrg
804444c061aSmrg	    /* We need to mask off the bits that could contain the information
805444c061aSmrg	     * about whether or not we desire Graphics and NoExpose events.  */
806444c061aSmrg
807444c061aSmrg	    if ( (COMP_EXPOSE_TYPE == XtExposeNoCompress) ||
808444c061aSmrg		 (event->type == NoExpose) )
809444c061aSmrg
810444c061aSmrg		(*widget->core.widget_class->core_class.expose)
811444c061aSmrg		    (widget, event, (Region)NULL);
812444c061aSmrg	    else {
813444c061aSmrg		CompressExposures(event, widget);
814444c061aSmrg	    }
815444c061aSmrg	    was_dispatched = True;
816444c061aSmrg	}
817444c061aSmrg    }
818444c061aSmrg
819444c061aSmrg    if ((mask == VisibilityChangeMask) &&
820444c061aSmrg        XtClass(widget)->core_class.visible_interest) {
821444c061aSmrg	    was_dispatched = True;
822444c061aSmrg	    /* our visibility just changed... */
823444c061aSmrg	    switch (((XVisibilityEvent *)event)->state) {
824444c061aSmrg		case VisibilityUnobscured:
825444c061aSmrg		    widget->core.visible = TRUE;
826444c061aSmrg		    break;
827444c061aSmrg
828444c061aSmrg		case VisibilityPartiallyObscured:
829444c061aSmrg		    /* what do we want to say here? */
830444c061aSmrg		    /* well... some of us is visible */
831444c061aSmrg		    widget->core.visible = TRUE;
832444c061aSmrg		    break;
833444c061aSmrg
834444c061aSmrg		case VisibilityFullyObscured:
835444c061aSmrg		    widget->core.visible = FALSE;
836444c061aSmrg		    /* do we want to mark our children obscured? */
837444c061aSmrg		    break;
838444c061aSmrg	    }
839444c061aSmrg	}
840444c061aSmrg    UNLOCK_PROCESS;
841444c061aSmrg
842444c061aSmrg    /* to maintain "copy" semantics we check TM now but call later */
843444c061aSmrg    if (widget->core.tm.translations &&
844444c061aSmrg	(mask & widget->core.tm.translations->eventMask))
845444c061aSmrg	call_tm = True;
846444c061aSmrg
847444c061aSmrg    cont_to_disp = True;
848444c061aSmrg    p=widget->core.event_table;
849444c061aSmrg    if (p) {
850444c061aSmrg	if (p->next) {
851444c061aSmrg	    XtEventHandler proc[EHSIZE];
852444c061aSmrg	    XtPointer closure[EHSIZE];
853444c061aSmrg	    int numprocs = 0;
854444c061aSmrg
855444c061aSmrg	    /* Have to copy the procs into an array, because one of them might
856444c061aSmrg	     * call XtRemoveEventHandler, which would break our linked list. */
857444c061aSmrg
858444c061aSmrg	    for (; p; p = p->next) {
859444c061aSmrg		if ((!p->has_type_specifier && (mask & p->mask)) ||
860444c061aSmrg		    (p->has_type_specifier && event->type == EXT_TYPE(p))) {
861444c061aSmrg		    if (numprocs >= EHSIZE)
862444c061aSmrg			break;
863444c061aSmrg		    proc[numprocs] = p->proc;
864444c061aSmrg		    closure[numprocs] = p->closure;
865444c061aSmrg		    numprocs++;
866444c061aSmrg		}
867444c061aSmrg	    }
868444c061aSmrg	    if (numprocs) {
869444c061aSmrg		if (p) {
870444c061aSmrg		    cont_to_disp = CallEventHandlers(widget, event, mask);
871444c061aSmrg		} else {
872444c061aSmrg		    int i;
873444c061aSmrg		    for (i = 0; i < numprocs && cont_to_disp; i++)
874444c061aSmrg			(*(proc[i]))(widget, closure[i], event, &cont_to_disp);
875444c061aSmrg/* FUNCTIONS CALLED THROUGH POINTER proc:
876444c061aSmrg		Selection.c:ReqCleanup,
877444c061aSmrg		"Shell.c":EventHandler,
878444c061aSmrg		PassivGrab.c:ActiveHandler,
879444c061aSmrg		PassivGrab.c:RealizeHandler,
880444c061aSmrg		Keyboard.c:QueryEventMask,
881444c061aSmrg		_XtHandleFocus,
882444c061aSmrg		Selection.c:HandleSelectionReplies,
883444c061aSmrg		Selection.c:HandleGetIncrement,
884444c061aSmrg		Selection.c:HandleIncremental,
885444c061aSmrg		Selection.c:HandlePropertyGone,
886444c061aSmrg		Selection.c:HandleSelectionEvents
887444c061aSmrg		*/
888444c061aSmrg		}
889444c061aSmrg		was_dispatched = True;
890444c061aSmrg	    }
891444c061aSmrg	} else if ((!p->has_type_specifier && (mask & p->mask)) ||
892444c061aSmrg		   (p->has_type_specifier && event->type == EXT_TYPE(p))) {
893444c061aSmrg	    (*p->proc)(widget, p->closure, event, &cont_to_disp);
894444c061aSmrg	    was_dispatched = True;
895444c061aSmrg	}
896444c061aSmrg    }
897444c061aSmrg    if (call_tm && cont_to_disp)
898444c061aSmrg	_XtTranslateEvent(widget, event);
899444c061aSmrg    UNLOCK_APP(app);
900444c061aSmrg    return (was_dispatched|call_tm);
901444c061aSmrg}
902444c061aSmrg
903444c061aSmrg/*
904444c061aSmrg * This structure is passed into the check exposure proc.
905444c061aSmrg */
906444c061aSmrg
907444c061aSmrgtypedef struct _CheckExposeInfo {
908444c061aSmrg    int type1, type2;		/* Types of events to check for. */
909444c061aSmrg    Boolean maximal;		/* Ignore non-exposure events? */
910444c061aSmrg    Boolean non_matching;	/* Was there an event that did not
911444c061aSmrg				   match either type? */
912444c061aSmrg    Window window;		/* Window to match. */
913444c061aSmrg} CheckExposeInfo;
914444c061aSmrg
915444c061aSmrg#define GetCount(ev) (((XExposeEvent *)(ev))->count)
916444c061aSmrg
917444c061aSmrgstatic void SendExposureEvent(XEvent *, Widget, XtPerDisplay);
918444c061aSmrgstatic Bool CheckExposureEvent(Display *, XEvent *, char *);
919444c061aSmrgstatic void AddExposureToRectangularRegion(XEvent *, Region);
920444c061aSmrg
921444c061aSmrg/*	Function Name: CompressExposures
922444c061aSmrg *	Description: Handles all exposure compression
923444c061aSmrg *	Arguments: event - the xevent that is to be dispatched
924444c061aSmrg *                 widget - the widget that this event occured in.
925444c061aSmrg *	Returns: none.
926444c061aSmrg *
927444c061aSmrg *      NOTE: Event must be of type Expose or GraphicsExpose.
928444c061aSmrg */
929444c061aSmrg
930444c061aSmrgstatic void
931444c061aSmrgCompressExposures(
932444c061aSmrgXEvent * event,
933444c061aSmrgWidget widget)
934444c061aSmrg{
935444c061aSmrg    CheckExposeInfo info;
936444c061aSmrg    int count;
937444c061aSmrg    Display* dpy = XtDisplay (widget);
938444c061aSmrg    XtPerDisplay pd = _XtGetPerDisplay(dpy);
939444c061aSmrg    XtEnum comp_expose;
940444c061aSmrg    XtEnum comp_expose_type;
941444c061aSmrg    Boolean no_region;
942444c061aSmrg
943444c061aSmrg    LOCK_PROCESS;
944444c061aSmrg    comp_expose = COMP_EXPOSE;
945444c061aSmrg    UNLOCK_PROCESS;
946444c061aSmrg    comp_expose_type = comp_expose & 0x0f;
947444c061aSmrg    no_region = ((comp_expose & XtExposeNoRegion) ? True : False);
948444c061aSmrg
949444c061aSmrg    if (no_region)
950444c061aSmrg	AddExposureToRectangularRegion(event, pd->region);
951444c061aSmrg    else
952444c061aSmrg	XtAddExposureToRegion(event, pd->region);
953444c061aSmrg
954444c061aSmrg    if ( GetCount(event) != 0 )
955444c061aSmrg 	return;
956444c061aSmrg
957444c061aSmrg    if ((comp_expose_type == XtExposeCompressSeries) ||
958444c061aSmrg	(XEventsQueued(dpy, QueuedAfterReading) == 0)) {
959444c061aSmrg	SendExposureEvent(event, widget, pd);
960444c061aSmrg	return;
961444c061aSmrg    }
962444c061aSmrg
963444c061aSmrg    if (comp_expose & XtExposeGraphicsExposeMerged) {
964444c061aSmrg	info.type1 = Expose;
965444c061aSmrg	info.type2 = GraphicsExpose;
966444c061aSmrg    }
967444c061aSmrg    else {
968444c061aSmrg	info.type1 = event->type;
969444c061aSmrg	info.type2 = 0;
970444c061aSmrg    }
971444c061aSmrg    info.maximal = (comp_expose_type == XtExposeCompressMaximal);
972444c061aSmrg    info.non_matching = FALSE;
973444c061aSmrg    info.window = XtWindow(widget);
974444c061aSmrg
975444c061aSmrg/*
976444c061aSmrg * We have to be very careful here not to hose down the processor
977444c061aSmrg * when blocking until count gets to zero.
978444c061aSmrg *
979444c061aSmrg * First, check to see if there are any events in the queue for this
980444c061aSmrg * widget, and of the correct type.
981444c061aSmrg *
982444c061aSmrg * Once we cannot find any more events, check to see that count is zero.
983444c061aSmrg * If it is not then block until we get another exposure event.
984444c061aSmrg *
985444c061aSmrg * If we find no more events, and count on the last one we saw was zero we
986444c061aSmrg * we can be sure that all events have been processed.
987444c061aSmrg *
988444c061aSmrg * Unfortunately, we wind up having to look at the entire queue
989444c061aSmrg * event if we're not doing Maximal compression, due to the
990444c061aSmrg * semantics of XCheckIfEvent (we can't abort without re-ordering
991444c061aSmrg * the event queue as a side-effect).
992444c061aSmrg */
993444c061aSmrg
994444c061aSmrg    count = 0;
995444c061aSmrg    while (TRUE) {
996444c061aSmrg	XEvent event_return;
997444c061aSmrg
998444c061aSmrg	if (XCheckIfEvent(dpy, &event_return,
999444c061aSmrg			  CheckExposureEvent, (char *) &info)) {
1000444c061aSmrg
1001444c061aSmrg	    count = GetCount(&event_return);
1002444c061aSmrg 	    if (no_region)
1003444c061aSmrg		AddExposureToRectangularRegion(&event_return, pd->region);
1004444c061aSmrg 	    else
1005444c061aSmrg		XtAddExposureToRegion(&event_return, pd->region);
1006444c061aSmrg	}
1007444c061aSmrg	else if (count != 0) {
1008444c061aSmrg	    XIfEvent(dpy, &event_return,
1009444c061aSmrg		     CheckExposureEvent, (char *) &info);
1010444c061aSmrg	    count = GetCount(&event_return);
1011444c061aSmrg 	    if (no_region)
1012444c061aSmrg		AddExposureToRectangularRegion(&event_return, pd->region);
1013444c061aSmrg 	    else
1014444c061aSmrg		XtAddExposureToRegion(&event_return, pd->region);
1015444c061aSmrg	}
1016444c061aSmrg	else /* count == 0 && XCheckIfEvent Failed. */
1017444c061aSmrg	    break;
1018444c061aSmrg    }
1019444c061aSmrg
1020444c061aSmrg    SendExposureEvent(event, widget, pd);
1021444c061aSmrg}
1022444c061aSmrg
1023444c061aSmrgvoid XtAddExposureToRegion(
1024444c061aSmrg    XEvent   *event,
1025444c061aSmrg    Region   region)
1026444c061aSmrg{
1027444c061aSmrg    XRectangle rect;
1028444c061aSmrg    XExposeEvent *ev = (XExposeEvent *) event;
1029444c061aSmrg    /* These Expose and GraphicsExpose fields are at identical offsets */
1030444c061aSmrg
1031444c061aSmrg    if (event->type == Expose || event->type == GraphicsExpose) {
1032444c061aSmrg	rect.x = ev->x;
1033444c061aSmrg	rect.y = ev->y;
1034444c061aSmrg	rect.width = ev->width;
1035444c061aSmrg	rect.height = ev->height;
1036444c061aSmrg	XUnionRectWithRegion(&rect, region, region);
1037444c061aSmrg    }
1038444c061aSmrg}
1039444c061aSmrg
1040444c061aSmrg#ifndef MAX
1041444c061aSmrg#define MAX(a,b) (((a) > (b)) ? (a) : (b))
1042444c061aSmrg#endif
1043444c061aSmrg
1044444c061aSmrg#ifndef MIN
1045444c061aSmrg#define MIN(a,b) (((a) < (b)) ? (a) : (b))
1046444c061aSmrg#endif
1047444c061aSmrg
1048444c061aSmrgstatic void AddExposureToRectangularRegion(
1049444c061aSmrg     XEvent *event, /* when called internally, type is always appropriate */
1050444c061aSmrg     Region  region)
1051444c061aSmrg{
1052444c061aSmrg    XRectangle rect;
1053444c061aSmrg    XExposeEvent *ev = (XExposeEvent *) event;
1054444c061aSmrg    /* These Expose and GraphicsExpose fields are at identical offsets */
1055444c061aSmrg
1056444c061aSmrg    rect.x = ev->x;
1057444c061aSmrg    rect.y = ev->y;
1058444c061aSmrg    rect.width = ev->width;
1059444c061aSmrg    rect.height = ev->height;
1060444c061aSmrg
1061444c061aSmrg    if (XEmptyRegion(region)) {
1062444c061aSmrg	XUnionRectWithRegion(&rect, region, region);
1063444c061aSmrg    } else {
1064444c061aSmrg	XRectangle merged, bbox;
1065444c061aSmrg
1066444c061aSmrg	XClipBox(region, &bbox);
1067444c061aSmrg	merged.x = MIN(rect.x, bbox.x);
1068444c061aSmrg	merged.y = MIN(rect.y, bbox.y);
1069444c061aSmrg	merged.width = MAX(rect.x + rect.width,
1070444c061aSmrg			   bbox.x + bbox.width) - merged.x;
1071444c061aSmrg	merged.height = MAX(rect.y + rect.height,
1072444c061aSmrg			    bbox.y + bbox.height) - merged.y;
1073444c061aSmrg	XUnionRectWithRegion(&merged, region, region);
1074444c061aSmrg    }
1075444c061aSmrg}
1076444c061aSmrg
1077444c061aSmrgstatic Region nullRegion;
1078444c061aSmrg/* READ-ONLY VARIABLES: nullRegion */
1079444c061aSmrg
1080444c061aSmrgvoid _XtEventInitialize(void)
1081444c061aSmrg{
1082444c061aSmrg#ifndef __lock_lint
1083444c061aSmrg    nullRegion = XCreateRegion();
1084444c061aSmrg#endif
1085444c061aSmrg}
1086444c061aSmrg
1087444c061aSmrg/*	Function Name: SendExposureEvent
1088444c061aSmrg *	Description: Sets the x, y, width, and height of the event
1089444c061aSmrg *                   to be the clip box of Expose Region.
1090444c061aSmrg *	Arguments: event  - the X Event to mangle; Expose or GraphicsExpose.
1091444c061aSmrg *                 widget - the widget that this event occured in.
1092444c061aSmrg *                 pd     - the per display information for this widget.
1093444c061aSmrg *	Returns: none.
1094444c061aSmrg */
1095444c061aSmrg
1096444c061aSmrgstatic void
1097444c061aSmrgSendExposureEvent(
1098444c061aSmrgXEvent * event,
1099444c061aSmrgWidget widget,
1100444c061aSmrgXtPerDisplay pd)
1101444c061aSmrg{
1102444c061aSmrg    XtExposeProc expose;
1103444c061aSmrg    XRectangle rect;
1104444c061aSmrg    XtEnum comp_expose;
1105444c061aSmrg    XExposeEvent *ev = (XExposeEvent *) event;
1106444c061aSmrg
1107444c061aSmrg    XClipBox(pd->region, &rect);
1108444c061aSmrg    ev->x = rect.x;
1109444c061aSmrg    ev->y = rect.y;
1110444c061aSmrg    ev->width = rect.width;
1111444c061aSmrg    ev->height = rect.height;
1112444c061aSmrg
1113444c061aSmrg    LOCK_PROCESS;
1114444c061aSmrg    comp_expose = COMP_EXPOSE;
1115444c061aSmrg    expose = widget->core.widget_class->core_class.expose;
1116444c061aSmrg    UNLOCK_PROCESS;
1117444c061aSmrg    if (comp_expose & XtExposeNoRegion)
1118444c061aSmrg	(*expose)(widget, event, NULL);
1119444c061aSmrg    else
1120444c061aSmrg	(*expose)(widget, event, pd->region);
1121444c061aSmrg    (void) XIntersectRegion(nullRegion, pd->region, pd->region);
1122444c061aSmrg}
1123444c061aSmrg
1124444c061aSmrg/*	Function Name: CheckExposureEvent
1125444c061aSmrg *	Description: Checks the event queue for an expose event
1126444c061aSmrg *	Arguments: display - the display connection.
1127444c061aSmrg *                 event - the event to check.
1128444c061aSmrg *                 arg - a pointer to the exposure info structure.
1129444c061aSmrg *	Returns: TRUE if we found an event of the correct type
1130444c061aSmrg *               with the right window.
1131444c061aSmrg *
1132444c061aSmrg * NOTE: The only valid types (info.type1 and info.type2) are Expose
1133444c061aSmrg *       and GraphicsExpose.
1134444c061aSmrg */
1135444c061aSmrg
1136444c061aSmrg/* ARGSUSED */
1137444c061aSmrgstatic Bool
1138444c061aSmrgCheckExposureEvent(
1139444c061aSmrgDisplay * disp,
1140444c061aSmrgXEvent * event,
1141444c061aSmrgchar * arg)
1142444c061aSmrg{
1143444c061aSmrg    CheckExposeInfo * info = ((CheckExposeInfo *) arg);
1144444c061aSmrg
1145444c061aSmrg    if ( (info->type1 == event->type) || (info->type2 == event->type)) {
1146444c061aSmrg	if (!info->maximal && info->non_matching) return FALSE;
1147444c061aSmrg	if (event->type == GraphicsExpose)
1148444c061aSmrg	    return(event->xgraphicsexpose.drawable == info->window);
1149444c061aSmrg	return(event->xexpose.window == info->window);
1150444c061aSmrg    }
1151444c061aSmrg    info->non_matching = TRUE;
1152444c061aSmrg    return(FALSE);
1153444c061aSmrg}
1154444c061aSmrg
1155444c061aSmrgstatic EventMask const masks[] = {
1156444c061aSmrg	0,			    /* Error, should never see  */
1157444c061aSmrg	0,			    /* Reply, should never see  */
1158444c061aSmrg	KeyPressMask,		    /* KeyPress			*/
1159444c061aSmrg	KeyReleaseMask,		    /* KeyRelease		*/
1160444c061aSmrg	ButtonPressMask,	    /* ButtonPress		*/
1161444c061aSmrg	ButtonReleaseMask,	    /* ButtonRelease		*/
1162444c061aSmrg	PointerMotionMask	    /* MotionNotify		*/
1163444c061aSmrg		| ButtonMotionMask,
1164444c061aSmrg	EnterWindowMask,	    /* EnterNotify		*/
1165444c061aSmrg	LeaveWindowMask,	    /* LeaveNotify		*/
1166444c061aSmrg	FocusChangeMask,	    /* FocusIn			*/
1167444c061aSmrg	FocusChangeMask,	    /* FocusOut			*/
1168444c061aSmrg	KeymapStateMask,	    /* KeymapNotify		*/
1169444c061aSmrg	ExposureMask,		    /* Expose			*/
1170444c061aSmrg	NonMaskableMask,	    /* GraphicsExpose, in GC    */
1171444c061aSmrg	NonMaskableMask,	    /* NoExpose, in GC		*/
1172444c061aSmrg	VisibilityChangeMask,       /* VisibilityNotify		*/
1173444c061aSmrg	SubstructureNotifyMask,     /* CreateNotify		*/
1174444c061aSmrg	StructureNotifyMask	    /* DestroyNotify		*/
1175444c061aSmrg		| SubstructureNotifyMask,
1176444c061aSmrg	StructureNotifyMask	    /* UnmapNotify		*/
1177444c061aSmrg		| SubstructureNotifyMask,
1178444c061aSmrg	StructureNotifyMask	    /* MapNotify		*/
1179444c061aSmrg		| SubstructureNotifyMask,
1180444c061aSmrg	SubstructureRedirectMask,   /* MapRequest		*/
1181444c061aSmrg	StructureNotifyMask	    /* ReparentNotify		*/
1182444c061aSmrg		| SubstructureNotifyMask,
1183444c061aSmrg	StructureNotifyMask	    /* ConfigureNotify		*/
1184444c061aSmrg		| SubstructureNotifyMask,
1185444c061aSmrg	SubstructureRedirectMask,   /* ConfigureRequest		*/
1186444c061aSmrg	StructureNotifyMask	    /* GravityNotify		*/
1187444c061aSmrg		| SubstructureNotifyMask,
1188444c061aSmrg	ResizeRedirectMask,	    /* ResizeRequest		*/
1189444c061aSmrg	StructureNotifyMask	    /* CirculateNotify		*/
1190444c061aSmrg		| SubstructureNotifyMask,
1191444c061aSmrg	SubstructureRedirectMask,   /* CirculateRequest		*/
1192444c061aSmrg	PropertyChangeMask,	    /* PropertyNotify		*/
1193444c061aSmrg	NonMaskableMask,	    /* SelectionClear		*/
1194444c061aSmrg	NonMaskableMask,	    /* SelectionRequest		*/
1195444c061aSmrg	NonMaskableMask,	    /* SelectionNotify		*/
1196444c061aSmrg	ColormapChangeMask,	    /* ColormapNotify		*/
1197444c061aSmrg	NonMaskableMask,	    /* ClientMessage		*/
1198444c061aSmrg	NonMaskableMask		    /* MappingNotify		*/
1199444c061aSmrg};
1200444c061aSmrg
1201444c061aSmrgEventMask _XtConvertTypeToMask (
1202444c061aSmrg    int		eventType)
1203444c061aSmrg{
1204444c061aSmrg    if ((Cardinal) eventType < XtNumber(masks))
1205444c061aSmrg	return masks[eventType];
1206444c061aSmrg    else
1207444c061aSmrg	return NoEventMask;
1208444c061aSmrg}
1209444c061aSmrg
1210444c061aSmrgBoolean _XtOnGrabList(
1211444c061aSmrg    register Widget widget,
1212444c061aSmrg    XtGrabRec  *grabList)
1213444c061aSmrg{
1214444c061aSmrg    register XtGrabRec* gl;
1215444c061aSmrg    for (; widget != NULL; widget = (Widget)widget->core.parent) {
1216444c061aSmrg	for (gl = grabList; gl != NULL; gl = gl->next) {
1217444c061aSmrg	    if (gl->widget == widget) return TRUE;
1218444c061aSmrg	    if (gl->exclusive) break;
1219444c061aSmrg	}
1220444c061aSmrg    }
1221444c061aSmrg    return FALSE;
1222444c061aSmrg}
1223444c061aSmrg
1224444c061aSmrgstatic Widget LookupSpringLoaded(
1225444c061aSmrg    XtGrabList	grabList)
1226444c061aSmrg{
1227444c061aSmrg    XtGrabList	gl;
1228444c061aSmrg
1229444c061aSmrg    for (gl = grabList; gl != NULL; gl = gl->next) {
1230444c061aSmrg	if (gl->spring_loaded) {
1231444c061aSmrg	  if (XtIsSensitive(gl->widget))
1232444c061aSmrg	    return gl->widget;
1233444c061aSmrg	  else
1234444c061aSmrg	    return NULL;
1235444c061aSmrg	}
1236444c061aSmrg	if (gl->exclusive) break;
1237444c061aSmrg    }
1238444c061aSmrg    return NULL;
1239444c061aSmrg}
1240444c061aSmrg
1241444c061aSmrgstatic Boolean DispatchEvent(
1242444c061aSmrg    XEvent* event,
1243444c061aSmrg    Widget widget)
1244444c061aSmrg{
1245444c061aSmrg
1246444c061aSmrg    if (event->type == EnterNotify &&
1247444c061aSmrg	event->xcrossing.mode == NotifyNormal &&
1248444c061aSmrg	widget->core.widget_class->core_class.compress_enterleave) {
1249444c061aSmrg	if (XPending(event->xcrossing.display)) {
1250444c061aSmrg	    XEvent nextEvent;
1251444c061aSmrg	    XPeekEvent(event->xcrossing.display, &nextEvent);
1252444c061aSmrg	    if (nextEvent.type == LeaveNotify &&
1253444c061aSmrg		event->xcrossing.window == nextEvent.xcrossing.window &&
1254444c061aSmrg		nextEvent.xcrossing.mode == NotifyNormal &&
1255444c061aSmrg		((event->xcrossing.detail != NotifyInferior &&
1256444c061aSmrg		 nextEvent.xcrossing.detail != NotifyInferior) ||
1257444c061aSmrg		 (event->xcrossing.detail == NotifyInferior &&
1258444c061aSmrg		 nextEvent.xcrossing.detail == NotifyInferior))) {
1259444c061aSmrg		/* skip the enter/leave pair */
1260444c061aSmrg		XNextEvent(event->xcrossing.display, &nextEvent);
1261444c061aSmrg		return False;
1262444c061aSmrg	    }
1263444c061aSmrg	}
1264444c061aSmrg    }
1265444c061aSmrg
1266444c061aSmrg    if (event->type == MotionNotify &&
1267444c061aSmrg	    widget->core.widget_class->core_class.compress_motion) {
1268444c061aSmrg	while (XPending(event->xmotion.display)) {
1269444c061aSmrg	    XEvent nextEvent;
1270444c061aSmrg	    XPeekEvent(event->xmotion.display, &nextEvent);
1271444c061aSmrg	    if (nextEvent.type == MotionNotify &&
1272444c061aSmrg		    event->xmotion.window == nextEvent.xmotion.window &&
1273444c061aSmrg		    event->xmotion.subwindow == nextEvent.xmotion.subwindow) {
1274444c061aSmrg		/* replace the current event with the next one */
1275444c061aSmrg		XNextEvent(event->xmotion.display, event);
1276444c061aSmrg	    } else break;
1277444c061aSmrg	}
1278444c061aSmrg    }
1279444c061aSmrg
1280444c061aSmrg    return XtDispatchEventToWidget(widget, event);
1281444c061aSmrg}
1282444c061aSmrg
1283444c061aSmrgtypedef enum _GrabType {pass, ignore, remap} GrabType;
1284444c061aSmrg
1285444c061aSmrg#if !defined(AIXV3) || !defined(AIXSHLIB)
1286444c061aSmrgstatic /* AIX shared libraries are broken */
1287444c061aSmrg#endif
1288444c061aSmrgBoolean _XtDefaultDispatcher(
1289444c061aSmrg    XEvent  *event)
1290444c061aSmrg{
1291444c061aSmrg    register    Widget widget;
1292444c061aSmrg    GrabType    grabType;
1293444c061aSmrg    XtPerDisplayInput pdi;
1294444c061aSmrg    XtGrabList  grabList;
1295444c061aSmrg    Boolean	was_dispatched = False;
1296444c061aSmrg    DPY_TO_APPCON(event->xany.display);
1297444c061aSmrg
1298444c061aSmrg    /* the default dispatcher discards all extension events */
1299444c061aSmrg    if (event->type >= LASTEvent)
1300444c061aSmrg	return False;
1301444c061aSmrg
1302444c061aSmrg    LOCK_APP(app);
1303444c061aSmrg
1304444c061aSmrg    switch (event->type) {
1305444c061aSmrg      case KeyPress:
1306444c061aSmrg      case KeyRelease:
1307444c061aSmrg      case ButtonPress:
1308444c061aSmrg      case ButtonRelease:	grabType = remap;	break;
1309444c061aSmrg      case MotionNotify:
1310444c061aSmrg      case EnterNotify:		grabType = ignore;	break;
1311444c061aSmrg      default:			grabType = pass;	break;
1312444c061aSmrg    }
1313444c061aSmrg
1314444c061aSmrg    widget = XtWindowToWidget (event->xany.display, event->xany.window);
1315444c061aSmrg    pdi = _XtGetPerDisplayInput(event->xany.display);
1316444c061aSmrg    grabList = *_XtGetGrabList(pdi);
1317444c061aSmrg
1318444c061aSmrg    if (widget == NULL) {
1319444c061aSmrg	if (grabType == remap
1320444c061aSmrg	    && (widget = LookupSpringLoaded(grabList)) != NULL) {
1321444c061aSmrg	    /* event occurred in a non-widget window, but we've promised also
1322444c061aSmrg	       to dispatch it to the nearest accessible spring_loaded widget */
1323444c061aSmrg	    was_dispatched = (XFilterEvent(event, XtWindow(widget))
1324444c061aSmrg			      || XtDispatchEventToWidget(widget, event));
1325444c061aSmrg	}
1326444c061aSmrg	else was_dispatched = XFilterEvent(event, None);
1327444c061aSmrg    }
1328444c061aSmrg    else if (grabType == pass) {
1329444c061aSmrg	if (event->type == LeaveNotify ||
1330444c061aSmrg	    event->type == FocusIn ||
1331444c061aSmrg	    event->type == FocusOut) {
1332444c061aSmrg		if (XtIsSensitive (widget))
1333444c061aSmrg		    was_dispatched = (XFilterEvent(event, XtWindow(widget)) ||
1334444c061aSmrg				      XtDispatchEventToWidget(widget, event));
1335444c061aSmrg	    } else was_dispatched = (XFilterEvent(event, XtWindow(widget)) ||
1336444c061aSmrg				     XtDispatchEventToWidget(widget, event));
1337444c061aSmrg    }
1338444c061aSmrg    else if (grabType == ignore) {
1339444c061aSmrg	if ((grabList == NULL || _XtOnGrabList(widget, grabList))
1340444c061aSmrg	    && XtIsSensitive(widget)) {
1341444c061aSmrg	    was_dispatched = (XFilterEvent(event, XtWindow(widget))
1342444c061aSmrg			      || DispatchEvent(event, widget));
1343444c061aSmrg	}
1344444c061aSmrg    }
1345444c061aSmrg    else if (grabType == remap) {
1346444c061aSmrg	EventMask	mask = _XtConvertTypeToMask(event->type);
1347444c061aSmrg	Widget		dspWidget;
1348444c061aSmrg	Boolean		was_filtered = False;
1349444c061aSmrg
1350444c061aSmrg	dspWidget = _XtFindRemapWidget(event, widget, mask, pdi);
1351444c061aSmrg
1352444c061aSmrg	if ((grabList == NULL ||_XtOnGrabList(dspWidget, grabList))
1353444c061aSmrg	    && XtIsSensitive(dspWidget)) {
1354444c061aSmrg	    if ((was_filtered = XFilterEvent(event, XtWindow(dspWidget)))) {
1355444c061aSmrg		/* If this event activated a device grab, release it. */
1356444c061aSmrg		_XtUngrabBadGrabs(event, widget, mask, pdi);
1357444c061aSmrg		was_dispatched = True;
1358444c061aSmrg	    } else
1359444c061aSmrg		was_dispatched = XtDispatchEventToWidget(dspWidget, event);
1360444c061aSmrg	}
1361444c061aSmrg	else _XtUngrabBadGrabs(event, widget, mask, pdi);
1362444c061aSmrg
1363444c061aSmrg	if (!was_filtered) {
1364444c061aSmrg	    /* Also dispatch to nearest accessible spring_loaded. */
1365444c061aSmrg	    /* Fetch this afterward to reflect modal list changes */
1366444c061aSmrg	    grabList = *_XtGetGrabList(pdi);
1367444c061aSmrg	    widget = LookupSpringLoaded(grabList);
1368444c061aSmrg	    if (widget != NULL && widget != dspWidget) {
1369444c061aSmrg		was_dispatched = (XFilterEvent(event, XtWindow(widget))
1370444c061aSmrg				  || XtDispatchEventToWidget(widget, event)
1371444c061aSmrg				  || was_dispatched);
1372444c061aSmrg	    }
1373444c061aSmrg	}
1374444c061aSmrg    }
1375444c061aSmrg    UNLOCK_APP(app);
1376444c061aSmrg    return was_dispatched;
1377444c061aSmrg}
1378444c061aSmrg
1379444c061aSmrgBoolean XtDispatchEvent (
1380444c061aSmrg    XEvent  *event)
1381444c061aSmrg{
1382444c061aSmrg    Boolean was_dispatched, safe;
1383444c061aSmrg    int dispatch_level;
1384444c061aSmrg    int starting_count;
1385444c061aSmrg    XtPerDisplay pd;
1386444c061aSmrg    Time	time = 0;
1387444c061aSmrg    XtEventDispatchProc dispatch = _XtDefaultDispatcher;
1388444c061aSmrg    XtAppContext app = XtDisplayToApplicationContext(event->xany.display);
1389444c061aSmrg
1390444c061aSmrg    LOCK_APP(app);
1391444c061aSmrg    dispatch_level = ++app->dispatch_level;
1392444c061aSmrg    starting_count = app->destroy_count;
1393444c061aSmrg
1394444c061aSmrg    switch (event->type) {
1395444c061aSmrg      case KeyPress:
1396444c061aSmrg      case KeyRelease:	   time = event->xkey.time;		break;
1397444c061aSmrg      case ButtonPress:
1398444c061aSmrg      case ButtonRelease:  time = event->xbutton.time;		break;
1399444c061aSmrg      case MotionNotify:   time = event->xmotion.time;		break;
1400444c061aSmrg      case EnterNotify:
1401444c061aSmrg      case LeaveNotify:	   time = event->xcrossing.time;	break;
1402444c061aSmrg      case PropertyNotify: time = event->xproperty.time;	break;
1403444c061aSmrg      case SelectionClear: time = event->xselectionclear.time;	break;
1404444c061aSmrg
1405444c061aSmrg      case MappingNotify:  _XtRefreshMapping(event, True);	break;
1406444c061aSmrg    }
1407444c061aSmrg    pd = _XtGetPerDisplay(event->xany.display);
1408444c061aSmrg    if (time) pd->last_timestamp = time;
1409444c061aSmrg    pd->last_event = *event;
1410444c061aSmrg
1411444c061aSmrg    if (pd->dispatcher_list) {
1412444c061aSmrg	dispatch = pd->dispatcher_list[event->type];
1413444c061aSmrg	if (dispatch == NULL) dispatch = _XtDefaultDispatcher;
1414444c061aSmrg    }
1415444c061aSmrg    was_dispatched = (*dispatch)(event);
1416444c061aSmrg
1417444c061aSmrg    /*
1418444c061aSmrg     * To make recursive XtDispatchEvent work, we need to do phase 2 destroys
1419444c061aSmrg     * only on those widgets destroyed by this particular dispatch.
1420444c061aSmrg     *
1421444c061aSmrg     */
1422444c061aSmrg
1423444c061aSmrg    if (app->destroy_count > starting_count)
1424444c061aSmrg	_XtDoPhase2Destroy(app, dispatch_level);
1425444c061aSmrg
1426444c061aSmrg    app->dispatch_level = dispatch_level - 1;
1427444c061aSmrg
1428444c061aSmrg    if ((safe = _XtSafeToDestroy(app))) {
1429444c061aSmrg	if (app->dpy_destroy_count != 0) _XtCloseDisplays(app);
1430444c061aSmrg	if (app->free_bindings) _XtDoFreeBindings(app);
1431444c061aSmrg    }
1432444c061aSmrg    UNLOCK_APP(app);
1433444c061aSmrg    LOCK_PROCESS;
1434444c061aSmrg    if (_XtAppDestroyCount != 0 && safe) _XtDestroyAppContexts();
1435444c061aSmrg    UNLOCK_PROCESS;
1436444c061aSmrg    return was_dispatched;
1437444c061aSmrg}
1438444c061aSmrg
1439444c061aSmrg/* ARGSUSED */
1440444c061aSmrgstatic void GrabDestroyCallback(
1441444c061aSmrg    Widget  widget,
1442444c061aSmrg    XtPointer closure,
1443444c061aSmrg    XtPointer call_data)
1444444c061aSmrg{
1445444c061aSmrg    /* Remove widget from grab list if it destroyed */
1446444c061aSmrg    XtRemoveGrab(widget);
1447444c061aSmrg}
1448444c061aSmrg
1449444c061aSmrgstatic XtGrabRec *NewGrabRec(
1450444c061aSmrg    Widget  widget,
1451444c061aSmrg    Boolean exclusive,
1452444c061aSmrg    Boolean spring_loaded)
1453444c061aSmrg{
1454444c061aSmrg    register XtGrabList    gl;
1455444c061aSmrg
1456444c061aSmrg    gl		      = XtNew(XtGrabRec);
1457444c061aSmrg    gl->next	      = NULL;
1458444c061aSmrg    gl->widget        = widget;
1459444c061aSmrg    gl->exclusive     = exclusive;
1460444c061aSmrg    gl->spring_loaded = spring_loaded;
1461444c061aSmrg
1462444c061aSmrg    return gl;
1463444c061aSmrg}
1464444c061aSmrg
1465444c061aSmrgvoid XtAddGrab(
1466444c061aSmrg    Widget  widget,
1467444c061aSmrg    _XtBoolean exclusive,
1468444c061aSmrg    _XtBoolean spring_loaded)
1469444c061aSmrg{
1470444c061aSmrg    register    XtGrabList gl;
1471444c061aSmrg    XtGrabList	*grabListPtr;
1472444c061aSmrg    XtAppContext app = XtWidgetToApplicationContext(widget);
1473444c061aSmrg
1474444c061aSmrg    LOCK_APP(app);
1475444c061aSmrg    LOCK_PROCESS;
1476444c061aSmrg    grabListPtr = _XtGetGrabList(_XtGetPerDisplayInput(XtDisplay(widget)));
1477444c061aSmrg
1478444c061aSmrg    if (spring_loaded && !exclusive) {
1479444c061aSmrg	XtAppWarningMsg(app,
1480444c061aSmrg		"grabError", "xtAddGrab", XtCXtToolkitError,
1481444c061aSmrg		"XtAddGrab requires exclusive grab if spring_loaded is TRUE",
1482444c061aSmrg		(String *) NULL, (Cardinal *) NULL);
1483444c061aSmrg	exclusive = TRUE;
1484444c061aSmrg    }
1485444c061aSmrg
1486444c061aSmrg    gl = NewGrabRec(widget, exclusive, spring_loaded);
1487444c061aSmrg    gl->next = *grabListPtr;
1488444c061aSmrg    *grabListPtr = gl;
1489444c061aSmrg
1490444c061aSmrg    XtAddCallback (widget, XtNdestroyCallback,
1491444c061aSmrg	    GrabDestroyCallback, (XtPointer) NULL);
1492444c061aSmrg    UNLOCK_PROCESS;
1493444c061aSmrg    UNLOCK_APP(app);
1494444c061aSmrg}
1495444c061aSmrg
1496444c061aSmrgvoid XtRemoveGrab(
1497444c061aSmrg    Widget  widget)
1498444c061aSmrg{
1499444c061aSmrg    register XtGrabList gl;
1500444c061aSmrg    register Boolean done;
1501444c061aSmrg    XtGrabList	*grabListPtr;
1502444c061aSmrg    XtAppContext app = XtWidgetToApplicationContext(widget);
1503444c061aSmrg
1504444c061aSmrg    LOCK_APP(app);
1505444c061aSmrg    LOCK_PROCESS;
1506444c061aSmrg
1507444c061aSmrg    grabListPtr = _XtGetGrabList(_XtGetPerDisplayInput(XtDisplay(widget)));
1508444c061aSmrg
1509444c061aSmrg    for (gl = *grabListPtr; gl != NULL; gl = gl->next) {
1510444c061aSmrg	if (gl->widget == widget) break;
1511444c061aSmrg    }
1512444c061aSmrg
1513444c061aSmrg    if (gl == NULL) {
1514444c061aSmrg	    XtAppWarningMsg(app,
1515444c061aSmrg		       "grabError","xtRemoveGrab",XtCXtToolkitError,
1516444c061aSmrg		       "XtRemoveGrab asked to remove a widget not on the list",
1517444c061aSmrg		       (String *)NULL, (Cardinal *)NULL);
1518444c061aSmrg	    UNLOCK_PROCESS;
1519444c061aSmrg    	    UNLOCK_APP(app);
1520444c061aSmrg	    return;
1521444c061aSmrg	}
1522444c061aSmrg
1523444c061aSmrg    do {
1524444c061aSmrg	gl = *grabListPtr;
1525444c061aSmrg	done = (gl->widget == widget);
1526444c061aSmrg	*grabListPtr = gl->next;
1527444c061aSmrg	XtRemoveCallback(gl->widget, XtNdestroyCallback,
1528444c061aSmrg		GrabDestroyCallback, (XtPointer)NULL);
1529444c061aSmrg	XtFree((char *)gl);
1530444c061aSmrg    } while (! done);
1531444c061aSmrg    UNLOCK_PROCESS;
1532444c061aSmrg    UNLOCK_APP(app);
1533444c061aSmrg    return;
1534444c061aSmrg}
1535444c061aSmrg
1536444c061aSmrgvoid XtMainLoop(void)
1537444c061aSmrg{
1538444c061aSmrg	XtAppMainLoop(_XtDefaultAppContext());
1539444c061aSmrg}
1540444c061aSmrg
1541444c061aSmrgvoid XtAppMainLoop(
1542444c061aSmrg	XtAppContext app)
1543444c061aSmrg{
1544444c061aSmrg    XEvent event;
1545444c061aSmrg
1546444c061aSmrg    LOCK_APP(app);
1547444c061aSmrg    do {
1548444c061aSmrg    	XtAppNextEvent(app, &event);
1549444c061aSmrg#ifdef XTHREADS
1550444c061aSmrg	/* assert(app == XtDisplayToApplicationContext(event.xany.display)); */
1551444c061aSmrg#endif
1552444c061aSmrg	XtDispatchEvent(&event);
1553444c061aSmrg    } while(app->exit_flag == FALSE);
1554444c061aSmrg    UNLOCK_APP(app);
1555444c061aSmrg}
1556444c061aSmrg
1557444c061aSmrgvoid _XtFreeEventTable(
1558444c061aSmrg    XtEventTable *event_table)
1559444c061aSmrg{
1560444c061aSmrg    register XtEventTable event;
1561444c061aSmrg
1562444c061aSmrg    event = *event_table;
1563444c061aSmrg    while (event != NULL) {
1564444c061aSmrg	register XtEventTable next = event->next;
1565444c061aSmrg	XtFree((char *) event);
1566444c061aSmrg	event = next;
1567444c061aSmrg    }
1568444c061aSmrg}
1569444c061aSmrg
1570444c061aSmrgTime XtLastTimestampProcessed(
1571444c061aSmrg    Display *dpy)
1572444c061aSmrg{
1573444c061aSmrg    Time time;
1574444c061aSmrg    DPY_TO_APPCON(dpy);
1575444c061aSmrg
1576444c061aSmrg    LOCK_APP(app);
1577444c061aSmrg    LOCK_PROCESS;
1578444c061aSmrg    time =  _XtGetPerDisplay(dpy)->last_timestamp;
1579444c061aSmrg    UNLOCK_PROCESS;
1580444c061aSmrg    UNLOCK_APP(app);
1581444c061aSmrg    return(time);
1582444c061aSmrg}
1583444c061aSmrg
1584444c061aSmrgXEvent* XtLastEventProcessed(
1585444c061aSmrg    Display* dpy)
1586444c061aSmrg{
1587444c061aSmrg    XEvent* le = NULL;
1588444c061aSmrg    DPY_TO_APPCON(dpy);
1589444c061aSmrg
1590444c061aSmrg    LOCK_APP(app);
1591444c061aSmrg    le = &_XtGetPerDisplay(dpy)->last_event;
1592444c061aSmrg    if (!le->xany.serial)
1593444c061aSmrg	le =  NULL;
1594444c061aSmrg    UNLOCK_APP(app);
1595444c061aSmrg    return le;
1596444c061aSmrg}
1597444c061aSmrg
1598444c061aSmrgvoid _XtSendFocusEvent(
1599444c061aSmrg    Widget child,
1600444c061aSmrg    int type)
1601444c061aSmrg{
1602444c061aSmrg    child = XtIsWidget(child) ? child : _XtWindowedAncestor(child);
1603444c061aSmrg    if (XtIsSensitive(child) && !child->core.being_destroyed
1604444c061aSmrg	&& XtIsRealized(child)
1605444c061aSmrg	&& (XtBuildEventMask(child) & FocusChangeMask))
1606444c061aSmrg    {
1607444c061aSmrg	XFocusChangeEvent event;
1608444c061aSmrg	Display* dpy = XtDisplay (child);
1609444c061aSmrg
1610444c061aSmrg	event.type = type;
1611444c061aSmrg	event.serial = LastKnownRequestProcessed(dpy);
1612444c061aSmrg	event.send_event = True;
1613444c061aSmrg	event.display = dpy;
1614444c061aSmrg	event.window = XtWindow(child);
1615444c061aSmrg	event.mode = NotifyNormal;
1616444c061aSmrg	event.detail = NotifyAncestor;
1617444c061aSmrg	if (XFilterEvent((XEvent*)&event, XtWindow(child)))
1618444c061aSmrg	    return;
1619444c061aSmrg	XtDispatchEventToWidget(child, (XEvent*)&event);
1620444c061aSmrg    }
1621444c061aSmrg}
1622444c061aSmrg
1623444c061aSmrgstatic XtEventDispatchProc* NewDispatcherList(void)
1624444c061aSmrg{
1625444c061aSmrg    XtEventDispatchProc* l =
1626444c061aSmrg	(XtEventDispatchProc*) __XtCalloc((Cardinal) 128,
1627444c061aSmrg					(Cardinal)sizeof(XtEventDispatchProc));
1628444c061aSmrg    return l;
1629444c061aSmrg}
1630444c061aSmrg
1631444c061aSmrgXtEventDispatchProc XtSetEventDispatcher(
1632444c061aSmrg    Display		*dpy,
1633444c061aSmrg    int			event_type,
1634444c061aSmrg    XtEventDispatchProc	proc)
1635444c061aSmrg{
1636444c061aSmrg    XtEventDispatchProc *list;
1637444c061aSmrg    XtEventDispatchProc old_proc;
1638444c061aSmrg    register XtPerDisplay pd;
1639444c061aSmrg    DPY_TO_APPCON(dpy);
1640444c061aSmrg
1641444c061aSmrg    LOCK_APP(app);
1642444c061aSmrg    LOCK_PROCESS;
1643444c061aSmrg    pd = _XtGetPerDisplay(dpy);
1644444c061aSmrg
1645444c061aSmrg    list = pd->dispatcher_list;
1646444c061aSmrg    if (!list) {
1647444c061aSmrg	if (proc) list = pd->dispatcher_list = NewDispatcherList();
1648444c061aSmrg	else return _XtDefaultDispatcher;
1649444c061aSmrg    }
1650444c061aSmrg    old_proc = list[event_type];
1651444c061aSmrg    list[event_type] = proc;
1652444c061aSmrg    if (old_proc == NULL) old_proc = _XtDefaultDispatcher;
1653444c061aSmrg    UNLOCK_PROCESS;
1654444c061aSmrg    UNLOCK_APP(app);
1655444c061aSmrg    return old_proc;
1656444c061aSmrg}
1657444c061aSmrg
1658444c061aSmrgvoid XtRegisterExtensionSelector(
1659444c061aSmrg    Display		*dpy,
1660444c061aSmrg    int			min_event_type,
1661444c061aSmrg    int			max_event_type,
1662444c061aSmrg    XtExtensionSelectProc	proc,
1663444c061aSmrg    XtPointer 		client_data)
1664444c061aSmrg{
1665444c061aSmrg    ExtSelectRec *e;
1666444c061aSmrg    XtPerDisplay pd;
1667444c061aSmrg    int i;
1668444c061aSmrg    DPY_TO_APPCON(dpy);
1669444c061aSmrg
1670444c061aSmrg    if (dpy == NULL) XtErrorMsg("nullDisplay",
1671444c061aSmrg		"xtRegisterExtensionSelector", XtCXtToolkitError,
1672444c061aSmrg		"XtRegisterExtensionSelector requires a non-NULL display",
1673444c061aSmrg		(String *) NULL, (Cardinal *) NULL);
1674444c061aSmrg
1675444c061aSmrg    LOCK_APP(app);
1676444c061aSmrg    LOCK_PROCESS;
1677444c061aSmrg    pd = _XtGetPerDisplay(dpy);
1678444c061aSmrg
1679444c061aSmrg    for (i = 0; i < pd->ext_select_count; i++) {
1680444c061aSmrg	e = &pd->ext_select_list[i];
1681444c061aSmrg	if (e->min == min_event_type && e->max == max_event_type) {
1682444c061aSmrg	    e->proc = proc;
1683444c061aSmrg	    e->client_data = client_data;
1684444c061aSmrg	    return;
1685444c061aSmrg	}
1686444c061aSmrg	if ((min_event_type >= e->min && min_event_type <= e->max) ||
1687444c061aSmrg	    (max_event_type >= e->min && max_event_type <= e->max)) {
1688444c061aSmrg	    XtErrorMsg("rangeError", "xtRegisterExtensionSelector",
1689444c061aSmrg		       XtCXtToolkitError,
1690444c061aSmrg	"Attempt to register multiple selectors for one extension event type",
1691444c061aSmrg		       (String *) NULL, (Cardinal *) NULL);
1692444c061aSmrg	    UNLOCK_PROCESS;
1693444c061aSmrg	    UNLOCK_APP(app);
1694444c061aSmrg	    return;
1695444c061aSmrg	}
1696444c061aSmrg    }
1697444c061aSmrg    pd->ext_select_count++;
1698444c061aSmrg    pd->ext_select_list =
1699444c061aSmrg	    (ExtSelectRec *) XtRealloc((char *) pd->ext_select_list,
1700444c061aSmrg		       pd->ext_select_count * sizeof(ExtSelectRec));
1701444c061aSmrg    for (i = pd->ext_select_count - 1; i > 0; i--) {
1702444c061aSmrg	if (pd->ext_select_list[i-1].min > min_event_type) {
1703444c061aSmrg	    pd->ext_select_list[i] = pd->ext_select_list[i-1];
1704444c061aSmrg	} else break;
1705444c061aSmrg    }
1706444c061aSmrg    pd->ext_select_list[i].min = min_event_type;
1707444c061aSmrg    pd->ext_select_list[i].max = max_event_type;
1708444c061aSmrg    pd->ext_select_list[i].proc = proc;
1709444c061aSmrg    pd->ext_select_list[i].client_data = client_data;
1710444c061aSmrg    UNLOCK_PROCESS;
1711444c061aSmrg    UNLOCK_APP(app);
1712444c061aSmrg}
1713444c061aSmrg
1714444c061aSmrgvoid _XtExtensionSelect(
1715444c061aSmrg    Widget widget)
1716444c061aSmrg{
1717444c061aSmrg    int i;
1718444c061aSmrg    XtPerDisplay pd;
1719444c061aSmrg    WIDGET_TO_APPCON(widget);
1720444c061aSmrg
1721444c061aSmrg    LOCK_APP(app);
1722444c061aSmrg    LOCK_PROCESS;
1723444c061aSmrg
1724444c061aSmrg    pd = _XtGetPerDisplay(XtDisplay(widget));
1725444c061aSmrg
1726444c061aSmrg    for (i = 0; i < pd->ext_select_count; i++) {
1727444c061aSmrg	CallExtensionSelector(widget, pd->ext_select_list+i, FALSE);
1728444c061aSmrg    }
1729444c061aSmrg    UNLOCK_PROCESS;
1730444c061aSmrg    UNLOCK_APP(app);
1731444c061aSmrg}
1732