Callback.c revision 0568f49b
1/***********************************************************
2Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
3
4Permission is hereby granted, free of charge, to any person obtaining a
5copy of this software and associated documentation files (the "Software"),
6to deal in the Software without restriction, including without limitation
7the rights to use, copy, modify, merge, publish, distribute, sublicense,
8and/or sell copies of the Software, and to permit persons to whom the
9Software is furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice (including the next
12paragraph) shall be included in all copies or substantial portions of the
13Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21DEALINGS IN THE SOFTWARE.
22
23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
24
25                        All Rights Reserved
26
27Permission to use, copy, modify, and distribute this software and its
28documentation for any purpose and without fee is hereby granted,
29provided that the above copyright notice appear in all copies and that
30both that copyright notice and this permission notice appear in
31supporting documentation, and that the name of Digital not be
32used in advertising or publicity pertaining to distribution of the
33software without specific, written prior permission.
34
35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41SOFTWARE.
42
43******************************************************************/
44
45/*
46
47Copyright 1987, 1988, 1998  The Open Group
48
49Permission to use, copy, modify, distribute, and sell this software and its
50documentation for any purpose is hereby granted without fee, provided that
51the above copyright notice appear in all copies and that both that
52copyright notice and this permission notice appear in supporting
53documentation.
54
55The above copyright notice and this permission notice shall be included in
56all copies or substantial portions of the Software.
57
58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64
65Except as contained in this notice, the name of The Open Group shall not be
66used in advertising or otherwise to promote the sale, use or other dealings
67in this Software without prior written authorization from The Open Group.
68
69*/
70
71#ifdef HAVE_CONFIG_H
72#include <config.h>
73#endif
74#include "IntrinsicI.h"
75
76static _Xconst _XtString XtNinvalidCallbackList = "invalidCallbackList";
77static _Xconst _XtString XtNxtAddCallback = "xtAddCallback";
78static _Xconst _XtString XtNxtRemoveCallback = "xtRemoveCallback";
79static _Xconst _XtString XtNxtRemoveAllCallback = "xtRemoveAllCallback";
80static _Xconst _XtString XtNxtCallCallback = "xtCallCallback";
81
82/* However it doesn't contain a final NULL record */
83#define ToList(p) ((XtCallbackList) ((p)+1))
84
85static InternalCallbackList* FetchInternalList(
86    Widget	widget,
87    _Xconst char *name)
88{
89    XrmQuark quark;
90    int n;
91    CallbackTable offsets;
92    InternalCallbackList* retval = NULL;
93
94    quark = StringToQuark(name);
95    LOCK_PROCESS;
96    offsets = (CallbackTable)
97	widget->core.widget_class->core_class.callback_private;
98
99    for (n = (int)(long) *(offsets++); --n >= 0; offsets++)
100	if (quark == (*offsets)->xrm_name) {
101	    retval = (InternalCallbackList *)
102		((char *) widget - (*offsets)->xrm_offset - 1);
103	    break;
104	}
105    UNLOCK_PROCESS;
106    return retval;
107}
108
109
110void _XtAddCallback(
111    InternalCallbackList*   callbacks,
112    XtCallbackProc	    callback,
113    XtPointer		    closure)
114{
115    register InternalCallbackList icl;
116    register XtCallbackList cl;
117    register int count;
118
119    icl = *callbacks;
120    count = icl ? icl->count : 0;
121
122    if (icl && icl->call_state) {
123	icl->call_state |= _XtCBFreeAfterCalling;
124	icl = (InternalCallbackList)
125	    __XtMalloc((Cardinal) (sizeof(InternalCallbackRec) +
126		     sizeof(XtCallbackRec) * (size_t) (count + 1)));
127	(void) memmove((char *)ToList(icl), (char *)ToList(*callbacks),
128		       sizeof(XtCallbackRec) * (size_t) count);
129    } else {
130	icl = (InternalCallbackList)
131	    XtRealloc((char *) icl, (Cardinal)(sizeof(InternalCallbackRec) +
132		      sizeof(XtCallbackRec) * (size_t) (count + 1)));
133    }
134    *callbacks = icl;
135    icl->count = (unsigned short) (count + 1);
136    icl->is_padded = 0;
137    icl->call_state = 0;
138    cl = ToList(icl) + count;
139    cl->callback = callback;
140    cl->closure = closure;
141} /* _XtAddCallback */
142
143void _XtAddCallbackOnce(
144    register InternalCallbackList*callbacks,
145    XtCallbackProc	    callback,
146    XtPointer		    closure)
147{
148    register XtCallbackList cl = ToList(*callbacks);
149    register int i;
150
151    for (i=(*callbacks)->count; --i >= 0; cl++)
152	if (cl->callback == callback && cl->closure == closure)
153	    return;
154
155    _XtAddCallback(callbacks, callback, closure);
156} /* _XtAddCallbackOnce */
157
158void XtAddCallback(
159    Widget	    widget,
160    _Xconst char*   name,
161    XtCallbackProc  callback,
162    XtPointer	    closure
163    )
164{
165    InternalCallbackList *callbacks;
166    XtAppContext app = XtWidgetToApplicationContext(widget);
167
168    LOCK_APP(app);
169    callbacks = FetchInternalList(widget, name);
170    if (!callbacks) {
171	XtAppWarningMsg(app,
172	       XtNinvalidCallbackList,XtNxtAddCallback,XtCXtToolkitError,
173              "Cannot find callback list in XtAddCallback",
174	      NULL, NULL);
175	UNLOCK_APP(app);
176	return;
177    }
178    _XtAddCallback(callbacks, callback, closure);
179    if (!_XtIsHookObject(widget)) {
180        Widget hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
181	if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
182	    XtChangeHookDataRec call_data;
183
184	    call_data.type = XtHaddCallback;
185	    call_data.widget = widget;
186	    call_data.event_data = (XtPointer) name;
187	    XtCallCallbackList(hookobj,
188		((HookObject)hookobj)->hooks.changehook_callbacks,
189		(XtPointer)&call_data);
190	}
191    }
192    UNLOCK_APP(app);
193} /* XtAddCallback */
194
195/* ARGSUSED */
196static void AddCallbacks(
197    Widget		    widget,
198    InternalCallbackList   *callbacks,
199    XtCallbackList	    newcallbacks)
200{
201    register InternalCallbackList icl;
202    register int i, j;
203    register XtCallbackList cl;
204
205    icl = *callbacks;
206    i = icl ? icl->count : 0;
207    for (j=0, cl = newcallbacks; cl->callback; cl++, j++);
208    if (icl && icl->call_state) {
209	icl->call_state |= _XtCBFreeAfterCalling;
210	icl = (InternalCallbackList) __XtMalloc((Cardinal)(sizeof(InternalCallbackRec) +
211					      sizeof(XtCallbackRec) * (size_t) (i+j)));
212	(void) memmove((char *)ToList(*callbacks), (char *)ToList(icl),
213		       sizeof(XtCallbackRec) * (size_t) i);
214    } else {
215	icl = (InternalCallbackList) XtRealloc((char *) icl,
216					       (Cardinal)(sizeof(InternalCallbackRec) +
217					       sizeof(XtCallbackRec) * (size_t) (i+j)));
218    }
219    *callbacks = icl;
220    icl->count = (unsigned short) (i+j);
221    icl->is_padded = 0;
222    icl->call_state = 0;
223    for (cl = ToList(icl) + i; --j >= 0; )
224	*cl++ = *newcallbacks++;
225} /* AddCallbacks */
226
227void XtAddCallbacks(
228    Widget	    widget,
229    _Xconst char*   name,
230    XtCallbackList  xtcallbacks
231    )
232{
233    InternalCallbackList* callbacks;
234    Widget hookobj;
235    XtAppContext app = XtWidgetToApplicationContext(widget);
236
237    LOCK_APP(app);
238    callbacks = FetchInternalList(widget, name);
239    if (!callbacks) {
240	XtAppWarningMsg(app,
241	       XtNinvalidCallbackList,XtNxtAddCallback,XtCXtToolkitError,
242              "Cannot find callback list in XtAddCallbacks",
243	      NULL, NULL);
244	UNLOCK_APP(app);
245	return;
246    }
247    AddCallbacks(widget, callbacks, xtcallbacks);
248    hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
249    if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
250	XtChangeHookDataRec call_data;
251
252	call_data.type = XtHaddCallbacks;
253	call_data.widget = widget;
254	call_data.event_data = (XtPointer) name;
255	XtCallCallbackList(hookobj,
256		((HookObject)hookobj)->hooks.changehook_callbacks,
257		(XtPointer)&call_data);
258    }
259    UNLOCK_APP(app);
260} /* XtAddCallbacks */
261
262void _XtRemoveCallback (
263    InternalCallbackList   *callbacks,
264    XtCallbackProc	    callback,
265    XtPointer		    closure)
266{
267    register InternalCallbackList icl;
268    register int i, j;
269    register XtCallbackList cl, ncl, ocl;
270
271    icl = *callbacks;
272    if (!icl) return;
273
274    cl = ToList(icl);
275    for (i=icl->count; --i >= 0; cl++) {
276	if (cl->callback == callback && cl->closure == closure) {
277	    if (icl->call_state) {
278		icl->call_state |= _XtCBFreeAfterCalling;
279		if (icl->count == 1) {
280		    *callbacks = NULL;
281		} else {
282		    j = icl->count - i - 1;
283		    ocl = ToList(icl);
284		    icl = (InternalCallbackList)
285			__XtMalloc((Cardinal) (sizeof(InternalCallbackRec) +
286				 sizeof(XtCallbackRec) * (size_t) (i + j)));
287		    icl->count = (unsigned short) (i + j);
288		    icl->is_padded = 0;
289		    icl->call_state = 0;
290		    ncl = ToList(icl);
291		    while (--j >= 0)
292			*ncl++ = *ocl++;
293		    while (--i >= 0)
294			*ncl++ = *++cl;
295		    *callbacks = icl;
296		}
297	    } else {
298		if (--icl->count) {
299		    ncl = cl + 1;
300		    while (--i >= 0)
301			*cl++ = *ncl++;
302		    icl = (InternalCallbackList)
303			XtRealloc((char *) icl, (Cardinal) (sizeof(InternalCallbackRec)
304				  + sizeof(XtCallbackRec) * icl->count));
305		    icl->is_padded = 0;
306		    *callbacks = icl;
307		} else {
308		    XtFree((char *) icl);
309		    *callbacks = NULL;
310		}
311	    }
312	    return;
313	}
314    }
315} /* _XtRemoveCallback */
316
317void XtRemoveCallback (
318    Widget	    widget,
319    _Xconst char*   name,
320    XtCallbackProc  callback,
321    XtPointer	    closure
322    )
323{
324    InternalCallbackList *callbacks;
325    Widget hookobj;
326    XtAppContext app = XtWidgetToApplicationContext(widget);
327
328    LOCK_APP(app);
329    callbacks = FetchInternalList(widget, name);
330    if (!callbacks) {
331	XtAppWarningMsg(app,
332	       XtNinvalidCallbackList,XtNxtRemoveCallback,XtCXtToolkitError,
333              "Cannot find callback list in XtRemoveCallback",
334	      NULL, NULL);
335	UNLOCK_APP(app);
336	return;
337    }
338    _XtRemoveCallback(callbacks, callback, closure);
339    hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
340    if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
341	XtChangeHookDataRec call_data;
342
343	call_data.type = XtHremoveCallback;
344	call_data.widget = widget;
345	call_data.event_data = (XtPointer) name;
346	XtCallCallbackList(hookobj,
347		((HookObject)hookobj)->hooks.changehook_callbacks,
348		(XtPointer)&call_data);
349    }
350    UNLOCK_APP(app);
351} /* XtRemoveCallback */
352
353
354void XtRemoveCallbacks (
355    Widget	    widget,
356    _Xconst char*   name,
357    XtCallbackList  xtcallbacks)
358{
359    InternalCallbackList *callbacks;
360    Widget hookobj;
361    int i;
362    InternalCallbackList icl;
363    XtCallbackList cl, ccl, rcl;
364    XtAppContext app = XtWidgetToApplicationContext(widget);
365
366    LOCK_APP(app);
367    callbacks = FetchInternalList(widget, name);
368    if (!callbacks) {
369	XtAppWarningMsg(app,
370	       XtNinvalidCallbackList,XtNxtRemoveCallback,XtCXtToolkitError,
371              "Cannot find callback list in XtRemoveCallbacks",
372	      NULL, NULL);
373	UNLOCK_APP(app);
374	return;
375    }
376
377    icl = *callbacks;
378    if (!icl) {
379	UNLOCK_APP(app);
380	return;
381    }
382
383    i = icl->count;
384    cl = ToList(icl);
385    if (icl->call_state) {
386	icl->call_state |= _XtCBFreeAfterCalling;
387	icl = (InternalCallbackList)__XtMalloc((Cardinal)(sizeof(InternalCallbackRec) +
388					     sizeof(XtCallbackRec) * (size_t) i));
389	icl->count = (unsigned short) i;
390	icl->call_state = 0;
391    }
392    ccl = ToList(icl);
393    while (--i >= 0) {
394	*ccl++ = *cl;
395	for (rcl=xtcallbacks; rcl->callback; rcl++) {
396	    if (cl->callback == rcl->callback && cl->closure == rcl->closure) {
397		ccl--;
398		icl->count--;
399		break;
400	    }
401	}
402	cl++;
403    }
404    if (icl->count) {
405	icl = (InternalCallbackList)
406	    XtRealloc((char *)icl, (Cardinal) (sizeof(InternalCallbackRec) +
407				    sizeof(XtCallbackRec) * icl->count));
408	icl->is_padded = 0;
409	*callbacks = icl;
410    } else {
411	XtFree((char *)icl);
412	*callbacks = NULL;
413    }
414    hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
415    if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
416	XtChangeHookDataRec call_data;
417
418	call_data.type = XtHremoveCallbacks;
419	call_data.widget = widget;
420	call_data.event_data = (XtPointer) name;
421	XtCallCallbackList(hookobj,
422		((HookObject)hookobj)->hooks.changehook_callbacks,
423		(XtPointer)&call_data);
424    }
425    UNLOCK_APP(app);
426} /* XtRemoveCallbacks */
427
428
429void _XtRemoveAllCallbacks (
430    InternalCallbackList *callbacks)
431{
432    register InternalCallbackList icl = *callbacks;
433
434    if (icl) {
435	if (icl->call_state)
436	    icl->call_state |= _XtCBFreeAfterCalling;
437	else
438	    XtFree((char *) icl);
439	*callbacks = NULL;
440    }
441} /* _XtRemoveAllCallbacks */
442
443void XtRemoveAllCallbacks(
444    Widget widget,
445    _Xconst char* name)
446{
447    InternalCallbackList *callbacks;
448    Widget hookobj;
449    XtAppContext app = XtWidgetToApplicationContext(widget);
450
451    LOCK_APP(app);
452    callbacks = FetchInternalList(widget, name);
453    if (!callbacks) {
454	XtAppWarningMsg(app,
455	       XtNinvalidCallbackList,XtNxtRemoveAllCallback,XtCXtToolkitError,
456              "Cannot find callback list in XtRemoveAllCallbacks",
457	      NULL, NULL);
458	UNLOCK_APP(app);
459	return;
460    }
461    _XtRemoveAllCallbacks(callbacks);
462    hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
463    if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
464	XtChangeHookDataRec call_data;
465
466	call_data.type = XtHremoveAllCallbacks;
467	call_data.widget = widget;
468	call_data.event_data = (XtPointer) name;
469	XtCallCallbackList(hookobj,
470		((HookObject)hookobj)->hooks.changehook_callbacks,
471		(XtPointer)&call_data);
472    }
473    UNLOCK_APP(app);
474} /* XtRemoveAllCallbacks */
475
476InternalCallbackList _XtCompileCallbackList(
477    XtCallbackList xtcallbacks)
478{
479    register int n;
480    register XtCallbackList xtcl, cl;
481    register InternalCallbackList callbacks;
482
483    for (n=0, xtcl=xtcallbacks; xtcl->callback; n++, xtcl++) {};
484    if (n == 0) return (InternalCallbackList) NULL;
485
486    callbacks = (InternalCallbackList) __XtMalloc((Cardinal) (sizeof(InternalCallbackRec) +
487						sizeof(XtCallbackRec) * (size_t) n));
488    callbacks->count = (unsigned short) n;
489    callbacks->is_padded = 0;
490    callbacks->call_state = 0;
491    cl = ToList(callbacks);
492    while (--n >= 0)
493	*cl++ = *xtcallbacks++;
494    return(callbacks);
495} /* _XtCompileCallbackList */
496
497
498XtCallbackList _XtGetCallbackList(
499    InternalCallbackList *callbacks)
500{
501    int i;
502    InternalCallbackList icl;
503    XtCallbackList cl;
504
505    icl = *callbacks;
506    if (!icl) {
507	static XtCallbackRec emptyList[1] = { {NULL, NULL} };
508	return (XtCallbackList)emptyList;
509    }
510    if (icl->is_padded)
511	return ToList(icl);
512    i = icl->count;
513    if (icl->call_state) {
514        XtCallbackList ocl;
515	icl->call_state |= _XtCBFreeAfterCalling;
516	ocl = ToList(icl);
517	icl = (InternalCallbackList) __XtMalloc((Cardinal)(sizeof(InternalCallbackRec) +
518					      sizeof(XtCallbackRec) * (size_t) (i+1)));
519	icl->count = (unsigned short) i;
520	icl->call_state = 0;
521	cl = ToList(icl);
522	while (--i >= 0)
523	    *cl++ = *ocl++;
524    } else {
525	icl = (InternalCallbackList) XtRealloc((char *)icl,
526					       (Cardinal)(sizeof(InternalCallbackRec) +
527					       sizeof(XtCallbackRec) * (size_t)(i+1)));
528	cl = ToList(icl) + i;
529    }
530    icl->is_padded = 1;
531    cl->callback = (XtCallbackProc) NULL;
532    cl->closure = NULL;
533    *callbacks = icl;
534    return ToList(icl);
535}
536
537void XtCallCallbacks(
538    Widget   widget,
539    _Xconst char* name,
540    XtPointer call_data
541    )
542{
543    InternalCallbackList *callbacks;
544    InternalCallbackList icl;
545    XtCallbackList cl;
546    int i;
547    char ostate;
548    XtAppContext app = XtWidgetToApplicationContext(widget);
549
550    LOCK_APP(app);
551    callbacks = FetchInternalList(widget, name);
552    if (!callbacks) {
553	XtAppWarningMsg(app,
554	       XtNinvalidCallbackList,XtNxtCallCallback,XtCXtToolkitError,
555              "Cannot find callback list in XtCallCallbacks",
556	      NULL, NULL);
557	UNLOCK_APP(app);
558	return;
559    }
560
561    icl = *callbacks;
562    if (!icl) {
563	UNLOCK_APP(app);
564	return;
565    }
566    cl = ToList(icl);
567    if (icl->count == 1) {
568	(*cl->callback) (widget, cl->closure, call_data);
569	UNLOCK_APP(app);
570	return;
571    }
572    ostate = icl->call_state;
573    icl->call_state = _XtCBCalling;
574    for (i = icl->count; --i >= 0; cl++)
575	(*cl->callback) (widget, cl->closure, call_data);
576    if (ostate)
577	icl->call_state |= ostate;
578    else if (icl->call_state & _XtCBFreeAfterCalling)
579	XtFree((char *)icl);
580    else
581	icl->call_state = ostate;
582    UNLOCK_APP(app);
583} /* XtCallCallbacks */
584
585
586XtCallbackStatus XtHasCallbacks(
587     Widget		widget,
588     _Xconst char*	callback_name
589     )
590{
591    InternalCallbackList *callbacks;
592    XtCallbackStatus retval = XtCallbackHasSome;
593    WIDGET_TO_APPCON(widget);
594
595    LOCK_APP(app);
596    callbacks = FetchInternalList(widget, callback_name);
597    if (!callbacks)
598	retval = XtCallbackNoList;
599    else if (!*callbacks)
600	retval = XtCallbackHasNone;
601    UNLOCK_APP(app);
602    return retval;
603} /* XtHasCallbacks */
604
605
606void XtCallCallbackList(
607    Widget widget,
608    XtCallbackList callbacks,
609    XtPointer call_data)
610{
611    register InternalCallbackList icl;
612    register XtCallbackList cl;
613    register int i;
614    char ostate;
615    WIDGET_TO_APPCON(widget);
616
617    LOCK_APP(app);
618    if (!callbacks) {
619	UNLOCK_APP(app);
620	return;
621    }
622    icl = (InternalCallbackList)callbacks;
623    cl = ToList(icl);
624    if (icl->count == 1) {
625	(*cl->callback) (widget, cl->closure, call_data);
626	UNLOCK_APP(app);
627	return;
628    }
629    ostate = icl->call_state;
630    icl->call_state = _XtCBCalling;
631    for (i = icl->count; --i >= 0; cl++)
632	(*cl->callback) (widget, cl->closure, call_data);
633    if (ostate)
634	icl->call_state |= ostate;
635    else if (icl->call_state & _XtCBFreeAfterCalling)
636	XtFree((char *)icl);
637    else
638	icl->call_state = 0;
639    UNLOCK_APP(app);
640} /* XtCallCallbackList */
641
642void _XtPeekCallback(
643    Widget widget,
644    XtCallbackList callbacks,
645    XtCallbackProc *callback,
646    XtPointer *closure)
647{
648    register InternalCallbackList icl = (InternalCallbackList) callbacks;
649    register XtCallbackList cl;
650
651    if (!callbacks) {
652	*callback = (XtCallbackProc) NULL;
653	return;
654    }
655    cl = ToList(icl);
656    *callback = cl->callback;
657    *closure = cl->closure;
658    return;
659}
660
661void _XtCallConditionalCallbackList(
662    Widget widget,
663    XtCallbackList callbacks,
664    XtPointer call_data,
665    _XtConditionProc cond_proc)
666{
667    register InternalCallbackList icl;
668    register XtCallbackList cl;
669    register int i;
670    char ostate;
671    WIDGET_TO_APPCON(widget);
672
673    LOCK_APP(app);
674    if (!callbacks) {
675	UNLOCK_APP(app);
676	return;
677    }
678    icl = (InternalCallbackList)callbacks;
679    cl = ToList(icl);
680    if (icl->count == 1) {
681	(*cl->callback) (widget, cl->closure, call_data);
682	(void) (*cond_proc)(call_data);
683	UNLOCK_APP(app);
684	return;
685    }
686    ostate = icl->call_state;
687    icl->call_state = _XtCBCalling;
688    for (i = icl->count; --i >= 0; cl++) {
689	(*cl->callback) (widget, cl->closure, call_data);
690	if (! (*cond_proc)(call_data))
691	    break;
692    }
693    if (ostate)
694	icl->call_state |= ostate;
695    else if (icl->call_state & _XtCBFreeAfterCalling)
696	XtFree((char *)icl);
697    else
698	icl->call_state = 0;
699    UNLOCK_APP(app);
700}
701