#include "IntrinsicI.h"
static String XtNinvalidCallbackList = "invalidCallbackList";
static String XtNxtAddCallback = "xtAddCallback";
static String XtNxtRemoveCallback = "xtRemoveCallback";
static String XtNxtRemoveAllCallback = "xtRemoveAllCallback";
static String XtNxtCallCallback = "xtCallCallback";
#define ToList(p) ((XtCallbackList) ((p)+1))
static InternalCallbackList* FetchInternalList(
Widget widget,
_Xconst char *name)
{
XrmQuark quark;
int n;
CallbackTable offsets;
InternalCallbackList* retval = NULL;
quark = StringToQuark(name);
LOCK_PROCESS;
offsets = (CallbackTable)
widget->core.widget_class->core_class.callback_private;
for (n = (int)(long) *(offsets++); --n >= 0; offsets++)
if (quark == (*offsets)->xrm_name) {
retval = (InternalCallbackList *)
((char *) widget - (*offsets)->xrm_offset - 1);
break;
}
UNLOCK_PROCESS;
return retval;
}
void _XtAddCallback(callbacks, callback, closure)
InternalCallbackList* callbacks;
XtCallbackProc callback;
XtPointer closure;
{
register InternalCallbackList icl;
register XtCallbackList cl;
register int count;
icl = *callbacks;
count = icl ? icl->count : 0;
if (icl && icl->call_state) {
icl->call_state |= _XtCBFreeAfterCalling;
icl = (InternalCallbackList)
__XtMalloc(sizeof(InternalCallbackRec) +
sizeof(XtCallbackRec) * (count + 1));
(void) memmove((char *)ToList(icl), (char *)ToList(*callbacks),
sizeof(XtCallbackRec) * count);
} else {
icl = (InternalCallbackList)
XtRealloc((char *) icl, sizeof(InternalCallbackRec) +
sizeof(XtCallbackRec) * (count + 1));
}
*callbacks = icl;
icl->count = count + 1;
icl->is_padded = 0;
icl->call_state = 0;
cl = ToList(icl) + count;
cl->callback = callback;
cl->closure = closure;
}
void _XtAddCallbackOnce(callbacks, callback, closure)
register InternalCallbackList*callbacks;
XtCallbackProc callback;
XtPointer closure;
{
register XtCallbackList cl = ToList(*callbacks);
register int i;
for (i=(*callbacks)->count; --i >= 0; cl++)
if (cl->callback == callback && cl->closure == closure)
return;
_XtAddCallback(callbacks, callback, closure);
}
void XtAddCallback(
Widget widget,
_Xconst char* name,
XtCallbackProc callback,
XtPointer closure
)
{
InternalCallbackList *callbacks;
Widget hookobj;
XtAppContext app = XtWidgetToApplicationContext(widget);
LOCK_APP(app);
callbacks = FetchInternalList(widget, name);
if (!callbacks) {
XtAppWarningMsg(app,
XtNinvalidCallbackList,XtNxtAddCallback,XtCXtToolkitError,
"Cannot find callback list in XtAddCallback",
(String *)NULL, (Cardinal *)NULL);
UNLOCK_APP(app);
return;
}
_XtAddCallback(callbacks, callback, closure);
if (!_XtIsHookObject(widget)) {
hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
XtChangeHookDataRec call_data;
call_data.type = XtHaddCallback;
call_data.widget = widget;
call_data.event_data = (XtPointer) name;
XtCallCallbackList(hookobj,
((HookObject)hookobj)->hooks.changehook_callbacks,
(XtPointer)&call_data);
}
}
UNLOCK_APP(app);
}
static void AddCallbacks(
Widget widget,
InternalCallbackList *callbacks,
XtCallbackList newcallbacks)
{
register InternalCallbackList icl;
register int i, j;
register XtCallbackList cl;
icl = *callbacks;
i = icl ? icl->count : 0;
for (j=0, cl = newcallbacks; cl->callback; cl++, j++);
if (icl && icl->call_state) {
icl->call_state |= _XtCBFreeAfterCalling;
icl = (InternalCallbackList) __XtMalloc(sizeof(InternalCallbackRec) +
sizeof(XtCallbackRec) * (i+j));
(void) memmove((char *)ToList(*callbacks), (char *)ToList(icl),
sizeof(XtCallbackRec) * i);
} else {
icl = (InternalCallbackList) XtRealloc((char *) icl,
sizeof(InternalCallbackRec) +
sizeof(XtCallbackRec) * (i+j));
}
*callbacks = icl;
icl->count = i+j;
icl->is_padded = 0;
icl->call_state = 0;
for (cl = ToList(icl) + i; --j >= 0; )
*cl++ = *newcallbacks++;
}
void XtAddCallbacks(
Widget widget,
_Xconst char* name,
XtCallbackList xtcallbacks
)
{
InternalCallbackList* callbacks;
Widget hookobj;
XtAppContext app = XtWidgetToApplicationContext(widget);
LOCK_APP(app);
callbacks = FetchInternalList(widget, name);
if (!callbacks) {
XtAppWarningMsg(app,
XtNinvalidCallbackList,XtNxtAddCallback,XtCXtToolkitError,
"Cannot find callback list in XtAddCallbacks",
(String *)NULL, (Cardinal *)NULL);
UNLOCK_APP(app);
return;
}
AddCallbacks(widget, callbacks, xtcallbacks);
hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
XtChangeHookDataRec call_data;
call_data.type = XtHaddCallbacks;
call_data.widget = widget;
call_data.event_data = (XtPointer) name;
XtCallCallbackList(hookobj,
((HookObject)hookobj)->hooks.changehook_callbacks,
(XtPointer)&call_data);
}
UNLOCK_APP(app);
}
void _XtRemoveCallback (callbacks, callback, closure)
InternalCallbackList *callbacks;
XtCallbackProc callback;
XtPointer closure;
{
register InternalCallbackList icl;
register int i, j;
register XtCallbackList cl, ncl, ocl;
icl = *callbacks;
if (!icl) return;
cl = ToList(icl);
for (i=icl->count; --i >= 0; cl++) {
if (cl->callback == callback && cl->closure == closure) {
if (icl->call_state) {
icl->call_state |= _XtCBFreeAfterCalling;
if (icl->count == 1) {
*callbacks = NULL;
} else {
j = icl->count - i - 1;
ocl = ToList(icl);
icl = (InternalCallbackList)
__XtMalloc(sizeof(InternalCallbackRec) +
sizeof(XtCallbackRec) * (i + j));
icl->count = i + j;
icl->is_padded = 0;
icl->call_state = 0;
ncl = ToList(icl);
while (--j >= 0)
*ncl++ = *ocl++;
while (--i >= 0)
*ncl++ = *++cl;
*callbacks = icl;
}
} else {
if (--icl->count) {
ncl = cl + 1;
while (--i >= 0)
*cl++ = *ncl++;
icl = (InternalCallbackList)
XtRealloc((char *) icl, sizeof(InternalCallbackRec)
+ sizeof(XtCallbackRec) * icl->count);
icl->is_padded = 0;
*callbacks = icl;
} else {
XtFree((char *) icl);
*callbacks = NULL;
}
}
return;
}
}
}
void XtRemoveCallback (
Widget widget,
_Xconst char* name,
XtCallbackProc callback,
XtPointer closure
)
{
InternalCallbackList *callbacks;
Widget hookobj;
XtAppContext app = XtWidgetToApplicationContext(widget);
LOCK_APP(app);
callbacks = FetchInternalList(widget, name);
if (!callbacks) {
XtAppWarningMsg(app,
XtNinvalidCallbackList,XtNxtRemoveCallback,XtCXtToolkitError,
"Cannot find callback list in XtRemoveCallback",
(String *)NULL, (Cardinal *)NULL);
UNLOCK_APP(app);
return;
}
_XtRemoveCallback(callbacks, callback, closure);
hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
XtChangeHookDataRec call_data;
call_data.type = XtHremoveCallback;
call_data.widget = widget;
call_data.event_data = (XtPointer) name;
XtCallCallbackList(hookobj,
((HookObject)hookobj)->hooks.changehook_callbacks,
(XtPointer)&call_data);
}
UNLOCK_APP(app);
}
void XtRemoveCallbacks (widget, name, xtcallbacks)
Widget widget;
_Xconst char* name;
XtCallbackList xtcallbacks;
{
InternalCallbackList *callbacks;
Widget hookobj;
int i;
InternalCallbackList icl;
XtCallbackList cl, ccl, rcl;
XtAppContext app = XtWidgetToApplicationContext(widget);
LOCK_APP(app);
callbacks = FetchInternalList(widget, name);
if (!callbacks) {
XtAppWarningMsg(app,
XtNinvalidCallbackList,XtNxtRemoveCallback,XtCXtToolkitError,
"Cannot find callback list in XtRemoveCallbacks",
(String *)NULL, (Cardinal *)NULL);
UNLOCK_APP(app);
return;
}
icl = *callbacks;
if (!icl) {
UNLOCK_APP(app);
return;
}
i = icl->count;
cl = ToList(icl);
if (icl->call_state) {
icl->call_state |= _XtCBFreeAfterCalling;
icl = (InternalCallbackList)__XtMalloc(sizeof(InternalCallbackRec) +
sizeof(XtCallbackRec) * i);
icl->count = i;
icl->call_state = 0;
}
ccl = ToList(icl);
while (--i >= 0) {
*ccl++ = *cl;
for (rcl=xtcallbacks; rcl->callback; rcl++) {
if (cl->callback == rcl->callback && cl->closure == rcl->closure) {
ccl--;
icl->count--;
break;
}
}
cl++;
}
if (icl->count) {
icl = (InternalCallbackList)
XtRealloc((char *)icl, (sizeof(InternalCallbackRec) +
sizeof(XtCallbackRec) * icl->count));
icl->is_padded = 0;
*callbacks = icl;
} else {
XtFree((char *)icl);
*callbacks = NULL;
}
hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
XtChangeHookDataRec call_data;
call_data.type = XtHremoveCallbacks;
call_data.widget = widget;
call_data.event_data = (XtPointer) name;
XtCallCallbackList(hookobj,
((HookObject)hookobj)->hooks.changehook_callbacks,
(XtPointer)&call_data);
}
UNLOCK_APP(app);
}
void _XtRemoveAllCallbacks (callbacks)
InternalCallbackList *callbacks;
{
register InternalCallbackList icl = *callbacks;
if (icl) {
if (icl->call_state)
icl->call_state |= _XtCBFreeAfterCalling;
else
XtFree((char *) icl);
*callbacks = NULL;
}
}
void XtRemoveAllCallbacks(widget, name)
Widget widget;
_Xconst char* name;
{
InternalCallbackList *callbacks;
Widget hookobj;
XtAppContext app = XtWidgetToApplicationContext(widget);
LOCK_APP(app);
callbacks = FetchInternalList(widget, name);
if (!callbacks) {
XtAppWarningMsg(app,
XtNinvalidCallbackList,XtNxtRemoveAllCallback,XtCXtToolkitError,
"Cannot find callback list in XtRemoveAllCallbacks",
(String *)NULL, (Cardinal *)NULL);
UNLOCK_APP(app);
return;
}
_XtRemoveAllCallbacks(callbacks);
hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
XtChangeHookDataRec call_data;
call_data.type = XtHremoveAllCallbacks;
call_data.widget = widget;
call_data.event_data = (XtPointer) name;
XtCallCallbackList(hookobj,
((HookObject)hookobj)->hooks.changehook_callbacks,
(XtPointer)&call_data);
}
UNLOCK_APP(app);
}
InternalCallbackList _XtCompileCallbackList(xtcallbacks)
XtCallbackList xtcallbacks;
{
register int n;
register XtCallbackList xtcl, cl;
register InternalCallbackList callbacks;
for (n=0, xtcl=xtcallbacks; xtcl->callback; n++, xtcl++) {};
if (n == 0) return (InternalCallbackList) NULL;
callbacks = (InternalCallbackList) __XtMalloc(sizeof(InternalCallbackRec) +
sizeof(XtCallbackRec) * n);
callbacks->count = n;
callbacks->is_padded = 0;
callbacks->call_state = 0;
cl = ToList(callbacks);
while (--n >= 0)
*cl++ = *xtcallbacks++;
return(callbacks);
}
XtCallbackList _XtGetCallbackList(callbacks)
InternalCallbackList *callbacks;
{
register int i;
register InternalCallbackList icl;
register XtCallbackList cl, ocl;
icl = *callbacks;
if (!icl) {
static XtCallbackRec emptyList[1] = { {NULL, NULL} };
return (XtCallbackList)emptyList;
}
if (icl->is_padded)
return ToList(icl);
i = icl->count;
if (icl->call_state) {
icl->call_state |= _XtCBFreeAfterCalling;
ocl = ToList(icl);
icl = (InternalCallbackList) __XtMalloc(sizeof(InternalCallbackRec) +
sizeof(XtCallbackRec) * (i+1));
icl->count = i;
icl->call_state = 0;
cl = ToList(icl);
while (--i >= 0)
*cl++ = *ocl++;
} else {
icl = (InternalCallbackList) XtRealloc((char *)icl,
sizeof(InternalCallbackRec) +
sizeof(XtCallbackRec) * (i+1));
cl = ToList(icl) + i;
}
icl->is_padded = 1;
cl->callback = (XtCallbackProc) NULL;
cl->closure = NULL;
*callbacks = icl;
return ToList(icl);
}
void XtCallCallbacks(
Widget widget,
_Xconst char* name,
XtPointer call_data
)
{
InternalCallbackList *callbacks;
InternalCallbackList icl;
XtCallbackList cl;
int i;
char ostate;
XtAppContext app = XtWidgetToApplicationContext(widget);
LOCK_APP(app);
callbacks = FetchInternalList(widget, name);
if (!callbacks) {
XtAppWarningMsg(app,
XtNinvalidCallbackList,XtNxtCallCallback,XtCXtToolkitError,
"Cannot find callback list in XtCallCallbacks",
(String *)NULL, (Cardinal *)NULL);
UNLOCK_APP(app);
return;
}
icl = *callbacks;
if (!icl) {
UNLOCK_APP(app);
return;
}
cl = ToList(icl);
if (icl->count == 1) {
(*cl->callback) (widget, cl->closure, call_data);
UNLOCK_APP(app);
return;
}
ostate = icl->call_state;
icl->call_state = _XtCBCalling;
for (i = icl->count; --i >= 0; cl++)
(*cl->callback) (widget, cl->closure, call_data);
if (ostate)
icl->call_state |= ostate;
else if (icl->call_state & _XtCBFreeAfterCalling)
XtFree((char *)icl);
else
icl->call_state = ostate;
UNLOCK_APP(app);
}
XtCallbackStatus XtHasCallbacks(
Widget widget,
_Xconst char* callback_name
)
{
InternalCallbackList *callbacks;
XtCallbackStatus retval = XtCallbackHasSome;
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
callbacks = FetchInternalList(widget, callback_name);
if (!callbacks)
retval = XtCallbackNoList;
else if (!*callbacks)
retval = XtCallbackHasNone;
UNLOCK_APP(app);
return retval;
}
void XtCallCallbackList(widget, callbacks, call_data)
Widget widget;
XtCallbackList callbacks;
XtPointer call_data;
{
register InternalCallbackList icl;
register XtCallbackList cl;
register int i;
char ostate;
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
if (!callbacks) {
UNLOCK_APP(app);
return;
}
icl = (InternalCallbackList)callbacks;
cl = ToList(icl);
if (icl->count == 1) {
(*cl->callback) (widget, cl->closure, call_data);
UNLOCK_APP(app);
return;
}
ostate = icl->call_state;
icl->call_state = _XtCBCalling;
for (i = icl->count; --i >= 0; cl++)
(*cl->callback) (widget, cl->closure, call_data);
if (ostate)
icl->call_state |= ostate;
else if (icl->call_state & _XtCBFreeAfterCalling)
XtFree((char *)icl);
else
icl->call_state = 0;
UNLOCK_APP(app);
}
void _XtPeekCallback(widget, callbacks, callback, closure)
Widget widget;
XtCallbackList callbacks;
XtCallbackProc *callback;
XtPointer *closure;
{
register InternalCallbackList icl = (InternalCallbackList) callbacks;
register XtCallbackList cl;
if (!callbacks) {
*callback = (XtCallbackProc) NULL;
return;
}
cl = ToList(icl);
*callback = cl->callback;
*closure = cl->closure;
return;
}
void _XtCallConditionalCallbackList(widget, callbacks, call_data, cond_proc)
Widget widget;
XtCallbackList callbacks;
XtPointer call_data;
_XtConditionProc cond_proc;
{
register InternalCallbackList icl;
register XtCallbackList cl;
register int i;
char ostate;
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
if (!callbacks) {
UNLOCK_APP(app);
return;
}
icl = (InternalCallbackList)callbacks;
cl = ToList(icl);
if (icl->count == 1) {
(*cl->callback) (widget, cl->closure, call_data);
(void) (*cond_proc)(call_data);
UNLOCK_APP(app);
return;
}
ostate = icl->call_state;
icl->call_state = _XtCBCalling;
for (i = icl->count; --i >= 0; cl++) {
(*cl->callback) (widget, cl->closure, call_data);
if (! (*cond_proc)(call_data))
break;
}
if (ostate)
icl->call_state |= ostate;
else if (icl->call_state & _XtCBFreeAfterCalling)
XtFree((char *)icl);
else
icl->call_state = 0;
UNLOCK_APP(app);
}