#include "assert.h"   /* must be first for use eith hc2 */
#include "ed.h"
#include "d2.h"
#include "d2args.h"
#include "rl.h"
#include "ru.h"
#include "assert.h"
#include "ruleset.h"
#include "RSreg.h"
#include "al.h"
#include "rs.h"
#include "verbrgy.h"
#include "MsgType.h"
#include "MTreg.h"
#include "FieldCore.h"
#include "FieldType.h"
#include "useful.h"
#include "ArgPack.h"
#include "bool.h"
#include "rem.h"
#include "childpack.h"
#include "a1client.h"
#include "memory.h"
#include "xstuff.h"
#include "rebox.h"
#include "repop.h"
#include "alfonts.h"
#include "alpop.h"
#include "text.h"
#include "RMFBuffer.h"
#include "darrayP.h"  /* experimental */
#include "menupack.h"
#include "Mu.h"

NORET ed_REMember_remake_form_without_me PROTOTYPE((reid,REMember));

#define ED_PRINTER_WARNING          "printer warning"
#define ED_PRINTER_WARNING_HELP     "printer warning help"
#define ED_PRINTER_CANT_OPEN        "printer cant open"
#define ED_PRINTER_CANT_OPEN_HELP        "printer cant open help"
#define ED_PRINTER_DONE_HELP        "printer done help"
#define ED_PRINTER_DONE             "printer done"

#define ED_ACTIONS_DELETE_W         "actions delete warning"
#define ED_ACTIONS_DELETE_W_H       "actions delete warning help"
#define ED_FIELDS_DELETE_W          "fields delete warning"
#define ED_FIELDS_DELETE_W_H        "fields delete warning help"

#define ED_VERBS_HELP_STRING        "backup help on verbs"
#define ED_QUIT_ON_MODIFY_STRING    "attempt to quit with modifications"
#define ED_QUIT_ON_MODIFY_HELP      "attempt to quit with modifications HELP"

/*--------------------------------------------------*/
void ed_Init(rei)
reid rei;
{
  rei->WidgetKillList=Darray_create();
}
  
/*--------------------------------------------------*/
NORET ed_Done_CB(w,rei,caddb)
Widget w;
reid rei;
caddr_t caddb;
{
  Darray       AlActions;
  AlRuleMember AlMember;
  AlRule       Rule;
  char* name;

  ed_ClearWidgetKillList(rei);
  AlActions=rl_TranslateActionsFromRE(rei,rei->Actions);
  AlMember=rl_TranslateFromRE(rei,rei->TopLevelMember);
  name=XmTextGetString(rei->RuleNameW);
  if (name==NULL || RapStr_is_empty(name)==Bool_TRUE)
    name="<no name>";
  Rule=AlRule_create(AlMember,AlActions,0,0,name);
  assert(Rule);
  (rei->SaveFunc)(rei,Rule,rei->UserData);
  rei->Modified=Bool_FALSE;
}

/*--------------------------------------------------*/
NORET ed_Abort_CB(w,rei,caddb)
     Widget w;
     reid rei;
     caddr_t  caddb;
{
  int ret;

  ed_ClearWidgetKillList(rei);
  if (rei->Modified==Bool_TRUE) {
    char *message;
    char *help;
    MuSetWaitCursor(rei->ShellW);
    message=AlText_get(RE_TEXT_FILE,ED_QUIT_ON_MODIFY_STRING);
    help=AlText_get(RE_TEXT_FILE,ED_QUIT_ON_MODIFY_HELP);
    ret=(int)AlPop_Query(ALPOP_QUESTION,
			 message,
			 help,
			 w,
			 ALPOP_HANG_BELOW,
			 rei->display,
			 ALPOP_OK | ALPOP_CANCEL | ALPOP_HELP);
    MuSetStandardCursor(rei->ShellW);
    if (ret==1) {
      (rei->QuitFunc)(rei,rei->UserData);
      return;
    }
    else 
      return;
  }
  else
    (rei->QuitFunc)(rei,rei->UserData);
}  

/*--------------------------------------------------*/
void ed_ClearWidgetKillList(rei)
reid rei;
{
  unsigned l1, i;
  /*
   *  destroy all widgets in kilkl list
   */
  l1=Darray_len(rei->WidgetKillList);
  if (l1!=0)  {
    for (i=0;i<l1;i++)
      XtDestroyWidget(Darray_remh(rei->WidgetKillList));
  }
}

/*--------------------------------------------------*/
void ed_AddMT_CB(w,p,cadda)
Widget w;
RapPack p;
caddr_t cadda;
{
  AlMsgType MT;
  Darray Keys=Darray_create();
  AlFieldCore FC;
  unsigned i,l;
  REMember REm;
  REField  REf;
  REMember NewTopMember; 
  char *FTN;
  const char *Key;
  char *MTN;
  reid rei;

  MTN=(char*)RapPack_get(p,0);
  rei=(reid)RapPack_get(p,1);

  if (rei->DisableEdit==Bool_TRUE) return;

  if (strcmp(MTN,MT_UNDEFINED_STRING)==0) {
    if (rei->message_type!=NULL) {
      Memory_free(rei->message_type);
      rei->message_type=NULL;
    }
    return;
  }
  
  MT=AlMTreg_get_obj_with_name(MTN);
  if (MT==NULL) {
    Al_warning1("Trying to add Message Type: %s which doesn't exist\n",MTN);
    Al_warning("  Probably because of nonexistant message type directory");
    Al_warning("  or bad path name in lens profile");
  }
  else {
    if (rei->message_type!=NULL)
      Memory_free(rei->message_type);
    rei->message_type=RapStr_duplicate(MTN);
    
    MuSetWaitCursor(rei->ShellW);
    AlMsgType_all_fields(MT,Keys);
    l=Darray_len(Keys);
    for (i=0;i<l;i++) {
      FC=(AlFieldCore)Darray_get(Keys,(unsigned)i);
      assert(FC);
      Key=AlFieldCore_get_key(FC);
      if (ed_FieldExists(rei,Key)==Bool_FALSE) {
	FTN=AlFieldCore_get_field_type_name(FC);
	if (rei->TopLevelMember!=NULL) {
	  if (rei->TopLevelMember->Type!=ALRMT_ASSOC)  {
	    NewTopMember=rl_REMember_create(ALRMT_ASSOC,
					    rl_REAssoc_create(rei,ALRAT_AND),
					    NULL);
	    rei->TopLevelMember->father=NewTopMember;
	    Darray_addh(NewTopMember->object.Assoc->Contents,rei->TopLevelMember);
	    rei->TopLevelMember=NewTopMember;
	  }
	}
	REf=rl_REField_create(rei,
			      ALRFT_MSG,
			      AlFieldCore_get_key(FC),
			      "",
			      FTN,
			      NULL,
			      REF_FROM_TEMPLATE);
	REm=rl_REMember_create(ALRMT_FIELD,REf,rei->TopLevelMember);
	if (rei->TopLevelMember==NULL)
	  rei->TopLevelMember=REm;
	d2_If_AddField(rei,REm,REF_FROM_TEMPLATE);
	rei->Modified=Bool_TRUE;
      }
    }
    if (rei->MTField==NULL) {
      REf=rl_REField_create(rei,
			    ALRFT_MSG,
			    MT_KEY_STRING,
			    MTN,
			    "Case Sensitive Text",
			    "exactly matches",
			    REF_FROM_TEMPLATE);
      REm=rl_REMember_create_at_index(ALRMT_FIELD,REf,rei->TopLevelMember,0);
      rei->MTField=REf;
      d2_If_AddField(rei,REm,REF_FROM_TEMPLATE);
    }
    else
      XmTextSetString(rei->MTField->ValueW,MTN);

    d2_Refresh_tab_groups(rei);
  }
  MuSetStandardCursor(rei->ShellW);
} 

