      /********************************************************/
      /*                   Widget-Builder               (3)   */
      /* This program was written by Brian R. Gardner, 1988.  */
      /* It was created as a visual, easy to use, technique   */
      /* for rapid proto-typing of user interfaces. It allows */
      /* its user to design the layout of an X-window based   */
      /* user interface, complete with sub-windows, buttons,  */
      /* labels, and other "widgets". This program will also  */
      /* serve as a programmer's aid by writing out to a file */
      /* the source code required to re-generate the created  */
      /* visual user interface. The code generated is usually */
      /* substantial, reflecting immense savings in the time  */
      /* neccessary to program using X-windows.               */
      /*    Note that this program is only a simple test      */
      /* version. It was the author's first introduction to   */
      /* the Athena environment, as well as X-windows and the */
      /*  X-Toolkit. It was written in 2 weeks.               */
      /*    This was written under the roof of Project Athena */
      /* at Massachusetts Institute of Technology, by         */
      /* Brian Gardner (DEC), and hence reasonably available. */
      /* Read that as "FREE"         :-)                      */
      /* with the usual friendly restrictions.                */
      /********************************************************/

     /************************************************************/
     /* Copyright 1988, Massachusetts Institute of Technology.   */
     /* See X(1) for a full statement of rights and permissions. */
     /************************************************************/

#include "wb_include.h"
#include "wbnodeP.h"

/****************************************************************/

WidgetNode *find_widgets_node(widget, starting_node)
     Widget widget;
     WidgetNode *starting_node;
 {
    WidgetNode *current_node, *wn;

    /* Locate the widget node in linked list for the search widget */
    /* ----------------------------------------------------------- */
    for (current_node = starting_node;
	 (current_node != NULL) && (current_node->widget != widget);
	 current_node = current_node->next)
      if ((wn = find_widgets_node(widget, current_node->first_child))
	  != NULL)
	return(wn);

    return(current_node);
  };         /* end of find_widgets_node() */

/****************************************************************/

WidgetNode *get_widgetnode_by_mmm_id(mmm_id, starting_node)
     int mmm_id;
     WidgetNode *starting_node;
 {
    WidgetNode *current_node, *wn;

    /* Locate the widget node in linked list for the search widget */
    /* ----------------------------------------------------------- */
    for (current_node = starting_node;
	 (current_node != NULL) && (current_node->mmm_id != mmm_id);
	 current_node = current_node->next)
      if ((wn = get_widgetnode_by_mmm_id(mmm_id, current_node->first_child))
	  != NULL)
	return(wn);

    return(current_node);
  };         /* end of get_widgetnode_by_mmm_id() */

/****************************************************************/

void WN_set_mmm_id(node, id)
     WidgetNode *node;
     int id;
  {
   /* Set the widget's mmm ID, used when being written to a mail file */
   node->mmm_id = id;

  };        /* end of WN_set_mmm_id()  */

/****************************************************************/

WidgetNode *add_widget_node(widget, parent_widget, type, prstr_func)
     Widget widget;
     Widget parent_widget;
     char *type;
     VOID_FUNCPTR prstr_func;
 {
   WidgetNode *new_node;
   char *genname();

   /* allocate space for the new node */
   new_node = (WidgetNode *) calloc(sizeof(WidgetNode), 1);

   /*  the widget's ID when being written to a mail file    */
   new_node->mmm_id = -1;   /* will be reset later, anyway */

   /* unique name of widget for X, often genname'ed         */
   new_node->name = genname();

   /* name of variable widget is assigned to in saved code */
   new_node->varName = new_node->name;

   /* type of widget (e.g.: "button", "label", etc.)       */
   new_node->type = type;  

   /* pointer to the actual widget                         */
   new_node->widget = widget;

   /* pointer to the widget's parent widget                */
   new_node->parent = parent_widget;

   /* pointer to the widget's popup child widget           */
   new_node->popup = NULL;

   /* name of callback function for widget (written later) */
   new_node->callback = NULL;

   /* use for holding ptr to Ascii Text widget's XtNstring */
   new_node->string = NULL;

   /* the name of the font used for  label of this widget  */
   new_node->font = (char *) calloc(15, 1);
   strcpy(new_node->font, "times-roman12");

   /* the struct of the font used this widget's label      */
   new_node->font_struct = timesRoman12;

   /* the struct used to keep track of this node's pop-up edit menu   */
   new_node->edit_states = (struct menu_state *)
     calloc(sizeof(struct menu_state), 1);

   /* The pointer to the function which prints a string of properties */
   new_node->prstr_func = (VOID_FUNCPTR) prstr_func;

   /* pointer to next widget node in linked list           */
   new_node->next = NULL;

   /* Set the pointer to the parent's widget node          */
   new_node->parent_node = find_widgets_node(parent_widget, HeadWidgetList);

   /* Link new node into linked list of child widget nodes */
   if (parent_widget == userArea)
     { /* add node to the top level list */
       if (HeadWidgetList == NULL)
	 {
	   HeadWidgetList = new_node;
	   TailWidgetList = new_node;
	 }
       else
	 {
	   TailWidgetList->next = new_node;
	   TailWidgetList = new_node;
	 };
     }
   else if (new_node->parent_node != NULL)
     { /* add node to a parents children list */
       if ((new_node->parent_node)->first_child == NULL)
	 {
	   (new_node->parent_node)->first_child = new_node;
	   (new_node->parent_node)->last_child = new_node;
	 }
       else
	 {
	   ((new_node->parent_node)->last_child)->next = new_node;
	   (new_node->parent_node)->last_child = new_node;
	 };
     }
   else
     { return(NULL);   /* can not add the node, nothing to add it to */
     };

   return(new_node);

 };             /* end of add_widget_node() */

/****************************************************************/

void traverse_widgets_nodes(starting_node, func, arg)
     WidgetNode   *starting_node;
     VOID_FUNCPTR  func;
     VOIDP         arg;
  {
     WidgetNode *current_node, *wn;

	 printf("Entering >> traverse_widgets_nodes(%s, %d, %d);\n", /*DEBUG */
		(starting_node != NULL) ? starting_node->name : "NULL",
		(int) func, (int) arg);                              /*DEBUG */

     /* Traverse linked tree, performing "func" on each widget node */
     for(current_node = starting_node;
	 current_node != NULL;
	 current_node = current_node->next)
       { 
	 printf("In -1--- >> traverse_widgets_nodes(%s, %d, %d);\n", /*DEBUG */
		current_node->name, (int) func, (int) arg);         /*DEBUG */

	 if (func != NULL)
	   (func)(arg, current_node);

	 printf("In -2--- >> traverse_widgets_nodes(%s, %d, %d);\n", /*DEBUG */
		current_node->name, (int) func, (int) arg);         /*DEBUG */

	 traverse_widgets_nodes(current_node->first_child,
				func, arg);

	 printf("In -3--- >> traverse_widgets_nodes(%s, %d, %d);\n", /*DEBUG */
		current_node->name, (int) func, (int) arg);         /*DEBUG */

       };

	 printf("Exiting  << traverse_widgets_nodes(%s, %d, %d);\n", /*DEBUG */
		(starting_node != NULL) ? starting_node->name : "NULL",
		(int) func, (int) arg);         /*DEBUG */
   };         /* end of traverse_widgets_nodes()  */

/****************************************************************/

int WNhas_mmm_parent(widgetnode)
     WidgetNode *widgetnode;
 {
   return(widgetnode->parent_mmm_id >= 0);
 };           /* end of WNhas_mmm_parent()  */

/****************************************************************/

