
#include "wbnlistP.h"
#include "wbnlist.h"

#define WBprstr_func(x) prstr_general_widget  /* dummy this out for now */

#define WNLfree(ptr)  

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

WNList *WNLcons_atom(atom, wnlist)
     WNLatom *atom;
     WNList *wnlist;
 { WNList *new_head;

   /* create a new element and add it to the head of the wnlist */
   new_head = (WNList *) calloc(1, sizeof(WNList));
   new_head->atom = atom;
   new_head->next = wnlist;
   return(new_head);
 };         /* end of WNLcons_atom()  */
/***************************************************************************/

WNList *WNLappend_atom(atom, wnlist)
     WNLatom *atom;
     WNList *wnlist;
 { WNList *new_tail, *last;

   /* create a new element and add it to the tail of the wnlist */
   new_tail = (WNList *) calloc(1, sizeof(WNList));
   new_tail->atom = atom;
   new_tail->next = NULL;

   if (wnlist == NULL)
     return(new_tail);

   /* Find tail of list to which to append the new element */
   for(last = wnlist; last->next != NULL; last = last->next);

   last->next = new_tail;
   return(new_tail);
 };         /* end of WNLcons_atom()  */

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

WNLatom *WNLatom_create(mmm_id, parent_mmm_id, class_name, widget_name,
			 value_string)
     int mmm_id;
     int parent_mmm_id;
     char *class_name, *widget_name;
     char *value_string;
{ WNLatom *new_atom;

  new_atom = (WNLatom *) calloc(1, sizeof(WNLatom));
  new_atom->mmm_id = mmm_id;
  new_atom->parent_mmm_id = parent_mmm_id;
  new_atom->class_name = class_name;
  new_atom->widget_name = widget_name;
  new_atom->value_string = value_string;

  return(new_atom);
};         /* end of WNLatom_create()  */

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

int WNLhas_a_parent(atom)
     WNLatom *atom;
 { 
   return(atom->parent_mmm_id >= 0);

  };       /* end of WNLhas_a_parent()  */

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