/*--------------------------------------------------*/
Bool ed_FE(rem,key)
REMember rem;
char *key;
{
  if (rem->Type==ALRMT_ASSOC) {
    int i,l;
    REAssoc rea=rem->object.Assoc;
    l=Darray_len(rea->Contents);
    for (i=0;i<l;i++) {
      if (ed_FE((REMember)Darray_get(rea->Contents,(unsigned)i),key)
	  ==Bool_TRUE)
	return(Bool_TRUE);
    }
    return(Bool_FALSE);
  }
  else {
    if (strcmp(rem->object.Field->Key,key)==0)
      return(Bool_TRUE);
    else
      return(Bool_FALSE);
  }
}

/*--------------------------------------------------*/
Bool ed_FieldExists(rei,Key)
reid rei;
char *Key;
{
  return(ed_FE(rei->TopLevelMember,Key));
}

/*--------------------------------------------------*/
NORET ed_Destroy_all_empty_parent_boxes(rei,Parent)
reid rei;
REMember Parent;
{
  if (Parent==NULL)
    return;
  assert(Parent->Type==ALRMT_ASSOC);
  if (Darray_len(Parent->object.Assoc->Contents)==0 &&
      (Parent!=rei->TopLevelMember)) {
    REAssoc rea=Parent->object.Assoc;
    Widget PrevW, NextW, ParentW;
    rl_Get_surrounding_widgets(rei,rea->container,
			       &PrevW,&NextW,&ParentW);
    if (NextW!=NULL) {
      Alxt_SetArg(NextW,XmNtopAttachment,(XtArgVal)XmATTACH_WIDGET);
      Alxt_SetArg(NextW,XmNtopWidget,(XtArgVal)PrevW);
    }
    if (rea->ContainerW!=NULL)
      XtDestroyWidget(rea->ContainerW);
    ed_rl_Assoc_remove(rei,rea);
    ed_Destroy_all_empty_parent_boxes(rei,Parent->father);
  }
}

/*--------------------------------------------------*/
NORET ed_Assoc_clear(assoc)
     REAssoc assoc;
{
  REField field;
  REAssoc Sassoc;
  REMember member;
  reid rei=assoc->rei;
  int i,l;
  
  l=Darray_len(assoc->Contents);
  for (i=0;i<l;i++) {
    member=(REMember)Darray_remh(assoc->Contents);
    if (member->Type==ALRMT_ASSOC) {
      Sassoc=member->object.Assoc;
      ed_Assoc_clear(Sassoc);
      if (Sassoc->ContainerW!=NULL) {
	XtUnmanageChild(Sassoc->ContainerW);
	Darray_addh(rei->WidgetKillList,Sassoc->ContainerW);
      }
      ed_rl_Assoc_remove(rei,Sassoc);
    }
    else {
      field=member->object.Field;
      XtUnmanageChild(field->ContainerW);
      Darray_addh(rei->WidgetKillList,field->ContainerW);
      ed_rl_Field_remove(rei,field);
    }
  }
  if (l!=0) {
    /* d2_Refresh_tab_groups(rei); */
    rei->SelectedType=RE_SELECT_NONE;
    rei->Modified=Bool_TRUE;
  }
}

/*--------------------------------------------------*/
NORET ed_Bar_delete(w,rei)
     Widget w;
     reid rei;
{
  REAssoc assoc=(REAssoc)rei->Selected;
  assert(assoc);
  if (AlPop_Query(ALPOP_WARNING,
		  AlText_get(RE_TEXT_FILE,ED_FIELDS_DELETE_W),
		  AlText_get(RE_TEXT_FILE,ED_FIELDS_DELETE_W_H),
		  assoc->BarW,
		  ALPOP_HANG_BELOW,
		  rei->display,
		  ALPOP_OK | ALPOP_CANCEL | ALPOP_HELP)==(VOIDP)1)
    ed_Assoc_clear(assoc);
  rei->SelectedType=RE_SELECT_NONE;
  d2_Buttons_update(rei);
}

/*--------------------------------------------------*/
NORET ed_Box_delete(w,rei)
     Widget w;
     reid rei;
{
  REAssoc assoc=(REAssoc)rei->Selected;
  assert(assoc);
  ed_Assoc_clear(assoc);
  ed_REMember_remake_form_without_me(rei,assoc->container);
  XmRemoveTabGroup(assoc->LabelW);
  XmRemoveTabGroup(assoc->BarW);
  XtUnmanageChild(assoc->ContainerW);
  Darray_addh(rei->WidgetKillList,assoc->ContainerW);
  ed_rl_Assoc_remove(rei,assoc);
  rei->SelectedType=RE_SELECT_NONE;
  d2_Buttons_update(rei);
}

/*--------------------------------------------------*/
NORET ed_Delete_CB(w,rei,cadda)
     Widget w;
     reid rei;
     caddr_t cadda;
{
  if (rei->DisableEdit==Bool_TRUE) return;
  MuSetWaitCursor(rei->ShellW);
  ed_ClearWidgetKillList(rei);
  XmUpdateDisplay(w);
  switch(rei->SelectedType) {
  case RE_SELECT_NONE: break;
  case RE_SELECT_FIELD: ed_Field_delete(w,rei,rei->Selected); break;
  case RE_SELECT_BOX:   ed_Box_delete(w,rei); break;
  case RE_SELECT_ACTION:  ed_Field_delete(w,rei,rei->Selected); break;
  case RE_SELECT_BAR:  ed_Bar_delete(w,rei); break;
  defautl: assert(0);
  }
  MuSetStandardCursor(rei->ShellW);
}

