      /********************************************************/
      /*                   Widget-Builder               (1)   */
      /* 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. */
     /************************************************************/

/*
 * Copyright 1988 by Digital Equipment Corporation.
 * 
 *                         All Rights Reserved
 * 
 * Permission to use, copy, modify, and distribute this software and its 
 * documentation for any purpose and without fee is hereby granted, 
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in 
 * supporting documentation, and that the name of Digital Equipment
 * Corporation not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior permission.  
 * 
 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

#include "wb_include.h"
#include "widget-builderP.h"
#define OR ||


/* Include file for saving the C code necessary to regenerate all widgets */
/* ---------------------------------------------------------------------- */
/* #include "wbsaveccode.h" */

Widget make_edit_menu(parent_widget, grandparent_widget, options, type)
     Widget parent_widget;
     Widget grandparent_widget;
     char *options[];       /* the list of options for the popup menu */
     char type[];           /* "button", "scrollbar", etc.            */
 {
   Widget edit_shell;  /* the Override Shell that holds button editor */
   Widget edit_menu;   /* the background box for button editor menu   */
   Widget widget;
   Widget menu_label;
   char *shell_name;       /* a unique shell name for this popup menu */
   char *str;
   int i;

   /* Create the popup edit menu for a widget */
   /* ---------------------------------------------- */
   shell_name = (char *) gensym();
   edit_shell = XtCreatePopupShell(shell_name,
			  overrideShellWidgetClass,
			  grandparent_widget,
			  NULL, 0);
   edit_menu = 
	   XtCreateManagedWidget((char *) gensym(),
		       boxWidgetClass,
   		       edit_shell,
		       NULL, 0);
   /* Force edit_menu to popdown when button is let up */
   /* XtAugmentTranslations(edit_shell, */
   XtOverrideTranslations(edit_shell, 
			 XtParseTranslationTable(
			  "<Btn1Down>,<Btn1Up>:MenuPopdown()"));

   /* Link new popup edit menu to parent_widget */
   /* ----------------------------------------- */
   /* alloc space for translation table string  */
   str = (char *) calloc((strlen(shell_name) + strlen(type) 
	    + strlen("<Btn1Down>: MarkWidget(\"\") MyDebug() MenuPopup(\"\")")
/* 	    + strlen(" pushshell(\"\")") + 10 */
	    + 1 + 10) , 1);  
   /* make translation table string */
   sprintf(str,
	   "<Btn1Down>: MarkWidget(\"%s\",\"%d\") MyDebug() MenuPopup(\"%s\")",
	   type, (int) edit_shell, shell_name);
   XtOverrideTranslations(parent_widget, 
   /* XtAugmentTranslations(parent_widget, */
			  XtParseTranslationTable(str));

   /* Place a sensible Label ontop of the popup edit menu */
   /* ------------------------------------------------------ */
   str = (char *) calloc((strlen(type) + 20), 1);
   sprintf(str, "   %s options   ", type);
   arg_list[0].name = XtNlabel;
   arg_list[0].value = (XtArgVal) str;
   menu_label = XtCreateManagedWidget((char *) gensym(),
			       labelWidgetClass, edit_menu,
			       arg_list, 1);
   inverseVideo(menu_label);    /* Highlight the label */

/*			       widget_builder_label_arg_list,
			       XtNumber(wb_label_arg_list)); 
   XtSetValues(menu_label, arg_list, 3); */

   for (i=0; options[i] != NULL; i++)
     {
       /* add an option to popup menu */
       /* --------------------------- */
       arg_list[0].name = XtNlabel;         /* label for the option button */
       arg_list[0].value = (XtArgVal) options[i]; 

       /* Create the Option Button */
       widget =
	   XtCreateManagedWidget((char *) gensym(),
		       commandWidgetClass,
   		       edit_menu,
		       arg_list, 1);

       /* make the button widget editable via a popup menu button editor */
       str = (char *) calloc((strlen(options[i]) + 28), 1);
       sprintf(str,
         "<Btn1Down>: EditWidget(\"%s\")", options[i]);
       /* XtAugmentTranslations(widget, */
       XtOverrideTranslations(widget, 
			      XtParseTranslationTable(str));
     };

   return(edit_menu);
 };         /* end of make_edit_menu() */

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

