/*
 * as_menuh.c:  procedures for creating menus recursively

 * (C) COPYRIGHT A. Stochniol, 1991 - 1992
 * All Rights Reserved
 *
 * Author:
 * Dr. Andrzej Stochniol
 * Department of Mechanical Engineering
 * Imperial College of Science, Technology and Medicine
 * London, SW7 2BX, UK
 *
 *    E-mail:  A.Stochniol@ic.ac.uk
 *
 *
 * History:
	Full version of a menu procedure (with accelerators) & help callbacks
	(this version is different from my standard as_menuf.c in
	supporting an additional field in as_menuh_struct - help callback)
	International names of menu entries ....
	29.10.1991 - created button widgets are added
		to the as_menuf_struct  structure
	2.11.1991  - memory allocated for label strings is freed
	11.11.1991 - recommended margin introduced ...
	12.11.1991 - recommended margin was moved to the resource file
		all lines used previously inside the code to set the margin
		are commented with **res** text; instead the resource
		file should contain something as follow:
		 asedit*XmRowColumn*XmPushbutton.marginWidth:     8
		 asedit*XmRowColumn*XmLabel.marginWidth:          8
		 asedit*XmRowColumn*XmCascadeButton.marginWidth:  8
	06.04.1992 - as_menuf_struct is replaced by as_menuh_struct that
		includes additionally a name of a help callback; the data
		passed to the callback is 'data'
	14.10.1992 - we set a name for a menu shell created by a call
		to XmCreatePullDownMenu that consists of the cascade
		button and a "_PullDown" suffix (this is to be able
		to recognize different pulldown menus with resources,
		if needed)
	26.10.1992 - support for non ANSI C (forced by port to SUN stations,
		where the standard C compiler do not support ANSI style
		prototypes); conditional compilation with _NO_PROTO symbol.
 *
 */

#ifdef AMIGA
#include "amiga.h"
#endif

#include <stdio.h>		/* for fprintf and stderr definition ... */
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>
#include <Xm/Xm.h>
#include <Xm/Separator.h>
#include <Xm/PushB.h>
/***  needed when toggle buttons are used  .... #include <Xm/ToggleB.h> **/
#include <Xm/CascadeB.h>
#include <Xm/RowColumn.h>
#include <Xm/Label.h>

#include "asedit.h"


#ifdef _NO_PROTO
void as_create_menuh(title, menu, menulist, nitems, charset)
char *title;
Widget menu;
as_menuh_struct *menulist;
int nitems;
XmStringCharSet charset;
#else  /* _NO_PROTO */
void as_create_menuh(char *title, Widget menu, as_menuh_struct *menulist, int nitems,
		XmStringCharSet charset)