/*--------------------------------------------------*/
void ed_Field_delete(w,rei,f)
     Widget w;
     REField f;
     reid rei;
{
  assert(f);
  ed_REMember_remake_form_without_me(rei,f->container);

  XmRemoveTabGroup(f->ContainerW); 
  XtUnmanageChild(f->ContainerW);
  Darray_addh(rei->WidgetKillList,f->ContainerW);

  ed_rl_Field_remove(rei,f);

  if (f==rei->MTField)
    rei->MTField=NULL;
  rei->SelectedType=RE_SELECT_NONE;
  rei->Modified=Bool_TRUE;
  d2_Buttons_update(rei);
  /* d2_Refresh_tab_groups(rei); */
}

/*--------------------------------------------------*/
NORET ed_REMember_remake_form_without_me(rei,member)
     reid rei;
     REMember member;
{
  Widget PrevW, NextW, ParentW;
  REMember Prev, Parent, Next;

  rl_Get_surrounding_members(rei,member,
			     &Prev,&Next,&Parent);
  rl_Get_surrounding_widgets(rei,member,
			     &PrevW,&NextW,&ParentW);
    
  if (NextW!=NULL) {
    if (PrevW!=NULL) {
      Alxt_SetArg(NextW,XmNtopAttachment,(XtArgVal)XmATTACH_WIDGET);
      Alxt_SetArg(NextW,XmNtopWidget,(XtArgVal)PrevW);
    }
    else {
      Alxt_SetArg(NextW,XmNtopAttachment,(XtArgVal)XmATTACH_WIDGET);
      Alxt_SetArg(NextW,XmNtopWidget,(XtArgVal) Parent->object.Assoc->BarW);
    }
  }
}

/*--------------------------------------------------*/
void ed_rl_Field_remove(rei,f)
reid rei;
REField f;
{
  REMember rem=f->container;
  REMember Frem=rem->father;

  if (Frem==NULL) {
    rei->TopLevelMember=NULL;
    Al_warning("ruleeditor: ed.c: ed_rl_Field_remove: bad rule.\n");
  }
  else {
    if (Frem->Type!=ALRMT_ASSOC) 
     Al_fatal_error("ruleeditor: ed.c: ed_rl_Field_remove: bad rule language.\n");
    rl_Darray_remove_ptr(Frem->object.Assoc->Contents,rem);
  }
  
  rl_REMember_destroy(rem);
}

/*--------------------------------------------------*/
NORET ed_rl_Assoc_remove(rei,rea)
     reid rei;
     REAssoc rea;
{
  REMember rem;
  REMember Prem;

  rem=rea->container;
  Prem=rem->father;
  if (Prem==NULL) {
    RE_debug("not removing top level and.\n");
  }
  else {
    rl_Darray_remove_ptr(Prem->object.Assoc->Contents,rem);
    rl_REMember_destroy(rem);
  }
}

/*--------------------------------------------------*/
void ed_Verb_change_CB(w,p,cadda)
     Widget w;
     RapPack p;
     caddr_t cadda;
{
  AlVerb Verb;
  int exists, goal, i, max, min;
  reid rei;
  REAction action;
  char* name;

  name=RapPack_get(p,0);
  action=(REAction)RapPack_get(p,1);
  rei=action->rei;
  
  if (rei->DisableEdit==Bool_TRUE) return;

  assert (action);

  MuSetWaitCursor(rei->ShellW);

  Memory_free(action->VerbName);
  action->VerbName=(char *)strcpy(Memory_allocate(strlen(name)+1),name);
  action->Verb=AlVerbReg_get_obj(name);

  /*  reset the actual verb object and find out what the differences in the */
  /*  numver of arguments we have as compared to the number of arguments we */
  /*  want is */
  /*  Not that Verbs are not destroyed. */
  Verb=AlVerbReg_get_obj(name);
  assert(Verb);
  action->Verb=Verb;
  exists=Darray_len(action->Arguments);
  goal=AlVerb_def_args(Verb);
  max=AlVerb_max_args(Verb);
  min=AlVerb_min_args(Verb);
  
  if (exists<=max && exists>=min)
    goal=exists;

  if (goal<exists) {
    for (i=0;i<exists;i++)
      ed_BlankArgument(action,i);
    ed_RemoveArgumentsToEnd(action,goal);
  }
  else {
    for (i=0;i<exists;i++)
      ed_BlankArgument(action,i);
    for (;i<goal;i++)
      ed_AddArgument(rei,action,i);
  } 
  rei->Modified=Bool_TRUE;
  MuSetStandardCursor(rei->ShellW);
}

/*--------------------------------------------------*/
void ed_RemoveArgumentsToEnd(REac,goal)
     REAction REac;
     unsigned goal;
{
  unsigned i;
  REArgument arg;
  for (i=Darray_len(REac->Arguments);i>goal;i--) {
    arg=(REArgument)Darray_remh(REac->Arguments);
    XtDestroyWidget(arg->ArgW);
    Memory_free(arg);
  }  
}
  
/*--------------------------------------------------*/
void ed_BlankArgument(REac,index)
REAction REac;
unsigned index;
{
}

/*--------------------------------------------------*/
void ed_AddArgument(rei,action,index)
     reid rei;
     REAction action;
     unsigned index;
{
  REArgument arg;
  arg=rl_REArgument_create(action->rei,(char*)"",action);
  RE_debug1("args LENGTH = %d\n",Darray_len(action->Arguments));
  action->Arguments=rl_Darray_insert(action->Arguments,arg,index);
  RE_debug1("args LENGTH = %d\n",Darray_len(action->Arguments));
  d2_Argument_add(action,arg);
  d2_Refresh_tab_groups(action->rei);
}

/*--------------------------------------------------*/
void ed_Argument_add_CB(w,rei,cadda)
     Widget w;
     reid rei;
     caddr_t cadda;
{
  REAction action;
  REArgument arg;
  int Index;

  if (rei->DisableEdit==Bool_TRUE) return;
  switch (rei->SelectedType) {
  case RE_SELECT_ARGUMENT:
    arg=(REArgument)rei->Selected;
    action=arg->action;
    if (RapDarray_pointer_index(action->Arguments,arg,&Index)==Bool_FALSE)
      Al_fatal_error("ed_Argument_add: couldn't find arg in action list.\n");
    ed_AddArgument(rei,action,Index+1);
    rei->Modified=Bool_TRUE;
    rei->SelectedType=RE_SELECT_NONE;
    d2_Buttons_update(rei);
    break;
  case RE_SELECT_ACTION:
    action=(REAction)rei->Selected;
    ed_AddArgument(rei,action,Darray_len(action->Arguments));
    rei->Modified=Bool_TRUE;
    rei->SelectedType=RE_SELECT_NONE;
    d2_Buttons_update(rei);
    break;
  default:
    break;
  }
}

/*--------------------------------------------------*/
void ed_UpdateAltsMenuSensitivity(action)
     REAction action;
{
  unsigned l;
  int Add, Delete;
  AlVerb Verb;

  l=Darray_len(action->Arguments);
  Verb=action->Verb;
  if (l<AlVerb_max_args(Verb))
    Add=TRUE;
  else
    Add=FALSE;
  if (l>AlVerb_min_args(Verb))
    Delete=TRUE;
  else
    Delete=FALSE;
  
}

