#include "ArgPack.h"
#include "rem.h"
#include "Mintrins.h"
#include "RMFBuffer.h"
#include "al.h"
#include "alfonts.h"
#include "alxms.h"
#include "assert.h"
#include "debug.h"
#include "memory.h"
#include "menupackP.h"
#include "registry.h"
#include "sysdep.h"
#include "useful.h"
#include "xstuff.h"
#include <X11/Shell.h>
#include <Xm/CascadeBG.h>
#include <Xm/Command.h>
#include <Xm/Label.h>
#include <Xm/LabelG.h>
#include <Xm/MenuShell.h>
#include <Xm/PushBG.h>
#include <Xm/RowColumn.h>
#include <Xm/SeparatoG.h>

/*+++++++ FILE FUNCTIONS +++++++*/
char * MakeMenuMgrName();

/*-------------------*/
MenuPack MenuPack_create_popup(w, menuName)
Widget w;
char *menuName;
{
  MenuPack cp;
  char mppadd[30];
  cp=(MenuPack)Memory_allocate(sizeof(struct MenuPack_str));
  cp->parentW=w;
  cp->menuName=(char *)Memory_allocate(strlen(menuName)+1);
  strcpy(cp->menuName,menuName);  /* this will not be freed because it will */
  cp->MenuPane=NULL;
  cp->MList=Darray_create();
  cp->Instantiated=Bool_FALSE;
  cp->Flags=MP_POPUP;
  sprintf(mppadd,"%x",cp);
  cp->MyAddress=strcpy(Memory_allocate(strlen(mppadd)+1),mppadd);
  cp->Strings=Alxms_create_registry();
  cp->optionName=NULL;
  cp->OptionRCArgs=NULL;
  cp->DefaultW=NULL;
  return(cp);                     /*       be used by the widgets           */
}
/*-------------------*/
MenuPack MenuPack_create_cascade(w, menuName)
Widget w;
char *menuName;
{
  MenuPack cp;
  char mppadd[30];
  cp=(MenuPack)Memory_allocate(sizeof(struct MenuPack_str));
  cp->parentW=w;
  cp->menuName=(char *)Memory_allocate(strlen(menuName)+1);
  strcpy(cp->menuName,menuName);  /* this will not be freed because it will */
  cp->MenuPane=NULL;
  cp->MList=Darray_create();
  cp->Instantiated=Bool_FALSE;
  cp->Flags=MP_SUBMENU;
  cp->MyAddress=NULL;
  cp->Strings=Alxms_create_registry();
  cp->optionName=NULL;
  cp->OptionRCArgs=NULL;
  cp->DefaultW=NULL;
  cp->shadow=(-1); cp->highlight=(-1);
  return(cp);                     /*       be used by the widgets           */
}
/*-------------------*/
MenuPack MenuPack_create_pulldown(menubar,cascade, menuName)
Widget menubar,cascade;
char *menuName;
{
  MenuPack cp;

  cp=(MenuPack)Memory_allocate(sizeof(struct MenuPack_str));
  cp->parentW=cascade;
  cp->menuName=(char *)Memory_allocate(strlen(menuName)+1);
  strcpy(cp->menuName,menuName);  /* this will not be freed because it will */
  cp->MenuPane=NULL;
  cp->MList=Darray_create();
  cp->Instantiated=Bool_FALSE;
  cp->parentMenuBar=menubar;
  cp->Flags=MP_PULLDOWN;
  cp->MyAddress=NULL;
  cp->Strings=Alxms_create_registry();
  cp->optionName=NULL;
  cp->OptionRCArgs=NULL;
  cp->DefaultW=NULL;
  cp->shadow=(-1); cp->highlight=(-1);
  return(cp);                     /*       be used by the widgets           */
}
/*-------------------*/
MenuPack MenuPack_create_option(parent, menuName, optionName)
Widget parent;
char *menuName;
char *optionName;
{
  MenuPack cp;
  char mppadd[20];

  cp=(MenuPack)Memory_allocate(sizeof(struct MenuPack_str));
  cp->parentW=parent;
  cp->menuName=(char *)Memory_allocate(strlen(menuName)+1);
  strcpy(cp->menuName,menuName);  /* this will not be freed because it will */
  cp->MenuPane=NULL;
  cp->MList=Darray_create();
  cp->Instantiated=Bool_FALSE;
  cp->parentMenuBar=NULL;
  cp->Flags=MP_OPTION;
  sprintf(mppadd,"%x",cp);
  cp->MyAddress=strcpy(Memory_allocate(strlen(mppadd)+1),mppadd);
  cp->Strings=Alxms_create_registry();
  cp->optionName=optionName;
  cp->OptionIsXmString=Bool_FALSE;
  cp->OptionRCArgs=NULL;
  cp->DefaultW=NULL;
  cp->shadow=(-1); cp->highlight=(-1);
  return(cp);                     /*       be used by the widgets           */
}
/*-------------------*/
MenuPack MenuPack_create_option_xm(parent, menuName, optionName)
     Widget parent;
     char *menuName;
     XmString optionName;
{
  MenuPack cp;
  char mppadd[20];

  cp=(MenuPack)Memory_allocate(sizeof(struct MenuPack_str));
  cp->parentW=parent;
  cp->menuName=(char *)Memory_allocate(strlen(menuName)+1);
  strcpy(cp->menuName,menuName);  /* this will not be freed because it will */
  cp->MenuPane=NULL;
  cp->MList=Darray_create();
  cp->Instantiated=Bool_FALSE;
  cp->parentMenuBar=NULL;
  cp->Flags=MP_OPTION;
  sprintf(mppadd,"%x",cp);
  cp->MyAddress=strcpy(Memory_allocate(strlen(mppadd)+1),mppadd);
  cp->Strings=Alxms_create_registry();
  cp->optionName=(char*)optionName;
  cp->OptionIsXmString=Bool_TRUE;
  cp->OptionRCArgs=NULL;
  cp->DefaultW=NULL;
  cp->shadow=(-1); cp->highlight=(-1);
  return(cp);                     /*       be used by the widgets           */
}
/*-------------------*/
MenuPack MenuPack_create_menupane(parent, menuName)
Widget parent;
char *menuName;
{
  MenuPack cp;
  char mppadd[20];

  cp=(MenuPack)Memory_allocate(sizeof(struct MenuPack_str));
  cp->parentW=parent;
  cp->menuName=(char *)Memory_allocate(strlen(menuName)+1);
  strcpy(cp->menuName,menuName); 
  cp->MenuPane=NULL;
  cp->MList=Darray_create();
  cp->Instantiated=Bool_FALSE;
  cp->parentMenuBar=NULL;
  cp->Flags=MP_MENUPANE;
  sprintf(mppadd,"%x",cp);
  cp->MyAddress=strcpy(Memory_allocate(strlen(mppadd)+1),mppadd);
  cp->Strings=Alxms_create_registry();
  cp->optionName=NULL;
  cp->OptionRCArgs=NULL;
  cp->DefaultW=NULL;
  cp->shadow=(-1); cp->highlight=(-1);
  return(cp);                    
}

