home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / Xt / Destroy.c.orig < prev    next >
Encoding:
Text File  |  1991-07-01  |  8.2 KB  |  293 lines

  1. /* $XConsortium: Destroy.c,v 1.43 91/06/30 17:02:46 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. struct _DestroyRec {
  30.     int dispatch_level;
  31.     Widget widget;
  32. };
  33.  
  34. static void Recursive(widget, proc)
  35.     Widget       widget;
  36.     XtWidgetProc proc;
  37. {
  38.     register int    i;
  39.     CompositePart   *cwp;
  40.  
  41.     /* Recurse down normal children */
  42.     if (XtIsComposite(widget)) {
  43.     cwp = &(((CompositeWidget) widget)->composite);
  44.     for (i = 0; i < cwp->num_children; i++) {
  45.         Recursive(cwp->children[i], proc);
  46.     }
  47.     }
  48.  
  49.     /* Recurse down popup children */
  50.     if (XtIsWidget(widget)) {
  51.     for (i = 0; i < widget->core.num_popups; i++) {
  52.         Recursive(widget->core.popup_list[i], proc);
  53.     }
  54.     }
  55.  
  56.     /* Finally, apply procedure to this widget */
  57.     (*proc) (widget);  
  58. } /* Recursive */
  59.  
  60. static void Phase1Destroy (widget)
  61.     Widget    widget;
  62. {
  63.     widget->core.being_destroyed = TRUE;
  64. } /* Phase1Destroy */
  65.  
  66. static void Phase2Callbacks(widget)
  67.     Widget    widget;
  68. {
  69.     if (widget->core.destroy_callbacks != NULL) {
  70.     XtCallCallbackList(widget,
  71.                widget->core.destroy_callbacks, (XtPointer) NULL);
  72.     }
  73. } /* Phase2Callbacks */
  74.  
  75. static void Phase2Destroy(widget)
  76.     register Widget widget;
  77. {
  78.     register WidgetClass        class;
  79.     register ConstraintWidgetClass  cwClass;
  80.  
  81.     /* Call constraint destroy procedures */
  82.     /* assert: !XtIsShell(w) => (XtParent(w) != NULL) */
  83.     if (!XtIsShell(widget) && XtIsConstraint(XtParent(widget))) {
  84.     cwClass = (ConstraintWidgetClass)XtParent(widget)->core.widget_class;
  85.     for (;;) {
  86.         if (cwClass->constraint_class.destroy != NULL)
  87.         (*(cwClass->constraint_class.destroy)) (widget);
  88.             if (cwClass == (ConstraintWidgetClass)constraintWidgetClass) break;
  89.             cwClass = (ConstraintWidgetClass) cwClass->core_class.superclass;
  90.     }
  91.     }
  92.  
  93.     /* Call widget destroy procedures */
  94.     for (class = widget->core.widget_class;
  95.      class != NULL; 
  96.      class = class->core_class.superclass) {
  97.     if ((class->core_class.destroy) != NULL)
  98.         (*(class->core_class.destroy))(widget);
  99.     }
  100. } /* Phase2Destroy */
  101.  
  102. static Boolean IsDescendant(widget, root)
  103.     register Widget widget, root;
  104. {
  105.     while ((widget = XtParent(widget)) != root) {
  106.     if (widget == NULL) return False;
  107.     }
  108.     return True;
  109. }
  110.  
  111. static void XtPhase2Destroy (widget)
  112.     register Widget widget;
  113. {
  114.     Display        *display;
  115.     Window        window;
  116.     Widget          parent;
  117.     XtAppContext    app = XtWidgetToApplicationContext(widget);
  118.     Widget        outerInPhase2Destroy = app->in_phase2_destroy;
  119.     int            starting_count = app->destroy_count;
  120.     Boolean        isPopup = False;
  121.  
  122.     /* invalidate focus trace cache for this display */
  123.     _XtGetPerDisplay(XtDisplayOfObject(widget))->pdi.traceDepth = 0;
  124.  
  125.     parent = widget->core.parent;
  126.  
  127.     if (parent && parent->core.num_popups) {
  128.     int i;
  129.     for (i = 0; i < parent->core.num_popups; i++) {
  130.         if (parent->core.popup_list[i] == widget) {
  131.         isPopup = True;
  132.         break;
  133.         }
  134.     }
  135.     }
  136.  
  137.     if (!isPopup && parent && XtIsComposite(parent)) {
  138.     XtWidgetProc delete_child =
  139.         ((CompositeWidgetClass) parent->core.widget_class)->
  140.         composite_class.delete_child;
  141.         if (XtIsRectObj(widget)) {
  142.                XtUnmanageChild(widget);
  143.         }
  144.     if (delete_child == NULL) {
  145.         String param = parent->core.widget_class->core_class.class_name;
  146.         Cardinal num_params = 1;
  147.         XtAppWarningMsg(XtWidgetToApplicationContext(widget),
  148.         "invalidProcedure","deleteChild",XtCXtToolkitError,
  149.         "null delete_child procedure for class %s in XtDestroy",
  150.         ¶m, &num_params);
  151.     } else {
  152.         (*delete_child) (widget);
  153.     }
  154.     }
  155.  
  156.     /* widget is freed in Phase2Destroy, so retrieve window now.
  157.      * Shells destroy their own windows, to prevent window leaks in
  158.      * popups; this test is practical only when XtIsShell() is cheap.
  159.      */
  160.     if (XtIsShell(widget) || !XtIsWidget(widget)) {
  161.     window = 0;
  162. #ifdef lint
  163.     display = 0;
  164. #endif
  165.     }
  166.     else {
  167.     display = XtDisplay(widget);
  168.     window = widget->core.window;
  169.     }
  170.  
  171.     Recursive(widget, Phase2Callbacks);
  172.     if (app->destroy_count > starting_count) {
  173.     int i = starting_count;
  174.     while (i < app->destroy_count) {
  175.  
  176.         DestroyRec * dr = app->destroy_list + i;
  177.         if (IsDescendant(dr->widget, widget)) {
  178.         Widget descendant = dr->widget;
  179.         register int j;
  180.         app->destroy_count--;
  181.         for (j = app->destroy_count - i; --j >= 0; dr++)
  182.             *dr = *(dr + 1);
  183.         XtPhase2Destroy(descendant);
  184.         }
  185.         else i++;
  186.     }
  187.     }
  188.  
  189.     app->in_phase2_destroy = widget;
  190.     Recursive(widget, Phase2Destroy);
  191.     app->in_phase2_destroy = outerInPhase2Destroy;
  192.  
  193.     if (isPopup) {
  194.     int i;
  195.     for (i = 0; i < parent->core.num_popups; i++)
  196.         if (parent->core.popup_list[i] == widget) {
  197.         parent->core.num_popups--;
  198.         while (i < parent->core.num_popups) {
  199.             parent->core.popup_list[i] = parent->core.popup_list[i+1];
  200.             i++;
  201.         }
  202.         break;
  203.         }
  204.     }
  205.  
  206.     /* %%% the following parent test hides a more serious problem,
  207.        but it avoids breaking those who depended on the old bug
  208.        until we have time to fix it properly. */
  209.  
  210.     if (window && (parent == NULL || !parent->core.being_destroyed))
  211.     XDestroyWindow(display, window);
  212. } /* XtPhase2Destroy */
  213.  
  214.  
  215. void _XtDoPhase2Destroy(app, dispatch_level)
  216.     XtAppContext app;
  217.     int dispatch_level;
  218. {
  219.     /* Phase 2 must occur in fifo order.  List is not necessarily
  220.      * contiguous in dispatch_level.
  221.      */
  222.  
  223.     int i = 0;
  224.     while (i < app->destroy_count) {
  225.  
  226.     /* XtPhase2Destroy can result in calls to XtDestroyWidget,
  227.      * and these could cause app->destroy_list to be reallocated.
  228.      */
  229.  
  230.     DestroyRec* dr = app->destroy_list + i;
  231.     if (dr->dispatch_level >= dispatch_level)  {
  232.         Widget w = dr->widget;
  233.         register int j;
  234.         app->destroy_count--;
  235.         for (j = app->destroy_count - i; --j >=0; dr++)
  236.         *dr = *(dr + 1);
  237.         XtPhase2Destroy(w);
  238.     }
  239.     else i++;
  240.     }
  241. }
  242.  
  243.  
  244. void XtDestroyWidget (widget)
  245.     Widget    widget;
  246. {
  247.     XtAppContext app = XtWidgetToApplicationContext(widget);
  248.     register DestroyRec *dr, *dr2;
  249.  
  250.     if (widget->core.being_destroyed) return;
  251.  
  252.     Recursive(widget, Phase1Destroy);
  253.  
  254.     if (app->in_phase2_destroy &&
  255.     IsDescendant(widget, app->in_phase2_destroy))
  256.     {
  257.     XtPhase2Destroy(widget);
  258.     return;
  259.     }
  260.  
  261.     if (app->destroy_count == app->destroy_list_size) {
  262.     app->destroy_list_size += 10;
  263.     app->destroy_list = (DestroyRec*)
  264.         XtRealloc( (char*)app->destroy_list,
  265.                (unsigned)sizeof(DestroyRec)*app->destroy_list_size
  266.               );
  267.     }
  268.     dr = app->destroy_list + app->destroy_count++;
  269.     dr->dispatch_level = app->dispatch_level;
  270.     dr->widget = widget;
  271.  
  272.     if (app->dispatch_level > 1) {
  273.     int i;
  274.     for (i = app->destroy_count - 1; i;) {
  275.         /* this handles only one case of nesting difficulties */
  276.          dr = app->destroy_list + (--i);
  277.          if (dr->dispatch_level < app->dispatch_level &&
  278.          IsDescendant(dr->widget, widget)) {
  279.              dr2 = app->destroy_list + (app->destroy_count-1);
  280.          dr2->dispatch_level = dr->dispatch_level;
  281.           break;
  282.           }
  283.       }
  284.     }
  285.  
  286.     if (_XtSafeToDestroy(app)) {
  287.     app->dispatch_level = 1; /* avoid nested _XtDoPhase2Destroy */
  288.     _XtDoPhase2Destroy(app, 0);
  289.     app->dispatch_level = 0;
  290.     }
  291.     
  292. } /* XtDestroyWidget */
  293.