/*                                                                         *
  *                                                                       *
  *=======================================================================*
  *                                                                       *
  *     The Boxer Routines                                                *
  *                                                                       *
  *=======================================================================*
  *                                                                       *
 *                                                                         */

/*--------------------------------------------------*/
NORET ed_AddBox_CB(w,rp,cadda)
     Widget w;
     RapPack rp;
     caddr_t cadda;
{
  reid rei;

  rei=(reid)RapPack_get(rp,1);

  if (rei->DisableEdit==Bool_TRUE) return;

  rebox_Set_callback_data(rei->IfW,(VOIDP)rp);
  rebox_Activate(rei->IfW);
  AlUI_AttachCursor(rei->IfW,BOXER_LEFT_CURSOR); 
}

/*--------------------------------------------------*/
Bool ed_Boxer_get_members(the_fields,Started,rem,Parent,ParentIndex,
			  dis,DestWin,
			  sx,sy,fx,fy)
Darray the_fields;
Bool *Started;
REMember rem, *Parent;
int *ParentIndex;       /* the member index which is previous to the new box */
Display *dis;
Window DestWin;
int sx,sy,fx,fy;
{
  int i,l;
  REAssoc rea;
  REMember Nrem;

  if (*Started==Bool_FALSE) {
    if (point_contains_member(dis,DestWin,rem,sx,sy,fx,fy)==Bool_TRUE) {
      *ParentIndex=rl_REMember_get_index(rem);
      RE_debug1("ParentIndex=%d\n",*ParentIndex);
      Darray_addh(the_fields,rem);
      *Parent=rem->father;
      *Started=Bool_TRUE;
    }

  /* once we get started we will simply get all members at one level.  Here */
  /* we do a depth first search of the tree untill we come across a member */
  /* in the box, then we switch over to the following else which just looks */
  /* for the end of the box. */

    else {
      if (rem->Type==ALRMT_ASSOC) {
	rea=rem->object.Assoc;
	l=Darray_len(rea->Contents);
	for (i=0;i<l;i++) {
	  Nrem=(REMember)Darray_get(rea->Contents,(unsigned)i);
	  if (ed_Boxer_get_members(the_fields,Started,Nrem,
				   Parent,ParentIndex,
				   dis,DestWin,sx,sy,fx,fy)==Bool_FALSE)
	    return(Bool_FALSE);
	}
      }
    }
    
    return(Bool_TRUE);
  }
  else {
    if (point_contains_member(dis,DestWin,rem,sx,sy,fx,fy)) {
      if (*Parent==rem->father) {
	Darray_addh(the_fields,rem);
	return(Bool_TRUE);
      }
      else {
	*Started=Bool_FALSE;
	return(Bool_FALSE);
      }
    }
    else
      return(Bool_FALSE);
  }
}

/*--------------------------------------------------*/
NORET ed_Boxer_CB(rp,x,y,x2,y2)
     RapPack rp;
     int x,y,x2,y2;
{
  reid rei;
  AlRAType rat;
  int sx,sy,fx,fy,ParentIndex;
  Darray the_fields=Darray_create();
  Window DestWin;
  Display *dis;
  REMember ParentMember;
  Bool Started;

  /* this rap pack is made in d2_FillBTBar */
  rat=(AlRAType)RapPack_get(rp,0);
  rei=(reid)RapPack_get(rp,1);

  dis=XtDisplay(rei->ShellW);
  sx=ed_min(x,x2);
  fx=ed_max(x,x2);
  sy=ed_min(y,y2);
  fy=ed_max(y,y2);

  /* this has to be the same widget that rebox was instanitated on. This is */
  /* done at the end of d2_Create.  Not nice I know. */
  DestWin=XtWindow(rei->IfW);

  /* find the members contained by the box drawn on the rule editor */
  Started=Bool_FALSE;

  ParentMember=NULL;
  ed_Boxer_get_members(the_fields,&Started,rei->TopLevelMember,
		       &ParentMember,&ParentIndex,dis,DestWin,sx,sy,fx,fy);

  if (Started==Bool_TRUE && Darray_len(the_fields)!=0) {
    REAssoc Nrea;
    REMember Nrem, rem;
    Widget PrevW, NextW, ParentW, d1,d2, assocW;
    Darray OldWidgets=Darray_create();
    int l,i;
    
    MuSetWaitCursor(rei->ShellW);
    rei->Modified=Bool_TRUE;
    rl_Get_surrounding_widgets(rei,(REMember)
			       Darray_get(the_fields,(unsigned)0),
			       &PrevW,&NextW,&ParentW);
    if ((l=Darray_len(the_fields))!=1) {
      rl_Get_surrounding_widgets(rei,(REMember)Darray_get(the_fields,
							  (unsigned)l-1),
				 &d1,&NextW,&d2);
      assert (d2==ParentW);
    }

#ifdef RE_DEBUG
    printf("\n ADDING A NEW BOX, parent index=%d \n",ParentIndex);
    for (i=0;i<l;i++) {
      rem=(REMember)Darray_get(the_fields,(unsigned)i);
      if (rem->Type==ALRMT_ASSOC)
	printf("adding box\n");
      else
	printf("adding field  %s\n",rem->object.Field->Key);
    }
#endif    

    Nrea=rl_REAssoc_create(rei,rat);
    Nrem=rl_REMember_create_at_index(ALRMT_ASSOC,Nrea,ParentMember,
				     ParentIndex);

    assocW=d2_Assoc_make(rei,Nrem);

    /* modify the actual rule to reflect the changes */
    ed_Boxer_modify_rule(rei,the_fields,ParentMember,ParentIndex,Nrem);
    
    /* replace all the old widgets with new ones, keeping track of the old */
    /* widgets to be killed */
    ed_Boxer_modify_screen(rei,the_fields,ParentMember,Nrem,OldWidgets);
    
    /* manage the new box, it should appear in front of the old members */
    if (assocW!=NULL)
      XtManageChild(assocW);
    
    /* the next widget should be linked to the new box */
    if (NextW!=NULL) {
      Alxt_SetArg(NextW,XmNtopAttachment,(XtArgVal) XmATTACH_WIDGET);
      Alxt_SetArg(NextW,XmNtopWidget,(XtArgVal) Nrea->ContainerW);
    }
    /* destroy all the old widgets (now behind the new box */

    /* l=Darray_len(OldWidgets);
       for (i=0;i<l;i++) 
       XtDestroyWidget((Widget)Darray_get(OldWidgets,(unsigned)i)); */

    /* refresh the tab groups */
    d2_Refresh_tab_groups(rei);
    MuSetStandardCursor(rei->ShellW);
  }
}