/*-----------------------*/
void MenuPack_attach_to_widget(mp,w)
MenuPack mp;
Widget w;
{
  if (mp->Instantiated==Bool_TRUE)
    Al_fatal_error1("menupack: attempt to attach menu %s to 2 when its already created.\n", 
		    mp->menuName);
  else
    mp->parentW=w;
}
/*----------------*/
void MenuPack_destroy(m)
MenuPack m;
{
  MenuPackRec mpRec;
  unsigned i;
  if (m==NULL) return;
  for (i=0;i<Darray_len(m->MList);i++) {
    mpRec=(MenuPackRec)Darray_get(m->MList,i);
    if (mpRec->IsWidget==1 && mpRec->sub_menu!=NULL)
      MenuPack_destroy(mpRec->sub_menu);
    Memory_free(mpRec->name);
    Memory_free(mpRec);
  }
  Memory_free(m->menuName);
  Memory_free(m->MyAddress);
  Alxms_destroy_all(m->Strings);
  Darray_destroy(m->MList);
  if (m->OptionRCArgs!=NULL)
    ArgPack_delete(m->OptionRCArgs);
  Memory_free(m);
}

/*----------------------*/
MenuPackRec MenuPack_create_rec(name,CB,data)
char *name;
XtCallbackProc CB;
caddr_t data;
{
  MenuPackRec mpr;
  mpr=(MenuPackRec)Memory_allocate(sizeof(struct MenuPackRec_str));
  if (name==NULL)
      Al_fatal_error("MenuPack: create record: must have either a name or a label\n");
  mpr->name=(char *)Memory_allocate(strlen(name)+1);
  strcpy(mpr->name,name); /* not be deleted because Widgets will use it */
  mpr->callback=CB;
  mpr->callback_data=data;
  mpr->IsWidget=(-1);
  mpr->InstanceW=NULL;
  mpr->sub_menu=NULL;
  mpr->Resources=ArgPack_create();
  mpr->Default=Bool_FALSE;
  mpr->Separator=Bool_FALSE;
  return(mpr);
}