WidgetNode *WNLrealize_atom(atom, parent_widget)
     WNLatom *atom;
     Widget parent_widget;
 { Widget widget;
   WidgetNode *node;
   MailBuffer *buffer;
   char *key, *value;
   int i;
   extern WidgetNode *HeadWidgetList;
   extern Widget make_editable_button();
   extern Widget make_editable_label();
   extern Widget make_editable_video();
   extern Widget make_editable_asciitext();
   extern Widget make_editable_blank_line();
   extern Widget make_editable_form();
   extern Widget make_editable_mail_field();

   WBdebug(printf(">> Entering: WNLrealize_atom(): atom->mmm_id=%d\n",
		  atom->mmm_id));

   /* create a new widget */
   /* ------------------- */
   if (strcmp(atom->class_name, "button") == 0)        /* add button    */
     { widget = make_editable_button(parent_widget);
     }
   else if (strcmp(atom->class_name, "label") == 0)    /* add label     */
     { widget = make_editable_label(parent_widget);
     }
   else if (strcmp(atom->class_name, "video") == 0)    /* add video     */
     { widget = make_editable_video(parent_widget);
     }
   else if (strcmp(atom->class_name, "asciitext") == 0)  /* + asciitext */
     { widget = make_editable_asciitext(parent_widget);
     }
   else if (strcmp(atom->class_name, "blank line") == 0) /* +blank line */
     { widget = make_editable_blank_line(parent_widget);     
     }
   else if (strcmp(atom->class_name, "form") == 0)      /* add form     */
     { widget = make_editable_form(parent_widget);
     }
   else if (strcmp(atom->class_name, "mail field") == 0) /* +mail field */
     { widget = make_editable_mail_field(parent_widget);     
     }
   else
     widget = NULL;

   if (widget == NULL)
     { WBdebug(printf("<< Exiting: WNLrealize_atom(): failed\n"));
       return(NULL);      /* Failed */
     };

   /* create a new widgetnode */
   /* ----------------------- */
   node = find_widgets_node(widget, HeadWidgetList);
   XtUnmanageChild(widget);

   if (node == NULL)
     { WBdebug(printf("<< Exiting: WNLrealize_atom(): failed\n"));
       return(NULL);      /* Failed */
     };

   /* initialize */
   /* ---------- */
   node->name = atom->widget_name;
   node->mmm_id = atom->mmm_id;

   /* initialize buffer objects */
   /* ------------------------- */
   buffer = AlMB_create();

   /* Process all of the properties */
   /* ----------------------------- */
   AlMB_replace_buffer(buffer, atom->value_string);
   while((key = AlMB_rdstring(buffer, ',')) != NULL)
     { AlMB_getch(buffer);                  /* skip over comma */
       AlMB_getch(buffer);                  /* skip over space */
       WBdebug(printf(" -- In WNLrealize_atom(): key = '%s'\n", key));
       if (AlMB_rdinteger(buffer, &i) == 1)   /* value is a number */
	 { XtSetArg(arg_list[0], key, (XtArgVal) i);
	   XtSetValues(widget, arg_list, 1);
	   WBdebug(printf(" -- In WNLrealize_atom(): value = # %d\n", i));
	   AlMB_getch(buffer);                            /* skip over comma */
	   AlMB_getch(buffer);                            /* skip over space */
	 }
       else
	 { value = AlMB_esc_rdstring(buffer, ',');
	   AlMB_getch(buffer);                            /* skip over comma */
	   AlMB_getch(buffer);                            /* skip over space */
	   if (value == NULL)
	     value = AlMB_esc_rdstring(buffer, '\0');
	   WBdebug(printf(" -- In WNLrealize_atom(): value = '%s'\n",
			  (value != NULL) ? value : "**NULL**"));
	   if (value != NULL)
	     {
	       if (strcmp(key, WBfont) == 0)               /* font change    */
		 { XtSetArg(arg_list[0], XtNfont,
			    (XtArgVal) fontstruct(value));
		   XtSetValues(widget, arg_list, 1);
		   node->font = value;
		 }
	       else if (strcmp(key, WBjustify) == 0)       /* re-justify     */
		 { XtSetArg(arg_list[0], XtNjustify, (XtArgVal) 
			    ((strcmp(value, "XtJustifyCenter") == 0)
			     ? XtJustifyCenter
			     : ((strcmp(value, "XtJustifyRight") == 0)
				? XtJustifyRight : XtJustifyLeft)));
		   XtSetValues(widget, arg_list, 1);
		   WNLfree(value);
		 }
	       else if (strcmp(key, "varName") == 0)            /* node info */
		 { node->varName = value;
		   WBdebug(printf(
		   " -- In WNLrealize_atom: varName_string='%s', value='%s'\n",
				  (node->edit_states)->varName_string, value));
		   strcpy((node->edit_states)->varName_string, value);
		 }
	       else if (strcmp(key, "WName") == 0)              /* node info */
		 { node->name = value;
		   strcpy((node->edit_states)->name_string, value);
		 }
	       else if (strcmp(key, "callback") == 0)          /* callback   */
		 { strcpy((node->edit_states)->callback_string, value);
		   WNLfree(value);
		 }
	       else if (strcmp(key, "string") == 0)              /* string   */
		 { if (strcmp(atom->class_name, "asciitext") == 0)
		     { if (node->string == NULL)
			 node->string = (char *)
			   calloc((((MIN_ASCII_STRING_LENGTH + 2)
				    > strlen(value))
				   ? (MIN_ASCII_STRING_LENGTH + 2)
				   : strlen(value)),
				  sizeof(char));
		       strcpy(node->string, value);
		     };
		   WNLfree(value);
		 }
	       else if (strcmp(key, "label") == 0)                /* label   */
		 { 
		   if ((node->edit_states)->label_string == NULL)
		     (node->edit_states)->label_string = (char *)
		       calloc(MIN_ASCII_STRING_LENGTH + 2, sizeof(char));
		   strcpy((node->edit_states)->label_string, value);
		   XtSetArg(arg_list[0], key, (XtArgVal) 
			    (node->edit_states)->label_string);
		   XtSetValues(widget, arg_list, 1);
		   WNLfree(value);
		 }
	       else if (strcmp(key, "videoMode") == 0)         /* Video Mode */
		 { if (strcmp(value, "still") == 0)  /* ??? NEEDS FIXING ??? */
		     XtSetVideoMode(widget, XtVideoStill);
		   WNLfree(value);
		 }
	       else if (strcmp(value, "TRUE") == 0)          /* Boolean TRUE */
		 { XtSetArg(arg_list[0], key, (XtArgVal) TRUE);
		   XtSetValues(widget, arg_list, 1);
		   WNLfree(value);
		 }
	       else if (strcmp(value, "FALSE") == 0)        /* Boolean FALSE */
		 { XtSetArg(arg_list[0], key, (XtArgVal) FALSE);
		   XtSetValues(widget, arg_list, 1);
		   WNLfree(value);
		 }
	       else if (strcmp(value, "XtChainTop") == 0)        /* Chaining */
		 { XtSetArg(arg_list[0], key, (XtArgVal) XtChainTop);
		   XtSetValues(widget, arg_list, 1);
		   WNLfree(value);
		 }
	       else if (strcmp(value, "XtChainLeft") == 0)       /* Chaining */
		 { XtSetArg(arg_list[0], key, (XtArgVal) XtChainLeft);
		   XtSetValues(widget, arg_list, 1);
		   WNLfree(value);
		 }
	       else if (strcmp(value, "XtChainRight") == 0)      /* Chaining */
		 { XtSetArg(arg_list[0], key, (XtArgVal) XtChainLeft);
		   XtSetValues(widget, arg_list, 1);
		   WNLfree(value);
		 }
	       else if (strcmp(value, "XtChainBottom") == 0)     /* Chaining */
		 { XtSetArg(arg_list[0], key, (XtArgVal) XtChainLeft);
		   XtSetValues(widget, arg_list, 1);
		   WNLfree(value);
		 }
	       else if (strcmp(value, "XtRubber") == 0)          /* Chaining */
		 { XtSetArg(arg_list[0], key, (XtArgVal) XtRubber);
		   XtSetValues(widget, arg_list, 1);
		   WNLfree(value);
		 }
	       else                       /* assume value should be a string */
		 { XtSetArg(arg_list[0], key, (XtArgVal) value);
		   XtSetValues(widget, arg_list, 1);
		   WNLfree(value);
		 };
	     };
	 };
       WNLfree(key);
     };

   AlMB_destroy(buffer);
   XtManageChild(widget);

   /* return new widgetnode */
   WBdebug(printf("<< Exiting: WNLrealize_atom(): successful\n"));
   return(node);

 };

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