/*--------------------------------------------------*/
Bool point_contains_member(dis,DestWin,rem,psx,psy,pfx,pfy)
Display *dis;
Window DestWin;
int psx,psy,pfx,pfy;
REMember rem;
{
  Window SrcWin, ChildWin;
  Widget container;
  int msx,msy,mfx,mfy;    /* the coordintes of the members container window */
			  /* with respect to the DestWin */
  int memberW, memberH;
  unsigned char units;

  if (rem->Type==ALRMT_FIELD)  {
    REField ref=rem->object.Field;
    container=ref->ContainerW;
  }
  else{
    REAssoc rea=rem->object.Assoc;
    container=rea->ContainerW;
  }

  if (container==NULL)
    return(Bool_FALSE);
  SrcWin=XtWindow(container);
  if (XTranslateCoordinates(dis,SrcWin,DestWin,0,0,
			    &msx,&msy,&ChildWin)==0) 
    Al_fatal_error("in point_above_member: fatal error in the extreme\n");

  memberW=(int)Alxt_get_widget_feature(container,XmNwidth);
  memberH=(int)Alxt_get_widget_feature(container,XmNheight);

  /* since all X functions deal with pixels we convert to pixels here */
  units=(unsigned char)Alxt_get_widget_feature(container,XmNunitType);
  RE_debug1("units=%d\n",units);

  /*!!! WARNING Xm100TH_MILLIMETERS below should be replaced with 'units' */
  /*but the above function returns erroneous data */
  memberW=XmConvertUnits(container,XmHORIZONTAL,Xm100TH_MILLIMETERS,
			 memberW,XmPIXELS);
  memberH=XmConvertUnits(container,XmVERTICAL,Xm100TH_MILLIMETERS,
			 memberH,XmPIXELS);
  
  if (XTranslateCoordinates(dis,SrcWin,DestWin,memberW,memberH,
			    &mfx,&mfy,&ChildWin)==0) 
    Al_fatal_error("in point_above_member: fatal error in the extreme-2\n");

  /* give them some horizontal leaway */
  msx=msx+20;
  mfx=mfx-20; if (mfx<0) mfx=0;
  msy=msy+4;
  mfy=mfy-4;

  RE_debug2("%d, %d to ",msx,msy);
  RE_debug2("%d, %d \n",mfx,mfy);
  RE_debug2("BOX %d, %d to ",psx,psy);
  RE_debug2("%d, %d \n",pfx,pfy);

  if (msy>psy && mfy<pfy )
    return(Bool_TRUE);
  else
    return(Bool_FALSE);
}


/*--------------------------------------------------*/
NORET ed_Boxer_modify_rule(rei,the_members,OldParent,OldIndex,NewParent)
reid rei;
Darray the_members;
REMember OldParent, NewParent;
int OldIndex;
{
  REAssoc Orea, Nrea;
  REMember Crem;
  int i,l;
  assert(OldParent->Type==ALRMT_ASSOC);
  assert(NewParent->Type==ALRMT_ASSOC);
  Orea=OldParent->object.Assoc;
  Nrea=NewParent->object.Assoc;

  l=Darray_len(the_members);
  for (i=0;i<l;i++) {
    Crem=(REMember)Darray_get(the_members,(unsigned)i);
    rl_Darray_remove_ptr(Orea->Contents,Crem);
    Crem->father=NewParent;
    Darray_addh(Nrea->Contents,Crem);
  }
}

/*--------------------------------------------------*/
NORET ed_Boxer_modify_screen(rei,the_members,OldParent,NewParent,ToKill)
reid rei;
Darray the_members, ToKill;
REMember OldParent, NewParent;
{
  int i,l;
  REMember rem;
  
  l=Darray_len(the_members);
  for (i=0;i<l;i++) {
    rem=(REMember)Darray_get(the_members,(unsigned)i);
    if (rem->Type==ALRMT_ASSOC)
      XtDestroyWidget(rem->object.Assoc->ContainerW);
    /* Darray_addh(ToKill,rem->object.Assoc->ContainerW); */
    else
      XtDestroyWidget(rem->object.Field->ContainerW);
    /* Darray_addh(ToKill,rem->object.Field->ContainerW); */
    rl_REMember_clear_for_screen(rem);
  }

  for (i=0;i<l;i++) {
    rem=(REMember)Darray_get(the_members,(unsigned)i);
    if (rem->Type==ALRMT_ASSOC) {
      RE_debug("adding assoc.\n");
      d2_If_AddAssoc(rei,rem);
    }
    else if (rem->Type==ALRMT_FIELD) {
      RE_debug1("adding field=%s\n",rem->object.Field->Key);
      d2_If_AddField(rei,rem,rem->object.Field->FromWhere);
    }
    else
      Al_fatal_error("file=ed.c ^^^7: bad REMember\n");
  }
}

/*=======================================================================*/
/*=======================================================================*/
/*=======================================================================*/

/*--------------------------------------------------*/
NORET ed_Select_bar_E(w,xe,parms,np)
     Widget w;
     XEvent *xe;
     char** parms;
     int *np;
{
  reid rei;
  REAssoc assoc;
  if (*np!=1)
    Al_fatal_error("box select without # parms==1\n");

  assoc=(REAssoc)atoi(parms[0]);
  rei=assoc->rei;
  rei->Selected=(VOIDP)assoc;
  rei->SelectedType=RE_SELECT_BAR;
}

/*--------------------------------------------------*/
NORET ed_Info_CB(w,rei,cadda)
Widget w;
reid rei;
caddr_t cadda;
{
}	      



/*--------------------------------------------------*/
NORET ed_Field_help(w,rei,rap)
Widget w;
reid rei;
RapPack rap;
{
  /* !!! fill in !!! */
}


/*--------------------------------------------------*/
NORET ed_Field_add(rei,field)
     reid rei;
     REField field;
{
  REMember member;
  int InsertIndex;

  if (rei->TopLevelMember!=NULL) {
    if (rei->TopLevelMember->Type!=ALRMT_ASSOC)  {
      REMember NewTopMember;
      NewTopMember=rl_REMember_create(ALRMT_ASSOC,
				      rl_REAssoc_create(rei,ALRAT_AND),
				      NULL);
      rei->TopLevelMember->father=NewTopMember;
      Darray_addh(NewTopMember->object.Assoc->Contents,rei->TopLevelMember);
      rei->TopLevelMember=NewTopMember;
    }
  }
  
  if (rei->SelectedType==RE_SELECT_FIELD) {
    REField SelectedField=(REField)rei->Selected;
    InsertIndex=rl_REMember_get_index(SelectedField->container);
    RE_debug1("insert index=%d\n",InsertIndex);
    member=rl_REMember_create_at_index(ALRMT_FIELD,field,
				       SelectedField->container->father,
				       InsertIndex+1);
  }
  else if (rei->SelectedType==RE_SELECT_BAR) {
    REAssoc SelectedAssoc=(REAssoc)rei->Selected;
    member=rl_REMember_create_at_index(ALRMT_FIELD,field,
				       SelectedAssoc->container,
				       0);
  }
  else if (rei->SelectedType==RE_SELECT_BOX) {
    REAssoc SelectedAssoc=(REAssoc)rei->Selected;
    InsertIndex=rl_REMember_get_index(SelectedAssoc->container);
    RE_debug1("box insert index=%d\n",InsertIndex);
    member=rl_REMember_create_at_index(ALRMT_FIELD,field,
				       SelectedAssoc->container->father,
				       InsertIndex+1);
  }
  else
    return;
    
  if (rei->TopLevelMember==NULL)
    rei->TopLevelMember=member;
  MuSetWaitCursor(rei->ShellW);
  d2_If_AddField(rei,member,REF_FROM_USER);
  d2_Refresh_tab_groups(rei);
  rei->Modified=Bool_TRUE;
  MuSetStandardCursor(rei->ShellW);
}