/*----------------------*/
void MenuPack_add_separator(menu,ap)
     MenuPack menu;
     ArgPack ap;
{
  MenuPackRec mpRec;
  mpRec=MenuPack_create_rec("",NULL,NULL);
  mpRec->IsWidget=1;
  mpRec->sub_menu=NULL;
  mpRec->Separator=Bool_TRUE;
  if (ap!=NULL)
    ArgPack_copy_and_append(mpRec->Resources,ap);
  Darray_addh(menu->MList,mpRec);
}

/*----------------------*/
void MenuPack_add_option(name,mpp,CB,data,ap)
char *name;
MenuPack mpp;
XtCallbackProc CB;
caddr_t data;
ArgPack ap;
{
  MenuPackRec mpRec;
  mpRec=MenuPack_create_rec(name,CB,data);
  mpRec->IsWidget=1;
  mpRec->sub_menu=NULL;
  if (ap!=NULL)
    ArgPack_copy_and_append(mpRec->Resources,ap);
  Darray_addh(mpp->MList,mpRec);
}
  
/*--------------------------------*/
void MenuPack_add_sub_menu(name,mpp,SubMenu)
char *name;
MenuPack mpp, SubMenu;
{
  MenuPackRec mpRec;
  if (SubMenu->Flags & MP_SUBMENU) {
    mpRec=MenuPack_create_rec(name,NULL,NULL);
    mpRec->IsWidget=0;
    mpRec->sub_menu=SubMenu;
    Darray_addh(mpp->MList,mpRec);
  }
  else {
    Al_fatal_error2("menupack: add_sub_menu: child of wrong type. Parent is %s Child is %s\n",mpp->menuName,SubMenu->menuName);
  }
}



static Arg MenuShellArgs[]= {
  { XmNshellUnitType, (XtArgVal) Xm100TH_MILLIMETERS },
  { NULL, (XtArgVal) NULL },
};

Arg MenuRCArgs[]={
  { XmNunitType, (XtArgVal) Xm100TH_MILLIMETERS },
  { XmNpacking, (XtArgVal) XmPACK_TIGHT },
  { XmNorientation, (XtArgVal) XmVERTICAL }, 
  { XmNadjustMargin, (XtArgVal) FALSE },
  { XmNisHomogeneous, (XtArgVal) FALSE },
  { NULL, (XtArgVal) NULL },
};

Arg MenuButtonArgs[]={
  { XmNunitType, (XtArgVal) Xm100TH_MILLIMETERS },
  { XmNlabelType, (XtArgVal) XmSTRING },
  { NULL, (XtArgVal) NULL },
};

Arg CascadeOnArgs[]={
  { XmNunitType, (XtArgVal) Xm100TH_MILLIMETERS },
  { NULL, NULL },
};

