Callback.c revision fdf6a26f
1/***********************************************************
2Copyright (c) 1993, Oracle and/or its affiliates.
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#if __STDC_VERSION__ >= 199901L
84#define ToList(p) ((p)->callbacks)
85#else
86#define ToList(p) ((XtCallbackList) ((p)+1))
87#endif
88
89static InternalCallbackList *
90FetchInternalList(Widget widget,
91                  _Xconst char *name)
92{
93    XrmQuark quark;
94    int n;
95    CallbackTable offsets;
96    InternalCallbackList *retval = NULL;
97
98    quark = StringToQuark(name);
99    LOCK_PROCESS;
100    offsets = (CallbackTable)
101        widget->core.widget_class->core_class.callback_private;
102
103    for (n = (int) (long) *(offsets++); --n >= 0; offsets++)
104        if (quark == (*offsets)->xrm_name) {
105            retval = (InternalCallbackList *)
106                ((char *) widget - (*offsets)->xrm_offset - 1);
107            break;
108        }
109    UNLOCK_PROCESS;
110    return retval;
111}
112
113void
114_XtAddCallback(InternalCallbackList *callbacks,
115               XtCallbackProc callback,
116               XtPointer closure)
117{
118    register InternalCallbackList icl;
119    register XtCallbackList cl;
120    register int count;
121
122    icl = *callbacks;
123    count = icl ? icl->count : 0;
124
125    if (icl && icl->call_state) {
126        icl->call_state |= _XtCBFreeAfterCalling;
127        icl = (InternalCallbackList)
128            __XtMalloc((Cardinal) (sizeof(InternalCallbackRec) +
129                                   sizeof(XtCallbackRec) * (size_t) (count +
130                                                                     1)));
131        (void) memmove((char *) ToList(icl), (char *) ToList(*callbacks),
132                       sizeof(XtCallbackRec) * (size_t) count);
133    }
134    else {
135        icl = (InternalCallbackList)
136            XtRealloc((char *) icl, (Cardinal) (sizeof(InternalCallbackRec) +
137                                                sizeof(XtCallbackRec) *
138                                                (size_t) (count + 1)));
139    }
140    *callbacks = icl;
141    icl->count = (unsigned short) (count + 1);
142    icl->is_padded = 0;
143    icl->call_state = 0;
144    cl = ToList(icl) + count;
145    cl->callback = callback;
146    cl->closure = closure;
147}                               /* _XtAddCallback */
148
149void
150_XtAddCallbackOnce(register InternalCallbackList *callbacks,
151                   XtCallbackProc callback,
152                   XtPointer closure)
153{
154    register XtCallbackList cl = ToList(*callbacks);
155    register int i;
156
157    for (i = (*callbacks)->count; --i >= 0; cl++)
158        if (cl->callback == callback && cl->closure == closure)
159            return;
160
161    _XtAddCallback(callbacks, callback, closure);
162}                               /* _XtAddCallbackOnce */
163
164void
165XtAddCallback(Widget widget,
166              _Xconst char *name,
167              XtCallbackProc callback,
168              XtPointer closure)
169{
170    InternalCallbackList *callbacks;
171    XtAppContext app = XtWidgetToApplicationContext(widget);
172
173    LOCK_APP(app);
174    callbacks = FetchInternalList(widget, name);
175    if (!callbacks) {
176        XtAppWarningMsg(app,
177                        XtNinvalidCallbackList, XtNxtAddCallback,
178                        XtCXtToolkitError,
179                        "Cannot find callback list in XtAddCallback", NULL,
180                        NULL);
181        UNLOCK_APP(app);
182        return;
183    }
184    _XtAddCallback(callbacks, callback, closure);
185    if (!_XtIsHookObject(widget)) {
186        Widget hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
187
188        if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
189            XtChangeHookDataRec call_data;
190
191            call_data.type = XtHaddCallback;
192            call_data.widget = widget;
193            call_data.event_data = (XtPointer) name;
194            XtCallCallbackList(hookobj,
195                               ((HookObject) hookobj)->hooks.
196                               changehook_callbacks, (XtPointer) &call_data);
197        }
198    }
199    UNLOCK_APP(app);
200}                               /* XtAddCallback */
201
202static void
203AddCallbacks(Widget widget _X_UNUSED,
204             InternalCallbackList *callbacks,
205             XtCallbackList newcallbacks)
206{
207    register InternalCallbackList icl;
208    register int i, j;
209    register XtCallbackList cl;
210
211    icl = *callbacks;
212    i = icl ? icl->count : 0;
213    for (j = 0, cl = newcallbacks; cl->callback; cl++, j++);
214    if (icl && icl->call_state) {
215        icl->call_state |= _XtCBFreeAfterCalling;
216        icl = (InternalCallbackList)
217            __XtMalloc((Cardinal)
218                       (sizeof(InternalCallbackRec) +
219                        sizeof(XtCallbackRec) * (size_t) (i + j)));
220        (void) memmove((char *) ToList(*callbacks), (char *) ToList(icl),
221                       sizeof(XtCallbackRec) * (size_t) i);
222    }
223    else {
224        icl = (InternalCallbackList) XtRealloc((char *) icl,
225                                               (Cardinal) (sizeof
226                                                           (InternalCallbackRec)
227                                                           +
228                                                           sizeof(XtCallbackRec)
229                                                           * (size_t) (i + j)));
230    }
231    *callbacks = icl;
232    icl->count = (unsigned short) (i + j);
233    icl->is_padded = 0;
234    icl->call_state = 0;
235    for (cl = ToList(icl) + i; --j >= 0;)
236        *cl++ = *newcallbacks++;
237}                               /* AddCallbacks */
238
239void
240XtAddCallbacks(Widget widget,
241               _Xconst char *name,
242               XtCallbackList xtcallbacks)
243{
244    InternalCallbackList *callbacks;
245    Widget hookobj;
246    XtAppContext app = XtWidgetToApplicationContext(widget);
247
248    LOCK_APP(app);
249    callbacks = FetchInternalList(widget, name);
250    if (!callbacks) {
251        XtAppWarningMsg(app,
252                        XtNinvalidCallbackList, XtNxtAddCallback,
253                        XtCXtToolkitError,
254                        "Cannot find callback list in XtAddCallbacks", NULL,
255                        NULL);
256        UNLOCK_APP(app);
257        return;
258    }
259    AddCallbacks(widget, callbacks, xtcallbacks);
260    hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
261    if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
262        XtChangeHookDataRec call_data;
263
264        call_data.type = XtHaddCallbacks;
265        call_data.widget = widget;
266        call_data.event_data = (XtPointer) name;
267        XtCallCallbackList(hookobj,
268                           ((HookObject) hookobj)->hooks.changehook_callbacks,
269                           (XtPointer) &call_data);
270    }
271    UNLOCK_APP(app);
272}                               /* XtAddCallbacks */
273
274void
275_XtRemoveCallback(InternalCallbackList *callbacks,
276                  XtCallbackProc callback,
277                  XtPointer closure)
278{
279    register InternalCallbackList icl;
280    register int i, j;
281    register XtCallbackList cl, ncl, ocl;
282
283    icl = *callbacks;
284    if (!icl)
285        return;
286
287    cl = ToList(icl);
288    for (i = icl->count; --i >= 0; cl++) {
289        if (cl->callback == callback && cl->closure == closure) {
290            if (icl->call_state) {
291                icl->call_state |= _XtCBFreeAfterCalling;
292                if (icl->count == 1) {
293                    *callbacks = NULL;
294                }
295                else {
296                    j = icl->count - i - 1;
297                    ocl = ToList(icl);
298                    icl = (InternalCallbackList)
299                        __XtMalloc((Cardinal) (sizeof(InternalCallbackRec) +
300                                               sizeof(XtCallbackRec) *
301                                               (size_t) (i + j)));
302                    icl->count = (unsigned short) (i + j);
303                    icl->is_padded = 0;
304                    icl->call_state = 0;
305                    ncl = ToList(icl);
306                    while (--j >= 0)
307                        *ncl++ = *ocl++;
308                    while (--i >= 0)
309                        *ncl++ = *++cl;
310                    *callbacks = icl;
311                }
312            }
313            else {
314                if (--icl->count) {
315                    ncl = cl + 1;
316                    while (--i >= 0)
317                        *cl++ = *ncl++;
318                    icl = (InternalCallbackList)
319                        XtRealloc((char *) icl,
320                                  (Cardinal) (sizeof(InternalCallbackRec)
321                                              +
322                                              sizeof(XtCallbackRec) *
323                                              icl->count));
324                    icl->is_padded = 0;
325                    *callbacks = icl;
326                }
327                else {
328                    XtFree((char *) icl);
329                    *callbacks = NULL;
330                }
331            }
332            return;
333        }
334    }
335}                               /* _XtRemoveCallback */
336
337void
338XtRemoveCallback(Widget widget,
339                 _Xconst char *name,
340                 XtCallbackProc callback,
341                 XtPointer closure)
342{
343    InternalCallbackList *callbacks;
344    Widget hookobj;
345    XtAppContext app = XtWidgetToApplicationContext(widget);
346
347    LOCK_APP(app);
348    callbacks = FetchInternalList(widget, name);
349    if (!callbacks) {
350        XtAppWarningMsg(app,
351                        XtNinvalidCallbackList, XtNxtRemoveCallback,
352                        XtCXtToolkitError,
353                        "Cannot find callback list in XtRemoveCallback", NULL,
354                        NULL);
355        UNLOCK_APP(app);
356        return;
357    }
358    _XtRemoveCallback(callbacks, callback, closure);
359    hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
360    if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
361        XtChangeHookDataRec call_data;
362
363        call_data.type = XtHremoveCallback;
364        call_data.widget = widget;
365        call_data.event_data = (XtPointer) name;
366        XtCallCallbackList(hookobj,
367                           ((HookObject) hookobj)->hooks.changehook_callbacks,
368                           (XtPointer) &call_data);
369    }
370    UNLOCK_APP(app);
371}                               /* XtRemoveCallback */
372
373void
374XtRemoveCallbacks(Widget widget,
375                  _Xconst char *name,
376                  XtCallbackList xtcallbacks)
377{
378    InternalCallbackList *callbacks;
379    Widget hookobj;
380    int i;
381    InternalCallbackList icl;
382    XtCallbackList cl, ccl, rcl;
383    XtAppContext app = XtWidgetToApplicationContext(widget);
384
385    LOCK_APP(app);
386    callbacks = FetchInternalList(widget, name);
387    if (!callbacks) {
388        XtAppWarningMsg(app,
389                        XtNinvalidCallbackList, XtNxtRemoveCallback,
390                        XtCXtToolkitError,
391                        "Cannot find callback list in XtRemoveCallbacks", NULL,
392                        NULL);
393        UNLOCK_APP(app);
394        return;
395    }
396
397    icl = *callbacks;
398    if (!icl) {
399        UNLOCK_APP(app);
400        return;
401    }
402
403    i = icl->count;
404    cl = ToList(icl);
405    if (icl->call_state) {
406        icl->call_state |= _XtCBFreeAfterCalling;
407        icl =
408            (InternalCallbackList)
409            __XtMalloc((Cardinal)
410                       (sizeof(InternalCallbackRec) +
411                        sizeof(XtCallbackRec) * (size_t) i));
412        icl->count = (unsigned short) i;
413        icl->call_state = 0;
414    }
415    ccl = ToList(icl);
416    while (--i >= 0) {
417        *ccl++ = *cl;
418        for (rcl = xtcallbacks; rcl->callback; rcl++) {
419            if (cl->callback == rcl->callback && cl->closure == rcl->closure) {
420                ccl--;
421                icl->count--;
422                break;
423            }
424        }
425        cl++;
426    }
427    if (icl->count) {
428        icl = (InternalCallbackList)
429            XtRealloc((char *) icl, (Cardinal) (sizeof(InternalCallbackRec) +
430                                                sizeof(XtCallbackRec) *
431                                                icl->count));
432        icl->is_padded = 0;
433        *callbacks = icl;
434    }
435    else {
436        XtFree((char *) icl);
437        *callbacks = NULL;
438    }
439    hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
440    if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
441        XtChangeHookDataRec call_data;
442
443        call_data.type = XtHremoveCallbacks;
444        call_data.widget = widget;
445        call_data.event_data = (XtPointer) name;
446        XtCallCallbackList(hookobj,
447                           ((HookObject) hookobj)->hooks.changehook_callbacks,
448                           (XtPointer) &call_data);
449    }
450    UNLOCK_APP(app);
451}                               /* XtRemoveCallbacks */
452
453void
454_XtRemoveAllCallbacks(InternalCallbackList *callbacks)
455{
456    register InternalCallbackList icl = *callbacks;
457
458    if (icl) {
459        if (icl->call_state)
460            icl->call_state |= _XtCBFreeAfterCalling;
461        else
462            XtFree((char *) icl);
463        *callbacks = NULL;
464    }
465}                               /* _XtRemoveAllCallbacks */
466
467void
468XtRemoveAllCallbacks(Widget widget, _Xconst char *name)
469{
470    InternalCallbackList *callbacks;
471    Widget hookobj;
472    XtAppContext app = XtWidgetToApplicationContext(widget);
473
474    LOCK_APP(app);
475    callbacks = FetchInternalList(widget, name);
476    if (!callbacks) {
477        XtAppWarningMsg(app,
478                        XtNinvalidCallbackList, XtNxtRemoveAllCallback,
479                        XtCXtToolkitError,
480                        "Cannot find callback list in XtRemoveAllCallbacks",
481                        NULL, NULL);
482        UNLOCK_APP(app);
483        return;
484    }
485    _XtRemoveAllCallbacks(callbacks);
486    hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
487    if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
488        XtChangeHookDataRec call_data;
489
490        call_data.type = XtHremoveAllCallbacks;
491        call_data.widget = widget;
492        call_data.event_data = (XtPointer) name;
493        XtCallCallbackList(hookobj,
494                           ((HookObject) hookobj)->hooks.changehook_callbacks,
495                           (XtPointer) &call_data);
496    }
497    UNLOCK_APP(app);
498}                               /* XtRemoveAllCallbacks */
499
500InternalCallbackList
501_XtCompileCallbackList(XtCallbackList xtcallbacks)
502{
503    register int n;
504    register XtCallbackList xtcl, cl;
505    register InternalCallbackList callbacks;
506
507    for (n = 0, xtcl = xtcallbacks; xtcl->callback; n++, xtcl++) {
508    };
509    if (n == 0)
510        return (InternalCallbackList) NULL;
511
512    callbacks =
513        (InternalCallbackList)
514        __XtMalloc((Cardinal)
515                   (sizeof(InternalCallbackRec) +
516                    sizeof(XtCallbackRec) * (size_t) n));
517    callbacks->count = (unsigned short) n;
518    callbacks->is_padded = 0;
519    callbacks->call_state = 0;
520    cl = ToList(callbacks);
521    while (--n >= 0)
522        *cl++ = *xtcallbacks++;
523    return (callbacks);
524}                               /* _XtCompileCallbackList */
525
526XtCallbackList
527_XtGetCallbackList(InternalCallbackList *callbacks)
528{
529    int i;
530    InternalCallbackList icl;
531    XtCallbackList cl;
532
533    icl = *callbacks;
534    if (!icl) {
535        static XtCallbackRec emptyList[1] = { {NULL, NULL} };
536        return (XtCallbackList) emptyList;
537    }
538    if (icl->is_padded)
539        return ToList(icl);
540    i = icl->count;
541    if (icl->call_state) {
542        XtCallbackList ocl;
543
544        icl->call_state |= _XtCBFreeAfterCalling;
545        ocl = ToList(icl);
546        icl = (InternalCallbackList)
547            __XtMalloc((Cardinal)
548                       (sizeof(InternalCallbackRec) +
549                        sizeof(XtCallbackRec) * (size_t) (i + 1)));
550        icl->count = (unsigned short) i;
551        icl->call_state = 0;
552        cl = ToList(icl);
553        while (--i >= 0)
554            *cl++ = *ocl++;
555    }
556    else {
557        icl = (InternalCallbackList)
558            XtRealloc((char *) icl, (Cardinal) (sizeof(InternalCallbackRec)
559                                                + sizeof(XtCallbackRec)
560                                                * (size_t) (i + 1)));
561        cl = ToList(icl) + i;
562    }
563    icl->is_padded = 1;
564    cl->callback = (XtCallbackProc) NULL;
565    cl->closure = NULL;
566    *callbacks = icl;
567    return ToList(icl);
568}
569
570void
571XtCallCallbacks(Widget widget,
572                _Xconst char *name,
573                XtPointer call_data)
574{
575    InternalCallbackList *callbacks;
576    InternalCallbackList icl;
577    XtCallbackList cl;
578    int i;
579    char ostate;
580    XtAppContext app = XtWidgetToApplicationContext(widget);
581
582    LOCK_APP(app);
583    callbacks = FetchInternalList(widget, name);
584    if (!callbacks) {
585        XtAppWarningMsg(app,
586                        XtNinvalidCallbackList, XtNxtCallCallback,
587                        XtCXtToolkitError,
588                        "Cannot find callback list in XtCallCallbacks", NULL,
589                        NULL);
590        UNLOCK_APP(app);
591        return;
592    }
593
594    icl = *callbacks;
595    if (!icl) {
596        UNLOCK_APP(app);
597        return;
598    }
599    cl = ToList(icl);
600    if (icl->count == 1) {
601        (*cl->callback) (widget, cl->closure, call_data);
602        UNLOCK_APP(app);
603        return;
604    }
605    ostate = icl->call_state;
606    icl->call_state = _XtCBCalling;
607    for (i = icl->count; --i >= 0; cl++)
608        (*cl->callback) (widget, cl->closure, call_data);
609    if (ostate)
610        icl->call_state |= ostate;
611    else if (icl->call_state & _XtCBFreeAfterCalling)
612        XtFree((char *) icl);
613    else
614        icl->call_state = ostate;
615    UNLOCK_APP(app);
616}                               /* XtCallCallbacks */
617
618XtCallbackStatus
619XtHasCallbacks(Widget widget,
620               _Xconst char *callback_name)
621{
622    InternalCallbackList *callbacks;
623    XtCallbackStatus retval = XtCallbackHasSome;
624
625    WIDGET_TO_APPCON(widget);
626
627    LOCK_APP(app);
628    callbacks = FetchInternalList(widget, callback_name);
629    if (!callbacks)
630        retval = XtCallbackNoList;
631    else if (!*callbacks)
632        retval = XtCallbackHasNone;
633    UNLOCK_APP(app);
634    return retval;
635}                               /* XtHasCallbacks */
636
637void
638XtCallCallbackList(Widget widget,
639                   XtCallbackList callbacks,
640                   XtPointer call_data)
641{
642    register InternalCallbackList icl;
643    register XtCallbackList cl;
644    register int i;
645    char ostate;
646
647    WIDGET_TO_APPCON(widget);
648
649    LOCK_APP(app);
650    if (!callbacks) {
651        UNLOCK_APP(app);
652        return;
653    }
654    icl = (InternalCallbackList) callbacks;
655    cl = ToList(icl);
656    if (icl->count == 1) {
657        (*cl->callback) (widget, cl->closure, call_data);
658        UNLOCK_APP(app);
659        return;
660    }
661    ostate = icl->call_state;
662    icl->call_state = _XtCBCalling;
663    for (i = icl->count; --i >= 0; cl++)
664        (*cl->callback) (widget, cl->closure, call_data);
665    if (ostate)
666        icl->call_state |= ostate;
667    else if (icl->call_state & _XtCBFreeAfterCalling)
668        XtFree((char *) icl);
669    else
670        icl->call_state = 0;
671    UNLOCK_APP(app);
672}                               /* XtCallCallbackList */
673
674void
675_XtPeekCallback(Widget widget _X_UNUSED,
676                XtCallbackList callbacks,
677                XtCallbackProc *callback,
678                XtPointer *closure)
679{
680    register InternalCallbackList icl = (InternalCallbackList) callbacks;
681    register XtCallbackList cl;
682
683    if (!callbacks) {
684        *callback = (XtCallbackProc) NULL;
685        return;
686    }
687    cl = ToList(icl);
688    *callback = cl->callback;
689    *closure = cl->closure;
690    return;
691}
692
693void
694_XtCallConditionalCallbackList(Widget widget,
695                               XtCallbackList callbacks,
696                               XtPointer call_data,
697                               _XtConditionProc cond_proc)
698{
699    register InternalCallbackList icl;
700    register XtCallbackList cl;
701    register int i;
702    char ostate;
703
704    WIDGET_TO_APPCON(widget);
705
706    LOCK_APP(app);
707    if (!callbacks) {
708        UNLOCK_APP(app);
709        return;
710    }
711    icl = (InternalCallbackList) callbacks;
712    cl = ToList(icl);
713    if (icl->count == 1) {
714        (*cl->callback) (widget, cl->closure, call_data);
715        (void) (*cond_proc) (call_data);
716        UNLOCK_APP(app);
717        return;
718    }
719    ostate = icl->call_state;
720    icl->call_state = _XtCBCalling;
721    for (i = icl->count; --i >= 0; cl++) {
722        (*cl->callback) (widget, cl->closure, call_data);
723        if (!(*cond_proc) (call_data))
724            break;
725    }
726    if (ostate)
727        icl->call_state |= ostate;
728    else if (icl->call_state & _XtCBFreeAfterCalling)
729        XtFree((char *) icl);
730    else
731        icl->call_state = 0;
732    UNLOCK_APP(app);
733}
734