/*--------------------------------------------------*/
NORET ed_Field_add_simple_CB(w,rap,motif)
     Widget w;
     RapPack rap;
     XmAnyCallbackStruct* motif;
{
  reid rei=(reid)RapPack_get(rap,0);
  char* fieldType=(char*)RapPack_get(rap,1);
  REField field;

  if (rei->DisableEdit==Bool_TRUE) return;

  ed_ClearWidgetKillList(rei);
  if (rei->SelectedType==RE_SELECT_FIELD ||
      rei->SelectedType==RE_SELECT_BAR ||
      rei->SelectedType==RE_SELECT_BOX) {
    field=rl_REField_create(rei,ALRFT_MSG,"","",fieldType,NULL,REF_FROM_USER);
    ed_Field_add(rei,field);
  }
}


/*--------------------------------------------------*/
NORET ed_Field_add_complex_CB(w,rei,motif)
     Widget w;
     reid rei;
     XmAnyCallbackStruct* motif;
{
  REField field;

  if (rei->DisableEdit==Bool_TRUE) return;

  ed_ClearWidgetKillList(rei);
  if (rei->SelectedType==RE_SELECT_FIELD ||
      rei->SelectedType==RE_SELECT_BAR ||
      rei->SelectedType==RE_SELECT_BOX) {
    field=rl_REField_create(rei,ALRFT_MSG,"","",NULL,NULL,REF_FROM_USER);
    field->VisibleMode=RE_MODE_COMPLEX;
    ed_Field_add(rei,field);
  }
}

/*--------------------------------------------------*/
NORET ed_Change_assoc(assoc,mode)
     REAssoc assoc;
     ReMode mode;
{
  int i,l;
  REMember member;
  REField field;
  l=Darray_len(assoc->Contents);
  RE_debug1("l=%d\n",l);
  for (i=0;i<l;i++) {
    member=(REMember)Darray_get(assoc->Contents,(unsigned)i);
    if (member->Type==ALRMT_ASSOC)
      ed_Change_assoc(member->object.Assoc);
    else {
      field=member->object.Field;
      if (mode==RE_MODE_COMPLEX)
	d2_Field_to_complex(field);
      else if (mode==RE_MODE_SIMPLE)
	d2_Field_to_simple(field);
    }
  }
  if (l!=0)
    d2_Refresh_tab_groups(assoc->rei);
}

/*--------------------------------------------------*/
NORET ed_Change_CB(w,rap,cadda)
     Widget w;
     RapPack rap;
     XmAnyCallbackStruct* cadda;
{
  reid rei=(reid)RapPack_get(rap,0);
  ReMode mode=(ReMode)RapPack_get(rap,1);
  /* XmToggleButtonCallbackStruct *tbc=(XmToggleButtonCallbackStruct*)cadda; */

  RE_debug2("rei->title=%s,  if field width=%d\n",rei->title,
	    rei->if_field_width);
  RE_debug2("rei->sele= %d = %d\n",rei->SelectedType, rei->Selected);

  /* if (tbc->set==FALSE) return;
     else
     RE_debug("ed_change_CB\n"); */
  
  MuSetWaitCursor(rei->ShellW);
  switch (rei->SelectedType) {

  case RE_SELECT_FIELD: {
    REField field=(REField)rei->Selected;
    RE_debug("change callback field\n");
    if (mode==RE_MODE_COMPLEX && field->VisibleMode!=RE_MODE_COMPLEX) {
      field->Mode=RE_MODE_COMPLEX;
      d2_Field_to_complex(field);   /* this will set the VisualMode */
      d2_Refresh_tab_groups(rei);
    }
    else if (mode==RE_MODE_SIMPLE && field->VisibleMode!=RE_MODE_SIMPLE) {
      field->Mode=RE_MODE_SIMPLE;
      d2_Field_to_simple(field);    /* this will set the VisualMode */  
      d2_Refresh_tab_groups(rei);
    }
  }
    break;
    
  case RE_SELECT_BAR:
  case RE_SELECT_BOX: {
    REAssoc assoc=(REAssoc)rei->Selected;
    ed_Change_assoc(assoc,mode);
    break;
  }
    
  default:
    break;
  }
  MuSetStandardCursor(rei->ShellW);
}

#define RULE_BUFF_INC 3000
/*--------------------------------------------------*/
NORET ed_Print_CB(w,rei,cadda)
     Widget w;
     reid rei;
     caddr_t cadda;
{
  Darray       AlActions;
  AlRuleMember AlMember;
  AlRule       Rule;
  char         *ruleBuff;
  int          RuleBuffLength;
  char         cmd_str[80];
  FILE         *printer;

  ed_ClearWidgetKillList(rei);
  AlActions=rl_TranslateActionsFromRE(rei,rei->Actions);
  AlMember=rl_TranslateFromRE(rei,rei->TopLevelMember);
  Rule=AlRule_create(AlMember,AlActions,0,0,(char*)NULL);
  assert(Rule);
  
  RuleBuffLength=RULE_BUFF_INC;
  ruleBuff=Memory_allocate(RuleBuffLength+1);
  while (Alruleprint(ruleBuff,RuleBuffLength,Bool_TRUE,Rule)==(-1)) {
    RuleBuffLength+=RULE_BUFF_INC;
    ruleBuff=Memory_reallocate(ruleBuff,RuleBuffLength+1);
  }

  /* some of Brian's code to open printer */
  /* Check that necessary environment variable is present */
  /* ---------------------------------------------------- */
  if (getenv("PRINTER") == NULL) {
    if ((int)AlPop_Query(ALPOP_QUESTION,
			 AlText_get(RE_TEXT_FILE,ED_PRINTER_WARNING),
			 AlText_get(RE_TEXT_FILE,ED_PRINTER_WARNING_HELP),
			 w,
			 ALPOP_HANG_BOTTOM_LEFT,
			 rei->display,
			 ALPOP_OK | ALPOP_CANCEL | ALPOP_HELP)==1)
      strcpy(cmd_str, "lpr");
    else
      return;
  }
  else
    strcpy(cmd_str, "lpr");
  
  if ((printer = popen(cmd_str, "w+")) == NULL) {
    AlPop_Query(ALPOP_ERROR,
		AlText_get(RE_TEXT_FILE,ED_PRINTER_CANT_OPEN),
		AlText_get(RE_TEXT_FILE,ED_PRINTER_CANT_OPEN_HELP),
		w,
		ALPOP_HANG_BOTTOM_LEFT,
		rei->display,
		ALPOP_OK | ALPOP_HELP);
    return;
  }
  
  fprintf(printer,"%s\n",ruleBuff);
  {
    AlPop_Query(ALPOP_INFO,
		AlText_get(RE_TEXT_FILE,ED_PRINTER_DONE),
		(char*)NULL,
		w,
		ALPOP_HANG_BOTTOM_LEFT,
		rei->display,
		ALPOP_OK);
  }
}

