Home | History | Annotate | Line # | Download | only in src
      1 /***********************************************************
      2 Copyright (c) 1993, Oracle and/or its affiliates.
      3 
      4 Permission is hereby granted, free of charge, to any person obtaining a
      5 copy of this software and associated documentation files (the "Software"),
      6 to deal in the Software without restriction, including without limitation
      7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 and/or sell copies of the Software, and to permit persons to whom the
      9 Software is furnished to do so, subject to the following conditions:
     10 
     11 The above copyright notice and this permission notice (including the next
     12 paragraph) shall be included in all copies or substantial portions of the
     13 Software.
     14 
     15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21 DEALINGS IN THE SOFTWARE.
     22 
     23 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
     24 
     25                         All Rights Reserved
     26 
     27 Permission to use, copy, modify, and distribute this software and its
     28 documentation for any purpose and without fee is hereby granted,
     29 provided that the above copyright notice appear in all copies and that
     30 both that copyright notice and this permission notice appear in
     31 supporting documentation, and that the name of Digital not be
     32 used in advertising or publicity pertaining to distribution of the
     33 software without specific, written prior permission.
     34 
     35 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     36 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     37 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     38 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     39 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     40 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     41 SOFTWARE.
     42 
     43 ******************************************************************/
     44 
     45 /*
     46 
     47 Copyright 1987, 1988, 1998  The Open Group
     48 
     49 Permission to use, copy, modify, distribute, and sell this software and its
     50 documentation for any purpose is hereby granted without fee, provided that
     51 the above copyright notice appear in all copies and that both that
     52 copyright notice and this permission notice appear in supporting
     53 documentation.
     54 
     55 The above copyright notice and this permission notice shall be included in
     56 all copies or substantial portions of the Software.
     57 
     58 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     59 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     60 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     61 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     62 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     63 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     64 
     65 Except as contained in this notice, the name of The Open Group shall not be
     66 used in advertising or otherwise to promote the sale, use or other dealings
     67 in 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 
     76 static _Xconst _XtString XtNinvalidCallbackList = "invalidCallbackList";
     77 static _Xconst _XtString XtNxtAddCallback = "xtAddCallback";
     78 static _Xconst _XtString XtNxtRemoveCallback = "xtRemoveCallback";
     79 static _Xconst _XtString XtNxtRemoveAllCallback = "xtRemoveAllCallback";
     80 static _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 
     89 static InternalCallbackList *
     90 FetchInternalList(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 
    113 void
    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 
    149 void
    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 
    164 void
    165 XtAddCallback(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 
    202 static void
    203 AddCallbacks(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 
    239 void
    240 XtAddCallbacks(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 
    274 void
    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 
    337 void
    338 XtRemoveCallback(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 
    373 void
    374 XtRemoveCallbacks(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 
    453 void
    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 
    467 void
    468 XtRemoveAllCallbacks(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 
    500 InternalCallbackList
    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 
    526 XtCallbackList
    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 
    570 void
    571 XtCallCallbacks(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 
    618 XtCallbackStatus
    619 XtHasCallbacks(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 
    637 void
    638 XtCallCallbackList(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 
    674 void
    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 
    693 void
    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