2003-08-19 15:19:38 -04:00
|
|
|
#include "xt.h"
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
PFX2S converter;
|
|
|
|
int num;
|
|
|
|
} CLIENT_DATA;
|
|
|
|
|
|
|
|
Object Get_Callbackfun (c) XtPointer c; {
|
|
|
|
register CLIENT_DATA *cd = (CLIENT_DATA *)c;
|
|
|
|
return cd ? Get_Function (cd->num) : False;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Callback_Proc (w, client_data, call_data) Widget w;
|
2003-09-02 04:12:11 -04:00
|
|
|
XtPointer client_data, call_data; {
|
2003-08-19 15:19:38 -04:00
|
|
|
register CLIENT_DATA *cd = (CLIENT_DATA *)client_data;
|
|
|
|
Object args;
|
|
|
|
GC_Node;
|
2003-08-19 15:25:03 -04:00
|
|
|
|
2003-08-19 15:19:38 -04:00
|
|
|
args = Null;
|
|
|
|
GC_Link (args);
|
|
|
|
if (cd->converter)
|
2003-09-02 04:12:11 -04:00
|
|
|
args = Cons ((cd->converter)((XtArgVal)call_data), args);
|
2003-08-19 15:19:38 -04:00
|
|
|
args = Cons (Make_Widget_Foreign (w), args);
|
|
|
|
GC_Unlink;
|
|
|
|
(void)Funcall (Get_Callbackfun (client_data), args, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
void Destroy_Callback_Proc (w, client_data, call_data) Widget w;
|
2003-09-02 04:12:11 -04:00
|
|
|
XtPointer client_data, call_data; {
|
2003-08-19 15:19:38 -04:00
|
|
|
Object x;
|
|
|
|
|
|
|
|
x = Find_Object (T_Widget, (GENERIC)0, Match_Xt_Obj, w);
|
|
|
|
if (Nullp (x) || WIDGET(x)->free)
|
2003-09-02 04:12:11 -04:00
|
|
|
return;
|
2003-08-19 15:19:38 -04:00
|
|
|
WIDGET(x)->free = 1;
|
|
|
|
Remove_All_Callbacks (w);
|
|
|
|
Deregister_Object (x);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The code assumes that callbacks are called in the order they
|
|
|
|
* have been added. The Destroy_Callback_Proc() must always be
|
|
|
|
* the last callback in the destroy callback list of each widget.
|
|
|
|
*
|
|
|
|
* When the destroy callback list of a widget is modified
|
|
|
|
* (via P_Add_Callbacks or P_Set_Values), Fiddle_Destroy_Callback()
|
|
|
|
* must be called to remove the Destroy_Callback_Proc() and put
|
|
|
|
* it back to the end of the callback list.
|
|
|
|
*/
|
|
|
|
void Fiddle_Destroy_Callback (w) Widget w; {
|
|
|
|
XtRemoveCallback (w, XtNdestroyCallback, Destroy_Callback_Proc,
|
2003-09-02 04:12:11 -04:00
|
|
|
(XtPointer)0);
|
2003-08-19 15:19:38 -04:00
|
|
|
XtAddCallback (w, XtNdestroyCallback, Destroy_Callback_Proc, (XtPointer)0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Check_Callback_List (x) Object x; {
|
|
|
|
Object tail;
|
|
|
|
|
|
|
|
Check_List (x);
|
|
|
|
for (tail = x; !Nullp (tail); tail = Cdr (tail))
|
2003-09-02 04:12:11 -04:00
|
|
|
Check_Procedure (Car (tail));
|
2003-08-19 15:19:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static Object P_Add_Callbacks (w, name, cbl) Object w, name, cbl; {
|
|
|
|
register char *s;
|
|
|
|
register n;
|
|
|
|
XtCallbackList callbacks;
|
|
|
|
Alloca_Begin;
|
|
|
|
|
|
|
|
Check_Widget (w);
|
|
|
|
Check_Callback_List (cbl);
|
|
|
|
s = Get_Strsym (name);
|
|
|
|
Make_Resource_Name (s);
|
|
|
|
n = Fast_Length (cbl);
|
|
|
|
Alloca (callbacks, XtCallbackRec*, (n+1) * sizeof (XtCallbackRec));
|
|
|
|
callbacks[n].callback = 0;
|
|
|
|
callbacks[n].closure = 0;
|
|
|
|
Fill_Callbacks (cbl, callbacks, n,
|
2003-09-02 04:12:11 -04:00
|
|
|
Find_Callback_Converter (XtClass (WIDGET(w)->widget), s, name));
|
2003-08-19 15:19:38 -04:00
|
|
|
XtAddCallbacks (WIDGET(w)->widget, s, callbacks);
|
|
|
|
if (streq (s, XtNdestroyCallback))
|
2003-09-02 04:12:11 -04:00
|
|
|
Fiddle_Destroy_Callback (WIDGET(w)->widget);
|
2003-08-19 15:19:38 -04:00
|
|
|
Alloca_End;
|
|
|
|
return Void;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Fill_Callbacks (src, dst, n, conv) Object src; XtCallbackList dst;
|
2003-09-02 04:12:11 -04:00
|
|
|
register n; PFX2S conv; {
|
2003-08-19 15:19:38 -04:00
|
|
|
register CLIENT_DATA *cd;
|
|
|
|
register i, j;
|
|
|
|
Object tail;
|
|
|
|
|
|
|
|
for (i = 0, tail = src; i < n; i++, tail = Cdr (tail)) {
|
2003-09-02 04:12:11 -04:00
|
|
|
j = Register_Function (Car (tail));
|
|
|
|
cd = (CLIENT_DATA *)XtMalloc (sizeof (CLIENT_DATA));
|
|
|
|
cd->converter = conv;
|
|
|
|
cd->num = j;
|
|
|
|
dst[i].callback = (XtCallbackProc)Callback_Proc;
|
|
|
|
dst[i].closure = (XtPointer)cd;
|
2003-08-19 15:19:38 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Remove_All_Callbacks (w) Widget w; {
|
|
|
|
Arg a[1];
|
|
|
|
XtCallbackList c;
|
|
|
|
XtResource *r;
|
|
|
|
int nr, nc;
|
|
|
|
register i, j;
|
|
|
|
|
|
|
|
Get_All_Resources (0, w, XtClass (w), &r, &nr, &nc);
|
|
|
|
for (j = 0; j < nr; j++) {
|
2003-09-02 04:12:11 -04:00
|
|
|
if (streq (r[j].resource_type, XtRCallback)) {
|
|
|
|
XtSetArg (a[0], r[j].resource_name, &c);
|
|
|
|
XtGetValues (w, a, 1);
|
|
|
|
for (i = 0; c[i].callback; i++) {
|
|
|
|
register CLIENT_DATA *cd = (CLIENT_DATA *)c[i].closure;
|
|
|
|
if (c[i].callback == (XtCallbackProc)Callback_Proc && cd) {
|
|
|
|
Deregister_Function (cd->num);
|
|
|
|
XtFree ((char *)cd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-08-19 15:19:38 -04:00
|
|
|
}
|
|
|
|
XtFree ((char *)r);
|
|
|
|
}
|
|
|
|
|
|
|
|
elk_init_xt_callback () {
|
|
|
|
Define_Primitive (P_Add_Callbacks, "add-callbacks", 3, 3, EVAL);
|
|
|
|
}
|