home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / editres / wtree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-09  |  18.5 KB  |  731 lines

  1. /*
  2.  * $XConsortium: wtree.c,v 1.13 91/07/09 12:08:53 rws Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <X11/Intrinsic.h>
  26. #include <X11/Xutil.h>
  27. #include <X11/StringDefs.h>
  28.  
  29. #include <X11/Xaw/Cardinals.h>
  30. #include <X11/Xaw/Toggle.h>
  31. #include <X11/Xaw/Viewport.h>    
  32. #include <X11/Xaw/Tree.h>
  33.  
  34. #include "editresP.h"
  35.  
  36. extern ScreenData global_screen_data;
  37. extern void SetMessage();
  38.  
  39. static Boolean IsActiveNode();
  40. static void AddChild(), FillNode();
  41. static void AddNode();
  42. static void AddNodeToActiveList(), RemoveNodeFromActiveList();
  43.  
  44. extern void PrepareToLayoutTree(), LayoutTree();
  45.  
  46. extern void _TreeSelectNode(), _TreeActivateNode(), _TreeRelabelNode();
  47. static WNode ** CopyActiveNodes();
  48.  
  49. void TreeToggle();
  50.  
  51. /*    Function Name: BuildVisualTree
  52.  *    Description: Creates the Tree and shows it.
  53.  *    Arguments: tree_parent - parent of the tree widget.
  54.  *                 event - the event that caused this action.
  55.  *    Returns: none.
  56.  */
  57.  
  58. /* ARGSUSED */
  59. void
  60. BuildVisualTree(tree_parent, event)
  61. Widget tree_parent;
  62. Event * event;
  63. {
  64.     WNode * top;
  65.     TreeInfo *CreateTree();
  66.     void AddTreeNode();
  67.     char msg[BUFSIZ];
  68.  
  69.     if (global_tree_info != NULL) {
  70.     XtDestroyWidget(global_tree_info->tree_widget);
  71.     XtFree((char *)global_tree_info->active_nodes);
  72.     XtFree((char *)global_tree_info);
  73.     }
  74.  
  75.     global_tree_info = CreateTree(event);
  76.     top = global_tree_info->top_node;
  77.  
  78.     global_tree_info->tree_widget = XtCreateWidget("tree", treeWidgetClass,
  79.                            tree_parent, NULL, ZERO);
  80.  
  81.     if (top == NULL) {
  82.     SetMessage(global_screen_data.info_label,
  83.            "There is no widget tree to display.");
  84.     return;
  85.     }
  86.  
  87.     AddTreeNode(global_tree_info->tree_widget, top);
  88.  
  89.     if (XtIsRealized(tree_parent)) /* hack around problems in Xt. */
  90.     XtRealizeWidget(global_tree_info->tree_widget);
  91.  
  92.     XtManageChild(global_tree_info->tree_widget);
  93.  
  94.     sprintf(msg, "Widget Tree for client %s(%s).", top->name, top->class);
  95.     SetMessage(global_screen_data.info_label, msg);
  96. }
  97.  
  98. /*    Function Name: AddTreeNode
  99.  *    Description: Adds all nodes below this to the Tree widget.
  100.  *    Arguments: parent - parent of the tree widget.
  101.  *                 top - the top node of the tree.
  102.  *    Returns: the tree widget.
  103.  *
  104.  * NOTE: This is a recursive function.
  105.  */
  106.  
  107. void
  108. AddTreeNode(tree, top) 
  109. Widget tree;
  110. WNode * top;
  111. {
  112.     int i;
  113.     Arg args[1];
  114.     Cardinal num_args = 0;
  115.     char msg[BUFSIZ];
  116.  
  117.     if (top->parent != NULL) {
  118.     if (top->parent->widget == NULL) {
  119.         sprintf( msg, "Loop in tree: node %s's parent (%s) has %s.\n",
  120.             top->name, top->parent->name, "not been created yet");
  121.         SetMessage(global_screen_data.info_label, msg);
  122.     }
  123.     XtSetArg(args[num_args], XtNtreeParent, top->parent->widget);
  124.     num_args++;
  125.     }
  126.  
  127.     top->widget = XtCreateManagedWidget(top->name, toggleWidgetClass, tree,
  128.                     args, num_args);
  129.  
  130.     if (XSaveContext(XtDisplay(top->widget), (Window) top->widget, 
  131.              NODE_INFO, (caddr_t) top) != 0) {
  132.     sprintf( msg, "XSaveContext failed on widget %s.", top->name);
  133.     SetMessage(global_screen_data.info_label, msg);
  134.     }    
  135.  
  136.     XtAddCallback(top->widget, XtNcallback, TreeToggle, (XtPointer) top);
  137.  
  138.     for (i = 0; i < top->num_children; i++) 
  139.     AddTreeNode(tree, top->children[i]);
  140. }
  141.  
  142. /*    Function Name: TreeToggle
  143.  *    Description: Called whenever a tree node is toggled.
  144.  *    Arguments: w - the tree widget.
  145.  *                 node_ptr - pointer to this node's information.
  146.  *                 state_ptr - state of the toggle.
  147.  *    Returns: none.
  148.  */
  149.  
  150. /* ARGSUSED */
  151. void
  152. TreeToggle(w, node_ptr, state_ptr)
  153. Widget w;
  154. caddr_t node_ptr, state_ptr;
  155. {
  156.     Boolean state = (Boolean) state_ptr;
  157.     WNode * node = (WNode *) node_ptr;
  158.  
  159.     if (state) 
  160.     AddNodeToActiveList(node);
  161.     else
  162.     RemoveNodeFromActiveList(node);
  163. }
  164.  
  165. /*    Function Name: AddNodeToActiveList
  166.  *    Description: Adds this node to the list of active toggles.
  167.  *    Arguments: node - node to add.
  168.  *    Returns: none.
  169.  */
  170.  
  171. static void
  172. AddNodeToActiveList(node)
  173. WNode * node;
  174. {
  175.     TreeInfo * info = node->tree_info;
  176.  
  177.     if (IsActiveNode(node))    /* node already active. */
  178.     return;
  179.  
  180.     if (info->num_nodes >= info->alloc_nodes) {
  181.     info->alloc_nodes += NUM_INC;
  182.     info->active_nodes =(WNode **)XtRealloc((XtPointer) info->active_nodes,
  183.                         sizeof(WNode *) * 
  184.                              info->alloc_nodes);
  185.     }
  186.  
  187.     info->active_nodes[info->num_nodes++] = node;
  188. }
  189.  
  190. /*    Function Name: RemoveNodeFromActiveList
  191.  *    Description: Removes a node from the active list.
  192.  *    Arguments: node - node to remove.
  193.  *    Returns: none.
  194.  */
  195.  
  196. static void
  197. RemoveNodeFromActiveList(node)
  198. WNode * node;
  199. {
  200.     TreeInfo * info = node->tree_info;
  201.     Boolean found_node = FALSE;
  202.     int i;
  203.  
  204.     if (!IsActiveNode(node))    /* This node is not active. */
  205.     return;
  206.  
  207.     for (i = 0; i < info->num_nodes; i++) {
  208.     if (found_node)
  209.         info->active_nodes[i - 1] = info->active_nodes[i];
  210.     else if (info->active_nodes[i] == node) 
  211.         found_node = TRUE;
  212.     }
  213.  
  214.     info->num_nodes--;
  215. }
  216.  
  217. /*    Function Name: IsActiveNode
  218.  *    Description: returns TRUE is this node is on the active list.
  219.  *    Arguments: node - node to check.
  220.  *    Returns: see above.
  221.  */
  222.  
  223. static Boolean
  224. IsActiveNode(node)
  225. WNode * node;
  226. {
  227.     TreeInfo * info = node->tree_info;
  228.     int i;
  229.  
  230.     for (i = 0; i < info->num_nodes; i++) 
  231.     if (info->active_nodes[i] == node)
  232.         return(TRUE);
  233.  
  234.     return(FALSE);
  235. }
  236.     
  237. /*    Function Name: CreateTree
  238.  *    Description: Creates a widget tree give a list of names and classes.
  239.  *    Arguments: event - the information from the client.
  240.  *    Returns: The tree_info about this new tree.
  241.  */
  242.     
  243. TreeInfo *
  244. CreateTree(event)
  245. Event * event;
  246. {
  247.     SendWidgetTreeEvent * send_event = (SendWidgetTreeEvent *) event;
  248.     int i;
  249.  
  250.     TreeInfo * tree_info;
  251.  
  252.     tree_info = (TreeInfo *) XtMalloc( (Cardinal) sizeof(TreeInfo));
  253.  
  254.     tree_info->tree_widget = NULL;
  255.     tree_info->top_node = NULL;
  256.     tree_info->active_nodes = NULL;
  257.     tree_info->num_nodes = tree_info->alloc_nodes = 0;
  258.     tree_info->flash_widgets = NULL;
  259.     tree_info->num_flash_widgets = tree_info->alloc_flash_widgets = 0;
  260.  
  261.     for ( i = 0; i < (int)send_event->num_entries; i++)
  262.     AddNode(&(tree_info->top_node), (send_event->info + i), tree_info);
  263.  
  264.     return(tree_info);
  265. }
  266.  
  267. /*    Function Name: PrintNodes
  268.  *    Description: Prints all nodes.
  269.  *    Arguments: top - the top node.
  270.  *    Returns: none.
  271.  */
  272.  
  273. void
  274. PrintNodes(top)
  275. WNode * top;
  276. {
  277.     int i;
  278.  
  279.     if (top->parent == NULL) 
  280.     printf("Top of Tree, Name: %10s, ID: %10ld, Class: %10s\n", 
  281.            top->name, top->id, top->class);
  282.     else
  283.     printf("Parent %10s, Name: %10s, ID: %10ld, Class: %10s\n", 
  284.            top->parent->name, top->name, top->id, top->class);
  285.  
  286.     for (i = 0; i < top->num_children; i++) 
  287.     PrintNodes(top->children[i]);
  288. }
  289.  
  290. /*    Function Name: _TreeRelabel
  291.  *    Description: Modifies the selected elements of the tree
  292.  *    Arguments: tree_info - the tree we are working on.
  293.  *                 type - type of selection to perform
  294.  *    Returns: none.
  295.  */
  296.  
  297. void
  298. _TreeRelabel(tree_info, type)
  299. TreeInfo * tree_info;
  300. LabelTypes type;
  301. {
  302.     WNode * top;
  303.  
  304.     if (tree_info == NULL) {
  305.     SetMessage(global_screen_data.info_label,
  306.            "No widget Tree is avaliable.");
  307.     return;
  308.     }
  309.  
  310.     top = tree_info->top_node;
  311.  
  312.     PrepareToLayoutTree(tree_info->tree_widget); 
  313.     _TreeRelabelNode(top, type, TRUE);
  314.     LayoutTree(tree_info->tree_widget); 
  315. }
  316.  
  317. /*    Function Name: _TreeSelect
  318.  *    Description: Activates relatives of the active nodes, as specified
  319.  *                   by type, or Selects all nodes as specified by type.
  320.  *    Arguments: tree_info - information about the tree to work on.
  321.  *                 type - type of activate to invode.
  322.  *    Returns: none.
  323.  */
  324.  
  325. void
  326. _TreeSelect(tree_info, type)
  327. TreeInfo * tree_info;
  328. SelectTypes type;
  329. {
  330.     WNode ** active_nodes;
  331.     Cardinal num_active_nodes;
  332.     int i;
  333.  
  334.     if (tree_info == NULL) {
  335.     SetMessage(global_screen_data.info_label,
  336.            "No widget Tree is avaliable.");
  337.     return;
  338.     }
  339.  
  340.     switch(type) {
  341.     case SelectNone:
  342.     case SelectAll:
  343.     case SelectInvert:
  344.     _TreeSelectNode(tree_info->top_node, type, TRUE);
  345.     return;
  346.     default:
  347.     break;            /* otherwise continue. */
  348.     }
  349.  
  350.     if (tree_info->num_nodes == 0) {
  351.     SetMessage(global_screen_data.info_label,
  352.            "There are no active nodes.");
  353.     return;
  354.     }
  355.  
  356.     active_nodes = CopyActiveNodes(tree_info);
  357.     num_active_nodes = tree_info->num_nodes;
  358.  
  359.     for (i = 0; i < num_active_nodes; i++)
  360.     _TreeActivateNode(active_nodes[i], type);
  361.  
  362.     XtFree((XtPointer) active_nodes);
  363. }
  364.  
  365. /*    Function Name: _TreeSelectNode
  366.  *    Description: Modifies the state of a node and all its decendants.
  367.  *    Arguments: node - node to operate on.
  368.  *                 type - type of selection to perform.
  369.  *                 recurse - whether to continue on down the tree.
  370.  *    Returns: none.
  371.  */
  372.  
  373. void
  374. _TreeSelectNode(node, type, recurse)
  375. WNode * node;
  376. SelectTypes type;
  377. Boolean recurse;
  378. {
  379.     int i;
  380.     Arg args[1];
  381.     Boolean state;
  382.  
  383.     switch(type) {
  384.     case SelectAll:
  385.     state = TRUE;
  386.     break;
  387.     case SelectNone:
  388.     state = FALSE;
  389.     break;
  390.     case SelectInvert:
  391.     XtSetArg(args[0], XtNstate, &state);
  392.     XtGetValues(node->widget, args, ONE);
  393.     
  394.     state = !state;
  395.     break;
  396.     default:
  397.     SetMessage(global_screen_data.info_label,
  398.            "Internal Error: Unknown select type.");
  399.     return;
  400.     }
  401.  
  402.     XtSetArg(args[0], XtNstate, state);
  403.     XtSetValues(node->widget, args, ONE);
  404.     TreeToggle(node->widget, (XtPointer) node, (XtPointer) state);
  405.  
  406.     if (!recurse)
  407.     return;
  408.  
  409.     for (i = 0; i < node->num_children; i++) 
  410.     _TreeSelectNode(node->children[i], type, recurse);
  411. }
  412.  
  413. /*    Function Name: _TreeRelabelNodes
  414.  *    Description: Modifies the node and all its decendants label.
  415.  *    Arguments: node - node to operate on.
  416.  *                 type - type of selection to perform.
  417.  *                 recurse - whether to continue on down the tree.
  418.  *    Returns: none.
  419.  */
  420.  
  421. void
  422. _TreeRelabelNode(node, type, recurse)
  423. WNode * node;
  424. LabelTypes type;
  425. Boolean recurse;
  426. {
  427.     int i;
  428.     Arg args[1];
  429.     char buf[30];
  430.     char *label;
  431.  
  432.     switch(type) {
  433.     case ClassLabel:
  434.     XtSetArg(args[0], XtNlabel, node->class);
  435.     break;
  436.     case NameLabel:
  437.     XtSetArg(args[0], XtNlabel, node->name);
  438.     break;
  439.     case IDLabel:
  440.     sprintf(buf, "id: 0x%lx", node->id);
  441.     XtSetArg(args[0], XtNlabel, buf);
  442.     break;
  443.     case WindowLabel:
  444.     if (node->window == EDITRES_IS_UNREALIZED) 
  445.         strcpy(buf, "unrealized widget");
  446.     else if (node->window == EDITRES_IS_OBJECT) 
  447.         strcpy(buf, "non windowed object");        
  448.     else
  449.         sprintf(buf, "win: 0x%lx", node->window);
  450.         
  451.     XtSetArg(args[0], XtNlabel, buf);
  452.     break;
  453.     case ToggleLabel:
  454.     XtSetArg(args[0], XtNlabel, &label);
  455.     XtGetValues(node->widget, args, ONE);
  456.     if (label && !strcmp(label, node->name))
  457.         XtSetArg(args[0], XtNlabel, node->class);
  458.     else
  459.         XtSetArg(args[0], XtNlabel, node->name);
  460.     break;
  461.     default:
  462.     SetMessage(global_screen_data.info_label,
  463.            "Internal Error: Unknown label type.");
  464.     return;
  465.     }
  466.  
  467.     XtSetValues(node->widget, args, ONE);
  468.  
  469.     if (!recurse)
  470.     return;
  471.  
  472.     for (i = 0; i < node->num_children; i++) 
  473.     _TreeRelabelNode(node->children[i], type, recurse);
  474. }
  475.  
  476. /*    Function Name: _TreeActivateNode
  477.  *    Description: Activates relatives of the node specfied, as specified
  478.  *                   by type.
  479.  *    Arguments: node - node to opererate on.
  480.  *                 type - type of activate to invode.
  481.  *    Returns: none.
  482.  */
  483.  
  484. void
  485. _TreeActivateNode(node, type)
  486. WNode * node;
  487. SelectTypes type;
  488. {
  489.     Arg args[1];
  490.     int i;
  491.  
  492.     XtSetArg(args[0], XtNstate, TRUE);
  493.  
  494.     if ((type == SelectParent) || (type == SelectAncestors)) {
  495.     node = node->parent;
  496.     if (node == NULL)
  497.         return;
  498.  
  499.     XtSetValues(node->widget, args, ONE);    
  500.     AddNodeToActiveList(node);
  501.  
  502.     if (type == SelectAncestors)
  503.         _TreeActivateNode(node, type);    
  504.     }
  505.     else if ((type == SelectChildren) || (type == SelectDescendants)) 
  506.     for (i = 0; i < node->num_children; i++) {
  507.         AddNodeToActiveList(node->children[i]);
  508.         XtSetValues(node->children[i]->widget, args, ONE);
  509.         if (type == SelectDescendants)
  510.         _TreeActivateNode(node->children[i], type);
  511.     }
  512.     else
  513.     SetMessage(global_screen_data.info_label,
  514.            "Internal Error: Unknown activate type.");    
  515. }
  516.  
  517. /************************************************************
  518.  *
  519.  * Non - Exported Functions. 
  520.  *
  521.  ************************************************************/
  522.  
  523. WNode * FindNode();
  524.  
  525. /*    Function Name: AddNode
  526.  *    Description: adds a node to the widget tree.
  527.  *    Arguments: top_node - a pointer to the current top node.
  528.  *                 info - the info from the client about the widget tree.
  529.  *                 tree_info - global information on this tree.
  530.  *    Returns: none.
  531.  */
  532.  
  533. static void
  534. AddNode(top_node, info, tree_info)
  535. WNode ** top_node;
  536. WidgetTreeInfo * info;
  537. TreeInfo * tree_info;
  538. {
  539.     WNode *node, *parent;
  540.     Boolean early_break = FALSE;
  541.     Cardinal number = info->widgets.num_widgets;
  542.  
  543.     if ( (node = FindNode(*top_node, info->widgets.ids, number)) == NULL) {
  544.     node = (WNode *) XtCalloc(sizeof(WNode), ONE);
  545.  
  546.     node->id = info->widgets.ids[number - 1];
  547.     FillNode(info, node, tree_info);
  548.  
  549.     for ( number--; number > 0; number--, node = parent) {
  550.         parent = FindNode(*top_node, info->widgets.ids, number);
  551.         if (parent == NULL) {
  552.         parent = (WNode *) XtCalloc(sizeof(WNode), ONE);
  553.         parent->id = info->widgets.ids[number - 1];
  554.         }
  555.         else
  556.         early_break = TRUE;
  557.  
  558.         AddChild(parent, node);
  559.  
  560.         if (early_break) 
  561.         break;
  562.     }
  563.  
  564.     if (!early_break) {
  565.         if (node->parent == NULL)
  566.         *top_node = node;
  567.         else
  568.         *top_node = node->parent;
  569.     }
  570.     }
  571.     else
  572.     FillNode(info, node, tree_info);
  573. }
  574.  
  575. /*    Function Name: FillNode
  576.  *    Description: Fills in everything but the node id in the node.
  577.  *    Arguments: info - the info from the client.
  578.  *                 node - node to fill.
  579.  *                 tree_info - global information on this tree.
  580.  *    Returns: none
  581.  */
  582.  
  583. static void
  584. FillNode(info, node, tree_info)
  585. WidgetTreeInfo * info;
  586. WNode * node;
  587. TreeInfo * tree_info;
  588. {
  589.     node->class = info->class;
  590.     info->class = NULL;    /* keeps it from deallocating. */
  591.     node->name = info->name;
  592.     info->name = NULL;
  593.     node->window = info->window;
  594.     node->tree_info = tree_info;
  595. }
  596.  
  597. /*    Function Name: AddChild
  598.  *    Description: Adds a child to an existing node.
  599.  *    Arguments: parent - parent node.
  600.  *                 child - child node to add.
  601.  *    Returns: none.
  602.  */
  603.  
  604. static void
  605. AddChild(parent, child)
  606. WNode * parent, * child;
  607. {
  608.     if (parent->num_children >= parent->alloc_children) {
  609.     parent->alloc_children += NUM_INC;
  610.     parent->children = (WNode **) XtRealloc((char *)parent->children, 
  611.                      sizeof(WNode *) * parent->alloc_children);
  612.     }
  613.  
  614.     parent->children[parent->num_children] = child;
  615.     (parent->num_children)++;
  616.  
  617.     child->parent = parent;
  618. }
  619.  
  620. /************************************************************
  621.  *
  622.  *  Functions that operate of the current tree.
  623.  * 
  624.  ************************************************************/
  625.     
  626. /*    Function Name: CopyActiveNodes
  627.  *    Description: returns a copy of the currently selected nodes.
  628.  *    Arguments: tree_info - the tree info struct.
  629.  *    Returns: a copy of the selected nodes.
  630.  */
  631.  
  632. static WNode ** 
  633. CopyActiveNodes(tree_info)
  634. TreeInfo * tree_info;
  635. {
  636.     WNode ** list;
  637.     int i;
  638.  
  639.     if ( (tree_info == NULL) || (tree_info->num_nodes == 0))
  640.     return(NULL);
  641.  
  642.     list = (WNode **) XtMalloc(sizeof(WNode *) * tree_info->num_nodes);
  643.  
  644.     for (i = 0; i < tree_info->num_nodes; i++)
  645.     list[i] = tree_info->active_nodes[i];
  646.  
  647.     return(list);
  648. }
  649.  
  650. /*    Function Name: SetAndCenterTreeNode
  651.  *    Description: Deactivates all nodes, activates the one specified, and
  652.  *                   and moves the tree to be centered on the current node.
  653.  *    Arguments: node - node to use.
  654.  *    Returns: none.
  655.  */
  656.  
  657. void
  658. SetAndCenterTreeNode(node)
  659. WNode * node;
  660. {
  661.     Arg args[5];
  662.     Cardinal num_args;
  663.     Position node_x, node_y;
  664.     Dimension port_width, port_height;
  665.     Dimension node_width, node_height, node_bw;
  666.  
  667.     _TreeSelect(node->tree_info, SelectNone); /* Unselect all nodes */
  668.     _TreeSelectNode(node, SelectAll, FALSE);  /* Select this node */
  669.  
  670.     /*
  671.      * Get porthole dimensions.
  672.      */
  673.  
  674.     num_args = 0;
  675.     XtSetArg(args[num_args], XtNwidth, &port_width); num_args++;
  676.     XtSetArg(args[num_args], XtNheight, &port_height); num_args++;
  677.     XtGetValues(XtParent(node->tree_info->tree_widget), args, num_args);
  678.  
  679.     /*
  680.      * Get node widget dimensions.
  681.      */
  682.  
  683.     num_args = 0;
  684.     XtSetArg(args[num_args], XtNwidth, &node_width); num_args++;
  685.     XtSetArg(args[num_args], XtNheight, &node_height); num_args++;
  686.     XtSetArg(args[num_args], XtNborderWidth, &node_bw); num_args++;
  687.     XtSetArg(args[num_args], XtNx, &node_x); num_args++;
  688.     XtSetArg(args[num_args], XtNy, &node_y); num_args++;
  689.     XtGetValues(node->widget, args, num_args);
  690.  
  691.     /*
  692.      * reset the node x and y location to be the new x and y location of
  693.      * the tree relative to the porthole.
  694.      */
  695.  
  696.     node_x = port_width/2 - (node_x + node_width/2 + node_bw);
  697.     node_y = port_height/2 - (node_y + node_height/2 + node_bw);
  698.  
  699.     num_args = 0;
  700.     XtSetArg(args[num_args], XtNx, node_x); num_args++;
  701.     XtSetArg(args[num_args], XtNy, node_y); num_args++;
  702.     XtSetValues(node->tree_info->tree_widget, args, num_args);    
  703. }
  704.  
  705. /*    Function Name: PerformTreeToFileDump
  706.  *    Description: Dumps the contents of the current widget tree to
  707.  *                   the file specified. 
  708.  *    Arguments: node - node to dump.
  709.  *                 num_tabs - number of spaces to indent.
  710.  *                 fp - pointer to the file to write to.
  711.  *    Returns: none.
  712.  */
  713.  
  714. void
  715. PerformTreeToFileDump(node, num_tabs, fp)
  716. WNode * node;
  717. int num_tabs;
  718. FILE * fp;
  719. {
  720.     int i;
  721.  
  722.     for (i = 0; i < num_tabs; i++) 
  723.     fprintf(fp, "\t");
  724.     fprintf(fp, "%s  %s\n", node->class, node->name);
  725.  
  726.     num_tabs++;
  727.     for (i = 0; i < node->num_children; i++)
  728.     PerformTreeToFileDump(node->children[i], num_tabs, fp);
  729. }
  730.  
  731.