WNList *WNLmmm_member(mmm_id, head_list)
     int mmm_id;
     WNList *head_list;
 { WNList *head;

   /* Return portion of list starting with atom of mmm_id to tail */
   head = head_list;
   while(head != NULL)
     { if (head->atom != NULL)
	 { if ((head->atom)->mmm_id == mmm_id)
	     return(head);
	 };
       head = head->next;
     };
   return(head);
 };               /* end of WNLmmm_member()  */

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

WidgetNode *WNLintern_realize_tree(mmm_id, head_list, how_many)
     int mmm_id;
     WNList *head_list;
     int *how_many;
 { WidgetNode *widgetnode, *parent;
   extern Widget userArea;
   extern WidgetNode *HeadWidgetList;
   WNList *list_item;
   extern Display *the_display;

   /* check if the widget with this mmm_id has already been realized */
   if ((widgetnode = get_widgetnode_by_mmm_id(mmm_id, HeadWidgetList) )
	    != NULL)
     return(widgetnode);    /* yes, already realized */

   /* retrieve the correct element of the list (with mmm_id) */
   list_item = WNLmmm_member(mmm_id, head_list);
   if (list_item == NULL)
     { WBdebug(printf(
         " -- In WNLintern_realize_tree(): mmm_id failed member test.\n"));
     return(NULL);   /* Failed */
     }
   else if (mmm_id == (list_item->atom)->parent_mmm_id)
     { XBell(the_display, 1);
       documentation_line(
	"Data contains infinite-loop: self-references in a parent ID found.");
       WBdebug(printf(
	" -- In WNLintern_realize_tree(): mmm_id=%d, is its own parent.\n",
		      mmm_id));
       return(NULL);
     };

   if ((list_item->atom)->parent_mmm_id == -1)   /* to be a top widgetnode */
     { widgetnode = WNLrealize_atom(list_item->atom, userArea);
       if (widgetnode != NULL)
	 (*how_many)++;
       return(widgetnode);
     }
   else if ((parent = get_widgetnode_by_mmm_id(
		          (list_item->atom)->parent_mmm_id,  /* id */
			  HeadWidgetList))
	    != NULL)         /* parent is already realized in tree */
     { widgetnode = WNLrealize_atom(list_item->atom, parent->widget);
       if (widgetnode != NULL)
	 (*how_many)++;
       return(widgetnode);
     }
   else
     { /* parent doesn't exist, yet. */

       parent = WNLintern_realize_tree((list_item->atom)->parent_mmm_id,
                              head_list, how_many);
       if (parent == NULL)
	 { 
#if (DEBUG == 1)
	   printf("DEBUG: Null parent (ID=%d), requesting child ID=%d\n",
		  (list_item->atom)->parent_mmm_id,
		  (list_item->atom)->mmm_id);
#endif
	   return(NULL);
	 };
       widgetnode = WNLrealize_atom(list_item->atom, parent->widget);
       if (widgetnode != NULL)
	 (*how_many)++;
       return(widgetnode);
     };
 };         /* end of WNLrealize_tree()  */

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

WidgetNode *WNLrealize_tree(the_list, how_many)
     WNList *the_list;
     int *how_many;
 { WidgetNode *widgetnode;
   WNList *head_list;
   extern Widget userArea;
   extern WidgetNode *HeadWidgetList;

   *how_many = 0;
   if (the_list == NULL)
     return(NULL);
   else if (the_list->atom == NULL)
     return(NULL);

   widgetnode = 
     WNLintern_realize_tree((the_list->atom)->mmm_id, the_list, how_many);
   for (head_list = the_list->next;
	head_list != NULL;
	head_list = head_list->next)
     WNLintern_realize_tree((head_list->atom)->mmm_id, the_list, how_many);

   /* some debugging code */
   WBdebug(for (head_list = the_list;
		head_list != NULL;
		head_list = head_list->next)
	   { printf(" -- In WNLrealize_tree(): list=> mmm_id=%d\n",
		    head_list->atom->mmm_id);
	   };)

   return(widgetnode);
 };         /* end of WNLrealize_tree()  */

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