/*----------------------*/
void FormMenu(mpp,TopMenuPane)
MenuPack mpp;
Widget TopMenuPane;
{
  Widget SubMenuCascadeW, PopShell2W;
  MenuPackRec mpRec;
  MenuPack SubMpp;
  unsigned i,l;
  ArgPack AP;
 
  l=Darray_len(mpp->MList);
  for (i=0;i<l;i++) {
    mpRec=(MenuPackRec)Darray_get(mpp->MList,i);

    if (mpRec->Separator==Bool_TRUE) {
      AP=ArgPack_create();
      ArgPack_add_arg(AP,XmNunitType, (XtArgVal) Xm100TH_MILLIMETERS );
      if (mpRec->Resources!=NULL)
	AP=ArgPack_copy_and_append(AP,mpRec->Resources);
      mpRec->InstanceW=XmCreateSeparatorGadget(mpp->MenuPane,
					       "menupack-separator",
					       ArgPack_the_args(AP), 
					       ArgPack_num_args(AP));
      XtManageChild(mpRec->InstanceW);
    }
      
    else if (mpRec->IsWidget==1) {
      AP=ArgPack_duplicate_args(MenuButtonArgs);
      ArgPack_add_arg(AP,XmNlabelString, (XtArgVal)
		      Alxms_create(mpp->Strings,
				   mpRec->name,
				   (char*)XmSTRING_DEFAULT_CHARSET));
      AP=ArgPack_copy_and_append(AP,mpRec->Resources);
      if (mpp->shadow!=(-1))
	ArgPack_add_arg(AP,XmNshadowThickness, (XtArgVal) mpp->shadow);
      if (mpp->highlight!=(-1))
	ArgPack_add_arg(AP,XmNhighlightThickness, (XtArgVal) mpp->highlight);
      ArgPack_add_arg(AP,XmNfontList, (XtArgVal)  
		      AlFonts_get_specific_fonts(mpp->MenuPane, 
						 ALFONTS_TEXT_MASK));
      mpRec->InstanceW=XtCreateManagedWidget(mpRec->name,
					     xmPushButtonGadgetClass,
					     mpp->MenuPane,
					     ArgPack_the_args(AP), 
					     ArgPack_num_args(AP));
      if (mpRec->callback!=NULL)
	XtAddCallback(mpRec->InstanceW,
		      XmNactivateCallback,
		      mpRec->callback,
		      mpRec->callback_data);
      if (mpRec->Default==Bool_TRUE) {
	if (!(mpp->Flags & MP_OPTION))
	  Alxt_ReverseVideo(mpRec->InstanceW);
	mpp->DefaultW=mpRec->InstanceW;
      }
      ArgPack_delete(AP);
    }
    else {
      if (mpRec->sub_menu==NULL)  assert(0);
      AP=ArgPack_create();
      ArgPack_add_arg(AP,XmNunitType, (XtArgVal) Xm100TH_MILLIMETERS);
      mpRec->sub_menu->MenuPane=XmCreatePulldownMenu(TopMenuPane,
						     mpp->menuName,
						     ArgPack_the_args(AP), 
						     ArgPack_num_args(AP));
      ArgPack_delete(AP);

      AP=ArgPack_duplicate_args(MenuButtonArgs);
      ArgPack_add_arg(AP,XmNlabelString, (XtArgVal) 
		      Alxms_create(mpp->Strings,
				   mpRec->name,
				   (char*)XmSTRING_DEFAULT_CHARSET));
      ArgPack_add_arg(AP,XmNsubMenuId, (XtArgVal) mpRec->sub_menu->MenuPane);
      if (mpp->shadow!=(-1))
	ArgPack_add_arg(AP,XmNshadowThickness, (XtArgVal) mpp->shadow);
      if (mpp->highlight!=(-1))
	ArgPack_add_arg(AP,XmNhighlightThickness, (XtArgVal) mpp->highlight);
      AP=ArgPack_copy_and_append(AP,mpRec->Resources);
      ArgPack_add_arg(AP,XmNfontList, (XtArgVal)  
		      AlFonts_get_specific_fonts(mpp->MenuPane, 
						 ALFONTS_TEXT_MASK));
      mpRec->InstanceW=XtCreateManagedWidget(mpRec->name,
					     xmCascadeButtonGadgetClass,
					     mpp->MenuPane,
					     ArgPack_the_args(AP), 
					     ArgPack_num_args(AP));
      if (mpRec->Default==Bool_TRUE) {
	if (!(mpp->Flags & MP_OPTION))
	  Alxt_ReverseVideo(mpRec->InstanceW);
	mpp->DefaultW=mpRec->InstanceW;
      }
      ArgPack_delete(AP);
      FormMenu(mpRec->sub_menu,TopMenuPane);
    }
  }
}

/*--------------------------------------------------*/
void MenuPost(w,xe,parms,nps)
Widget w;
XEvent *xe;
char **parms;
int    *nps;
{
  MenuPack mpp;
  XButtonPressedEvent*  bpe=(XButtonPressedEvent*)xe;
   /** !!! Make sure that this type of event matches the event defined by **/
   /** AL_MENU_POST !!!                                                   **/
  if (*nps<1)
    Al_fatal_error("MenuPost: called without one parameter\n");
  mpp=(MenuPack)AlMonitor_get_obj_from_string(parms[0]);
  assert(mpp);
  Alxt_SetArg(mpp->MenuPane,XmNx,(XtArgVal)bpe->x_root);
  Alxt_SetArg(mpp->MenuPane,XmNy,(XtArgVal)bpe->y_root);
  XtManageChild(mpp->MenuPane);
}


