home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / Xt / Callback.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  14.5 KB  |  536 lines

  1. /* $XConsortium: Callback.c,v 1.35 91/11/21 14:36:30 converse Exp $ */
  2.  
  3. /***********************************************************
  4. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
  5. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  6.  
  7.                         All Rights Reserved
  8.  
  9. Permission to use, copy, modify, and distribute this software and its 
  10. documentation for any purpose and without fee is hereby granted, 
  11. provided that the above copyright notice appear in all copies and that
  12. both that copyright notice and this permission notice appear in 
  13. supporting documentation, and that the names of Digital or MIT not be
  14. used in advertising or publicity pertaining to distribution of the
  15. software without specific, written prior permission.  
  16.  
  17. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  18. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  19. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  20. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  22. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  23. SOFTWARE.
  24.  
  25. ******************************************************************/
  26.  
  27. #include "IntrinsicI.h"
  28.  
  29. static String XtNinvalidCallbackList = "invalidCallbackList";
  30. static String XtNxtAddCallback = "xtAddCallback";
  31. static String XtNxtRemoveCallback = "xtRemoveCallback";
  32. static String XtNxtRemoveAllCallback = "xtRemoveAllCallback";
  33. static String XtNxtCallCallback = "xtCallCallback";
  34.  
  35. /* However it doesn't contain a final NULL record */
  36. #define ToList(p) ((XtCallbackList) ((p)+1))
  37.  
  38. static InternalCallbackList* FetchInternalList(widget, name)
  39.     Widget    widget;
  40.     String    name;
  41. {
  42.     register XrmQuark        quark;
  43.     register int         n;
  44.     register CallbackTable    offsets;
  45.  
  46.     quark = StringToQuark(name);
  47.     offsets = (CallbackTable) 
  48.     widget->core.widget_class->core_class.callback_private;
  49.  
  50.     for (n = (int) *(offsets++); --n >= 0; offsets++)
  51.     if (quark == (*offsets)->xrm_name)
  52.         return (InternalCallbackList *) 
  53.         ((char *) widget - (*offsets)->xrm_offset - 1);
  54.     return NULL;
  55. }
  56.  
  57.  
  58. void _XtAddCallback(callbacks, callback, closure)
  59.     InternalCallbackList*   callbacks;
  60.     XtCallbackProc        callback;
  61.     XtPointer            closure;
  62. {
  63.     register InternalCallbackList icl;
  64.     register XtCallbackList cl;
  65.     register int count;
  66.     
  67.     icl = *callbacks;
  68.     count = icl ? icl->count : 0;
  69.  
  70.     if (icl && icl->call_state) {
  71.     icl->call_state |= _XtCBFreeAfterCalling;
  72.     icl = (InternalCallbackList)
  73.         XtMalloc(sizeof(InternalCallbackRec) +
  74.              sizeof(XtCallbackRec) * (count + 1));
  75.     bcopy((char *)ToList(*callbacks), (char *)ToList(icl),
  76.           sizeof(XtCallbackRec) * count);
  77.     } else {
  78.     icl = (InternalCallbackList)
  79.         XtRealloc((char *) icl, sizeof(InternalCallbackRec) +
  80.               sizeof(XtCallbackRec) * (count + 1));
  81.     }
  82.     *callbacks = icl;
  83.     icl->count = count + 1;
  84.     icl->is_padded = 0;
  85.     icl->call_state = 0;
  86.     cl = ToList(icl) + count;
  87.     cl->callback = callback;
  88.     cl->closure = closure;
  89. } /* _XtAddCallback */
  90.  
  91. void _XtAddCallbackOnce(callbacks, callback, closure)
  92.     register InternalCallbackList*callbacks;
  93.     XtCallbackProc        callback;
  94.     XtPointer            closure;
  95. {
  96.     register XtCallbackList cl = ToList(*callbacks);
  97.     register int i;
  98.     
  99.     for (i=(*callbacks)->count; --i >= 0; cl++)
  100.     if (cl->callback == callback && cl->closure == closure)
  101.         return;
  102.  
  103.     _XtAddCallback(callbacks, callback, closure);
  104. } /* _XtAddCallbackOnce */
  105.  
  106. #if NeedFunctionPrototypes
  107. void XtAddCallback(
  108.     Widget        widget,
  109.     _Xconst char*   name,
  110.     XtCallbackProc  callback,
  111.     XtPointer        closure
  112.     )
  113. #else
  114. void XtAddCallback(widget, name, callback, closure)
  115.     Widget        widget;
  116.     String        name;
  117.     XtCallbackProc  callback;
  118.     XtPointer        closure;
  119. #endif
  120. {
  121.     InternalCallbackList *callbacks;
  122.  
  123.     callbacks = FetchInternalList(widget, name);
  124.     if (!callbacks) {
  125.        XtAppWarningMsg(XtWidgetToApplicationContext(widget),
  126.            XtNinvalidCallbackList,XtNxtAddCallback,XtCXtToolkitError,
  127.               "Cannot find callback list in XtAddCallback",
  128.           (String *)NULL, (Cardinal *)NULL);
  129.        return;
  130.     }
  131.     _XtAddCallback(callbacks, callback, closure);
  132. } /* XtAddCallback */
  133.  
  134. /* ARGSUSED */
  135. static void AddCallbacks(widget, callbacks, newcallbacks)
  136.     Widget            widget;
  137.     InternalCallbackList   *callbacks;
  138.     XtCallbackList        newcallbacks;
  139. {
  140.     register InternalCallbackList icl;
  141.     register int i, j;
  142.     register XtCallbackList cl;
  143.  
  144.     icl = *callbacks;
  145.     i = icl ? icl->count : 0;
  146.     for (j=0, cl = newcallbacks; cl->callback; cl++, j++);
  147.     if (icl && icl->call_state) {
  148.     icl->call_state |= _XtCBFreeAfterCalling;
  149.     icl = (InternalCallbackList) XtMalloc(sizeof(InternalCallbackRec) +
  150.                           sizeof(XtCallbackRec) * (i+j));
  151.     bcopy((char *)ToList(*callbacks), (char *)ToList(icl),
  152.           sizeof(XtCallbackRec) * i);
  153.     } else {
  154.     icl = (InternalCallbackList) XtRealloc((char *) icl,
  155.                            sizeof(InternalCallbackRec) + 
  156.                            sizeof(XtCallbackRec) * (i+j));
  157.     }
  158.     *callbacks = icl;
  159.     icl->count = i+j;
  160.     icl->is_padded = 0;
  161.     icl->call_state = 0;
  162.     for (cl = ToList(icl) + i; --j >= 0; )
  163.     *cl++ = *newcallbacks++;
  164. } /* AddCallbacks */
  165.  
  166. #if NeedFunctionPrototypes
  167. void XtAddCallbacks(
  168.     Widget        widget,
  169.     _Xconst char*   name,
  170.     XtCallbackList  xtcallbacks
  171.     )
  172. #else
  173. void XtAddCallbacks(widget, name, xtcallbacks)
  174.     Widget        widget;
  175.     String        name;
  176.     XtCallbackList  xtcallbacks;
  177. #endif
  178. {
  179.     InternalCallbackList* callbacks;
  180.  
  181.     callbacks = FetchInternalList(widget, name);
  182.     if (!callbacks) {
  183.        XtAppWarningMsg(XtWidgetToApplicationContext(widget),
  184.            XtNinvalidCallbackList,XtNxtAddCallback,XtCXtToolkitError,
  185.               "Cannot find callback list in XtAddCallbacks",
  186.           (String *)NULL, (Cardinal *)NULL);
  187.        return;
  188.     }
  189.     AddCallbacks(widget, callbacks, xtcallbacks);
  190. } /* XtAddCallbacks */
  191.  
  192. void _XtRemoveCallback (callbacks, callback, closure)
  193.     InternalCallbackList   *callbacks;
  194.     XtCallbackProc        callback;
  195.     XtPointer            closure;
  196.  
  197. {
  198.     register InternalCallbackList icl;
  199.     register int i, j;
  200.     register XtCallbackList cl, ncl, ocl;
  201.  
  202.     icl = *callbacks;
  203.     if (!icl) return;
  204.  
  205.     cl = ToList(icl);
  206.     for (i=icl->count; --i >= 0; cl++) {
  207.     if (cl->callback == callback && cl->closure == closure) {
  208.         if (icl->call_state) {
  209.         icl->call_state |= _XtCBFreeAfterCalling;
  210.         if (icl->count == 1) {
  211.             *callbacks = NULL;
  212.         } else {
  213.             j = icl->count - i - 1;
  214.             ocl = ToList(icl);
  215.             icl = (InternalCallbackList)
  216.             XtMalloc(sizeof(InternalCallbackRec) +
  217.                  sizeof(XtCallbackRec) * (i + j));
  218.             icl->count = i + j;
  219.             icl->is_padded = 0;
  220.             icl->call_state = 0;
  221.             ncl = ToList(icl);
  222.             while (--j >= 0)
  223.             *ncl++ = *ocl++;
  224.             while (--i >= 0)
  225.             *ncl++ = *++cl;
  226.             *callbacks = icl;
  227.         }
  228.         } else {
  229.         if (--icl->count) {
  230.             ncl = cl + 1;
  231.             while (--i >= 0)
  232.             *cl++ = *ncl++;
  233.             icl = (InternalCallbackList)
  234.             XtRealloc((char *) icl, sizeof(InternalCallbackRec)
  235.                   + sizeof(XtCallbackRec) * icl->count);
  236.             icl->is_padded = 0;
  237.             *callbacks = icl;
  238.         } else {
  239.             XtFree((char *) icl);
  240.             *callbacks = NULL;
  241.         }
  242.         }
  243.         return;
  244.     }
  245.     }
  246. } /* _XtRemoveCallback */
  247.  
  248. #if NeedFunctionPrototypes
  249. void XtRemoveCallback (
  250.     Widget        widget,
  251.     _Xconst char*   name,
  252.     XtCallbackProc  callback,
  253.     XtPointer        closure
  254.     )
  255. #else
  256. void XtRemoveCallback (widget, name, callback, closure)
  257.     Widget        widget;
  258.     String        name;
  259.     XtCallbackProc  callback;
  260.     XtPointer        closure;
  261. #endif
  262. {
  263.     InternalCallbackList *callbacks;
  264.  
  265.     callbacks = FetchInternalList(widget, name);
  266.     if (!callbacks) {
  267.        XtAppWarningMsg(XtWidgetToApplicationContext(widget),
  268.            XtNinvalidCallbackList,XtNxtRemoveCallback,XtCXtToolkitError,
  269.               "Cannot find callback list in XtRemoveCallbacks",
  270.           (String *)NULL, (Cardinal *)NULL);
  271.     return;
  272.     }
  273.  
  274.     _XtRemoveCallback(callbacks, callback, closure);
  275. } /* XtRemoveCallback */
  276.  
  277.  
  278. #if NeedFunctionPrototypes
  279. void XtRemoveCallbacks (widget, name, xtcallbacks)
  280.     Widget        widget;
  281.     _Xconst char*   name;
  282.     XtCallbackList  xtcallbacks;
  283. #else
  284. void XtRemoveCallbacks (widget, name, xtcallbacks)
  285.     Widget        widget;
  286.     String        name;
  287.     XtCallbackList  xtcallbacks;
  288. #endif
  289. {
  290.     InternalCallbackList *callbacks;
  291.     register int i;
  292.     register InternalCallbackList icl;
  293.     register XtCallbackList cl, ccl, rcl;
  294.  
  295.     callbacks = FetchInternalList(widget, name);
  296.     if (!callbacks) {
  297.        XtAppWarningMsg(XtWidgetToApplicationContext(widget),
  298.            XtNinvalidCallbackList,XtNxtRemoveCallback,XtCXtToolkitError,
  299.               "Cannot find callback list in XtRemoveCallbacks",
  300.           (String *)NULL, (Cardinal *)NULL);
  301.     return;
  302.     }
  303.  
  304.     icl = *callbacks;
  305.     if (!icl) return;
  306.  
  307.     i = icl->count;
  308.     cl = ToList(icl);
  309.     if (icl->call_state) {
  310.     icl->call_state |= _XtCBFreeAfterCalling;
  311.     icl = (InternalCallbackList)XtMalloc(sizeof(InternalCallbackRec) +
  312.                          sizeof(XtCallbackRec) * i);
  313.     icl->count = i;
  314.     icl->call_state = 0;
  315.     }
  316.     ccl = ToList(icl);
  317.     while (--i >= 0) {
  318.     *ccl++ = *cl;
  319.     for (rcl=xtcallbacks; rcl->callback; rcl++) {
  320.         if (cl->callback == rcl->callback && cl->closure == rcl->closure) {
  321.         ccl--;
  322.         icl->count--;
  323.         break;
  324.         }
  325.     }
  326.     cl++;
  327.     }
  328.     if (icl->count) {
  329.     icl = (InternalCallbackList)
  330.         XtRealloc((char *)icl, (sizeof(InternalCallbackRec) +
  331.                     sizeof(XtCallbackRec) * icl->count));
  332.     icl->is_padded = 0;
  333.     *callbacks = icl;
  334.     } else {
  335.     XtFree((char *)icl);
  336.     *callbacks = NULL;
  337.     }
  338. } /* XtRemoveCallbacks */
  339.  
  340.  
  341. void _XtRemoveAllCallbacks (callbacks)
  342.     InternalCallbackList *callbacks;
  343. {
  344.     register InternalCallbackList icl = *callbacks;
  345.  
  346.     if (icl) {
  347.     if (icl->call_state)
  348.         icl->call_state |= _XtCBFreeAfterCalling;
  349.     else
  350.         XtFree((char *) icl);
  351.     *callbacks = NULL;
  352.     }
  353. } /* _XtRemoveAllCallbacks */
  354.  
  355. #if NeedFunctionPrototypes
  356. void XtRemoveAllCallbacks(widget, name)
  357.     Widget widget;
  358.     _Xconst char* name;
  359. #else
  360. void XtRemoveAllCallbacks(widget, name)
  361.     Widget widget;
  362.     String name;
  363. #endif
  364. {
  365.     InternalCallbackList *callbacks;
  366.  
  367.     callbacks = FetchInternalList(widget, name);
  368.     if (!callbacks) {
  369.        XtAppWarningMsg(XtWidgetToApplicationContext(widget),
  370.            XtNinvalidCallbackList,XtNxtRemoveAllCallback,XtCXtToolkitError,
  371.               "Cannot find callback list in XtRemoveAllCallbacks",
  372.           (String *)NULL, (Cardinal *)NULL);
  373.  
  374.     return;
  375.     }
  376.     _XtRemoveAllCallbacks(callbacks);
  377. } /* XtRemoveAllCallbacks */
  378.  
  379. InternalCallbackList _XtCompileCallbackList(xtcallbacks)
  380.     XtCallbackList xtcallbacks;
  381. {
  382.     register int n;
  383.     register XtCallbackList xtcl, cl;
  384.     register InternalCallbackList callbacks;
  385.  
  386.     for (n=0, xtcl=xtcallbacks; xtcl->callback; n++, xtcl++) {};
  387.     if (n == 0) return (InternalCallbackList) NULL;
  388.  
  389.     callbacks = (InternalCallbackList) XtMalloc(sizeof(InternalCallbackRec) +
  390.                         sizeof(XtCallbackRec) * n);
  391.     callbacks->count = n;
  392.     callbacks->is_padded = 0;
  393.     callbacks->call_state = 0;
  394.     cl = ToList(callbacks);
  395.     while (--n >= 0)
  396.     *cl++ = *xtcallbacks++;
  397.     return(callbacks);
  398. } /* _XtCompileCallbackList */
  399.  
  400.  
  401. XtCallbackList _XtGetCallbackList(callbacks)
  402.     InternalCallbackList *callbacks;
  403. {
  404.     register int i;
  405.     register InternalCallbackList icl;
  406.     register XtCallbackList cl, ocl;
  407.  
  408.     icl = *callbacks;
  409.     if (!icl) {
  410.     static XtCallbackRec emptyList[1] = { {NULL, NULL} };
  411.     return (XtCallbackList)emptyList;
  412.     }
  413.     if (icl->is_padded)
  414.     return ToList(icl);
  415.     i = icl->count;
  416.     if (icl->call_state) {
  417.     icl->call_state |= _XtCBFreeAfterCalling;
  418.     ocl = ToList(icl);
  419.     icl = (InternalCallbackList) XtMalloc(sizeof(InternalCallbackRec) +
  420.                           sizeof(XtCallbackRec) * (i+1));
  421.     icl->count = i;
  422.     icl->call_state = 0;
  423.     cl = ToList(icl);
  424.     while (--i >= 0)
  425.         *cl++ = *ocl++;
  426.     } else {
  427.     icl = (InternalCallbackList) XtRealloc((char *)icl,
  428.                            sizeof(InternalCallbackRec) +
  429.                            sizeof(XtCallbackRec) * (i+1));
  430.     cl = ToList(icl) + i;
  431.     }
  432.     icl->is_padded = 1;
  433.     cl->callback = (XtCallbackProc) NULL;
  434.     cl->closure = NULL;
  435.     *callbacks = icl;
  436.     return ToList(icl);
  437. }
  438.  
  439. #if NeedFunctionPrototypes
  440. void XtCallCallbacks(
  441.     Widget   widget,
  442.     _Xconst char* name,
  443.     XtPointer call_data
  444.     )
  445. #else
  446. void XtCallCallbacks(widget, name, call_data)
  447.     Widget   widget;
  448.     String   name;
  449.     XtPointer call_data;
  450. #endif
  451. {
  452.     InternalCallbackList *callbacks;
  453.     register InternalCallbackList icl;
  454.     register XtCallbackList cl;
  455.     register int i;
  456.     char ostate;
  457.  
  458.     callbacks = FetchInternalList(widget, name);
  459.     if (!callbacks) {
  460.        XtAppWarningMsg(XtWidgetToApplicationContext(widget),
  461.            XtNinvalidCallbackList,XtNxtCallCallback,XtCXtToolkitError,
  462.               "Cannot find callback list in XtCallCallbacks",
  463.           (String *)NULL, (Cardinal *)NULL);
  464.     return;
  465.     }
  466.  
  467.     icl = *callbacks;
  468.     if (!icl) return;
  469.     cl = ToList(icl);
  470.     if (icl->count == 1) {
  471.     (*cl->callback) (widget, cl->closure, call_data);
  472.     return;
  473.     }
  474.     ostate = icl->call_state;
  475.     icl->call_state = _XtCBCalling;
  476.     for (i = icl->count; --i >= 0; cl++)
  477.     (*cl->callback) (widget, cl->closure, call_data);
  478.     if (ostate)
  479.     icl->call_state |= ostate;
  480.     else if (icl->call_state & _XtCBFreeAfterCalling)
  481.     XtFree((char *)icl);
  482.     else
  483.     icl->call_state = ostate;
  484. } /* XtCallCallbacks */
  485.  
  486.  
  487. #if NeedFunctionPrototypes
  488. XtCallbackStatus XtHasCallbacks(
  489.      Widget        widget,
  490.      _Xconst char*    callback_name
  491.      )
  492. #else
  493. XtCallbackStatus XtHasCallbacks(widget, callback_name)
  494.      Widget        widget;
  495.      String        callback_name;
  496. #endif
  497. {
  498.     InternalCallbackList *callbacks;
  499.     callbacks = FetchInternalList(widget, callback_name);
  500.     if (!callbacks)
  501.     return XtCallbackNoList;
  502.     else if (!*callbacks)
  503.     return XtCallbackHasNone;
  504.     return XtCallbackHasSome;
  505. } /* XtHasCallbacks */
  506.  
  507.  
  508. void XtCallCallbackList(widget, callbacks, call_data)
  509.     Widget widget;
  510.     XtCallbackList callbacks;
  511.     XtPointer call_data;
  512. {
  513.     register InternalCallbackList icl;
  514.     register XtCallbackList cl;
  515.     register int i;
  516.     char ostate;
  517.  
  518.     if (!callbacks) return;
  519.     icl = (InternalCallbackList)callbacks;
  520.     cl = ToList(icl);
  521.     if (icl->count == 1) {
  522.     (*cl->callback) (widget, cl->closure, call_data);
  523.     return;
  524.     }
  525.     ostate = icl->call_state;
  526.     icl->call_state = _XtCBCalling;
  527.     for (i = icl->count; --i >= 0; cl++)
  528.     (*cl->callback) (widget, cl->closure, call_data);
  529.     if (ostate)
  530.     icl->call_state |= ostate;
  531.     else if (icl->call_state & _XtCBFreeAfterCalling)
  532.     XtFree((char *)icl);
  533.     else
  534.     icl->call_state = 0;
  535. } /* XtCallCallbackList */
  536.