void make_saveCcode_button(parent_widget, option, index)
     Widget parent_widget;
     char *option;
     int index;
 {
   Widget widget, edit_menu, edit_shell;
   Widget filename_button;
   String null_edit_options[1];
   char  *str, *shell_name;

   null_edit_options[0] = NULL;

   /* Create the WBSaveAsCCode(op) button widget */
   /* -------------------------------------- */
   XtSetArg(arg_list[0], XtNlabel, option);
   widget = XtCreateWidget(option,
                   commandWidgetClass,
   	           parent_widget, arg_list, 1);

   /* make the button widget editable via a popup menu button editor */
   /* this must be done before the new widget is realized (managed)  */
   /*--------------------------------------------------------------- */
   shell_name = (char *) gensym();
   edit_shell = XtCreatePopupShell(shell_name,
			  overrideShellWidgetClass,
			  parent_widget,
			  NULL, 0);
   edit_menu = 
	   XtCreateManagedWidget((char *) gensym(),
		       boxWidgetClass,
   		       edit_shell,
		       NULL, 0); 

   /* Force edit_menu to popdown when button is let up */
   XtOverrideTranslations(edit_shell, 
            XtParseTranslationTable(
		"<Btn1Up>: \n\
                 <Btn1Up>,<Btn1Down>,<Btn1Up>:MenuPopdown() WBPopdown()"));

   /* Link new popup edit menu to widget */
   /* ----------------------------------------- */
   /* alloc space for translation table string  */
   str = (char *) calloc((strlen(shell_name) + strlen("Widget Builder") 
	     + strlen("<Btn1Down>: MarkWidget(\"\") MenuPopup(\"\")")
	     + 1 + 10) , 1); 
   /* make translation table string */
   sprintf(str,
	   "<Btn1Down>: MarkWidget(\"%s\",\"%d\") MenuPopup(\"%s\")",
	   "Widget Builder", (int) edit_shell, shell_name);    
   XtOverrideTranslations(widget, 
			  XtParseTranslationTable(str));


   /* Now allow the new widget to become managed (and realized) */
   XtManageChild(widget);

   /* Create the dialog box which will get the filename for C code saving */
   XtSetArg(arg_list[0], XtNlabel, 
            "Enter Filename (full path) for output:");
   XtSetArg(arg_list[1], XtNvalue, "");
   XtSetArg(arg_list[2], XtNwidth, 100);

   filename_widget[index] = XtCreateManagedWidget("Enter Filename:",
				   dialogWidgetClass,
				   edit_menu, arg_list, 3);
   filename_button = XtCreateManagedWidget("Ready", commandWidgetClass,
		  filename_widget[index],
		  arg_list, 0);

   /* make the button widget editable via a popup menu button editor */
   str = (char *) calloc(((strlen(option) * 2) + 38), 1);
   sprintf(str, "<Btn1Down>: GotFilename(\"%s\") EditWidget(\"%s\")",
	   option, option);
   XtOverrideTranslations(filename_button,
			  XtParseTranslationTable(str));

     };       /* end of make_saveCcode_button()  */

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

Widget make_saveCcode_buttons(parent_widget)
     Widget parent_widget;
 {
   make_saveCcode_button(parent_widget, WBSaveAsCCode, 0);
   make_saveCcode_button(parent_widget, WBSaveAsCCodeOp, 1);
   return(parent_widget);
 };          /* end of make_saveCcode_buttons()  */

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

Widget make_mailer_buttons(parent_widget)
     Widget parent_widget;
 {
   make_saveCcode_button(parent_widget, WBWriteFile, 3);
   make_saveCcode_button(parent_widget, WBReadFile, 2);
   return(parent_widget);
 };          /* end of make_mailer_buttons()  */

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

