#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "IntrinsicI.h"
#include "Shell.h"
#include "StringDefs.h"
typedef struct _XtEventRecExt {
int type;
XtPointer select_data[1];
} XtEventRecExt;
#define EXT_TYPE(p) (((XtEventRecExt*) ((p)+1))->type)
#define EXT_SELECT_DATA(p,n) (((XtEventRecExt*) ((p)+1))->select_data[n])
#define NonMaskableMask ((EventMask)0x80000000L)
#define COMP_EXPOSE (widget->core.widget_class->core_class.compress_exposure)
#define COMP_EXPOSE_TYPE (COMP_EXPOSE & 0x0f)
#define GRAPHICS_EXPOSE ((XtExposeGraphicsExpose & COMP_EXPOSE) || \
(XtExposeGraphicsExposeMerged & COMP_EXPOSE))
#define NO_EXPOSE (XtExposeNoExpose & COMP_EXPOSE)
EventMask XtBuildEventMask(
Widget widget)
{
XtEventTable ev;
EventMask mask = 0L;
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
for (ev = widget->core.event_table; ev != NULL; ev = ev->next)
if (ev->select) {
if (!ev->has_type_specifier)
mask |= ev->mask;
else {
if (EXT_TYPE(ev) < LASTEvent) {
Cardinal i;
for (i = 0; i < ev->mask; i++)
if (EXT_SELECT_DATA(ev, i))
mask |= *(EventMask*)EXT_SELECT_DATA(ev, i);
}
}
}
LOCK_PROCESS;
if (widget->core.widget_class->core_class.expose != NULL)
mask |= ExposureMask;
if (widget->core.widget_class->core_class.visible_interest)
mask |= VisibilityChangeMask;
UNLOCK_PROCESS;
if (widget->core.tm.translations)
mask |= widget->core.tm.translations->eventMask;
mask = mask & ~NonMaskableMask;
UNLOCK_APP(app);
return mask;
}
static void CallExtensionSelector(
Widget widget,
ExtSelectRec* rec,
Boolean forceCall)
{
XtEventRec* p;
XtPointer* data;
int* types;
Cardinal i, count = 0;
for (p = widget->core.event_table; p != NULL; p = p->next)
if (p->has_type_specifier &&
EXT_TYPE(p) >= rec->min && EXT_TYPE(p) <= rec->max)
count += p->mask;
if (count == 0 && !forceCall) return;
data = (XtPointer *) ALLOCATE_LOCAL(count * sizeof (XtPointer));
types = (int *) ALLOCATE_LOCAL(count * sizeof (int));
count = 0;
for (p = widget->core.event_table; p != NULL; p = p->next)
if (p->has_type_specifier &&
EXT_TYPE(p) >= rec->min && EXT_TYPE(p) <= rec->max)
for (i =0; i < p->mask; i++) {
types[count] = EXT_TYPE(p);
data[count++] = EXT_SELECT_DATA(p, i);
}
(*rec->proc)(widget, types, data, count, rec->client_data);
DEALLOCATE_LOCAL((char*) types);
DEALLOCATE_LOCAL((char*) data);
}
static void
RemoveEventHandler(
Widget widget,
XtPointer select_data,
int type,
Boolean has_type_specifier,
Boolean other,
XtEventHandler proc,
XtPointer closure,
Boolean raw)
{
XtEventRec *p, **pp;
EventMask eventMask, oldMask = XtBuildEventMask(widget);
if (raw) raw = 1;
pp = &widget->core.event_table;
while ((p = *pp) &&
(p->proc != proc || p->closure != closure || p->select == raw ||
has_type_specifier != p->has_type_specifier ||
(has_type_specifier && EXT_TYPE(p) != type)))
pp = &p->next;
if (!p) return;
if (!has_type_specifier) {
eventMask = *(EventMask*)select_data;
eventMask &= ~NonMaskableMask;
if (other)
eventMask |= NonMaskableMask;
p->mask &= ~eventMask;
} else {
Cardinal i;
for (i = 0; i < p->mask && select_data != EXT_SELECT_DATA(p,i);) i++;
if (i == p->mask) return;
if (p->mask == 1) p->mask = 0;
else {
p->mask--;
while (i < p->mask) {
EXT_SELECT_DATA(p,i) = EXT_SELECT_DATA(p, i+1);
i++;
}
}
}
if (!p->mask) {
*pp = p->next;
XtFree((char *)p);
}
if ( !raw && XtIsRealized(widget) && !widget->core.being_destroyed) {
EventMask mask = XtBuildEventMask(widget);
Display* dpy = XtDisplay (widget);
if (oldMask != mask)
XSelectInput(dpy, XtWindow(widget), mask);
if (has_type_specifier) {
XtPerDisplay pd = _XtGetPerDisplay(dpy);
int i;
for (i = 0; i < pd->ext_select_count; i++) {
if (type >= pd->ext_select_list[i].min &&
type <= pd->ext_select_list[i].max) {
CallExtensionSelector(widget, pd->ext_select_list+i, TRUE);
break;
}
if (type < pd->ext_select_list[i].min) break;
}
}
}
}
static void
AddEventHandler(
Widget widget,
XtPointer select_data,
int type,
Boolean has_type_specifier,
Boolean other,
XtEventHandler proc,
XtPointer closure,
XtListPosition position,
Boolean force_new_position,
Boolean raw)
{
register XtEventRec *p, **pp;
EventMask oldMask = 0, eventMask = 0;
if (!has_type_specifier) {
eventMask = *(EventMask*)select_data & ~NonMaskableMask;
if (other) eventMask |= NonMaskableMask;
if (!eventMask) return;
} else if (!type) return;
if (XtIsRealized(widget) && !raw) oldMask = XtBuildEventMask(widget);
if (raw) raw = 1;
pp = &widget->core.event_table;
while ((p = *pp) &&
(p->proc != proc || p->closure != closure || p->select == raw ||
has_type_specifier != p->has_type_specifier ||
(has_type_specifier && EXT_TYPE(p) != type)))
pp = &p->next;
if (!p) {
if (has_type_specifier) {
p = (XtEventRec*) __XtMalloc(sizeof(XtEventRec) +
sizeof(XtEventRecExt));
EXT_TYPE(p) = type;
EXT_SELECT_DATA(p,0) = select_data;
p->mask = 1;
p->has_type_specifier = True;
} else {
p = (XtEventRec*) __XtMalloc(sizeof(XtEventRec));
p->mask = eventMask;
p->has_type_specifier = False;
}
p->proc = proc;
p->closure = closure;
p->select = ! raw;
if (position == XtListHead) {
p->next = widget->core.event_table;
widget->core.event_table = p;
pp = &widget->core.event_table;
} else {
*pp = p;
p->next = NULL;
}
}
else {
if (force_new_position) {
*pp = p->next;
if (position == XtListHead) {
p->next = widget->core.event_table;
widget->core.event_table = p;
} else {
while (*pp)
pp = &(*pp)->next;
*pp = p;
p->next = NULL;
}
}
if (!has_type_specifier)
p->mask |= eventMask;
else {
Cardinal i;
for (i = 0; i < p->mask && select_data != EXT_SELECT_DATA(p,i); )
i++;
if (i == p->mask) {
p = (XtEventRec*) XtRealloc((char*)p,
sizeof(XtEventRec) +
sizeof(XtEventRecExt) +
p->mask * sizeof(XtPointer));
EXT_SELECT_DATA(p,i) = select_data;
p->mask++;
*pp = p;
}
}
}
if (XtIsRealized(widget) && !raw) {
EventMask mask = XtBuildEventMask(widget);
Display* dpy = XtDisplay (widget);
if (oldMask != mask)
XSelectInput(dpy, XtWindow(widget), mask);
if (has_type_specifier) {
XtPerDisplay pd = _XtGetPerDisplay (dpy);
int i;
for (i = 0; i < pd->ext_select_count; i++) {
if (type >= pd->ext_select_list[i].min &&
type <= pd->ext_select_list[i].max) {
CallExtensionSelector(widget, pd->ext_select_list+i, FALSE);
break;
}
if (type < pd->ext_select_list[i].min) break;
}
}
}
}
void XtRemoveEventHandler(
Widget widget,
EventMask eventMask,
_XtBoolean other,
XtEventHandler proc,
XtPointer closure)
{
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
RemoveEventHandler(widget, (XtPointer) &eventMask, 0, FALSE,
other, proc, closure, FALSE);
UNLOCK_APP(app);
}
void XtAddEventHandler(
Widget widget,
EventMask eventMask,
_XtBoolean other,
XtEventHandler proc,
XtPointer closure)
{
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
proc, closure, XtListTail, FALSE, FALSE);
UNLOCK_APP(app);
}
void XtInsertEventHandler(
Widget widget,
EventMask eventMask,
_XtBoolean other,
XtEventHandler proc,
XtPointer closure,
XtListPosition position)
{
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
proc, closure, position, TRUE, FALSE);
UNLOCK_APP(app);
}
void XtRemoveRawEventHandler(
Widget widget,
EventMask eventMask,
_XtBoolean other,
XtEventHandler proc,
XtPointer closure)
{
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
RemoveEventHandler(widget, (XtPointer) &eventMask, 0, FALSE,
other, proc, closure, TRUE);
UNLOCK_APP(app);
}
void XtInsertRawEventHandler(
Widget widget,
EventMask eventMask,
_XtBoolean other,
XtEventHandler proc,
XtPointer closure,
XtListPosition position)
{
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
proc, closure, position, TRUE, TRUE);
UNLOCK_APP(app);
}
void XtAddRawEventHandler(
Widget widget,
EventMask eventMask,
_XtBoolean other,
XtEventHandler proc,
XtPointer closure)
{
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
proc, closure, XtListTail, FALSE, TRUE);
UNLOCK_APP(app);
}
void XtRemoveEventTypeHandler(
Widget widget,
int type,
XtPointer select_data,
XtEventHandler proc,
XtPointer closure)
{
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
RemoveEventHandler(widget, select_data, type, TRUE,
FALSE, proc, closure, FALSE);
UNLOCK_APP(app);
}
void XtInsertEventTypeHandler(
Widget widget,
int type,
XtPointer select_data,
XtEventHandler proc,
XtPointer closure,
XtListPosition position)
{
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
AddEventHandler(widget, select_data, type, TRUE, FALSE,
proc, closure, position, TRUE, FALSE);
UNLOCK_APP(app);
}
typedef struct _WWPair {
struct _WWPair *next;
Window window;
Widget widget;
} *WWPair;
typedef struct _WWTable {
unsigned int mask;
unsigned int rehash;
unsigned int occupied;
unsigned int fakes;
Widget *entries;
WWPair pairs;
} *WWTable;
static const WidgetRec WWfake;
#define WWHASH(tab,win) ((win) & tab->mask)
#define WWREHASHVAL(tab,win) ((((win) % tab->rehash) + 2) | 1)
#define WWREHASH(tab,idx,rehash) ((idx + rehash) & tab->mask)
#define WWTABLE(display) (_XtGetPerDisplay(display)->WWtable)
static void ExpandWWTable(WWTable);
void XtRegisterDrawable(
Display* display,
Drawable drawable,
Widget widget)
{
WWTable tab;
int idx, rehash;
Widget entry;
Window window = (Window) drawable;
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
LOCK_PROCESS;
tab = WWTABLE(display);
if (window != XtWindow(widget)) {
WWPair pair;
pair = XtNew(struct _WWPair);
pair->next = tab->pairs;
pair->window = window;
pair->widget = widget;
tab->pairs = pair;
UNLOCK_PROCESS;
UNLOCK_APP(app);
return;
}
if ((tab->occupied + (tab->occupied >> 2)) > tab->mask)
ExpandWWTable(tab);
idx = WWHASH(tab, window);
if ((entry = tab->entries[idx]) && entry != &WWfake) {
rehash = WWREHASHVAL(tab, window);
do {
idx = WWREHASH(tab, idx, rehash);
} while ((entry = tab->entries[idx]) && entry != &WWfake);
}
if (!entry)
tab->occupied++;
else if (entry == &WWfake)
tab->fakes--;
tab->entries[idx] = widget;
UNLOCK_PROCESS;
UNLOCK_APP(app);
}
void XtUnregisterDrawable(
Display* display,
Drawable drawable)
{
WWTable tab;
int idx, rehash;
Widget entry;
Window window = (Window) drawable;
Widget widget = XtWindowToWidget (display, window);
DPY_TO_APPCON(display);
if (widget == NULL) return;
LOCK_APP(app);
LOCK_PROCESS;
tab = WWTABLE(display);
if (window != XtWindow(widget)) {
WWPair *prev, pair;
prev = &tab->pairs;
while ((pair = *prev) && pair->window != window)
prev = &pair->next;
if (pair) {
*prev = pair->next;
XtFree((char *)pair);
}
UNLOCK_PROCESS;
UNLOCK_APP(app);
return;
}
idx = WWHASH(tab, window);
if ((entry = tab->entries[idx])) {
if (entry != widget) {
rehash = WWREHASHVAL(tab, window);
do {
idx = WWREHASH(tab, idx, rehash);
if (!(entry = tab->entries[idx])) {
UNLOCK_PROCESS;
UNLOCK_APP(app);
return;
}
} while (entry != widget);
}
tab->entries[idx] = (Widget)&WWfake;
tab->fakes++;
}
UNLOCK_PROCESS;
UNLOCK_APP(app);
}
static void ExpandWWTable(
register WWTable tab)
{
unsigned int oldmask;
register Widget *oldentries, *entries;
register Cardinal oldidx, newidx, rehash;
register Widget entry;
LOCK_PROCESS;
oldmask = tab->mask;
oldentries = tab->entries;
tab->occupied -= tab->fakes;
tab->fakes = 0;
if ((tab->occupied + (tab->occupied >> 2)) > tab->mask) {
tab->mask = (tab->mask << 1) + 1;
tab->rehash = tab->mask - 2;
}
entries = tab->entries = (Widget *) __XtCalloc(tab->mask+1, sizeof(Widget));
for (oldidx = 0; oldidx <= oldmask; oldidx++) {
if ((entry = oldentries[oldidx]) && entry != &WWfake) {
newidx = WWHASH(tab, XtWindow(entry));
if (entries[newidx]) {
rehash = WWREHASHVAL(tab, XtWindow(entry));
do {
newidx = WWREHASH(tab, newidx, rehash);
} while (entries[newidx]);
}
entries[newidx] = entry;
}
}
XtFree((char *)oldentries);
UNLOCK_PROCESS;
}
Widget XtWindowToWidget(
register Display *display,
register Window window)
{
register WWTable tab;
register int idx, rehash;
register Widget entry;
WWPair pair;
DPY_TO_APPCON(display);
if (!window) return NULL;
LOCK_APP(app);
LOCK_PROCESS;
tab = WWTABLE(display);
idx = WWHASH(tab, window);
if ((entry = tab->entries[idx]) && XtWindow(entry) != window) {
rehash = WWREHASHVAL(tab, window);
do {
idx = WWREHASH(tab, idx, rehash);
} while ((entry = tab->entries[idx]) && XtWindow(entry) != window);
}
if (entry) {
UNLOCK_PROCESS;
UNLOCK_APP(app);
return entry;
}
for (pair = tab->pairs; pair; pair = pair->next) {
if (pair->window == window) {
entry = pair->widget;
UNLOCK_PROCESS;
UNLOCK_APP(app);
return entry;
}
}
UNLOCK_PROCESS;
UNLOCK_APP(app);
return NULL;
}
void _XtAllocWWTable(
XtPerDisplay pd)
{
register WWTable tab;
tab = (WWTable) __XtMalloc(sizeof(struct _WWTable));
tab->mask = 0x7f;
tab->rehash = tab->mask - 2;
tab->entries = (Widget *) __XtCalloc(tab->mask+1, sizeof(Widget));
tab->occupied = 0;
tab->fakes = 0;
tab->pairs = NULL;
pd->WWtable = tab;
}
void _XtFreeWWTable(
register XtPerDisplay pd)
{
register WWPair pair, next;
for (pair = pd->WWtable->pairs; pair; pair = next) {
next = pair->next;
XtFree((char *)pair);
}
XtFree((char *)pd->WWtable->entries);
XtFree((char *)pd->WWtable);
}
#define EHMAXSIZE 25
static Boolean CallEventHandlers(
Widget widget,
XEvent *event,
EventMask mask)
{
register XtEventRec *p;
XtEventHandler *proc;
XtPointer *closure;
XtEventHandler procs[EHMAXSIZE];
XtPointer closures[EHMAXSIZE];
Boolean cont_to_disp = True;
int i, numprocs;
numprocs = 0;
for (p=widget->core.event_table; p; p = p->next) {
if ((!p->has_type_specifier && (mask & p->mask)) ||
(p->has_type_specifier && event->type == EXT_TYPE(p)))
numprocs++;
}
if (numprocs > EHMAXSIZE) {
proc = (XtEventHandler *)__XtMalloc(numprocs * (sizeof(XtEventHandler) +
sizeof(XtPointer)));
closure = (XtPointer *)(proc + numprocs);
} else {
proc = procs;
closure = closures;
}
numprocs = 0;
for (p=widget->core.event_table; p; p = p->next) {
if ((!p->has_type_specifier && (mask & p->mask)) ||
(p->has_type_specifier && event->type == EXT_TYPE(p))) {
proc[numprocs] = p->proc;
closure[numprocs] = p->closure;
numprocs++;
}
}
for (i = 0; i < numprocs && cont_to_disp; i++)
(*(proc[i]))(widget, closure[i], event, &cont_to_disp);
if (numprocs > EHMAXSIZE)
XtFree((char *)proc);
return cont_to_disp;
}
static void CompressExposures(XEvent *, Widget);
#define KnownButtons (Button1MotionMask|Button2MotionMask|Button3MotionMask|\
Button4MotionMask|Button5MotionMask)
#define EHSIZE 4
Boolean XtDispatchEventToWidget(
Widget widget,
XEvent* event)
{
register XtEventRec *p;
Boolean was_dispatched = False;
Boolean call_tm = False;
Boolean cont_to_disp;
EventMask mask;
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
mask = _XtConvertTypeToMask(event->type);
if (event->type == MotionNotify)
mask |= (event->xmotion.state & KnownButtons);
LOCK_PROCESS;
if ( (mask == ExposureMask) ||
((event->type == NoExpose) && NO_EXPOSE) ||
((event->type == GraphicsExpose) && GRAPHICS_EXPOSE) ) {
if (widget->core.widget_class->core_class.expose != NULL ) {
if ( (COMP_EXPOSE_TYPE == XtExposeNoCompress) ||
(event->type == NoExpose) )
(*widget->core.widget_class->core_class.expose)
(widget, event, (Region)NULL);
else {
CompressExposures(event, widget);
}
was_dispatched = True;
}
}
if ((mask == VisibilityChangeMask) &&
XtClass(widget)->core_class.visible_interest) {
was_dispatched = True;
switch (((XVisibilityEvent *)event)->state) {
case VisibilityUnobscured:
widget->core.visible = TRUE;
break;
case VisibilityPartiallyObscured:
widget->core.visible = TRUE;
break;
case VisibilityFullyObscured:
widget->core.visible = FALSE;
break;
}
}
UNLOCK_PROCESS;
if (widget->core.tm.translations &&
(mask & widget->core.tm.translations->eventMask))
call_tm = True;
cont_to_disp = True;
p=widget->core.event_table;
if (p) {
if (p->next) {
XtEventHandler proc[EHSIZE];
XtPointer closure[EHSIZE];
int numprocs = 0;
for (; p; p = p->next) {
if ((!p->has_type_specifier && (mask & p->mask)) ||
(p->has_type_specifier && event->type == EXT_TYPE(p))) {
if (numprocs >= EHSIZE)
break;
proc[numprocs] = p->proc;
closure[numprocs] = p->closure;
numprocs++;
}
}
if (numprocs) {
if (p) {
cont_to_disp = CallEventHandlers(widget, event, mask);
} else {
int i;
for (i = 0; i < numprocs && cont_to_disp; i++)
(*(proc[i]))(widget, closure[i], event, &cont_to_disp);
}
was_dispatched = True;
}
} else if ((!p->has_type_specifier && (mask & p->mask)) ||
(p->has_type_specifier && event->type == EXT_TYPE(p))) {
(*p->proc)(widget, p->closure, event, &cont_to_disp);
was_dispatched = True;
}
}
if (call_tm && cont_to_disp)
_XtTranslateEvent(widget, event);
UNLOCK_APP(app);
return (was_dispatched|call_tm);
}
typedef struct _CheckExposeInfo {
int type1, type2;
Boolean maximal;
Boolean non_matching;
Window window;
} CheckExposeInfo;
#define GetCount(ev) (((XExposeEvent *)(ev))->count)
static void SendExposureEvent(XEvent *, Widget, XtPerDisplay);
static Bool CheckExposureEvent(Display *, XEvent *, char *);
static void AddExposureToRectangularRegion(XEvent *, Region);
static void
CompressExposures(
XEvent * event,
Widget widget)
{
CheckExposeInfo info;
int count;
Display* dpy = XtDisplay (widget);
XtPerDisplay pd = _XtGetPerDisplay(dpy);
XtEnum comp_expose;
XtEnum comp_expose_type;
Boolean no_region;
LOCK_PROCESS;
comp_expose = COMP_EXPOSE;
UNLOCK_PROCESS;
comp_expose_type = comp_expose & 0x0f;
no_region = ((comp_expose & XtExposeNoRegion) ? True : False);
if (no_region)
AddExposureToRectangularRegion(event, pd->region);
else
XtAddExposureToRegion(event, pd->region);
if ( GetCount(event) != 0 )
return;
if ((comp_expose_type == XtExposeCompressSeries) ||
(XEventsQueued(dpy, QueuedAfterReading) == 0)) {
SendExposureEvent(event, widget, pd);
return;
}
if (comp_expose & XtExposeGraphicsExposeMerged) {
info.type1 = Expose;
info.type2 = GraphicsExpose;
}
else {
info.type1 = event->type;
info.type2 = 0;
}
info.maximal = (comp_expose_type == XtExposeCompressMaximal);
info.non_matching = FALSE;
info.window = XtWindow(widget);
count = 0;
while (TRUE) {
XEvent event_return;
if (XCheckIfEvent(dpy, &event_return,
CheckExposureEvent, (char *) &info)) {
count = GetCount(&event_return);
if (no_region)
AddExposureToRectangularRegion(&event_return, pd->region);
else
XtAddExposureToRegion(&event_return, pd->region);
}
else if (count != 0) {
XIfEvent(dpy, &event_return,
CheckExposureEvent, (char *) &info);
count = GetCount(&event_return);
if (no_region)
AddExposureToRectangularRegion(&event_return, pd->region);
else
XtAddExposureToRegion(&event_return, pd->region);
}
else
break;
}
SendExposureEvent(event, widget, pd);
}
void XtAddExposureToRegion(
XEvent *event,
Region region)
{
XRectangle rect;
XExposeEvent *ev = (XExposeEvent *) event;
if (event->type == Expose || event->type == GraphicsExpose) {
rect.x = ev->x;
rect.y = ev->y;
rect.width = ev->width;
rect.height = ev->height;
XUnionRectWithRegion(&rect, region, region);
}
}
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
static void AddExposureToRectangularRegion(
XEvent *event,
Region region)
{
XRectangle rect;
XExposeEvent *ev = (XExposeEvent *) event;
rect.x = ev->x;
rect.y = ev->y;
rect.width = ev->width;
rect.height = ev->height;
if (XEmptyRegion(region)) {
XUnionRectWithRegion(&rect, region, region);
} else {
XRectangle merged, bbox;
XClipBox(region, &bbox);
merged.x = MIN(rect.x, bbox.x);
merged.y = MIN(rect.y, bbox.y);
merged.width = MAX(rect.x + rect.width,
bbox.x + bbox.width) - merged.x;
merged.height = MAX(rect.y + rect.height,
bbox.y + bbox.height) - merged.y;
XUnionRectWithRegion(&merged, region, region);
}
}
static Region nullRegion;
void _XtEventInitialize(void)
{
#ifndef __lock_lint
nullRegion = XCreateRegion();
#endif
}
static void
SendExposureEvent(
XEvent * event,
Widget widget,
XtPerDisplay pd)
{
XtExposeProc expose;
XRectangle rect;
XtEnum comp_expose;
XExposeEvent *ev = (XExposeEvent *) event;
XClipBox(pd->region, &rect);
ev->x = rect.x;
ev->y = rect.y;
ev->width = rect.width;
ev->height = rect.height;
LOCK_PROCESS;
comp_expose = COMP_EXPOSE;
expose = widget->core.widget_class->core_class.expose;
UNLOCK_PROCESS;
if (comp_expose & XtExposeNoRegion)
(*expose)(widget, event, NULL);
else
(*expose)(widget, event, pd->region);
(void) XIntersectRegion(nullRegion, pd->region, pd->region);
}
static Bool
CheckExposureEvent(
Display * disp,
XEvent * event,
char * arg)
{
CheckExposeInfo * info = ((CheckExposeInfo *) arg);
if ( (info->type1 == event->type) || (info->type2 == event->type)) {
if (!info->maximal && info->non_matching) return FALSE;
if (event->type == GraphicsExpose)
return(event->xgraphicsexpose.drawable == info->window);
return(event->xexpose.window == info->window);
}
info->non_matching = TRUE;
return(FALSE);
}
static EventMask const masks[] = {
0,
0,
KeyPressMask,
KeyReleaseMask,
ButtonPressMask,
ButtonReleaseMask,
PointerMotionMask
| ButtonMotionMask,
EnterWindowMask,
LeaveWindowMask,
FocusChangeMask,
FocusChangeMask,
KeymapStateMask,
ExposureMask,
NonMaskableMask,
NonMaskableMask,
VisibilityChangeMask,
SubstructureNotifyMask,
StructureNotifyMask
| SubstructureNotifyMask,
StructureNotifyMask
| SubstructureNotifyMask,
StructureNotifyMask
| SubstructureNotifyMask,
SubstructureRedirectMask,
StructureNotifyMask
| SubstructureNotifyMask,
StructureNotifyMask
| SubstructureNotifyMask,
SubstructureRedirectMask,
StructureNotifyMask
| SubstructureNotifyMask,
ResizeRedirectMask,
StructureNotifyMask
| SubstructureNotifyMask,
SubstructureRedirectMask,
PropertyChangeMask,
NonMaskableMask,
NonMaskableMask,
NonMaskableMask,
ColormapChangeMask,
NonMaskableMask,
NonMaskableMask
};
EventMask _XtConvertTypeToMask (
int eventType)
{
if ((Cardinal) eventType < XtNumber(masks))
return masks[eventType];
else
return NoEventMask;
}
Boolean _XtOnGrabList(
register Widget widget,
XtGrabRec *grabList)
{
register XtGrabRec* gl;
for (; widget != NULL; widget = (Widget)widget->core.parent) {
for (gl = grabList; gl != NULL; gl = gl->next) {
if (gl->widget == widget) return TRUE;
if (gl->exclusive) break;
}
}
return FALSE;
}
static Widget LookupSpringLoaded(
XtGrabList grabList)
{
XtGrabList gl;
for (gl = grabList; gl != NULL; gl = gl->next) {
if (gl->spring_loaded) {
if (XtIsSensitive(gl->widget))
return gl->widget;
else
return NULL;
}
if (gl->exclusive) break;
}
return NULL;
}
static Boolean DispatchEvent(
XEvent* event,
Widget widget)
{
if (event->type == EnterNotify &&
event->xcrossing.mode == NotifyNormal &&
widget->core.widget_class->core_class.compress_enterleave) {
if (XPending(event->xcrossing.display)) {
XEvent nextEvent;
XPeekEvent(event->xcrossing.display, &nextEvent);
if (nextEvent.type == LeaveNotify &&
event->xcrossing.window == nextEvent.xcrossing.window &&
nextEvent.xcrossing.mode == NotifyNormal &&
((event->xcrossing.detail != NotifyInferior &&
nextEvent.xcrossing.detail != NotifyInferior) ||
(event->xcrossing.detail == NotifyInferior &&
nextEvent.xcrossing.detail == NotifyInferior))) {
XNextEvent(event->xcrossing.display, &nextEvent);
return False;
}
}
}
if (event->type == MotionNotify &&
widget->core.widget_class->core_class.compress_motion) {
while (XPending(event->xmotion.display)) {
XEvent nextEvent;
XPeekEvent(event->xmotion.display, &nextEvent);
if (nextEvent.type == MotionNotify &&
event->xmotion.window == nextEvent.xmotion.window &&
event->xmotion.subwindow == nextEvent.xmotion.subwindow) {
XNextEvent(event->xmotion.display, event);
} else break;
}
}
return XtDispatchEventToWidget(widget, event);
}
typedef enum _GrabType {pass, ignore, remap} GrabType;
#if !defined(AIXV3) || !defined(AIXSHLIB)
static
#endif
Boolean _XtDefaultDispatcher(
XEvent *event)
{
register Widget widget;
GrabType grabType;
XtPerDisplayInput pdi;
XtGrabList grabList;
Boolean was_dispatched = False;
DPY_TO_APPCON(event->xany.display);
if (event->type >= LASTEvent)
return False;
LOCK_APP(app);
switch (event->type) {
case KeyPress:
case KeyRelease:
case ButtonPress:
case ButtonRelease: grabType = remap; break;
case MotionNotify:
case EnterNotify: grabType = ignore; break;
default: grabType = pass; break;
}
widget = XtWindowToWidget (event->xany.display, event->xany.window);
pdi = _XtGetPerDisplayInput(event->xany.display);
grabList = *_XtGetGrabList(pdi);
if (widget == NULL) {
if (grabType == remap
&& (widget = LookupSpringLoaded(grabList)) != NULL) {
was_dispatched = (XFilterEvent(event, XtWindow(widget))
|| XtDispatchEventToWidget(widget, event));
}
else was_dispatched = XFilterEvent(event, None);
}
else if (grabType == pass) {
if (event->type == LeaveNotify ||
event->type == FocusIn ||
event->type == FocusOut) {
if (XtIsSensitive (widget))
was_dispatched = (XFilterEvent(event, XtWindow(widget)) ||
XtDispatchEventToWidget(widget, event));
} else was_dispatched = (XFilterEvent(event, XtWindow(widget)) ||
XtDispatchEventToWidget(widget, event));
}
else if (grabType == ignore) {
if ((grabList == NULL || _XtOnGrabList(widget, grabList))
&& XtIsSensitive(widget)) {
was_dispatched = (XFilterEvent(event, XtWindow(widget))
|| DispatchEvent(event, widget));
}
}
else if (grabType == remap) {
EventMask mask = _XtConvertTypeToMask(event->type);
Widget dspWidget;
Boolean was_filtered = False;
dspWidget = _XtFindRemapWidget(event, widget, mask, pdi);
if ((grabList == NULL ||_XtOnGrabList(dspWidget, grabList))
&& XtIsSensitive(dspWidget)) {
if ((was_filtered = XFilterEvent(event, XtWindow(dspWidget)))) {
_XtUngrabBadGrabs(event, widget, mask, pdi);
was_dispatched = True;
} else
was_dispatched = XtDispatchEventToWidget(dspWidget, event);
}
else _XtUngrabBadGrabs(event, widget, mask, pdi);
if (!was_filtered) {
grabList = *_XtGetGrabList(pdi);
widget = LookupSpringLoaded(grabList);
if (widget != NULL && widget != dspWidget) {
was_dispatched = (XFilterEvent(event, XtWindow(widget))
|| XtDispatchEventToWidget(widget, event)
|| was_dispatched);
}
}
}
UNLOCK_APP(app);
return was_dispatched;
}
Boolean XtDispatchEvent (
XEvent *event)
{
Boolean was_dispatched, safe;
int dispatch_level;
int starting_count;
XtPerDisplay pd;
Time time = 0;
XtEventDispatchProc dispatch = _XtDefaultDispatcher;
XtAppContext app = XtDisplayToApplicationContext(event->xany.display);
LOCK_APP(app);
dispatch_level = ++app->dispatch_level;
starting_count = app->destroy_count;
switch (event->type) {
case KeyPress:
case KeyRelease: time = event->xkey.time; break;
case ButtonPress:
case ButtonRelease: time = event->xbutton.time; break;
case MotionNotify: time = event->xmotion.time; break;
case EnterNotify:
case LeaveNotify: time = event->xcrossing.time; break;
case PropertyNotify: time = event->xproperty.time; break;
case SelectionClear: time = event->xselectionclear.time; break;
case MappingNotify: _XtRefreshMapping(event, True); break;
}
pd = _XtGetPerDisplay(event->xany.display);
if (time) pd->last_timestamp = time;
pd->last_event = *event;
if (pd->dispatcher_list) {
dispatch = pd->dispatcher_list[event->type];
if (dispatch == NULL) dispatch = _XtDefaultDispatcher;
}
was_dispatched = (*dispatch)(event);
if (app->destroy_count > starting_count)
_XtDoPhase2Destroy(app, dispatch_level);
app->dispatch_level = dispatch_level - 1;
if ((safe = _XtSafeToDestroy(app))) {
if (app->dpy_destroy_count != 0) _XtCloseDisplays(app);
if (app->free_bindings) _XtDoFreeBindings(app);
}
UNLOCK_APP(app);
LOCK_PROCESS;
if (_XtAppDestroyCount != 0 && safe) _XtDestroyAppContexts();
UNLOCK_PROCESS;
return was_dispatched;
}
static void GrabDestroyCallback(
Widget widget,
XtPointer closure,
XtPointer call_data)
{
XtRemoveGrab(widget);
}
static XtGrabRec *NewGrabRec(
Widget widget,
Boolean exclusive,
Boolean spring_loaded)
{
register XtGrabList gl;
gl = XtNew(XtGrabRec);
gl->next = NULL;
gl->widget = widget;
gl->exclusive = exclusive;
gl->spring_loaded = spring_loaded;
return gl;
}
void XtAddGrab(
Widget widget,
_XtBoolean exclusive,
_XtBoolean spring_loaded)
{
register XtGrabList gl;
XtGrabList *grabListPtr;
XtAppContext app = XtWidgetToApplicationContext(widget);
LOCK_APP(app);
LOCK_PROCESS;
grabListPtr = _XtGetGrabList(_XtGetPerDisplayInput(XtDisplay(widget)));
if (spring_loaded && !exclusive) {
XtAppWarningMsg(app,
"grabError", "xtAddGrab", XtCXtToolkitError,
"XtAddGrab requires exclusive grab if spring_loaded is TRUE",
(String *) NULL, (Cardinal *) NULL);
exclusive = TRUE;
}
gl = NewGrabRec(widget, exclusive, spring_loaded);
gl->next = *grabListPtr;
*grabListPtr = gl;
XtAddCallback (widget, XtNdestroyCallback,
GrabDestroyCallback, (XtPointer) NULL);
UNLOCK_PROCESS;
UNLOCK_APP(app);
}
void XtRemoveGrab(
Widget widget)
{
register XtGrabList gl;
register Boolean done;
XtGrabList *grabListPtr;
XtAppContext app = XtWidgetToApplicationContext(widget);
LOCK_APP(app);
LOCK_PROCESS;
grabListPtr = _XtGetGrabList(_XtGetPerDisplayInput(XtDisplay(widget)));
for (gl = *grabListPtr; gl != NULL; gl = gl->next) {
if (gl->widget == widget) break;
}
if (gl == NULL) {
XtAppWarningMsg(app,
"grabError","xtRemoveGrab",XtCXtToolkitError,
"XtRemoveGrab asked to remove a widget not on the list",
(String *)NULL, (Cardinal *)NULL);
UNLOCK_PROCESS;
UNLOCK_APP(app);
return;
}
do {
gl = *grabListPtr;
done = (gl->widget == widget);
*grabListPtr = gl->next;
XtRemoveCallback(gl->widget, XtNdestroyCallback,
GrabDestroyCallback, (XtPointer)NULL);
XtFree((char *)gl);
} while (! done);
UNLOCK_PROCESS;
UNLOCK_APP(app);
return;
}
void XtMainLoop(void)
{
XtAppMainLoop(_XtDefaultAppContext());
}
void XtAppMainLoop(
XtAppContext app)
{
XEvent event;
LOCK_APP(app);
do {
XtAppNextEvent(app, &event);
#ifdef XTHREADS
#endif
XtDispatchEvent(&event);
} while(app->exit_flag == FALSE);
UNLOCK_APP(app);
}
void _XtFreeEventTable(
XtEventTable *event_table)
{
register XtEventTable event;
event = *event_table;
while (event != NULL) {
register XtEventTable next = event->next;
XtFree((char *) event);
event = next;
}
}
Time XtLastTimestampProcessed(
Display *dpy)
{
Time time;
DPY_TO_APPCON(dpy);
LOCK_APP(app);
LOCK_PROCESS;
time = _XtGetPerDisplay(dpy)->last_timestamp;
UNLOCK_PROCESS;
UNLOCK_APP(app);
return(time);
}
XEvent* XtLastEventProcessed(
Display* dpy)
{
XEvent* le = NULL;
DPY_TO_APPCON(dpy);
LOCK_APP(app);
le = &_XtGetPerDisplay(dpy)->last_event;
if (!le->xany.serial)
le = NULL;
UNLOCK_APP(app);
return le;
}
void _XtSendFocusEvent(
Widget child,
int type)
{
child = XtIsWidget(child) ? child : _XtWindowedAncestor(child);
if (XtIsSensitive(child) && !child->core.being_destroyed
&& XtIsRealized(child)
&& (XtBuildEventMask(child) & FocusChangeMask))
{
XFocusChangeEvent event;
Display* dpy = XtDisplay (child);
event.type = type;
event.serial = LastKnownRequestProcessed(dpy);
event.send_event = True;
event.display = dpy;
event.window = XtWindow(child);
event.mode = NotifyNormal;
event.detail = NotifyAncestor;
if (XFilterEvent((XEvent*)&event, XtWindow(child)))
return;
XtDispatchEventToWidget(child, (XEvent*)&event);
}
}
static XtEventDispatchProc* NewDispatcherList(void)
{
XtEventDispatchProc* l =
(XtEventDispatchProc*) __XtCalloc((Cardinal) 128,
(Cardinal)sizeof(XtEventDispatchProc));
return l;
}
XtEventDispatchProc XtSetEventDispatcher(
Display *dpy,
int event_type,
XtEventDispatchProc proc)
{
XtEventDispatchProc *list;
XtEventDispatchProc old_proc;
register XtPerDisplay pd;
DPY_TO_APPCON(dpy);
LOCK_APP(app);
LOCK_PROCESS;
pd = _XtGetPerDisplay(dpy);
list = pd->dispatcher_list;
if (!list) {
if (proc) list = pd->dispatcher_list = NewDispatcherList();
else return _XtDefaultDispatcher;
}
old_proc = list[event_type];
list[event_type] = proc;
if (old_proc == NULL) old_proc = _XtDefaultDispatcher;
UNLOCK_PROCESS;
UNLOCK_APP(app);
return old_proc;
}
void XtRegisterExtensionSelector(
Display *dpy,
int min_event_type,
int max_event_type,
XtExtensionSelectProc proc,
XtPointer client_data)
{
ExtSelectRec *e;
XtPerDisplay pd;
int i;
DPY_TO_APPCON(dpy);
if (dpy == NULL) XtErrorMsg("nullDisplay",
"xtRegisterExtensionSelector", XtCXtToolkitError,
"XtRegisterExtensionSelector requires a non-NULL display",
(String *) NULL, (Cardinal *) NULL);
LOCK_APP(app);
LOCK_PROCESS;
pd = _XtGetPerDisplay(dpy);
for (i = 0; i < pd->ext_select_count; i++) {
e = &pd->ext_select_list[i];
if (e->min == min_event_type && e->max == max_event_type) {
e->proc = proc;
e->client_data = client_data;
return;
}
if ((min_event_type >= e->min && min_event_type <= e->max) ||
(max_event_type >= e->min && max_event_type <= e->max)) {
XtErrorMsg("rangeError", "xtRegisterExtensionSelector",
XtCXtToolkitError,
"Attempt to register multiple selectors for one extension event type",
(String *) NULL, (Cardinal *) NULL);
UNLOCK_PROCESS;
UNLOCK_APP(app);
return;
}
}
pd->ext_select_count++;
pd->ext_select_list =
(ExtSelectRec *) XtRealloc((char *) pd->ext_select_list,
pd->ext_select_count * sizeof(ExtSelectRec));
for (i = pd->ext_select_count - 1; i > 0; i--) {
if (pd->ext_select_list[i-1].min > min_event_type) {
pd->ext_select_list[i] = pd->ext_select_list[i-1];
} else break;
}
pd->ext_select_list[i].min = min_event_type;
pd->ext_select_list[i].max = max_event_type;
pd->ext_select_list[i].proc = proc;
pd->ext_select_list[i].client_data = client_data;
UNLOCK_PROCESS;
UNLOCK_APP(app);
}
void _XtExtensionSelect(
Widget widget)
{
int i;
XtPerDisplay pd;
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
LOCK_PROCESS;
pd = _XtGetPerDisplay(XtDisplay(widget));
for (i = 0; i < pd->ext_select_count; i++) {
CallExtensionSelector(widget, pd->ext_select_list+i, FALSE);
}
UNLOCK_PROCESS;
UNLOCK_APP(app);
}