/*--------------------------------------------------*/
NORET ed_Help_CB(w,rap,cadda)
     Widget w;
     RapPack rap;
     caddr_t cadda;
{
  RMFBuffer buff;
  char* name=(char*)RapPack_get(rap,0);
  char* helpString=(char*)RapPack_get(rap,1);
  reid rei=(reid)RapPack_get(rap,2);
  EdHelpVerifyFunction func;
  VOIDP data=RapPack_get(rap,4);
  char *info, *help;
  
  func=(EdHelpVerifyFunction)RapPack_get(rap,3);

  MuSetWaitCursor(rei->ShellW);
  buff=RMFBuffer_create(name,40);
  RMFBuffer_append(buff,RE_HELP_POSTFIX);
  info=AlText_get(RE_TEXT_FILE,RMFBuffer_copy_of_buff(buff));
  RMFBuffer_destroy(buff);
  MuSetStandardCursor(rei->ShellW);
  
  if (helpString!=NULL)
    help=AlText_get(RE_TEXT_FILE,helpString);
  else
    help=NULL;

  AlPop_Query(ALPOP_INFO,
	      info,
	      help,
	      rei->ThenBarW,
	      ALPOP_HANG_BELOW,
	      rei->display,
	      ALPOP_OK | ALPOP_HELP);

  if (func!=NULL)
    (func)((VOIDP)data);
}

/*--------------------------------------------------*/
/* this is a quick and dirty copy of ed_help_Cb used to popup a query when a */
/* proportional font is required */
/*--------------------------------*/
NORET ed_Help2_CB(w,rap,cadda)
     Widget w;
     RapPack rap;
     caddr_t cadda;
{
  RMFBuffer buff;
  char* name=(char*)RapPack_get(rap,0);
  char* helpString=(char*)RapPack_get(rap,1);
  reid rei=(reid)RapPack_get(rap,2);
  EdHelpVerifyFunction func;
  VOIDP data=RapPack_get(rap,4);
  char *info, *help;
  
  func=(EdHelpVerifyFunction)RapPack_get(rap,3);

  MuSetWaitCursor(rei->ShellW);
  buff=RMFBuffer_create(name,40);
  RMFBuffer_append(buff,RE_HELP_POSTFIX);
  info=AlText_get(RE_TEXT_FILE,RMFBuffer_copy_of_buff(buff));
  RMFBuffer_destroy(buff);
  MuSetStandardCursor(rei->ShellW);
  
  if (helpString!=NULL)
    help=AlText_get(RE_TEXT_FILE,helpString);
  else
    help=NULL;

  AlPop_Query_named(ALPOP_INFO,
		    info,
		    help,
		    rei->ThenBarW,
		    ALPOP_HANG_BELOW,
		    rei->display,
		    ALPOP_OK | ALPOP_HELP,
		    "argus-monospaced-popup");

  if (func!=NULL)
    (func)((VOIDP)data);
}



/*--------------------------------------------------*/
void ed_Action_add_CB(w,p,cadda)
     Widget w;
     RapPack p;
     caddr_t cadda;
{
  int  i,nargs, InsertIndex;
  REAction SAction, action;
  REArgument arg;
  Darray Args=Darray_create();
  AlVerb Verb;
  char *buff;
  char *VerbName;
  reid rei;

  VerbName=(char*)RapPack_get(p,0);
  rei=(reid)RapPack_get(p,1);

  if (rei->DisableEdit==Bool_TRUE) return;

  ed_ClearWidgetKillList(rei);

  InsertIndex=(-1);
  switch (rei->SelectedType) {
  case RE_SELECT_ACTION: 
    SAction=(REAction)rei->Selected;
    if (RapDarray_pointer_index(rei->Actions,
				SAction,&InsertIndex)==Bool_FALSE)
      Al_fatal_error("AddAction: action selected but not found in Actions\n");

    break;
  case RE_SELECT_ARGUMENT: 
    arg=(REArgument)rei->Selected;
    SAction=arg->action;
    if (RapDarray_pointer_index(rei->Actions,
				SAction,&InsertIndex)==Bool_FALSE)
      Al_fatal_error("AddAction: action selected but not found in Actions\n");
    break;
  case RE_SELECT_THEN_BAR:
    InsertIndex=(-1);
    break;
  default:
    return;
    break;
  }
  RE_debug1("Action Insert index=%d\n",InsertIndex);

  MuSetWaitCursor(rei->ShellW);

  Verb=AlVerbReg_get_obj(VerbName);
  nargs=AlVerb_def_args(Verb);
  for (i=0;i<nargs;i++) {
    buff=Memory_allocate(2);
    buff[0]='\0';
    Darray_addh(Args,buff);
  }
  action=rl_REAction_create(rei,VerbName,Args);
  assert(action);

  rl_Darray_insert(rei->Actions,action,InsertIndex+1);

  d2_Action_add(rei,action);

  d2_Refresh_tab_groups(rei);
  rei->Modified=Bool_TRUE;
  MuSetStandardCursor(rei->ShellW);
}

/*--------------------------------------------------*/
NORET ed_Argument_delete_CB(w,rei,cadda)
     Widget w;
     reid rei;
     caddr_t cadda;
{
  if (rei->DisableEdit==Bool_TRUE) return;

  switch(rei->SelectedType) {
  case RE_SELECT_ARGUMENT:
    MuSetWaitCursor(rei->ShellW);
    ed_Argument_delete((REArgument)rei->Selected);
    rei->Modified=Bool_TRUE;
    rei->SelectedType=RE_SELECT_NONE;
    d2_Buttons_update(rei);
    MuSetStandardCursor(rei->ShellW);
    break;

  default:
    break;
  }
}


