diff pkg-src/tree-x/intf.c @ 163:0132846995bd r20-3b8

Import from CVS: tag r20-3b8
author cvs
date Mon, 13 Aug 2007 09:43:35 +0200
parents
children 85ec50267440
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkg-src/tree-x/intf.c	Mon Aug 13 09:43:35 2007 +0200
@@ -0,0 +1,2004 @@
+/* ----------------------------------------------------------------------------
+ * File    : intf.c
+ * Purpose : X11/Athena interface code
+ * ----------------------------------------------------------------------------
+ */
+
+#define GLOBALS 1
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include <X11/IntrinsicP.h>
+#include <X11/ShellP.h>
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+
+#ifdef XAW3D
+  #include <X11/Xaw3d/Box.h>
+  #include <X11/Xaw3d/Simple.h>
+  #include <X11/Xaw3d/MenuButton.h>
+  #include <X11/Xaw3d/SimpleMenu.h>
+  #include <X11/Xaw3d/SmeBSB.h>
+  #include <X11/Xaw3d/SmeLine.h>
+  #include <X11/Xaw3d/Form.h>
+  #include <X11/Xaw3d/Label.h>
+  #include <X11/Xaw3d/Dialog.h>
+  #include <X11/Xaw3d/AsciiText.h>
+  #include <X11/Xaw3d/AsciiSrc.h>
+  #include <X11/Xaw3d/Viewport.h>
+  #include <X11/Xaw3d/Scrollbar.h>
+  #include <X11/Xaw3d/Paned.h>
+  #include <X11/Xaw3d/Panner.h>
+  #include <X11/Xaw3d/Reports.h>
+#else  
+  #include <X11/Xaw/Box.h>
+  #include <X11/Xaw/Simple.h>
+  #include <X11/Xaw/MenuButton.h>
+  #include <X11/Xaw/SimpleMenu.h>
+  #include <X11/Xaw/SmeBSB.h>
+  #include <X11/Xaw/SmeLine.h>
+  #include <X11/Xaw/Form.h>
+  #include <X11/Xaw/Label.h>
+  #include <X11/Xaw/Dialog.h>
+  #include <X11/Xaw/AsciiText.h>
+  #include <X11/Xaw/AsciiSrc.h>
+  #include <X11/Xaw/Viewport.h>
+  #include <X11/Xaw/Scrollbar.h>
+  #include <X11/Xaw/Paned.h>
+  #include <X11/Xaw/Panner.h>
+  #include <X11/Xaw/Reports.h>
+  #endif
+
+#include "defs.h"
+#include "tree.h"
+#include "dbl.h"
+#include "intf.h"
+#include "rsrc.h"
+#include "input.h"
+#include "help.h"
+
+#include <X11/cursorfont.h>
+
+
+/* ------------------------------------------------------------------------- */
+/*				Global Variables                             */
+/* ------------------------------------------------------------------------- */
+
+extern char  *EnvNm;    /* Stores name of current Envir file */
+
+Atom	      wm_delete_window;
+Widget        TreeTopLevel;
+Widget        TreeDrawingArea;
+Display      *TreeDisplay;
+XtAppContext  app;
+int           TreeScreen;
+int           TreeContourWidth;
+int           TreeBorderSize = BORDER_SIZE;
+int           TreeParentDistance = PARENT_DISTANCE;
+XFontStruct  *TreeLabelFont;
+DoubleBuffer *TreeDrawingAreaDB;
+ContourOption TreeShowContourOption = NoContours;
+DensityOption TreeLayoutDensity = Fixed;
+char          TreeShowSteps =  FALSE;
+char          TreeAlignNodes = FALSE;
+char          PauseAfterStep    = FALSE;
+
+/* ------------------------------------------------------------------------- */
+/*				Local Variables                              */
+/* ------------------------------------------------------------------------- */
+
+static Tree *PopupNode;		/* node selected for popup */
+static NodePosition NodePos;
+
+static Widget mainWindow;
+static Widget topForm;
+
+static Widget statusLabel;
+static Widget statusText;
+
+static Widget scrolledWindow;
+
+static Widget helpShell;
+static Widget helpForm;
+static Widget helpScrollWindow;
+static Widget helpText;
+static Widget helpDoneButton;
+static Widget helpTitle;
+static Widget helpFrame;
+
+static Widget treeMenubar;
+static Widget treeMenus[NUM_MENUS];
+static Widget treeMenuBtns[NUM_MENUS - 1];   /* don't need button for */
+					     /* node popup menu       */
+
+static Widget treeMenuItems[TREE_MENU_ITEMS];
+static Widget layoutMenuItems[LAYOUT_MENU_ITEMS];
+static Widget nodeMenuItems[NODE_MENU_ITEMS];
+static Widget helpBtn;
+
+static String labelStr[NUM_MENU_STRS];
+static String errStr[NUM_ERRS];
+
+static Widget dialog[NUM_DLG];
+
+/* globals used for state values */
+
+static Widget dlgLevelScale, dlgLevelValuator, 
+              dlgSiblingValuator, dlgSiblingScale;
+static int dlgLevelValue;
+static int dlgSiblingValue;
+static int loading_file = 0;
+
+static Pixmap check_pixmap, slider_pixmap;
+
+static Boolean nodeFound;
+
+static int    PauseTime         = ANIMATION_SPEED_FAST;
+static Cursor PauseCursor;
+
+static XtResource applRsrcsDesc[] = {
+   {
+      TrNbackgroundColor,       TrCBackgroundColor,
+      XtRPixel,                 sizeof(Pixel),
+      XtOffset(ApplRsrcDataPtr, background_color),
+      XtRString,                TrDefaultBackgroundColor
+   },
+   {
+      TrNtreeColor,             TrCTreeColor,
+      XtRPixel,                 sizeof(Pixel),
+      XtOffset(ApplRsrcDataPtr, tree_color),
+      XtRString,                TrDefaultTreeColor
+   },
+   {
+      TrNcontourColor,          TrCContourColor,
+      XtRPixel,                 sizeof(Pixel),
+      XtOffset(ApplRsrcDataPtr, contour_color),
+      XtRString,                TrDefaultContourColor
+   },
+   {
+      TrNsplitColor,            TrCSplitColor,
+      XtRPixel,                 sizeof(Pixel),
+      XtOffset(ApplRsrcDataPtr, split_color),
+      XtRString,                TrDefaultSplitColor
+   },
+   {
+      TrNhighlightColor,        TrCHighlightColor,
+      XtRPixel,                 sizeof(Pixel),
+      XtOffset(ApplRsrcDataPtr, highlight_color),
+      XtRString,                TrDefaultHighlightColor
+   },
+   {
+      TrNactionColor,           TrCActionColor,
+      XtRPixel,                 sizeof(Pixel),
+      XtOffset(ApplRsrcDataPtr, action_color),
+      XtRString,                TrDefaultActionColor
+   },
+   {
+      TrNcontourWidth,          TrCContourWidth,
+      XtRInt,                   sizeof(int),
+      XtOffset(ApplRsrcDataPtr, contour_width),
+      XtRImmediate,             (XtPointer) TrDefaultContourWidth
+   },
+};
+
+static void popdown_action();
+static void activate_action();
+static void quit_action();
+static void Action();
+
+static void select_action();
+static void button_action();
+static void menu_popup_action();
+
+static void set_levelscale_CB();
+static void levelscale_CB();
+static void set_siblingscale_CB();
+static void siblingscale_CB();
+static void set_levelvalue_CB();
+static void set_siblingvalue_CB();
+static void levelvalue_CB();
+static void siblingvalue_CB();
+
+static void center_widget();
+
+static XtActionsRec local_actions[] = {
+  {"wmpopdown", popdown_action},
+  {"dlg_activate", activate_action},
+  {"node_select", select_action},
+  {"node_menu_prepare", button_action},
+  {"maybe_menu_popup", menu_popup_action},
+  {"quit", quit_action},
+};
+
+String fallback_resources[]  = {
+"*statusText.width:                      310",
+"*treeDrawingArea.width:                 310",
+"*treeDrawingArea.height:                400",
+"*Text.Font:	      -*-lucidatypewriter-medium-r-*-*-12-*-*-*-*-*-iso8859-1",
+"*Label.Font:	      -*-helvetica-medium-r-*-*-12-*-*-*-*-*-iso8859-1",
+"*Command.Font:	      -*-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-1",
+"*SimpleMenu.Font:    -*-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-1",
+"*SmeBSB.Font:	      -*-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-1",
+"*MenuButton.Font:    -*-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-1",
+"*List.Font:	      -*-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-1",
+"*treeMenuBtn.label:			Tree",
+"*layoutMenuBtn.label:			Layout",
+"*helpBtn.label:			Help...",
+"*treeMenu*treeMenuNew.label:		New Tree",
+"*treeMenu*treeMenuLoad.label:		Load Tree",
+"*treeMenu*treeMenuSave.label:		Save Tree",
+"*treeMenu*treeMenuQuit.label:		Quit",
+"*layoutMenu*layoutMenuFixed.label:	Fixed",
+"*layoutMenu*layoutMenuVariable.label:	Variable",
+"*layoutMenu*layoutMenuSpacing.label:	Spacing...",
+"*layoutMenu*layoutMenuAlignNodes.label: Align Nodes on Level",
+"*dlgNewTree.title:			New Tree",
+"*dlgNodeName.title:			Node Name",
+"*dlgInfo.title:			Information",
+"*dlgError.title:			Error!",
+"*dlgSpacing.title:			Tree Node Spacing",
+"*helpShell.title:			Help",
+"*dlgNewTreeForm.label:			Enter name of root node:",
+"*dlgNodeNameForm.label:		Enter name of new node:",
+"*dlgFileForm.label:			Enter name of file:",
+"*dlgInfoForm.label:			Information:",
+"*dlgErrorForm.label:			Error:",
+"*dlgSpacing.label:			Spacing Dialog",
+"*dlgLevelLabel.label:			Level spacing:",
+"*dlgSiblingLabel.label:		Sibling spacing:",
+"*dlgLevelValuator.width:		40",
+"*dlgLevelValuator.width:		40",
+"*dlgNewTreeOk.label:			Ok",
+"*dlgNewTreeCancel.label:		Cancel",
+"*dlgFileOk.label:			Ok",
+"*dlgFileCancel.label:			Cancel",
+"*dlgInfoButton.label:			Acknowledged",
+"*dlgErrorButton.label:			Acknowledged",
+"*dlgOkButton.label:			Ok",
+"*dlgCancelButton.label:		Cancel",
+"*dlgNodeNameOk.label:			Ok",
+"*dlgNodeNameCancel.label:		Cancel",
+"*helpDoneButton.label:			Dismiss",
+"*helpTitle.label:			Help for Drawing Dynamic Trees",
+"*treeDrawingArea.Translations: #override \\n\
+                                <Btn1Down>:	node_select(EDIT)\\n\
+                                <Btn2Down>:	node_select(VIEW)\\n\
+                                <Btn3Down>:	XawPositionSimpleMenu(nodeMenu)node_menu_prepare()XtMenuPopup(nodeMenu)\\n",
+NULL,
+};
+
+static ApplRsrcData    applRsrcs;
+static ApplRsrcDataPtr applRsrcsPtr;
+
+/* included bitmaps */
+
+#define gray_width 8
+#define gray_height 8
+static unsigned char gray_bits[] = {
+  0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa
+};
+
+/* This is a check mark stolen from the xmh application. :) */
+#define check_width 9
+#define check_height 8
+static unsigned char check_bits[] = {
+  0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
+  0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00
+};
+
+#define slider_pixmap_width 4
+#define slider_pixmap_height 4
+static char slider_pixmap_bits[] = {
+  0x05, 0x0a, 0x05, 0x0a
+};
+
+/* ------------------------------------------------------------------------- */
+/*			 Forward Function Declarations                       */
+/* ------------------------------------------------------------------------- */
+
+static void popup_dialog();
+
+static void Quit_CB();
+
+static void Contours_CB();
+static void ShowContours_CB();
+static void Pause_CB();
+static void Speed_CB();
+
+static void Help_CB();
+static void HelpDone_CB();
+static void Scale_CB();
+
+static void TreeMenu_CB();
+static void LayoutMenu_CB();
+static void NodeMenu_CB();
+
+static void NodeLabel_CB();
+static void NewTree_CB();
+static void File_CB();
+
+static void Popdown_CB();
+static void ButtonHandler();
+
+extern void ExposeHandler();
+
+/* ------------------------------------------------------------------------- */
+/*				   Functions                                 */
+/* ------------------------------------------------------------------------- */
+
+/* ----------------------------------------------------------------------------
+ * 
+ *   Status() displays the specified text in the status area.
+ *   'urgent' overrides the value of TreeShowSteps.
+ * 
+ * ----------------------------------------------------------------------------
+ */
+
+void
+StatusMsg(msg, urgent)
+     char *msg;
+     int  urgent;
+{
+  if (TreeShowSteps || urgent) 
+    XtVaSetValues(statusText, XtNlabel, msg, NULL);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * 
+ *  Pause is a trivial function, for the benefit of interface-dependent code
+ *  inside tree.c. This avoids having to include X11 stuff inside that file.
+ *  PauseTime is expected to contain an integer indicating 1/10ths of a sec.
+ * 
+ * ----------------------------------------------------------------------------
+ */
+
+void
+Pause()
+{
+  XEvent event;
+  
+  if (PauseAfterStep) {
+    XGrabKeyboard(TreeDisplay, XtWindow(TreeTopLevel), False,
+		  GrabModeAsync, GrabModeAsync, CurrentTime);
+    XGrabPointer(TreeDisplay, XtWindow(TreeTopLevel), False,
+		 ButtonPressMask | ButtonReleaseMask,
+		 GrabModeAsync, GrabModeAsync, None,
+		 PauseCursor, CurrentTime);
+    XMaskEvent(TreeDisplay, ButtonPressMask | KeyPress, &event);
+    XUngrabPointer(TreeDisplay, CurrentTime);
+    XUngrabKeyboard(TreeDisplay, CurrentTime);
+  }
+  else if (TreeShowSteps) {
+    XSync(TreeDisplay, 0);
+    usleep(PauseTime * 100000);
+  }
+}
+
+/* ----------------------------------------------------------------------------
+ * 
+ *   BuildPopupMenus() builds the popup menus for use in the application
+ *   window.
+ * 
+ * ----------------------------------------------------------------------------
+ */
+
+void
+BuildPopupMenus(parent)
+     Widget parent;
+{
+  Arg      args[2];
+  String   xstr;
+  
+  labelStr[STR_NODE_COLLAPSE] = "Collapse Node";
+  labelStr[STR_NODE_EXPAND]   = "Expand Node";
+  
+  treeMenus[NODE_MENU] = XtVaCreatePopupShell("nodeMenu",
+					      simpleMenuWidgetClass,
+					      parent, 
+					      XtNlabel, " ",
+					      NULL);
+  
+  (void)  XtVaCreateManagedWidget("nodeMenuAddChild", smeLineObjectClass,
+				  treeMenus[NODE_MENU],
+				  NULL);
+  
+  nodeMenuItems[NODE_MENU_ADD_CHILD] = 
+    XtVaCreateManagedWidget("nodeMenuAddChild", smeBSBObjectClass,
+			    treeMenus[NODE_MENU],
+			    XtNlabel, "Add Child",
+			    NULL);
+  XtAddCallback(nodeMenuItems[NODE_MENU_ADD_CHILD],
+		XtNcallback, NodeMenu_CB, (XtPointer) NODE_MENU_ADD_CHILD);
+  
+  nodeMenuItems[NODE_MENU_ADD_BEFORE] = 
+    XtVaCreateManagedWidget("nodeMenuAddSiblingBefore", smeBSBObjectClass,
+			    treeMenus[NODE_MENU],
+			    XtNlabel, "Add Sibling Before",
+			    NULL);
+  XtAddCallback(nodeMenuItems[NODE_MENU_ADD_BEFORE],
+		 XtNcallback, NodeMenu_CB, (XtPointer) NODE_MENU_ADD_BEFORE);
+		 
+   nodeMenuItems[NODE_MENU_ADD_AFTER] = 
+       XtVaCreateManagedWidget("nodeMenuAddSiblingAfter", smeBSBObjectClass,
+			       treeMenus[NODE_MENU],
+			       XtNlabel, "Add Sibling After",
+			       NULL);
+   XtAddCallback(nodeMenuItems[NODE_MENU_ADD_AFTER],
+		 XtNcallback, NodeMenu_CB, (XtPointer) NODE_MENU_ADD_AFTER);
+
+   nodeMenuItems[NODE_MENU_ELISION] =
+       XtVaCreateManagedWidget("nodeMenuElision", smeBSBObjectClass,
+			       treeMenus[NODE_MENU],
+			       XtNlabel, labelStr[STR_NODE_COLLAPSE],
+			       NULL);
+   XtAddCallback(nodeMenuItems[NODE_MENU_ELISION],
+		 XtNcallback, NodeMenu_CB, (XtPointer) NODE_MENU_ELISION);
+
+   
+   nodeMenuItems[NODE_MENU_DELETE] =
+       XtVaCreateManagedWidget("nodeMenuDeleteNode", smeBSBObjectClass,
+			       treeMenus[NODE_MENU],
+			       XtNlabel, "Delete Node",
+			       NULL);
+   XtAddCallback(nodeMenuItems[NODE_MENU_DELETE],
+		 XtNcallback, NodeMenu_CB, (XtPointer) NODE_MENU_DELETE);
+
+		 
+}
+
+/* ----------------------------------------------------------------------------
+ * 
+ *   BuildMenubar() builds the menubar that appears in the main window.
+ * 
+ * ----------------------------------------------------------------------------
+ */
+
+
+void
+BuildMenubar(parent)
+   Widget parent;
+{
+   Arg args[4];
+   int i;
+   Widget box;
+
+   box = XtVaCreateManagedWidget("menuBox",
+				 boxWidgetClass,
+				 parent,
+				 XtNshowGrip, FALSE,
+				 XtNborderWidth, 0,
+				 NULL);
+				 
+
+   /* menu button widgets */
+   treeMenuBtns[TREE_MENU] = 
+       XtVaCreateManagedWidget("treeMenuBtn",
+			       menuButtonWidgetClass,
+			       box,
+			       XtNmenuName, "treeMenu",
+			       NULL);
+   treeMenuBtns[LAYOUT_MENU] =
+       XtVaCreateManagedWidget("layoutMenuBtn",
+			       menuButtonWidgetClass,
+			       box,
+			       XtNmenuName, "layoutMenu",
+			       NULL);
+
+   helpBtn = XtVaCreateManagedWidget("helpBtn",
+				     commandWidgetClass,
+				     box,
+				     NULL);
+
+   XtAddCallback(helpBtn, XtNcallback, Help_CB, NULL);
+
+   /* create pulldwon menus */
+
+   treeMenus[TREE_MENU] = XtVaCreatePopupShell("treeMenu",
+					       simpleMenuWidgetClass,
+					       treeMenuBtns[TREE_MENU],
+					       NULL, 0);
+   treeMenus[LAYOUT_MENU] = XtVaCreatePopupShell("layoutMenu",
+						 simpleMenuWidgetClass,
+						 treeMenuBtns[LAYOUT_MENU],
+						 NULL, 0);
+
+
+   /* adding menu entries */
+   
+   /* Tree menu */
+
+   treeMenuItems[TREE_MENU_NEW] = 
+       XtVaCreateManagedWidget("treeMenuNew", smeBSBObjectClass,
+			       treeMenus[TREE_MENU],
+			       NULL);
+   XtAddCallback(treeMenuItems[TREE_MENU_NEW],
+		 XtNcallback, TreeMenu_CB, TREE_MENU_NEW);
+   
+   treeMenuItems[TREE_MENU_LOAD] = 
+       XtVaCreateManagedWidget("treeMenuLoad", smeBSBObjectClass,
+			       treeMenus[TREE_MENU],
+			       NULL);
+   XtAddCallback(treeMenuItems[TREE_MENU_LOAD],
+		 XtNcallback, TreeMenu_CB, (XtPointer) TREE_MENU_LOAD);
+		 
+   treeMenuItems[TREE_MENU_SAVE] = 
+       XtVaCreateManagedWidget("treeMenuSave", smeBSBObjectClass,
+			       treeMenus[TREE_MENU],
+			       NULL);
+   XtAddCallback(treeMenuItems[TREE_MENU_SAVE],
+		 XtNcallback, TreeMenu_CB, (XtPointer) TREE_MENU_SAVE);
+		 
+   treeMenuItems[TREE_MENU_SEP1] = 
+       XtVaCreateManagedWidget("treeMenuSep1", smeLineObjectClass,
+			       treeMenus[TREE_MENU],
+			       NULL);
+
+#ifdef COMMENT
+   treeMenuItems[TREE_MENU_STATS] = 
+       XtVaCreateManagedWidget("treeMenuStats", smeBSBObjectClass,
+			       treeMenus[TREE_MENU],
+			       XtNlabel, labelStr[STR_SHOW_STATS],
+			       NULL);
+
+   XtAddCallback(treeMenuItems[TREE_MENU_STATS],
+		 XtNcallback, TreeMenu_CB, (XtPointer) TREE_MENU_STATS);
+
+   XtSetSensitive(treeMenuItems[TREE_MENU_STATS], FALSE);
+
+   treeMenuItems[TREE_MENU_SEP2] = 
+       XtVaCreateManagedWidget("treeMenuSep2", smeLineObjectClass,
+			       treeMenus[TREE_MENU],
+			       NULL);
+#endif /* COMMENT */
+   
+   treeMenuItems[TREE_MENU_QUIT] = 
+       XtVaCreateManagedWidget("treeMenuQuit", smeBSBObjectClass,
+			       treeMenus[TREE_MENU],
+			       NULL);
+   XtAddCallback(treeMenuItems[TREE_MENU_QUIT],
+		 XtNcallback, TreeMenu_CB, (XtPointer) TREE_MENU_QUIT);
+		 
+
+
+   /* Layout menu */
+
+#ifdef COMMENT
+   treeMenuItems[LAYOUT_MENU_FIXED] = 
+       XtVaCreateManagedWidget("layoutMenuFixed", smeBSBObjectClass,
+			       treeMenus[LAYOUT_MENU],
+			       XtNleftMargin, 18,
+			       NULL);
+
+   XtAddCallback(treeMenuItems[LAYOUT_MENU_FIXED],
+		 XtNcallback, LayoutMenu_CB, (XtPointer) LAYOUT_MENU_FIXED);
+
+   treeMenuItems[LAYOUT_MENU_VARIABLE] = 
+       XtVaCreateManagedWidget("layoutMenuVariable", smeBSBObjectClass,
+			       treeMenus[LAYOUT_MENU],
+			       XtNleftMargin, 18,
+			       NULL);
+
+   XtAddCallback(treeMenuItems[LAYOUT_MENU_VARIABLE],
+		 XtNcallback, LayoutMenu_CB, (XtPointer) LAYOUT_MENU_VARIABLE);
+
+
+   treeMenuItems[LAYOUT_MENU_SEP1] = 
+       XtVaCreateManagedWidget("layoutSep1", smeLineObjectClass,
+			       treeMenus[LAYOUT_MENU],
+			       NULL);
+#endif /* COMMENT */
+
+   treeMenuItems[LAYOUT_MENU_SPACING] = 
+       XtVaCreateManagedWidget("layoutMenuSpacing", smeBSBObjectClass,
+			       treeMenus[LAYOUT_MENU],
+			       XtNleftMargin, 18,
+			       NULL);
+   XtAddCallback(treeMenuItems[LAYOUT_MENU_SPACING],
+		 XtNcallback, LayoutMenu_CB, (XtPointer) LAYOUT_MENU_SPACING);
+
+   treeMenuItems[LAYOUT_MENU_SEP2] = 
+       XtVaCreateManagedWidget("layoutMenuSep2", smeLineObjectClass,
+			       treeMenus[LAYOUT_MENU],
+			       NULL);
+
+   /* the following is a toggle button - we hack it using a bitmap */
+   treeMenuItems[LAYOUT_MENU_ALIGN_NODES] = 
+       XtVaCreateManagedWidget("layoutMenuAlignNodes", smeBSBObjectClass,
+			       treeMenus[LAYOUT_MENU],
+			       XtNleftMargin, 18,
+			       NULL);
+   XtAddCallback(treeMenuItems[LAYOUT_MENU_ALIGN_NODES],
+		 XtNcallback, LayoutMenu_CB, 
+		 (XtPointer) LAYOUT_MENU_ALIGN_NODES);
+
+}
+
+/* ----------------------------------------------------------------------------
+ * 
+ *   BuildDialogs() builds all the dialogs used in this application. 
+ * 
+ * ----------------------------------------------------------------------------
+ */
+
+
+BuildDialogs(parent)
+     Widget parent;
+{
+  int	i;
+  Widget 
+    tmpwidget, dlgForm, dlgValue, 
+    dlgLevelLabel, dlgSiblingLabel, 
+    dlgOkButton, dlgCancelButton;
+  
+  labelStr[STR_LOAD_FILE] = "Name of file to load:";
+  labelStr[STR_SAVE_FILE] = "Name of file to save:";
+  
+  errStr[ERR_OPENFAIL]  = "Failed to open file.";
+  errStr[ERR_EMPTYFILE] = "Input file is empty.";
+  errStr[ERR_MEMALLOC]  = "Memory allocation failed.";
+  errStr[ERR_NOBEGIN] = "End of list does not have a matching beginning.";
+  errStr[ERR_NOEND] = "Beginning of list does not have a matching end.";
+  errStr[ERR_NOROOT] = "Input file does not have a root label.";
+  errStr[ERR_MANYROOT] = "Input file has more than one root label.";
+  
+  
+  dialog[DLG_NEW] = XtVaCreatePopupShell("dlgNewTree",
+					 transientShellWidgetClass,
+					 parent,
+					 XtNresizable, TRUE,
+					 NULL);
+  
+  tmpwidget = XtVaCreateManagedWidget("dlgNewTreeForm",
+				      dialogWidgetClass,
+				      dialog[DLG_NEW], 
+				      XtNresizable, TRUE,
+				      XtNvalue, "",
+				      NULL);
+  
+  XawDialogAddButton(tmpwidget, "dlgNewTreeOk", NewTree_CB, 
+		     (XtPointer) TRUE);
+  XawDialogAddButton(tmpwidget, "dlgNewTreeCancel", NewTree_CB, 
+		     (XtPointer) FALSE);
+  
+  dlgValue = XtNameToWidget(tmpwidget, "value");
+  
+  XtOverrideTranslations
+    (dlgValue, XtParseTranslationTable
+     ("<Key>Return:dlg_activate(dlgNewTreeOk)\n"));
+  
+  
+  dialog[DLG_NODE_NAME] = XtVaCreatePopupShell("dlgNodeName",
+					       transientShellWidgetClass,
+					       TreeTopLevel,
+					       XtNresizable, TRUE,
+					       NULL);
+				    
+  
+  tmpwidget= XtVaCreateManagedWidget("dlgNodeNameForm",
+				     dialogWidgetClass,
+				     dialog[DLG_NODE_NAME], 
+				     XtNresizable, TRUE,
+				     XtNvalue, "",
+				     NULL);
+  
+  XawDialogAddButton(tmpwidget, "dlgNodeNameOk", NodeLabel_CB, 
+		     (XtPointer) TRUE);
+  XawDialogAddButton(tmpwidget, "dlgNodeNameCancel", NodeLabel_CB, 
+		     (XtPointer) FALSE);
+  
+  dlgValue = XtNameToWidget(tmpwidget, "value");
+  
+  XtOverrideTranslations
+    (dlgValue, XtParseTranslationTable
+     ("<Key>Return: dlg_activate(dlgNodeNameOk)\n"));
+  
+
+  dialog[DLG_FILE] = XtVaCreatePopupShell("dlgFile",
+					  transientShellWidgetClass,
+					  TreeTopLevel, 
+					  XtNresizable, TRUE,
+					  NULL);
+
+  tmpwidget = XtVaCreateManagedWidget("dlgFileForm",
+				      dialogWidgetClass,
+				      dialog[DLG_FILE], 
+				      XtNresizable, TRUE,
+				      XtNvalue, "",
+				      NULL);
+   
+  XawDialogAddButton(tmpwidget, "dlgFileOk", File_CB, (XtPointer) TRUE);
+  XawDialogAddButton(tmpwidget, "dlgFileCancel", File_CB, (XtPointer) FALSE);
+
+  dlgValue = XtNameToWidget(tmpwidget, "value");
+  
+  XtOverrideTranslations
+    (dlgValue, XtParseTranslationTable
+     ("<Key>Return:dlg_activate(dlgFileOk)\n"));
+  
+
+  dialog[DLG_INFO] = XtVaCreatePopupShell("dlgInfo",
+					  transientShellWidgetClass,
+					  TreeTopLevel, 
+					  XtNresizable, TRUE,
+					  NULL);
+  
+  tmpwidget = XtVaCreatePopupShell("dlgInfoForm",
+				   dialogWidgetClass,
+				   dialog[DLG_INFO], 
+				   XtNresizable, TRUE,
+				   XtNvalue, "",
+				   NULL);
+  
+  XawDialogAddButton(tmpwidget, "dlgInfoButton", Popdown_CB, 
+		     (XtPointer) dialog[DLG_INFO]);
+  
+  
+  dialog[DLG_ERROR] = XtVaCreatePopupShell("dlgError",
+					   transientShellWidgetClass,
+					   TreeTopLevel, 
+					   XtNresizable, TRUE,
+					   NULL);
+   
+  tmpwidget = XtVaCreateManagedWidget("dlgErrorForm",
+				      dialogWidgetClass,
+				      dialog[DLG_ERROR], 
+				      XtNresizable, TRUE,
+				      XtNvalue, "",
+				      NULL);
+   
+  XawDialogAddButton(tmpwidget, "dlgErrorButton", Popdown_CB, 
+		     (XtPointer) dialog[DLG_ERROR]);
+   
+
+  dialog[DLG_SPACING] = XtVaCreatePopupShell("dlgSpacing",
+					     transientShellWidgetClass,
+					     TreeTopLevel, 
+					     XtNresizable, FALSE,
+					     NULL);
+  dlgForm = XtVaCreateManagedWidget("dlgSpacingForm",
+				    formWidgetClass,
+				    dialog[DLG_SPACING],
+				    XtNresizable, FALSE,
+				    NULL);
+   
+  dlgLevelLabel = XtVaCreateManagedWidget("dlgLevelLabel",
+					  labelWidgetClass,
+					  dlgForm,
+					  XtNfromVert, NULL,
+					  XtNfromHoriz, NULL,
+					  XtNtop, XawChainTop,
+					  XtNbottom, XawChainTop,
+					  XtNleft, XawChainLeft,
+					  XtNright, XawChainLeft,
+					  XtNborderWidth, 0,
+					  NULL);
+
+  dlgLevelValuator = XtVaCreateManagedWidget("dlgLevelValuator",
+					     labelWidgetClass,
+					     dlgForm,
+					     XtNfromVert, NULL,
+					     XtNfromHoriz, dlgLevelLabel,
+					     XtNtop, XawChainTop,
+					     XtNbottom, XawChainTop,
+					     XtNleft, XawChainLeft,
+					     XtNright, XawChainLeft,
+					     XtNlabel, "   ",
+					     NULL);
+
+  
+  dlgLevelScale = XtVaCreateManagedWidget("dlgLevelScale",
+					  pannerWidgetClass,
+					  dlgForm,
+					  XtNfromVert, dlgLevelLabel,
+					  XtNfromHoriz, NULL,
+					  XtNtop, XawChainTop,
+					  XtNbottom, XawChainTop,
+					  XtNleft, XawChainLeft,
+					  XtNright, XawChainLeft,
+					  XtNcanvasWidth, 110,
+					  XtNdefaultScale, 1,
+					  XtNinternalSpace, 1,
+					  XtNrubberBand, FALSE,
+					  XtNshadowThickness, 0,
+					  XtNallowOff, FALSE,
+					  XtNwidth, 200,
+					  XtNsliderWidth, 10,
+					  XtNheight, 15,
+					  NULL);
+  
+  XtOverrideTranslations(dlgLevelScale, XtParseTranslationTable("\
+<Btn2Down>:		start()\n\
+<Btn2Motion>:		move()\n\
+<Btn2Up>:		notify()stop()\n\
+<Btn3Down>:		abort()\n"));
+
+  XtAddCallback(dlgLevelScale, XtNreportCallback, levelscale_CB,
+		(XtPointer) dlgLevelValuator);
+  XtAddCallback(dlgLevelScale, XtNreportCallback, levelvalue_CB,
+		(XtPointer) &dlgLevelValue);
+
+  dlgSiblingLabel = XtVaCreateManagedWidget("dlgSiblingLabel",
+					    labelWidgetClass,
+					    dlgForm,
+					    XtNfromVert, dlgLevelScale,
+					    XtNfromHoriz, NULL,
+					    XtNtop, XawChainTop,
+					    XtNbottom, XawChainTop,
+					    XtNleft, XawChainLeft,
+					    XtNright, XawChainLeft,
+					    XtNborderWidth, 0,
+					    NULL);
+
+  dlgSiblingValuator = XtVaCreateManagedWidget("dlgLevelValuator",
+					       labelWidgetClass,
+					       dlgForm,
+					       XtNfromVert, dlgLevelScale,
+					       XtNfromHoriz, dlgSiblingLabel,
+					       XtNtop, XawChainTop,
+					       XtNbottom, XawChainTop,
+					       XtNleft, XawChainLeft,
+					       XtNright, XawChainLeft,
+					       XtNlabel, "   ",
+					       NULL);
+  dlgSiblingScale = XtVaCreateManagedWidget("dlgSiblingScale",
+					    pannerWidgetClass,
+					    dlgForm,
+					    XtNfromVert, dlgSiblingLabel,
+					    XtNfromHoriz, NULL,
+					    XtNtop, XawChainTop,
+					    XtNbottom, XawChainTop,
+					    XtNleft, XawChainLeft,
+					    XtNright, XawChainLeft,
+					    XtNcanvasWidth, 110,
+					    XtNdefaultScale, 1,
+					    XtNinternalSpace, 1,
+					    XtNrubberBand, FALSE,
+					    XtNshadowThickness, 0,
+					    XtNallowOff, FALSE,
+					    XtNwidth, 200,
+					    XtNsliderWidth, 10,
+					    XtNheight, 15,
+					    NULL);
+  
+  XtOverrideTranslations(dlgSiblingScale, XtParseTranslationTable("\
+<Btn2Down>:		start()\n\
+<Btn2Motion>:		move()\n\
+<Btn2Up>:		notify()stop()\n\
+<Btn3Down>:		abort()\n"));
+
+  XtAddCallback(dlgSiblingScale, XtNreportCallback, siblingscale_CB,
+		(XtPointer) dlgSiblingValuator);
+  XtAddCallback(dlgSiblingScale, XtNreportCallback, siblingvalue_CB,
+		(XtPointer) &dlgSiblingValue);
+  
+  dlgOkButton = XtVaCreateManagedWidget("dlgOkButton",
+					commandWidgetClass,
+					dlgForm,
+					XtNfromVert, dlgSiblingScale,
+					XtNfromHoriz, NULL,
+					XtNtop, XawChainTop,
+					XtNbottom, XawChainTop,
+					XtNleft, XawChainLeft,
+					XtNright, XawChainLeft,
+					NULL);
+  
+  dlgCancelButton = XtVaCreateManagedWidget("dlgCancelButton",
+					    commandWidgetClass,
+					    dlgForm,
+					    XtNfromVert, dlgSiblingScale,
+					    XtNfromHoriz, dlgOkButton,
+					    XtNtop, XawChainTop,
+					    XtNbottom, XawChainTop,
+					    XtNleft, XawChainLeft,
+					    XtNright, XawChainLeft,
+					    NULL);
+  
+  XtAddCallback(dlgOkButton, XtNcallback, Scale_CB, (XtPointer) TRUE);
+  XtAddCallback(dlgCancelButton, XtNcallback, Scale_CB, (XtPointer) FALSE);
+}
+
+/* ----------------------------------------------------------------------------
+ * 
+ *   BuildHelpWindow() builds the help window that is displayed when the
+ *   Help button on the application main window is pressed.
+ * 
+ * ----------------------------------------------------------------------------
+ */
+
+
+static void
+BuildHelpWindow(parent)
+     Widget parent;
+{
+  int	i;
+
+  helpShell = XtVaCreatePopupShell("helpShell", transientShellWidgetClass,
+				   parent,
+				   NULL);
+  
+  helpForm = XtVaCreateManagedWidget("helpForm",
+				     formWidgetClass,
+				     helpShell,
+				     NULL);
+
+  helpDoneButton = XtVaCreateManagedWidget("helpDoneButton",
+					   commandWidgetClass,
+					   helpForm,
+					   XtNfromVert, NULL,
+					   XtNfromHoriz, NULL,
+					   XtNtop, XawChainTop,
+					   XtNbottom, XawChainTop,
+					   XtNleft, XawChainLeft,
+					   XtNright, XawChainLeft,
+					   NULL);
+  
+  XtAddCallback(helpDoneButton, XtNcallback, Popdown_CB, 
+		(XtPointer) helpShell);
+
+  helpTitle = XtVaCreateManagedWidget("helpTitle",
+				      labelWidgetClass,
+				      helpForm,
+				      XtNfromVert, NULL,
+				      XtNfromHoriz, helpDoneButton,
+				      XtNtop, XawChainTop,
+				      XtNbottom, XawChainTop,
+				      XtNleft, XawChainLeft,
+				      XtNright, XawChainLeft,
+				      XtNborderWidth, 0,
+				      XtNlabel, "",
+				      NULL);
+
+  helpText = XtVaCreateManagedWidget("helpText",
+				     asciiTextWidgetClass,
+				     helpForm,
+				     XtNfromVert, helpDoneButton,
+				     XtNfromHoriz, NULL,
+				     XtNtop, XawChainTop,
+				     XtNbottom, XawChainBottom,
+				     XtNleft, XawChainLeft,
+				     XtNright, XawChainRight,
+				     XtNeditType, XawtextRead,
+				     XtNdisplayCaret, FALSE,
+				     XtNscrollVertical, XawtextScrollAlways,
+				     XtNscrollHorizontal, 
+				     XawtextScrollWhenNeeded,
+				     XtNuseStringInPlace, TRUE,
+				     XtNstring, help_text,
+				     XtNwidth, 530,
+				     XtNheight, 650,
+				     NULL);
+}
+
+/* ----------------------------------------------------------------------------
+ * 
+ *   BuildApplicationWindow() assumes that TreeTopLevel has been initialized 
+ *   by XtInitialize(). TreeDrawingArea is set to the drawing area in this
+ *   application window.
+ * 
+ * ----------------------------------------------------------------------------
+ */
+
+
+static void
+BuildApplicationWindow(parent)
+     Widget parent;
+{
+  Widget	topPane, box;
+
+  topPane = XtVaCreateManagedWidget("topPane",
+				    panedWidgetClass,
+				    parent,
+				    XtNorientation, XtorientVertical,
+				    NULL);
+
+  BuildMenubar(topPane);
+
+  statusText = XtVaCreateManagedWidget("statusText",
+				       labelWidgetClass,
+				       topPane,
+				       XtNborderWidth, 0,
+				       NULL);
+
+  scrolledWindow = XtVaCreateManagedWidget("scrolledWindow",
+					   viewportWidgetClass,
+					   topPane, 
+					   XtNshowGrip, FALSE,
+					   XtNallowHoriz, TRUE,
+					   XtNallowVert, TRUE,
+					   XtNuseBottom, TRUE,
+					   XtNuseRight, TRUE,
+					   NULL);
+
+  TreeDrawingArea = XtVaCreateManagedWidget("treeDrawingArea",
+					    simpleWidgetClass,
+					    scrolledWindow,
+					    NULL);
+}
+
+/* ----------------------------------------------------------------------------
+ * 
+ *   HandleError() is used when ReadTreeFromFile() or SaveTreeToFile() returns
+ *   an error. 
+ * 
+ * ----------------------------------------------------------------------------
+ */
+
+void
+HandleError(error, tree)
+     ErrCode error;
+     Tree *tree;
+{
+  Widget	dlg, text;
+  
+  if (tree) {
+    dlg = XtNameToWidget(dialog[DLG_INFO], "dlgInfoForm");
+    if (dlg) {
+      XtVaSetValues(dlg, 
+		    XtNvalue, errStr[error],
+		    XtNwidth, 200,
+		    NULL);
+      text = XtNameToWidget(dlg, "value");
+      if (text) {
+	XtVaSetValues(text, XtNdisplayCaret, FALSE, NULL);
+	XtVaSetValues(XawTextGetSource(text), XtNeditType, XawtextRead, NULL);
+      }
+    }
+    popup_dialog(dialog[DLG_INFO], XtGrabExclusive);
+  } else {
+    dlg = XtNameToWidget(dialog[DLG_ERROR], "dlgErrorForm");
+    if (dlg) {
+      XtVaSetValues(dlg, 
+		    XtNvalue, errStr[error], 
+		    XtNwidth, 200,
+		    NULL);
+      text = XtNameToWidget(dlg, "value");
+      if (text) {
+	XtVaSetValues(text, XtNdisplayCaret, FALSE, NULL);
+	XtVaSetValues(XawTextGetSource(text), XtNeditType, XawtextRead, NULL);
+      }
+    }
+    popup_dialog(dialog[DLG_ERROR], XtGrabExclusive);
+  }
+}
+
+
+/* ----------------------------------------------------------------------------
+ * 
+ *   InitializeInterface() initializes the environment for displaying
+ *   the tree and creates the necessary supporting structures for interaction
+ *   and display. This function should be called only once.
+ * 
+ * ----------------------------------------------------------------------------
+ */
+
+void
+InitializeInterface(argc, argv)
+     int *argc;
+     char *argv[];
+{
+  XrmValue       rmvalue;
+  char          *rmtype;
+  Window         win;
+  Pixel          background;
+  XColor         colors[NUM_COLORS];
+  Colormap       cmap;
+  Pixmap         gray_pixmap;
+  Atom		 wm_delete_window;
+
+  /* XtSetLanguageProc is broken on some systems.
+     The symptom is an error of the form:
+        Warning: X locale modifiers not supported, using default
+     so don't use this call:
+
+        XtSetLanguageProc(NULL, NULL, NULL);
+  */
+  
+  TreeTopLevel = XtVaAppInitialize(&app, "Xoobr", 
+				   NULL, 0,
+				   argc, argv, 
+				   fallback_resources, 
+				   NULL);
+  
+  ASSERT(TreeTopLevel, "failed to open connection to X server");
+  
+  TreeDisplay = XtDisplay(TreeTopLevel);
+  TreeScreen  = DefaultScreen(TreeDisplay);
+
+  /* set up color resources */
+  applRsrcsPtr = &applRsrcs;
+  XtGetApplicationResources(TreeTopLevel, applRsrcsPtr,
+			    applRsrcsDesc, XtNumber(applRsrcsDesc),
+			    NULL, 0);
+
+  /* add actions */
+  XtAppAddActions(app, local_actions, 6);
+  XawSimpleMenuAddGlobalActions(app);
+  
+  TreeContourWidth = applRsrcsPtr->contour_width;
+  
+  /* set up label font info */
+  if (XrmGetResource(XtDatabase(TreeDisplay),
+		     X11_FONT_RESOURCE, X11_FONT_CLASS_RESOURCE,
+		     &rmtype, &rmvalue)) {
+    if (! (TreeLabelFont = XLoadQueryFont(TreeDisplay, rmvalue.addr)) ) {
+      WARN_4("cannot load user-specified font:", rmvalue.addr,
+	     "using font:", X11_DEFAULT_FONT);
+      TreeLabelFont = XLoadQueryFont(TreeDisplay, X11_DEFAULT_FONT);
+    }
+  }
+  else
+    TreeLabelFont = XLoadQueryFont(TreeDisplay, X11_DEFAULT_FONT);
+  TreeLabelFont = XLoadQueryFont(TreeDisplay, "fixed");
+  
+  check_pixmap =
+    XCreateBitmapFromData(TreeDisplay, RootWindow(TreeDisplay, TreeScreen),
+			  check_bits, check_width, check_height);
+  
+  slider_pixmap =
+    XCreateBitmapFromData(TreeDisplay, RootWindow(TreeDisplay, TreeScreen),
+			  slider_pixmap_bits, slider_pixmap_width, 
+			  slider_pixmap_height);
+  
+  BuildApplicationWindow(TreeTopLevel);
+  BuildHelpWindow(TreeTopLevel);
+  BuildPopupMenus(TreeTopLevel);
+  BuildDialogs(TreeTopLevel);
+  
+  
+  XtAddEventHandler(TreeDrawingArea, ExposureMask, FALSE,
+		    ExposeHandler, (XtPointer) NULL);
+  
+  XtVaSetValues(TreeDrawingArea, 
+		XtNbackground, applRsrcsPtr->background_color, 
+		NULL);
+  
+  XtRealizeWidget(TreeTopLevel);
+  
+  XtOverrideTranslations
+    (TreeTopLevel,
+     XtParseTranslationTable("<Message>WM_PROTOCOLS: quit()"));
+
+  wm_delete_window = XInternAtom(TreeDisplay, "WM_DELETE_WINDOW", FALSE);
+  (void) XSetWMProtocols(TreeDisplay, XtWindow(TreeTopLevel),
+			 &wm_delete_window, 1);
+
+
+  win = XtWindow(TreeDrawingArea);
+  cmap = DefaultColormap(TreeDisplay, TreeScreen);
+  
+  /* set up double buffer */
+  colors[BACKGROUND_COLOR].pixel = applRsrcsPtr->background_color;
+  XQueryColor(TreeDisplay, cmap, &(colors[BACKGROUND_COLOR]));
+  colors[TREE_COLOR].pixel = applRsrcsPtr->tree_color;
+  XQueryColor(TreeDisplay, cmap, &(colors[TREE_COLOR]));
+  colors[CONTOUR_COLOR].pixel = applRsrcsPtr->contour_color;
+  XQueryColor(TreeDisplay, cmap, &(colors[CONTOUR_COLOR]));
+  colors[HIGHLIGHT_COLOR].pixel = applRsrcsPtr->highlight_color;
+  XQueryColor(TreeDisplay, cmap, &(colors[HIGHLIGHT_COLOR]));
+  colors[SPLIT_COLOR].pixel = applRsrcsPtr->split_color;
+  XQueryColor(TreeDisplay, cmap, &(colors[SPLIT_COLOR]));
+  colors[ACTION_COLOR].pixel = applRsrcsPtr->action_color;
+  XQueryColor(TreeDisplay, cmap, &(colors[ACTION_COLOR]));
+  
+  TreeDrawingAreaDB = 
+    DBLcreate_double_buffer(TreeDisplay, 
+			    XtWindow(TreeDrawingArea), TRUE,
+			    colors, NUM_COLORS);
+
+  ASSERT(TreeDrawingAreaDB, "could not create double buffer");
+  
+  background = DBLinq_background(TreeDrawingAreaDB);
+  
+  
+  XtVaSetValues(TreeDrawingArea, XtNbackground, background, NULL);
+  
+  /* also set the scrolledWindow background to same color */
+  XtVaSetValues(XtParent(TreeDrawingArea), XtNbackground, background, NULL);
+  
+  XSetFont(TreeDrawingAreaDB->display, TreeDrawingAreaDB->gc,
+	   TreeLabelFont->fid); 
+  
+  gray_pixmap =
+    XCreatePixmapFromBitmapData(TreeDisplay, XtWindow(TreeDrawingArea),
+				gray_bits, gray_width, gray_height,
+				TreeDrawingAreaDB->colors[TREE_COLOR],
+				background,
+				DefaultDepth(TreeDisplay, TreeScreen));
+  
+#ifdef COMMENT
+  XtVaSetValues(treeMenuItems[LAYOUT_MENU_VARIABLE],
+		XtNleftBitmap, check_pixmap, 
+		NULL);
+#endif
+
+  XSetTile(TreeDrawingAreaDB->display, TreeDrawingAreaDB->gc, gray_pixmap);
+  SetDrawColor(TREE_COLOR);
+  
+  InitializeDissolveEffect(TreeDisplay, XtWindow(TreeDrawingArea),
+			   TreeDrawingAreaDB->colors[TREE_COLOR], background);
+  
+  PauseCursor = XCreateFontCursor(TreeDisplay, XC_watch);
+  
+  StatusMsg("Ready", TRUE);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * 
+ *   UserEventLoop() is called after InitializeInterface() to handle
+ *   processing of events.
+ * 
+ * ----------------------------------------------------------------------------
+ */
+
+void
+UserEventLoop()
+{
+  XtAppMainLoop(app);
+}
+
+
+/* ------------------------------------------------------------------------- */
+/*			  Callback Routines                                  */
+/* ------------------------------------------------------------------------- */
+
+static void
+TreeMenu_CB(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data;
+     XtPointer call_data;
+{
+  long		menuItem = (long) client_data;
+  Widget	dlgFileForm;
+  
+  switch (menuItem) {
+  case TREE_MENU_NEW:
+    popup_dialog(dialog[DLG_NEW], XtGrabExclusive);
+    break;
+  case TREE_MENU_LOAD:
+    loading_file = 1;
+    XtVaSetValues(dialog[DLG_FILE],  XtNtitle, "Load File", NULL);
+    dlgFileForm = XtNameToWidget(dialog[DLG_FILE], "dlgFileForm");
+    XtVaSetValues(dlgFileForm, XtNvalue, "", NULL);
+    popup_dialog(dialog[DLG_FILE], XtGrabExclusive);
+    break;
+  case TREE_MENU_SAVE:
+    loading_file = 0;
+    XtVaSetValues(dialog[DLG_FILE],  XtNtitle, "Save File", NULL);
+    dlgFileForm = XtNameToWidget(dialog[DLG_FILE], "dlgFileForm");
+    XtVaSetValues(dlgFileForm, XtNvalue, "", NULL);
+    popup_dialog(dialog[DLG_FILE], XtGrabExclusive);
+    break;
+  case TREE_MENU_QUIT:
+    exit(0);
+    break;
+    
+  default:
+    WARN("unknown menu item in TreeMenu_CB");
+  }
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+static void
+LayoutMenu_CB(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data;
+     XtPointer call_data;
+{
+  long	menuItem = (long) client_data;
+  char	tmpstr[10];
+  
+  switch (menuItem) {
+#ifdef COMMENT
+  case LAYOUT_MENU_FIXED:
+    XtVaSetValues(layoutMenuItems[LAYOUT_MENU_VARIABLE],
+                  XtNleftBitmap, None, NULL);
+    XtVaSetValues(layoutMenuItems[LAYOUT_MENU_FIXED], 
+                  XtNleftBitmap, check_pixmap, NULL);
+
+    if (TreeLayoutDensity != Fixed) {
+      TreeLayoutDensity = Fixed;
+      DeleteTree(TheTree, TRUE);
+      SetupTree(TheTree);
+    }
+    break;    
+  case LAYOUT_MENU_VARIABLE:
+    XtVaSetValues(layoutMenuItems[LAYOUT_MENU_VARIABLE],
+                  XtNleftBitmap, check_pixmap, NULL);
+    XtVaSetValues(layoutMenuItems[LAYOUT_MENU_FIXED], 
+                  XtNleftBitmap, None, NULL);
+    
+    if (TreeLayoutDensity != Variable) {
+      TreeLayoutDensity = Variable;
+      DeleteTree(TheTree, TRUE);
+      SetupTree(TheTree);
+    }
+    break;
+#endif COMMENT
+  case LAYOUT_MENU_SPACING:
+    dlgLevelValue = TreeParentDistance;
+    dlgSiblingValue = TreeBorderSize;
+    sprintf(tmpstr, "%d  ", dlgLevelValue);
+    XtVaSetValues(dlgLevelValuator, XtNlabel, tmpstr, NULL);
+
+    /* These setvalues need some adjustments... */
+    XtVaSetValues(dlgLevelScale, 
+		  XtNsliderX, (dlgLevelValue * 2),
+		  NULL);
+    sprintf(tmpstr, "%d  ", dlgSiblingValue);
+    XtVaSetValues(dlgSiblingValuator, XtNlabel, tmpstr, NULL);
+    XtVaSetValues(dlgSiblingScale, 
+		  XtNsliderX, (dlgSiblingValue * 4),
+		  NULL);
+    popup_dialog(dialog[DLG_SPACING], XtGrabNone);
+    break;
+  case LAYOUT_MENU_ALIGN_NODES:
+    TreeAlignNodes = !TreeAlignNodes;
+    XtVaSetValues(treeMenuItems[LAYOUT_MENU_ALIGN_NODES],
+		  XtNleftBitmap, TreeAlignNodes ? check_pixmap : None, 
+		  NULL);
+    DeleteTree(TheTree, TRUE);
+    ResetLabels(TheTree);
+    SetupTree(TheTree);
+    break;
+  default:
+    WARN("unknown menu item in LayoutMenu_CB");
+  }
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+static void
+NodeMenu_CB(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data;
+     XtPointer call_data;
+{
+  long	menuItem = (long) client_data;
+   
+  switch (menuItem) {
+  case NODE_MENU_ADD_CHILD:
+    NodePos = Child;
+    popup_dialog(dialog[DLG_NODE_NAME], XtGrabExclusive);
+    break;
+  case NODE_MENU_ADD_BEFORE:
+    NodePos = Before;
+    popup_dialog(dialog[DLG_NODE_NAME], XtGrabExclusive);
+    break;
+  case NODE_MENU_ADD_AFTER:
+    NodePos = After;
+    popup_dialog(dialog[DLG_NODE_NAME], XtGrabExclusive);
+    break;
+  case NODE_MENU_ELISION:
+    ExpandCollapseNode(PopupNode);
+    break;
+  case NODE_MENU_DELETE:
+    DeleteNode(PopupNode);
+    if (TheTree == NULL)
+      XtSetSensitive(treeMenuItems[TREE_MENU_SAVE], FALSE);
+    break;
+  default:
+    WARN("unknown menu item in NodeMenu_CB");
+  }
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+static void
+Help_CB(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data;
+     XtPointer call_data;
+{
+  popup_dialog(helpShell, XtGrabNone);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+static void
+HelpDone_CB(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data;
+     XtPointer call_data;
+{
+  XtPopdown(helpShell);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+static void
+NodeLabel_CB(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data;
+     XtPointer call_data;
+{
+  char	*node_label;
+
+  XtPopdown(dialog[DLG_NODE_NAME]);
+  if (client_data == (XtPointer) TRUE) {
+    node_label = XtMalloc(strlen(XawDialogGetValueString(XtParent(w)))
+			  * sizeof(char));
+    node_label = strcpy(node_label, XawDialogGetValueString(XtParent(w)));
+    if (*node_label) 
+      InsertNode(PopupNode, NodePos, node_label);
+  }
+}
+      
+
+/* ------------------------------------------------------------------------- */
+
+static void
+NewTree_CB(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data;
+     XtPointer call_data;
+{
+  char	*node_label;
+  Tree	*tree;
+  
+  XtPopdown(dialog[DLG_NEW]);
+  if (client_data == (XtPointer) TRUE) {
+    node_label = XtMalloc((strlen(XawDialogGetValueString(XtParent(w))) + 1)
+			  * sizeof(char));
+    node_label = strcpy(node_label, XawDialogGetValueString(XtParent(w)));
+    if (*node_label) {
+      if (TheTree) {
+	Delete(TheTree);
+	XtSetSensitive(treeMenuItems[TREE_MENU_SAVE], FALSE);
+      }
+      tree = MakeNode();
+      SetNodeLabel(tree, node_label);
+      SetupTree(tree);
+      XtSetSensitive(treeMenuItems[TREE_MENU_SAVE], TRUE);
+    }
+  }
+  XSync(TreeDisplay, FALSE);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+static void
+File_CB(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data;
+     XtPointer call_data;
+{
+  char *fname;
+  Tree *tree;
+  ErrCode error;
+  Arg args[1];
+  int menuItem;
+  
+  if (client_data == (XtPointer) TRUE) {
+    fname = XawDialogGetValueString(XtParent(w));
+    if (*fname) { 
+      
+      if (loading_file == 1) {
+	if (TheTree) {
+	  Delete(TheTree);
+	  XtSetSensitive(treeMenuItems[TREE_MENU_SAVE], FALSE);
+	}
+	tree = ReadTreeFromFile(fname, &error);
+	XtPopdown(dialog[DLG_FILE]);
+	if (error != ERR_NONE)
+	  HandleError(error, tree);
+	XSync(TreeDisplay, 0);
+	if (tree) {
+	  SetupTree(tree);
+	  XtSetSensitive(treeMenuItems[TREE_MENU_SAVE], TRUE);
+	} else {
+	  SetDrawingTree(NULL);
+	  BeginFrame();
+	  EndFrame();
+	}
+      } else if (menuItem == TREE_MENU_SAVE) {
+	if (!SaveTreeToFile(TheTree, fname)) {
+	  XtPopdown(dialog[DLG_FILE]);
+	  HandleError(ERR_OPENFAIL, NULL);
+	} else
+	  XtPopdown(dialog[DLG_FILE]);
+      }
+    } else
+      XtPopdown(dialog[DLG_FILE]);
+  } else 
+    XtPopdown(dialog[DLG_FILE]); 
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+static void
+Scale_CB(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data;
+     XtPointer call_data;
+{
+  int	level_value, sibling_value;
+  float	tmp;
+    
+  XtPopdown(dialog[DLG_SPACING]);
+
+  /* check if OK button was selected */
+  if (client_data) {
+    level_value = dlgLevelValue;
+    
+    sibling_value = dlgSiblingValue;
+    
+    if (level_value != TreeParentDistance ||
+	sibling_value != TreeBorderSize) {
+      
+      TreeParentDistance = level_value;
+      TreeBorderSize = sibling_value;
+      XSync(TreeDisplay, 0);
+      if (TheTree) {
+	DeleteTree(TheTree, TRUE);
+	if (TreeAlignNodes)
+	  ResetLabels(TheTree);
+	SetupTree(TheTree);
+      }
+    }
+  }
+}
+
+
+/* ------------------------------------------------------------------------- */
+/*									     */
+/* Auxilary actions and callback functions                                   */
+/*									     */
+/* ------------------------------------------------------------------------- */
+
+static void
+Popdown_CB(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data;
+     XtPointer call_data;
+{
+  Widget	widget = (Widget) client_data;
+    
+  XtPopdown(widget);
+}
+
+static void
+activate_action(w, event, params, num_params)
+     Widget w;
+     XButtonEvent *event;
+     String *params;
+     Cardinal *num_params;
+{
+  Widget	button;
+  
+  if (*num_params == 1) {
+    button = XtNameToWidget(XtParent(w), params[0]);
+    
+    if (button)
+      XtCallCallbacks(button, XtNcallback, (XtPointer) TRUE);
+  }
+}
+
+static void
+quit_action(w, event, params, num_params)
+     Widget w;
+     XButtonEvent *event;
+     String *params;
+     Cardinal *num_params;
+{
+  exit(0);
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+
+static void 
+select_action(w, event, params, num_params)
+     Widget w;
+     XButtonEvent *event;
+     String *params;
+     Cardinal *num_params;
+{
+  Tree		*node;
+  int		height;
+  Boolean	edit = FALSE;
+
+  if ((*num_params > 0) && 
+      (!strcmp(params[0], "EDIT") ||
+       !strcmp(params[0], "edit")))
+    edit = TRUE;
+
+  if (SearchTree(TheTree, event->x, event->y, &node)) {
+    static Tree *PrevNode = NULL;
+    Tree *ParNode = NULL;
+    
+    PopupNode = node;
+    if (PrevNode != NULL)
+      DrawNode(PrevNode, New);
+    PrevNode = PopupNode;
+    
+    printf("%s^^%s^^%s\n", 
+	   EnvNm,
+	   edit ? "br-edit" : "br-view",
+	   (PopupNode->value) ? PopupNode->value : PopupNode->label.text);
+
+    StatusMsg(PopupNode->label.text, 1);
+    
+    ParNode = PopupNode->parent;
+    PopupNode->parent = NULL;
+    HiliteNode(PopupNode, New);
+    PopupNode->parent = ParNode;
+  }
+}
+
+static void 
+menu_popup_action(w, event, params, num_params)
+     Widget w;
+     XEvent *event;
+     String *params;
+     Cardinal *num_params;
+{
+  Widget menu;
+  Boolean popup;
+  ShellWidget shell_widget;
+
+  char	    *strargs[] = {"nodeMenu", NULL};
+  
+  menu = XtNameToWidget(TreeTopLevel, params[0]);
+  shell_widget = (ShellWidget) menu;
+  
+  if (nodeFound) {
+
+    /* This is giving me a headache. 
+     * Why does popup menus come up unselectable? 
+     */
+
+    XtCallActionProc(TreeDrawingArea,
+		     "XtMenuPopup",
+		     event,
+		     strargs,
+		     1);
+		 
+/*
+    XtSetSensitive(menu, TRUE);
+    XtPopupSpringLoaded(menu);
+ */
+
+/*    if (!XtIsShell(menu)) {
+      printf("error: not shell widget!\n");
+    } else {
+      if (! shell_widget->shell.popped_up) {
+	
+	XtGrabKind call_data = XtGrabExclusive;
+	
+	XtCallCallbacks(menu, XtNpopupCallback, (XtPointer) &call_data);
+	
+	shell_widget->shell.popped_up = TRUE;
+	shell_widget->shell.grab_kind = XtGrabExclusive;
+	shell_widget->shell.spring_loaded = TRUE;
+	
+	if (shell_widget->shell.create_popup_child_proc != NULL) {
+	  (*(shell_widget->shell.create_popup_child_proc))(menu);
+	}
+	
+	XtAddGrab(menu, TRUE, TRUE);
+	
+	XtRealizeWidget(menu);
+	
+	XMapRaised(XtDisplay(menu), XtWindow(menu));
+	
+      } else
+	XRaiseWindow(XtDisplay(menu), XtWindow(menu));   
+    }
+    */
+  }
+}
+
+
+static void 
+button_action(w, event, params, num_params)
+     Widget w;
+     XEvent *event;
+     String *params;
+     Cardinal *num_params;
+{
+  Tree     *node;
+  
+  if (SearchTree(TheTree, event->xbutton.x, event->xbutton.y, &node)) {
+    
+    nodeFound = TRUE;
+    
+    XtSetSensitive(nodeMenuItems[NODE_MENU_DELETE], TRUE);
+
+    XtVaSetValues(treeMenus[NODE_MENU], 
+		  XtNlabel, node->label.text, 
+		  NULL);
+    PopupNode = node;
+    if (IS_LEAF(node))  {
+      
+      XtSetSensitive(nodeMenuItems[NODE_MENU_ELISION], FALSE);
+      
+      XtVaSetValues(nodeMenuItems[NODE_MENU_ELISION], 
+		    XtNlabel, labelStr[STR_NODE_COLLAPSE], 
+		    NULL);
+      
+    } else {
+      
+      XtSetSensitive(nodeMenuItems[NODE_MENU_ELISION], TRUE);
+      if (node->elision) {
+	XtVaSetValues(nodeMenuItems[NODE_MENU_ELISION],
+		      XtNlabel, labelStr[STR_NODE_EXPAND],
+		      NULL);
+      } else {
+	XtVaSetValues(nodeMenuItems[NODE_MENU_ELISION],
+		      XtNlabel, labelStr[STR_NODE_COLLAPSE],
+		      NULL);
+      }
+    }
+    
+    if (node->parent) {
+      XtSetSensitive(nodeMenuItems[NODE_MENU_ADD_BEFORE], TRUE);
+      XtSetSensitive(nodeMenuItems[NODE_MENU_ADD_AFTER], TRUE);
+    } else {
+      XtSetSensitive(nodeMenuItems[NODE_MENU_ADD_BEFORE], FALSE);
+      XtSetSensitive(nodeMenuItems[NODE_MENU_ADD_AFTER], FALSE);
+    }
+    
+    if (node->elision) {
+      XtSetSensitive(nodeMenuItems[NODE_MENU_ADD_CHILD], FALSE);
+    } else {
+      XtSetSensitive(nodeMenuItems[NODE_MENU_ADD_CHILD], TRUE);
+    }
+    
+  } else {
+    nodeFound = FALSE;
+
+    XtVaSetValues(treeMenus[NODE_MENU], 
+		  XtNlabel, " ", 
+		  NULL);
+
+    XtSetSensitive(nodeMenuItems[NODE_MENU_ADD_BEFORE], FALSE);
+    XtSetSensitive(nodeMenuItems[NODE_MENU_ADD_AFTER], FALSE);
+    XtSetSensitive(nodeMenuItems[NODE_MENU_ADD_CHILD], FALSE);
+    XtSetSensitive(nodeMenuItems[NODE_MENU_ELISION], FALSE);
+    XtSetSensitive(nodeMenuItems[NODE_MENU_DELETE], FALSE);
+  }
+}
+
+
+/* ------------------------------------------------------------------------- */
+/*									     */
+/* General purpose popdown widget callback (for dialog popdown buttons)      */
+/*									     */
+/* ------------------------------------------------------------------------- */
+
+static void center_widget(w, x, y)
+Widget w;
+int x, y;
+{
+  Dimension	width, height, border;
+  Position	max_x, max_y;
+  
+  XtVaGetValues(w,
+		XtNwidth, &width,
+		XtNheight, &height,
+		XtNborderWidth, &border,
+		NULL);
+  
+  width += 2 * border;
+  height += 2 * border;
+  
+  x -= ((Position) width / 2);
+  y -= ((Position) height / 2);
+  
+  if (x < 0) x = 0;
+  if (y < 0) y = 0;
+  
+  if (x > (max_x = (Position) (XtScreen(w)->width - width)) )
+    x = max_x;
+  
+  if (y > (max_y = (Position) (XtScreen(w)->height - height)) )
+    y = max_y;
+  
+  XtVaSetValues(w,
+		XtNx, x,
+		XtNy, y,
+		NULL);
+}
+
+#define shell_translations "<Message>WM_PROTOCOLS: wmpopdown()\n"
+		     
+static void 
+popup_dialog(shell, grab_kind)
+     Widget shell;
+     XtGrabKind grab_kind;
+{
+  int		idummy, x, y;
+  Window	wdummy;
+
+  XtOverrideTranslations(shell, XtParseTranslationTable(shell_translations));
+  XtRealizeWidget(shell);
+  wm_delete_window = XInternAtom(XtDisplay(shell), "WM_DELETE_WINDOW", 
+				 FALSE);
+  (void) XSetWMProtocols(XtDisplay(shell), XtWindow(shell),
+			 &wm_delete_window, 1);
+  
+  XQueryPointer(TreeDisplay, DefaultRootWindow(TreeDisplay), 
+		&wdummy, &wdummy,
+		&x, &y, &idummy, &idummy, &idummy);
+  
+  center_widget(shell, x, y);
+  
+  XtPopup(shell, grab_kind);
+}
+
+static void 
+popdown_action(widget, event, params, num_params)
+     Widget widget;
+     XEvent *event;
+     String *params;
+     Cardinal *num_params;
+{
+  XtPopdown(widget);
+}
+
+static void 
+set_siblingscale_CB(widget, w, percent_ptr)
+     Widget widget;
+     XtPointer w;
+     XtPointer percent_ptr;
+{
+  char tmpstr[10];
+  
+  sprintf(tmpstr, "%d  ", (int) (*(float*) percent_ptr*MAX_BORDER_SIZE));
+  
+  XtVaSetValues((Widget) w, XtNlabel, tmpstr, NULL);
+}
+
+static void 
+siblingscale_CB(widget, w, report)
+     Widget widget;
+     XtPointer w;
+     XawPannerReport *report;
+{
+  char tmpstr[10];
+  
+  sprintf(tmpstr, "%d ", (int) 
+	  ((float) report->slider_x / report->slider_width 
+	   * MAX_BORDER_SIZE / 10));
+  
+  XtVaSetValues((Widget) w, XtNlabel, tmpstr, NULL);
+}
+
+static void
+set_levelscale_CB(widget, w, percent_ptr)
+     Widget widget;
+     XtPointer w;
+     XtPointer percent_ptr;
+{
+  char	tmpstr[10];
+
+  sprintf(tmpstr, "%d  ", (int) (*(float*) percent_ptr*MAX_PARENT_DISTANCE));
+
+  XtVaSetValues((Widget) w, XtNlabel, tmpstr, NULL);
+}
+
+static void
+levelscale_CB(widget, w, report)
+     Widget widget;
+     XtPointer w;
+     XawPannerReport *report;
+{
+  char	tmpstr[10];
+  
+  sprintf(tmpstr, "%d ", (int) 
+	  ((float) report->slider_x / report->slider_width 
+	   * MAX_PARENT_DISTANCE / 10));
+  
+  XtVaSetValues((Widget) w, XtNlabel, tmpstr, NULL);
+}
+
+static void 
+set_siblingvalue_CB(widget, var_ptr, percent_ptr)
+     Widget widget;
+     XtPointer var_ptr;
+     XtPointer percent_ptr;
+{
+  * (int *)var_ptr = (int) (*(float*) percent_ptr*MAX_BORDER_SIZE);
+}
+
+static void 
+set_levelvalue_CB(widget, var_ptr, percent_ptr)
+     Widget widget;
+     XtPointer var_ptr;
+     XtPointer percent_ptr;
+{
+  * (int *)var_ptr = (int) (*(float*) percent_ptr*MAX_PARENT_DISTANCE);
+}
+
+
+static void 
+siblingvalue_CB(widget, var_ptr, report)
+     Widget widget;
+     XtPointer var_ptr;
+     XawPannerReport *report;
+{
+  * (int *) var_ptr = (int) 
+    ((float) report->slider_x / report->slider_width 
+     * MAX_BORDER_SIZE / 10);
+}
+
+static void 
+levelvalue_CB(widget, var_ptr, report)
+     Widget widget;
+     XtPointer var_ptr;
+     XawPannerReport *report;
+{
+  * (int *) var_ptr = (int) 
+    ((float) report->slider_x / report->slider_width 
+     * MAX_PARENT_DISTANCE / 10);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * 
+ *   Main routine
+ * 
+ * ----------------------------------------------------------------------------
+ */
+
+main(argc, argv)
+     int argc;
+     char *argv[];
+{
+  Tree *tree = NULL;
+  ErrCode error = ERR_NONE;
+  
+  ProgramName = strdup(argv[0]);
+  if (ProgramName == NULL) {
+    fprintf(stderr, "%s: insufficient memory available\n", argv[0]);
+    exit(0);
+  }
+  
+  InitializeInterface(&argc, argv);
+  XSync(TreeDisplay, 0);
+
+  if (argc >= 2) {
+    tree = ReadTreeFromFile(argv[1], &error);
+    if (tree) StatusMsg(argv[1], TRUE);
+    if (argc > 2)
+      WARN("extraneous arguments ignored");
+  } 
+     
+  if (tree) {
+    SetupTree(tree);
+    XtSetSensitive(treeMenuItems[TREE_MENU_SAVE], TRUE);
+  } else {
+    SetDrawingTree(NULL);
+    XtSetSensitive(treeMenuItems[TREE_MENU_SAVE], FALSE);
+  }
+
+  if (error != ERR_NONE)
+    HandleError(error, tree);
+  
+  StatusMsg("Left = Edit Node; Mid = View Node; Right = Node Menu", 1);
+  UserEventLoop();
+}
+
+/* ------------------------------------------------------------------------- */
+/*				  End of File                                */
+/* ------------------------------------------------------------------------- */
+
+
+
+
+
+