/*--------------------------------------------------*/
void AddCursorToTop(w,xe,parms,nps)
Widget w;
XEvent *xe;
char **parms;
int    *nps;
{
  static int Inited=0;
  static Registry AccountedFor;
  if (Inited==0) {
    Inited=1;
    AccountedFor=Registry_create(Registry_ptrcmp,Registry_ptrhash);
  }
  if (Registry_get(AccountedFor,w)==NULL) {
    AlUI_AttachCursor(w,MENU_BUTTON_CURSOR);
    Registry_add(AccountedFor,(VOIDP)w,(VOIDP)0xffff);
  }
}

static XtActionsRec MenuActions[] = {
  { "AddCursorToTop", AddCursorToTop },
  { "MenuPost", MenuPost }, 
};

#define AL_MENU_POST "<Btn2Down>"

static char * MenuTranslations = 
  "<Enter>: AddCursorToTop()\n\
   <Btn2Down>: MenuPost(";


/*--------------------------*/
void MenuPack_make_menu(mpp)
MenuPack mpp;
{
  ArgPack AP;
  static int AddedActions=0;

  assert(mpp->parentW);
  assert(mpp->Flags & ( MP_POPUP | MP_PULLDOWN | MP_OPTION) | MP_MENUPANE );
  if (mpp->Flags & MP_POPUP) {
    RMFBuffer B;
    if (AddedActions==0) {
      AddedActions=1;
      XtAddActions(MenuActions,2);
    }
    B=RMFBuffer_create(MenuTranslations,20);
    RMFBuffer_append(B,mpp->MyAddress);
    RMFBuffer_append_char(B,')');
    XtOverrideTranslations(mpp->parentW,
			   XtParseTranslationTable(RMFBuffer_copy_of_buff(B)));
    AlMonitor_register_address(mpp,mpp->MyAddress); 
    RMFBuffer_destroy(B);

    AP=ArgPack_duplicate_args(MenuRCArgs);
    mpp->MenuPane=XmCreatePopupMenu(mpp->parentW,
				    mpp->menuName,
				    ArgPack_the_args(AP),
				    ArgPack_num_args(AP));
    ArgPack_delete(AP);
  }
  else if (mpp->Flags & (MP_OPTION | MP_MENUPANE)) {
    AP=ArgPack_duplicate_args(MenuRCArgs);
    mpp->MenuPane=XmCreatePulldownMenu(mpp->parentW,
				       mpp->menuName,
				       ArgPack_the_args(AP),
				       ArgPack_num_args(AP));
    ArgPack_delete(AP);
  }
  else if (mpp->Flags & MP_PULLDOWN) {
    AP=ArgPack_duplicate_args(MenuRCArgs);
    mpp->MenuPane=XmCreatePulldownMenu(mpp->parentMenuBar,
				       mpp->menuName,
				       ArgPack_the_args(AP),
				       ArgPack_num_args(AP));
    ArgPack_delete(AP);
    /* check that parent is a cascade button in this case */
    Alxt_SetArg(mpp->parentW,XmNsubMenuId,(XtArgVal)mpp->MenuPane);
  }
  else
    Al_fatal_error("menupack_make_menu: invalid menu type\n");
  
  FormMenu(mpp,mpp->MenuPane);
  mpp->Instantiated=Bool_TRUE;
  
  if (mpp->Flags & MP_OPTION) {
    AP=ArgPack_create();
    if (mpp->OptionRCArgs!=NULL)
      AP=ArgPack_copy_and_append(AP,mpp->OptionRCArgs);
    ArgPack_add_arg(AP,XmNsubMenuId,(XtArgVal)mpp->MenuPane);
    ArgPack_add_arg(AP,XmNfontList,(XtArgVal)AlFonts_get(mpp->MenuPane));
    if (mpp->OptionIsXmString==Bool_FALSE)
      ArgPack_add_arg(AP,XmNlabelString,(XtArgVal)Alxms_create(mpp->Strings,
							       mpp->optionName,
						     ALFONTS_MINOR_HEADING));
    else
      ArgPack_add_arg(AP,XmNlabelString,(XtArgVal) mpp->optionName );

    mpp->OptionW=XmCreateOptionMenu(mpp->parentW,
				    mpp->menuName,
				    ArgPack_the_args(AP),
				    ArgPack_num_args(AP));
    XtManageChild(mpp->OptionW);
    if (mpp->DefaultW!=NULL)
      Alxt_SetArg(mpp->OptionW,XmNmenuHistory, (XtArgVal) mpp->DefaultW);
    ArgPack_delete(AP);
  }
}