void edit_wb(widget, event)
     Widget widget;
     XEvent *event;
 {
   FILE *outfile, *fopen();
   MailBuffer *buffer;
  
   printf(" DEBUG: >> Entering edit_wb()\n");    /* DEBUG */
   if (strcmp(WBMarkedWidgetOption,
	      WBAddCommandButton) == 0)     /* Add a Command Button */
       make_editable_button(userArea);
   else if (strcmp(WBMarkedWidgetOption,
		   WBAddLabel) == 0)        /* Add a Label Widget */
       make_editable_label(userArea);
   else if (strcmp(WBMarkedWidgetOption,
		   WBAddAsciiText) == 0)    /* Add Ascii Text Widget */
       make_editable_asciitext(userArea);
   else if (strcmp(WBMarkedWidgetOption,
		   WBAddVideo) == 0)        /* Add a Video Widget */
       make_editable_video(userArea);
   else if (strcmp(WBMarkedWidgetOption,
		   WBAddBlankLine) == 0)    /* Add a Blank Line Widget */
       make_editable_blank_line(userArea);
   else if (strcmp(WBMarkedWidgetOption,
		   WBAddFormWidget) == 0)        /* Add a Form Widget */
       make_editable_form(userArea);
   else if (strcmp(WBMarkedWidgetOption,
	         WBAddKeyedMailField) == 0) /* Add a Keyed Mail Field */
       make_editable_mail_field(userArea);
   else if (strcmp(WBMarkedWidgetOption,
	         WBAddBlankMailField) == 0) /* Add a Blank Mail Field */
     ;
   else if (strcmp(WBMarkedWidgetOption,
	         WBResizeWorkingArea) == 0) /* Resize the User Area */
     ;
   else if (strcmp(WBMarkedWidgetOption,
		   "Ready") == 0)           /* User Entered Filename */
       filename_not_done = FALSE;   /* used by dialogbox to get filename */
   else if ((strcmp(WBMarkedWidgetOption,
		   WBSaveAsCCode) == 0)     /* Save as C code to file   */
	    OR
	    (strcmp(WBMarkedWidgetOption,
		    WBSaveAsCCodeOp) == 0)) /* Save as C code Optimized */
     {
       /* Set the optimizing flag for the routines that the write code */
       if (strcmp(WBMarkedWidgetOption,
		  WBSaveAsCCodeOp) == 0)
	 not_optimizing = FALSE;
       else
	 not_optimizing = TRUE;

       /* Open file and write out a C program that re-generates userArea */
       printf(" DEBUG: --   In edit_wb(): filename=\"%s\"\n",    /* DEBUG */
	      XtDialogGetValueString(                            /* DEBUG */
	       filename_widget[(not_optimizing == TRUE) ? 0 : 1])); /* DEBUG */

       if ((outfile = fopen(XtDialogGetValueString(
                            filename_widget[(not_optimizing == TRUE) ? 0 : 1]),
			   "w"))
	   == NULL)
         {
	   if ((outfile = fopen("tempwbMMM.c",
			   "w"))
	   == NULL)
	     { documentation_line("Error in filename. File not Saved.");
	       XBell(the_display, 1); /* beep console just above base volume */
	     }
	   else
	     {
	       XBell(the_display, 1); /* beep console just above base volume */
	       documentation_line(
		 "C code FAILED to file specified. Re-routed to: tempwbMMM.c");
	       write_headers(outfile);
	       write_widgets(outfile);
	       write_main(outfile);
	       fclose(outfile);
	     };
         }
       else
         {
	   write_headers(outfile);
           write_widgets(outfile);
	   write_main(outfile);
	   fclose(outfile);
	   documentation_line("C code successfully saved to file.");
	 };
     }
   else if (strcmp(WBMarkedWidgetOption,
		   WBWriteFile) == 0)       /* Save as mailer type file   */
     { 
       if ((outfile = fopen(XtDialogGetValueString(
                            filename_widget[3]),
			   "w"))
	   == NULL)
         {
	   documentation_line("Error in filename. File not Saved.");
           XBell(the_display, 1); /* beep console just above base volume */
         }
       else
         { buffer = AlMB_create();
	   prstr_all_widgets(HeadWidgetList, buffer, 0);
           AlMB_write_to_file(outfile, buffer);
	   AlMB_destroy(buffer);
	   buffer = NULL;
	   fclose(outfile);
	   documentation_line("Mailer format successfully saved to file.");
	 };
     }
   else if (strcmp(WBMarkedWidgetOption,
		   WBReadFile) == 0)        /* Read from a mailer type file */
     { WNdestroy_all(HeadWidgetList, TRUE);  /* Destroy all widgets, too */

       WBdebug(printf("DEBUG: reading widgets from file: %s\n", 
	         XtDialogGetValueString(
                              filename_widget[2])));
       XtUnmanageChild(userArea);
       WBread_all_widgets_from_file(
	                  XtDialogGetValueString(
                              filename_widget[2]));
       XtManageChild(userArea);
       if (HeadWidgetList == NULL)
	 { XBell(the_display, 1); /* beep console just above base volume */
	   documentation_line("FAILED to read mailer format from file.");
	 }
       else
	 documentation_line("Mailer format successfully read from file.");
     }
   else if (strcmp(WBMarkedWidgetOption,
		   WBQuit) == 0)            /* Exit Widget Builder Program */
     exit(0);
   else
    ;                                       /* Ignore Others */

   printf(" DEBUG: << Exiting edit_wb()\n");    /* DEBUG */

 };          /* end of edit_wb() */

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

