162 lines
5.0 KiB
C
162 lines
5.0 KiB
C
/* callback.c
|
|
*
|
|
* $Id$
|
|
*
|
|
* Copyright 1990, 1991, 1992, 1993, 1994, 1995, Oliver Laumann, Berlin
|
|
* Copyright 2002, 2003 Sam Hocevar <sam@hocevar.net>, Paris
|
|
*
|
|
* This software was derived from Elk 1.2, which was Copyright 1987, 1988,
|
|
* 1989, Nixdorf Computer AG and TELES GmbH, Berlin (Elk 1.2 has been written
|
|
* by Oliver Laumann for TELES Telematic Services, Berlin, in a joint project
|
|
* between TELES and Nixdorf Microprocessor Engineering, Berlin).
|
|
*
|
|
* Oliver Laumann, TELES GmbH, Nixdorf Computer AG and Sam Hocevar, as co-
|
|
* owners or individual owners of copyright in this software, grant to any
|
|
* person or company a worldwide, royalty free, license to
|
|
*
|
|
* i) copy this software,
|
|
* ii) prepare derivative works based on this software,
|
|
* iii) distribute copies of this software or derivative works,
|
|
* iv) perform this software, or
|
|
* v) display this software,
|
|
*
|
|
* provided that this notice is not removed and that neither Oliver Laumann
|
|
* nor Teles nor Nixdorf are deemed to have made any representations as to
|
|
* the suitability of this software for any purpose nor are held responsible
|
|
* for any defects of this software.
|
|
*
|
|
* THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
|
*/
|
|
|
|
#include "xt.h"
|
|
|
|
void Remove_All_Callbacks (Widget w);
|
|
|
|
typedef struct {
|
|
PFX2S converter;
|
|
int num;
|
|
} CLIENT_DATA;
|
|
|
|
Object Get_Callbackfun (XtPointer c) {
|
|
register CLIENT_DATA *cd = (CLIENT_DATA *)c;
|
|
return cd ? Get_Function (cd->num) : False;
|
|
}
|
|
|
|
static void Callback_Proc (Widget w, XtPointer client_data,
|
|
XtPointer call_data) {
|
|
register CLIENT_DATA *cd = (CLIENT_DATA *)client_data;
|
|
Object args;
|
|
GC_Node;
|
|
|
|
args = Null;
|
|
GC_Link (args);
|
|
if (cd->converter)
|
|
args = Cons ((cd->converter)((XtArgVal)call_data), args);
|
|
args = Cons (Make_Widget_Foreign (w), args);
|
|
GC_Unlink;
|
|
(void)Funcall (Get_Callbackfun (client_data), args, 0);
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
void Destroy_Callback_Proc (Widget w, XtPointer client_data,
|
|
XtPointer call_data) {
|
|
Object x;
|
|
|
|
x = Find_Object (T_Widget, (GENERIC)0, Match_Xt_Obj, w);
|
|
if (Nullp (x) || WIDGET(x)->free)
|
|
return;
|
|
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 (Widget w) {
|
|
XtRemoveCallback (w, XtNdestroyCallback, Destroy_Callback_Proc,
|
|
(XtPointer)0);
|
|
XtAddCallback (w, XtNdestroyCallback, Destroy_Callback_Proc, (XtPointer)0);
|
|
}
|
|
|
|
void Check_Callback_List (Object x) {
|
|
Object tail;
|
|
|
|
Check_List (x);
|
|
for (tail = x; !Nullp (tail); tail = Cdr (tail))
|
|
Check_Procedure (Car (tail));
|
|
}
|
|
|
|
static Object P_Add_Callbacks (Object w, Object name, Object cbl) {
|
|
register char *s;
|
|
register int 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,
|
|
Find_Callback_Converter (XtClass (WIDGET(w)->widget), s, name));
|
|
XtAddCallbacks (WIDGET(w)->widget, s, callbacks);
|
|
if (streq (s, XtNdestroyCallback))
|
|
Fiddle_Destroy_Callback (WIDGET(w)->widget);
|
|
Alloca_End;
|
|
return Void;
|
|
}
|
|
|
|
void Fill_Callbacks (Object src, XtCallbackList dst, register int n,
|
|
PFX2S conv) {
|
|
register CLIENT_DATA *cd;
|
|
register int i, j;
|
|
Object tail;
|
|
|
|
for (i = 0, tail = src; i < n; i++, tail = Cdr (tail)) {
|
|
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;
|
|
}
|
|
}
|
|
|
|
void Remove_All_Callbacks (Widget w) {
|
|
Arg a[1];
|
|
XtCallbackList c;
|
|
XtResource *r;
|
|
int nr, nc;
|
|
register int i, j;
|
|
|
|
Get_All_Resources (0, w, XtClass (w), &r, &nr, &nc);
|
|
for (j = 0; j < nr; j++) {
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
XtFree ((char *)r);
|
|
}
|
|
|
|
void elk_init_xt_callback () {
|
|
Define_Primitive (P_Add_Callbacks, "add-callbacks", 3, 3, EVAL);
|
|
}
|