/*---------------------*/
Widget MenuPack_get_widget(tmp,name)
     MenuPack tmp;
     char *name;
{
  unsigned i;
  MenuPackRec mpr;
  Widget W;

  if (strcmp(name,tmp->menuName)==0)
    return (MenuPack_get_top_level_manager(tmp));
  for (i=0;i<Darray_len(tmp->MList);i++) {
    mpr=(MenuPackRec)Darray_get(tmp->MList,i);
    if (strcmp(name,mpr->name)==0)
      return(mpr->InstanceW);
    if (mpr->IsWidget==0) {
      if ((W=MenuPack_get_widget(mpr->sub_menu,name))!=NULL)
	return(W);
    }
  }
  return(NULL);
}

/*---------------------*/
MenuPackRec MenuPack_get_option(tmp,name)
MenuPack tmp;
char *name;
{
  unsigned i;
  MenuPackRec mpr,mpr2;

  if (strcmp(name,tmp->menuName)==0)
    return(NULL);
  for (i=0;i<Darray_len(tmp->MList);i++) {
    mpr=(MenuPackRec)Darray_get(tmp->MList,i);
    if (strcmp(name,mpr->name)==0)
      return(mpr);
    if (mpr->IsWidget==0) {
      if ((mpr2=MenuPack_get_option(mpr->sub_menu,name))!=NULL)
	return(mpr2);
    }
  }
  return(NULL);
}
      

  
  
/*--------------------------------------------------*/
Widget MenuPack_get_top_level_manager(mp)
MenuPack mp;
{
  if (mp->Flags & MP_OPTION)
    return(mp->OptionW);
  else
    return(mp->MenuPane);
}

/*--------------------------------------------------*/
NORET    MenuPack_add_arg_to_all(mp,arg,val)
MenuPack mp;
char* arg;
XtArgVal val;
{
  unsigned i;
  MenuPackRec mpr;
  
  for (i=0;i<Darray_len(mp->MList);i++) {
    mpr=(MenuPackRec)Darray_get(mp->MList,i);
    if (mpr->IsWidget==1) 
      Alxt_SetArg(mpr->InstanceW,arg,val);
    else
      MenuPack_add_arg_to_all(mpr->sub_menu,arg,val);
  }
}
/*--------------------------------------------------*/
void MenuPack_do_nothing(w,xe,p,c)
Widget w;
XEvent *xe;
char*p;
Cardinal *c;
{
}

static XtActionsRec MPDoNothingActions[]={
  {"MenuPack_do_nothing", MenuPack_do_nothing}
};

static String MenuPackDoNothingTT =
  "<Btn1Down>:MenuPack_do_nothing()";
/*--------------------------------------------------*/
NORET MenuPack_detach_menu(mp)
     MenuPack mp;
{
  XtAddActions(MPDoNothingActions,1);
  XtOverrideTranslations(mp->parentW,
			 XtParseTranslationTable(MenuPackDoNothingTT));
}

/*
NORET MenuPack_reattach_menu(mp)
     MenuPack mp;
{
  assert(mp);
  Alxt_SetArg(mp->PopMgrW,XtNmenuPost, (XtArgVal) AL_MENU_POST);
}

*/

/*--------------------------------------------------*/
Bool MenuPack_set_feature(mpp,item_name,arg,argval)
MenuPack mpp;
char* item_name;
char* arg;
XtArgVal argval;
{
  MenuPackRec mpr;
  mpr=MenuPack_get_option(mpp,item_name);
  if (mpr==NULL) {  /* !!! this warning should be changed to a debug option */
    Al_warning2("menupack: set_feature: attempt to set option %s in %s when option does not exist.\n",item_name,mpp->menuName);
    return(Bool_FALSE);
  }
  if (mpp->Instantiated==Bool_TRUE) {
    Alxt_SetArg(mpr->InstanceW,arg,argval);
    return(Bool_TRUE);
  }
  else {
    ArgPack_add_arg(mpr->Resources,arg,argval);
    return(Bool_TRUE);
  }
}