void GotFilename(widget, event, widget_option, num_strings)
     Widget widget;
     XEvent *event;
     String *widget_option;      /* array of 1 string, like "Ready" */
     Cardinal num_strings; /* number of strings in widget_option array */
 {
   printf(" DEBUG printf: Entering GotFilename()\n");
   filename_not_done = FALSE;   /* used by dialogbox to get filename */
   printf(" DEBUG printf: Entering GotFilename()\n");
 };        /* end of GotFilename()  */
/****************************************************************/

void WBPopdown(widget, event, widget_option, num_strings)
     Widget widget;
     XEvent *event;
     String *widget_option;      /* array of 1 string, like "Ready" */
     Cardinal num_strings; /* number of strings in widget_option array */
 {
   printf(" DEBUG printf: Entering WBPopdown()\n");
   XtPopdown(WBMarkedShell);
   printf(" DEBUG printf: Entering WBPopdown()\n");
 };        /* end of WBPopdown()  */

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

void WBPopup(widget, event, widget_option, num_strings)
     Widget widget;
     XEvent *event;
     String *widget_option;      /* array of 1 string, like "Ready" */
     Cardinal num_strings; /* number of strings in widget_option array */
 {
   printf(" DEBUG printf: Entering WBPopup()\n");
   XtPopup(WBMarkedShell);
   printf(" DEBUG printf: Entering WBPopup()\n");
 };        /* end of WBPopup()  */

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

void MyDebug(widget, event, myWidgetType, num_myWidgetTypes)
     Widget widget;
     XEvent *event;
     String *myWidgetType;       /* array of strings, like "button", etc    */
     Cardinal num_myWidgetTypes; /* number of strings in myWidgetType array */
 {
   XButtonEvent *buttonevent;
   Position rootx, rooty;
   int widget_ID;
  
   buttonevent = (XButtonEvent *) event;

   /* Print info in Global vars */
   /* ------------------------- */
   printf(
  " DEBUG: WBMarkedShell = %d, WBMarkedWidget = %d, WBMarkedWidgetType = %s\n",
          (int) WBMarkedShell, (int) WBMarkedWidget, WBMarkedWidgetType);
   printf("       debug: window = %d, subwindow = %d\n",
          (int) (buttonevent->window), (int) (buttonevent->subwindow));

 };         /* end of MyDebug() */

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