#endif
{
  Arg        wargs[10];
  int        i, n=0;
  WidgetList buttons;
  int        separators = 0;
  XmString   label_string;
  char	     pull_down_name[40];	/* to construct ..._PullDown strings */

  /**res** int 	     recommended_margin=8;  **res**/	/* margin for buttons etc. recommended
					   for their nice look; for separators default
					   0 margin is used */


  /* Allocate a widget list to hold all button widgets. */
  buttons = (WidgetList) XtMalloc(nitems * sizeof(Widget));

  /* If a title is given, create Label and Separator widgets. */
  if(title)
  {
    n = 0;
    /**res** XtSetArg(wargs[n], XmNmarginWidth, recommended_margin); n++; **/
    XtCreateManagedWidget(title, xmLabelWidgetClass, menu, wargs, n);

    n = 0;
    XtCreateManagedWidget("separator", xmSeparatorWidgetClass, menu, wargs, n);
  }

  /* Create an entry for each item in the menu. */
  for(i=0; i<nitems; i++)
  {
   if(menulist[i].name == NULL)	  /* A NULL name represents a separator.*/
   {
     n = 0;
     XtCreateManagedWidget("separator", xmSeparatorWidgetClass, menu, wargs, n);
     separators++; 		/* Count how many entries aren't buttons */
   }

   /* If there is a name and a callback, create a "normal"
    * menu entry and register the callback function.
    */
   else if(menulist[i].func)
   {
     n=0;
     label_string = XmStringCreateLtoR(menulist[i].name, charset);
     XtSetArg(wargs[n], XmNlabelString, label_string ); n++;

     if(menulist[i].mnemonic) { XtSetArg(wargs[n],XmNmnemonic,menulist[i].mnemonic); n++; }

     if(menulist[i].acceleratorText)
     {
	 XtSetArg(wargs[n], XmNacceleratorText,
		 XmStringCreateLtoR(menulist[i].acceleratorText, charset)); n++;
#ifdef _AS_DEBUG
	 /* check during debugging if for the accelerator text in the menu the
		appropriate accelerator was defined (be warry that sometimes
		accelerators need not to be defined, e.g. for "Del" for Text widget;
		at such	case ignore the warning during debugging) */
	 if(menulist[i].accelerator == NULL)
	 {
		fprintf(stderr,"_AS_DEBUG WARNING in as_create_menuh: for '%s' accelerator text  \n",
			menulist[i].acceleratorText,
			"   the appropriate accelerator was not defined (now is equal to NULL) ! \n");
	 }
#endif
     }

     if(menulist[i].accelerator) { XtSetArg(wargs[n], XmNaccelerator,
					menulist[i].accelerator); n++; }
     /***res** XtSetArg(wargs[n], XmNmarginWidth, recommended_margin); n++; ***/

     /* try set callback during creation of the push button */

     if( menulist[i].helpCB )
     {
	XtSetArg(wargs[n], XmNhelpCallback,
		   menulist[i].helpCB);    n++;
     }
     buttons[i-separators] = XmCreatePushButton (menu, menulist[i].name,
				      wargs, n);
     XtAddCallback(buttons[i-separators], XmNactivateCallback,
		   menulist[i].func, menulist[i].data); 

     /* because XmString is copied into an internal area by the label widget
     we can free the storage associated with the string by calling XmStringFree
     (after XtCreateManagedWidget or XtSetValues are finished) */
     XmStringFree(label_string);

     if( menulist[i].helpCB )
	XtAddCallback(buttons[i-separators], XmNhelpCallback,
		   menulist[i].helpCB, menulist[i].data);

   }
   /*
    * If there is a name, but no callback function, the entry
    * must be a label, unless there is a submenu.
    */
   else if(!menulist[i].sub_menu)
   {
     n = 0;
     /**res** XtSetArg(wargs[n], XmNmarginWidth, recommended_margin); n++; ***/
     buttons[i-separators] = XtCreateWidget(menulist[i].name,
					   xmLabelWidgetClass,
					   menu, wargs, n);
   }
   /*
    * If we got here, the entry must be a submenu.
    * Create a pulldown menu pane and an XmCascadeButton
    * widget. Attach the menu pane and make a recursive call
    * to create the entries in the submenu.
    */
   else
   {
    Widget sub_menu;

    /*  old (the name of the pull down menu was never set if sub_menu_title
	was not	specified, which is the usual situation)
	    sub_menu =XmCreatePulldownMenu(menu,
				   menulist[i].sub_menu_title,
				   NULL, 0);
    ***OLD  (before 14.10.1992)  */

    /* first construct a name for the pull down widget (practically menu shell widget) */

    strcpy(pull_down_name, menulist[i].name);
    strcat(pull_down_name,"_PullDown");

    sub_menu =XmCreatePulldownMenu(menu,
				   pull_down_name,
				   NULL, 0);

    n=0;
    XtSetArg(wargs[n], XmNsubMenuId, sub_menu); n++;
    label_string = XmStringCreateLtoR(menulist[i].name, charset);
    XtSetArg(wargs[n], XmNlabelString, label_string ); n++;
    if(menulist[i].mnemonic) { XtSetArg(wargs[n],XmNmnemonic,menulist[i].mnemonic); n++; }

    if(menulist[i].acceleratorText)
    {
	 XtSetArg(wargs[n], XmNacceleratorText,
		 XmStringCreateLtoR(menulist[i].acceleratorText, charset)); n++;
#ifdef _AS_DEBUG
	 /* check during debugging if for the accelerator text in the menu the
		appropriate accelerator was defined (be warry that sometimes
		accelerators need not to be defined, e.g. for "Del" for Text widget;
		at such	case ignore the warning during debugging) */
	 if(menulist[i].accelerator == NULL)
	 {
		fprintf(stderr,"_AS_DEBUG WARNING in as_create_menuh: for '%s' accelerator text  \n",
			menulist[i].acceleratorText,
			"   the appropriate accelerator was not defined (now is equal to NULL) ! \n");
	 }
#endif
    }

    if(menulist[i].accelerator) { XtSetArg(wargs[n], XmNaccelerator,
					menulist[i].accelerator); n++; }
    /**res** XtSetArg(wargs[n], XmNmarginWidth, recommended_margin); n++; ***/

    buttons[i-separators] = XmCreateCascadeButton (menu,
				 menulist[i].name, wargs, n);
    XmStringFree(label_string);

    /* install a help callback if specified */
     if( menulist[i].helpCB )
	XtAddCallback(buttons[i-separators], XmNhelpCallback,
		   menulist[i].helpCB, menulist[i].data);



    as_create_menuh(menulist[i].sub_menu_title,
			  sub_menu, menulist[i].sub_menu,
			  menulist[i].n_sub_items, charset);
   }
   /* put the address of a created button widget into menulist[i]  */
   if(menulist[i].name != NULL)
   { 	/* O.K., otherwise a separator element has been created .... */
	menulist[i].w = buttons[i-separators];
   }

  }


  /*
   * Manage all button widgets. Menu panes are not managed.
   */
  XtManageChildren(buttons, nitems - separators);

} /* as_create_menuh */