/*--------------------------------------------------*/
Bool Alxt_set_menu_item_with_arg(mp,item_name,arg,value)
MenuPack mp;
char *item_name, *arg;
XtArgVal value;
{
  Widget SW;
				  
  if ((SW=MenuPack_get_widget(mp,item_name))!=NULL) {
    Alxt_SetArg(SW,arg,value);
    return(Bool_TRUE);
  }
  else
    return(Bool_FALSE);
}

/*--------------------------------------------------*/
NORET MenuPack_set_as_default(mp,name)
MenuPack mp;
char* name;
{
  Pixel fgv;
  Widget w;
  MenuPackRec mprec;
  w=MenuPack_get_widget(mp,name);

  mprec=MenuPack_get_option(mp,name);
  mprec->Default=Bool_TRUE;
  if (mp->Instantiated==Bool_TRUE) {
    if (w==NULL) return;
    if (mp->Flags & MP_OPTION)
      Alxt_SetArg(mp->OptionW,XmNmenuHistory, (XtArgVal) w);
    else
      Alxt_ReverseVideo(w);
  }
}


/*--------------------------------------------------*/
NORET MenuPack_unset_as_default(mp,name)
MenuPack mp;
char* name;
{
  Pixel fgv;
  Widget w;
  MenuPackRec mprec;
  w=MenuPack_get_widget(mp,name);

  mprec=MenuPack_get_option(mp,name);
  mprec->Default=Bool_FALSE;
  if (mp->Instantiated==Bool_TRUE) {
    if (w==NULL) return;
    if (!(mp->Flags & MP_OPTION))
      Alxt_NormalVideo(w,mp->parentW);
  }
}

/*--------------------------------------------------------*/
Widget MenuPack_option_get_label(mpp)
MenuPack mpp;
{
  extern Widget XmOptionLabelGadget();
  if (!(mpp->Flags & MP_OPTION))
    Al_fatal_error("menupack: attempt to get label widget from non option menu\n");
  if (mpp->Instantiated==Bool_TRUE)
    return(XmOptionLabelGadget(mpp->OptionW));
  else
    return(NULL);
}

/*--------------------------------------------------------*/
Widget MenuPack_option_get_button(mpp)
MenuPack mpp;
{
  extern Widget XmOptionButtonGadget();
  if (!(mpp->Flags & MP_OPTION))
    Al_fatal_error("menupack: attempt to get button widget from non option menu\n");
  if (mpp->Instantiated==Bool_TRUE)
    return(XmOptionButtonGadget(mpp->OptionW));
  else
    return(NULL);
}

/*--------------------------------------------------*/
NORET MenuPack_option_set_args(mpp,args)
MenuPack mpp;
ArgPack args;
{
  RE_debug1("option set args on menu  %s\n",mpp->menuName);
  RE_debug2("mpp=%d rela=%d\n",mpp->Flags, MP_OPTION);
  if (!(mpp->Flags & MP_OPTION)) {
    Al_warning("menupack: attempt to set args from non option menu\n");
    assert(0);
  }
  if (mpp->OptionRCArgs==NULL)
    mpp->OptionRCArgs=ArgPack_create();
  mpp->OptionRCArgs=ArgPack_copy_and_append(mpp->OptionRCArgs,args);
}

/*--------------------------------------------------*/
Widget MenuPack_get_menupane(mp)
     MenuPack mp;
{
  return(mp->MenuPane);
}

/*--------------------------------------------------*/
NORET MenuPack_set_shadow(menu,s)
     MenuPack menu;
     int s;
{
  menu->shadow=s;
}
/*--------------------------------------------------*/
NORET MenuPack_set_highlight(menu,s)
     MenuPack menu;
     int s;
{
  menu->highlight=s;
}

/*======================================================================*/
/* backweard compatibility functions */

/*--------------------------------------------------*/
Widget MenuPack_get_top_level_shellW(mp)
MenuPack mp;
{
  if (mp->Flags & MP_OPTION)
    return(mp->OptionW);
  else
    return(mp->MenuPane);
}