/*--------------------------------------------------*/
void ed_Action_delete_CB(w,rei,cadda)
     Widget w;
     reid rei;
     caddr_t cadda;
{
  if (rei->DisableEdit==Bool_TRUE) return;

  MuSetWaitCursor(rei->ShellW);
  switch(rei->SelectedType) {
  case RE_SELECT_ACTION:
    ed_Action_delete((REAction)rei->Selected);
    rei->SelectedType=RE_SELECT_NONE;
    rei->Modified=Bool_TRUE;
    d2_Buttons_update(rei);
    break;
  case RE_SELECT_ARGUMENT: {
    REArgument arg=(REArgument)rei->Selected;
    ed_Action_delete(arg->action);
    rei->SelectedType=RE_SELECT_NONE;
    rei->Modified=Bool_TRUE;
    d2_Buttons_update(rei);
    break;
  }
  case RE_SELECT_THEN_BAR:
    if (AlPop_Query(ALPOP_WARNING,
		    AlText_get(RE_TEXT_FILE,ED_ACTIONS_DELETE_W),
		    AlText_get(RE_TEXT_FILE,ED_ACTIONS_DELETE_W_H),
		    w,
		    ALPOP_HANG_BOTTOM_LEFT,
		    rei->display,
		    ALPOP_OK | ALPOP_CANCEL | ALPOP_HELP)==(VOIDP)1)
      {
	int i,l;
	l=Darray_len(rei->Actions);
        /* could be done quicker but I am in a rush now */
	for (i=l-1;i>=0;i--) 
	  ed_Action_delete((REAction)Darray_get(rei->Actions,(unsigned)i));
	rei->SelectedType=RE_SELECT_NONE;
	rei->Modified=Bool_TRUE;
	d2_Buttons_update(rei);
      }
    break;
    
  default:
    break;
  }
  MuSetStandardCursor(rei->ShellW);
}

/*--------------------------------------------------*/
NORET ed_Action_delete(action)
     REAction action;
{
  reid rei=action->rei;
  int i,l;
  Widget PreviousW, NextW;
  
  /* XmRemoveTabGroup(action->MenuW); */
  XtUnmanageChild(action->ContainerW); 

  rl_Actions_get_surrounding_widgets(rei,action,&PreviousW,&NextW);

  l=Darray_len(action->Arguments);
  for (i=l-1;i>=0;i--) 
    ed_Argument_delete((REArgument)Darray_get(action->Arguments,(unsigned)i));

  if (NextW!=NULL) {
    if (PreviousW!=NULL) {
      Alxt_SetArg(NextW, XmNtopAttachment, (XtArgVal)  XmATTACH_WIDGET );
      Alxt_SetArg(NextW, XmNtopWidget, (XtArgVal)  PreviousW );
    }
    else 
      Alxt_SetArg(NextW, XmNtopAttachment, (XtArgVal)  XmATTACH_FORM );
  }
  else if (PreviousW!=NULL && PreviousW!=rei->ThenBarW)
    Alxt_SetArg(PreviousW, XmNbottomAttachment, (XtArgVal)  XmATTACH_FORM );

  rl_Darray_remove_ptr(rei->Actions,action);

  XtDestroyWidget(action->ContainerW);
  /* Darray_addh(rei->WidgetKillList,(VOIDP)action->ContainerW); */
  rl_REAction_destroy(action);
}


/*--------------------------------------------------*/
NORET ed_Argument_delete(arg)
     REArgument arg;
{
  REAction action=arg->action;
  reid rei=action->rei;
  Widget PreviousW, NextW;

  rl_Arguments_get_surrounding_widgets(action,arg,&PreviousW,&NextW);
  
  if (NextW!=NULL) {
    if (PreviousW!=NULL) {
      Alxt_SetArg(NextW, XmNtopAttachment, (XtArgVal)  XmATTACH_WIDGET );
      Alxt_SetArg(NextW, XmNtopWidget, (XtArgVal)  PreviousW );
    }
    else 
      Alxt_SetArg(NextW, XmNtopAttachment, (XtArgVal)  XmATTACH_FORM );
  }
  else if (PreviousW!=NULL)
    Alxt_SetArg(PreviousW, XmNbottomAttachment, (XtArgVal)  XmATTACH_FORM );
  
  rl_Darray_remove_ptr(action->Arguments,arg);
  
  /* XmRemoveTabGroup(arg->ArgW); */
  XtDestroyWidget(arg->ArgW);
  /*  XtUnmanageChild(arg->ArgW); 
      Darray_addh(rei->WidgetKillList,(VOIDP)arg->ArgW); */

  /* MEMORY LEAK!!! destroying this argument causes the next call to */
  /* d2_Argument_select_CB to be passed a bad argument 
     rl_REArgument_destroy(arg); */
  {
    int full;
    full=Darray_len(action->Arguments)*rei->if_field_height;
    if (full!=0)
      Alxt_SetArg(action->ContainerW,XmNheight,(XtArgVal)full);
  }
}

/*--------------------------------------------------*/
NORET ed_Help_on_verb_CB(w,rap,cadda)
     Widget w;
     RapPack rap;
     caddr_t cadda;
{
  RMFBuffer buff;
  char *name=(char*)RapPack_get(rap,0);
  reid rei=(reid)RapPack_get(rap,1);
  char *info, *help;
  
  buff=RMFBuffer_create(name,40);
  RMFBuffer_append(buff," HELP");
  info=AlText_get(RE_TEXT_FILE,RMFBuffer_copy_of_buff(buff));
  RMFBuffer_destroy(buff);
  
  help=AlText_get(RE_TEXT_FILE,ED_VERBS_HELP_STRING);

  AlPop_Query(ALPOP_INFO,
	      info,
	      help,
	      rei->ThenBarW,
	      ALPOP_HANG_BELOW,
	      rei->display,
	      ALPOP_OK | ALPOP_HELP);
}

/*--------------------------------------------------*/
NORET ed_Reset_verb(rei)
     reid rei;
{
  REAction action=(REAction)rei->Selected;
  if (rei->SelectedType!=RE_SELECT_ACTION)
    return;
  MenuPack_set_as_default(action->Menu,action->VerbName);
}

/*--------------------------------------------------*/
NORET ed_Field_key_justify_CB (w,field,cadda)
     Widget w;
     REField field;
     caddr_t cadda;
{
  char *tkey;
  int mod;
  mod=0;
  RE_debug("ed rj KEY\n");
  if (field->Type==ALRFT_MSG) {    
    tkey=rl_Key_rj_and_add_colon(XmTextGetString(field->KeyW),
				 KEY_LENGTH,&mod);
    RE_debug1("tkey=%s\n",tkey);
    if (mod==1) {
      /* if (field->Key!=NULL)
	 Memory_free(field->Key);
	 field->Key=RapStr_duplicate(tkey);
	 */
      XmTextSetString(field->KeyW,tkey);
      Memory_free(tkey);
    }
  }
}