void MarkWidget(widget, event, myWidgetType, num_myWidgetTypes)
     Widget widget;
     XEvent *event;
     String *myWidgetType;       /* array of strings, like "button", etc    */
     Cardinal num_myWidgetTypes; /* number of strings in myWidgetType array */
 {
   XButtonEvent *buttonevent;
   Position rootx, rooty;
   int widget_ID;

   /* Store info in Global vars, for EditWidget to access on Popdown */
   /* -------------------------------------------------------------- */
   WBMarkedWidget = widget;                        /* set widget */
   strcpy(WBMarkedWidgetType, myWidgetType[0]);    /* set type   */

   /* Store x,y of future popup menu */
   /* ------------------------------ */
   buttonevent = (XButtonEvent *) event;
   XtTranslateCoords(widget, buttonevent->x, buttonevent->y,
		     &rootx, &rooty);

   /* Change the position of the popup about to reveal itself */
   /* ------------------------------------------------------- */
   sscanf(myWidgetType[1], "%d", &widget_ID);
   WBMarkedShell = (Widget) widget_ID;
   XtMoveWidget(WBMarkedShell, rootx, rooty);

 };         /* end of MarkWidget() */

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

void EditWidget(widget, event, widget_option, num_myWidgetTypes)
     Widget widget;
     XEvent *event;
     String *widget_option;    /* array of 1 resource string, like XtNwidth */
     Cardinal num_myWidgetTypes; /* number of strings in myWidgetType array */
 {
   /* Store more info in a Global var, for edit_button to access */
   /* ---------------------------------------------------------- */
   strcpy(WBMarkedWidgetOption, widget_option[0]); /* set option */

   if (strcmp(WBMarkedWidgetType,"button") == 0)     /* button */
     edit_button(widget, event);
   else if (strcmp(WBMarkedWidgetType,
		   "Widget Builder") == 0)     /* Basic Functions */
       edit_wb(widget, event);
   else if (strcmp(WBMarkedWidgetType,
		   "key field") == 0)          /* Mail Field Keyword */
     edit_key_field(widget, event);
   else
     ;
 };         /* end of EditWidget() */

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

Widget WBcreate_wb(parent, menu_invoker, parent_of_menu_invoker)
     Widget parent, menu_invoker, parent_of_menu_invoker;
 {
   Widget minsize_userArea;
   Widget WBform;
   Widget box_label;          /* label for the Widget Builder main box */
   Widget box2_label;         /* label for the Widget Builder main box */
   extern Widget userArea;

   /* Set up new widget actions */
   /* ------------------------- */
   if (actions_added == 0)
     { XtAddActions(action_list, num_actions);
       actions_added = 1;

       /* Set the cursor to make editable things easily visible */
       /* ----------------------------------------------------- */
       the_display = XtDisplay(parent);     /* first get the display */
       the_cursor = XCreateFontCursor(the_display, XC_hand2);
       the_other_cursor = XCreateFontCursor(the_display, XC_star);
     };

   /* Create user's work area */
   /* ----------------------- */
   userArea = XtCreateWidget("WB User Area", formWidgetClass, parent,
			       userArea_arg_list,
			       XtNumber(userArea_arg_list));

   /* Create a minimum width & height by using a blank form */
   /* ----------------------------------------------------- */
   minsize_userArea = XtCreateManagedWidget("MinSize User Area",
			       labelWidgetClass, userArea,
			       minsize_userArea_arg_list,
			       XtNumber(minsize_userArea_arg_list));

   XtManageChild(userArea);

   /* Set up defaults for later. Used when saving C code to file. */
   /* Useful as an optimization hack.                             */
   /* ----------------------------------------------------------- */
   load_widget_defaults_from(userArea);
   not_optimizing = FALSE;

   /* Attach Basic Functions popup menu to the userArea */
   /* ------------------------------------------------- */
   make_mailer_buttons(
     make_saveCcode_buttons(make_edit_menu(
			  menu_invoker, parent_of_menu_invoker,
     		          widget_builder_options, "Widget Builder")));


   /* Set flags for types of widgets used, applications shell & user area */
   /* ------------------------------------------------------------------- */
   widgetsUsed.shell = TRUE;
   widgetsUsed.box  = TRUE;

   return(userArea);

 };        /* end of WBcreate_wb() */

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