/*
 * xman - X window system manual page display program.
 *
 * $XConsortium: buttons.c,v 1.32 91/09/03 17:41:59 dave Exp $
 *
 * Copyright 1987, 1988 Massachusetts Institute of Technology
 *
 * 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 M.I.T. not be used in advertising or
 * publicity pertaining to distribution of the software without specific,
 * written prior permission.  M.I.T. makes no representations about the
 * suitability of this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
 *
 * Author:    Chris D. Peterson, MIT Project Athena
 * Created:   October 27, 1987
 */

#include "globals.h"

/* The files with the icon bits in them. */

#include "icon_open.h"
#include "icon_help.h"
#include "iconclosed.h"

static void CreateOptionMenu(), CreateSectionMenu();
static void StartManpage();
static Widget * ConvertNamesToWidgets();
ManpageGlobals * InitPsuedoGlobals();

#ifdef MOTIF
/* Motif pushbutton widget's translation table cannot be augmented.
   So, use callbacks to workaround it. */

static void quitCB( Widget w, XtPointer ptr1, XtPointer ptr2 )
{
  Quit( w, NULL, NULL, NULL );
}

static void popupHelpCB( Widget w, XtPointer ptr1, XtPointer ptr2 )
{
  PopupHelp( w, NULL, NULL, NULL );
}

static void createNewManpage( Widget w, XtPointer ptr1, XtPointer ptr2 )
{
  CreateNewManpage( w, NULL, NULL, NULL );
}
#endif

/*	Function Name: MakeTopBox
 *	Description: This funtion creates the top menu, in a shell widget.
 *	Arguments: none.
 *	Returns: the top level widget
 */

#define TOPARGS 5

static Atom wm_delete_window;

Widget top;			/* needed in PopupWarning, misc.c */
#ifdef MOTIF
Widget topBoxWidget = NULL;
#endif

void
MakeTopBox()
{
#ifdef MOTIF
  Widget helpBtn, quitBtn;
#endif
  Widget form, command, label; /* widgets. */
  Arg arglist[TOPARGS];		/* An argument list */
  Cardinal num_args = 0;	/* The number of arguments. */
  ManpageGlobals * man_globals;
  static char * full_size[] = {
    "topLabel", MANPAGE_BUTTON, NULL
  };
  static char * half_size[] = {
    HELP_BUTTON, QUIT_BUTTON, NULL
  };
  
/* create the top icon. */

  num_args = 0;
  XtSetArg(arglist[num_args], XtNiconPixmap,
	   XCreateBitmapFromData( XtDisplay(initial_widget), 
				 XtScreen(initial_widget)->root,
				 (char *)iconclosed_bits, iconclosed_width,
				 iconclosed_height));
  num_args++;
  XtSetArg(arglist[num_args], XtNtitle, resources.title);
  num_args++;
  XtSetArg(arglist[num_args], XtNiconic, resources.iconic);
  num_args++;
#ifdef MOTIF
  topBoxWidget = 
#endif
    top = XtCreatePopupShell(TOPBOXNAME, topLevelShellWidgetClass, 
			   initial_widget, arglist, num_args);

#ifdef MOTIF
  form = XtCreateManagedWidget("form", xmFormWidgetClass, top, 
#else
  form = XtCreateManagedWidget("form", formWidgetClass, top, 
#endif
			       NULL, (Cardinal) 0);

#ifdef MOTIF
  label = XtCreateManagedWidget("topLabel", xmLabelWidgetClass, form, 
#else
  label = XtCreateManagedWidget("topLabel", labelWidgetClass, form, 
#endif
			       NULL, (Cardinal) 0);

  num_args = 0;
#ifdef MOTIF
  XtSetArg(arglist[num_args], XmNtopAttachment, XmATTACH_WIDGET); num_args++;
  XtSetArg(arglist[num_args], XmNtopWidget, label); num_args++;
  helpBtn = XtCreateManagedWidget(HELP_BUTTON, xmPushButtonWidgetClass, form, 
				  arglist, num_args);
  XtAddCallback( helpBtn, XmNactivateCallback, popupHelpCB, NULL );
#else
  XtSetArg(arglist[num_args], XtNfromVert, label); num_args++;
  command = XtCreateManagedWidget(HELP_BUTTON, commandWidgetClass, form, 
				  arglist, num_args);
#endif

#ifdef MOTIF
  /* same args as help widget */
  XtSetArg(arglist[num_args], XmNleftAttachment, XmATTACH_WIDGET); num_args++;
  XtSetArg(arglist[num_args], XmNleftWidget, helpBtn); num_args++;
  quitBtn = XtCreateManagedWidget(QUIT_BUTTON, xmPushButtonWidgetClass, form, 
				  arglist, num_args);
  XtAddCallback( quitBtn, XmNactivateCallback, quitCB, NULL );
#else
  /* use same vertical as help widget. */
  XtSetArg(arglist[num_args], XtNfromHoriz, command); num_args++;
  command = XtCreateManagedWidget(QUIT_BUTTON, commandWidgetClass, form, 
				  arglist, num_args);
#endif

  num_args = 0;
#ifdef MOTIF
  XtSetArg(arglist[num_args], XmNtopAttachment, XmATTACH_WIDGET); num_args++;
  XtSetArg(arglist[num_args], XmNtopWidget, quitBtn); num_args++;
  command = XtCreateManagedWidget(MANPAGE_BUTTON, xmPushButtonWidgetClass, form, 
				  arglist, num_args);
  XtAddCallback( command, XmNactivateCallback, createNewManpage, NULL );
#else
  XtSetArg(arglist[num_args], XtNfromVert, command); num_args++;
  command = XtCreateManagedWidget(MANPAGE_BUTTON, commandWidgetClass, form, 
				  arglist, num_args);
#endif

  help_widget = NULL;		/* We have not seen the help yet. */

#ifdef MOTIF
  /* (7/6/93:hajadi) */
  /* Someday this will be the motif version of FormUpWidgets. */
  /* For now just let form widget do its magic.. */
#else
  FormUpWidgets(form, full_size, half_size);
#endif

  XtRealizeWidget(top);
				/* add WM_COMMAND property */
  XSetCommand(XtDisplay(top), XtWindow(top), saved_argv, saved_argc);

  man_globals = (ManpageGlobals*) XtMalloc( (Cardinal) sizeof(ManpageGlobals));
  man_globals->label = NULL;
  man_globals->manpagewidgets.directory = NULL;
  man_globals->manpagewidgets.manpage = NULL;
  man_globals->manpagewidgets.box = NULL;
  man_globals->current_directory = 0;
  MakeSearchWidget(man_globals, top);
  MakeSaveWidgets(man_globals, top);

  SaveGlobals( (man_globals->This_Manpage = top), man_globals);
  XtMapWidget(top);
  AddCursor(top, resources.cursors.top);

/*
 * Set up ICCCM delete window.
 */
  wm_delete_window = XInternAtom(XtDisplay(top), "WM_DELETE_WINDOW",
				 False);
  XtOverrideTranslations
      (top, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()"));
  (void) XSetWMProtocols (XtDisplay(top), XtWindow(top),
			  &wm_delete_window, 1);
  

}

/*	Function Name: CreateManpage
 *	Description: Creates a new manpage.
 *	Arguments: none.
 *	Returns: none.
 */

Widget
CreateManpage( file )
FILE * file;
{
  ManpageGlobals * man_globals;	/* The psuedo global structure. */

  man_globals = InitPsuedoGlobals();
  CreateManpageWidget(man_globals, MANNAME, TRUE);
  
  if (file == NULL)
    StartManpage( man_globals, OpenHelpfile(man_globals), FALSE );
  else {
    OpenFile(man_globals, file);
    StartManpage( man_globals, FALSE, TRUE);
  }
  return(man_globals->This_Manpage);
}

/*	Function Name: InitPsuedoGlobals
 *	Description: Initializes the psuedo global variables.
 *	Arguments: none.
 *	Returns: a pointer to a new pseudo globals structure.
 */

ManpageGlobals * 
InitPsuedoGlobals()
{
  ManpageGlobals * man_globals;

  /*
   * Allocate necessary memory. 
   */

  man_globals = (ManpageGlobals *) 
                XtMalloc( (Cardinal) sizeof(ManpageGlobals));

  man_globals->section_name = (char **) XtMalloc( (Cardinal) (sections *
							      sizeof(char *)));
  man_globals->manpagewidgets.box = (Widget *) XtCalloc( (Cardinal) sections,
						    (Cardinal) sizeof(Widget));
  
  /* Initialize the number of screens that will be shown */

  man_globals->both_shown = resources.both_shown_initial;
  
  return(man_globals);
}
  
/*	Function Name: CreateManpageWidget
 *	Description: Creates a new manual page widget.
 *	Arguments: man_globals - a new man_globals structure.
 *                 name         - name of this shell widget instance.
 *                 full_instance - if true then create a full manpage,
 *                                 otherwise create stripped down version
 *                                 used for help.
 *	Returns: none
 */

#define MANPAGEARGS 10

void
CreateManpageWidget(man_globals, name, full_instance)
ManpageGlobals * man_globals;
char * name;
Boolean full_instance;
{
#ifdef MOTIF
  register int i;
  XmString xms;
  Widget mainWindow, menuBar, form;
  Widget pulldown; 

  /* using doug young's menu support package */
  static MenuDescription optionsMenu[] = {
    { LABEL, "mxmanOptions" },
    { SEPARATOR },
    { BUTTON, DIRECTORY, OptionCallback },
    { BUTTON, MANPAGE, OptionCallback },
    { BUTTON, HELP, OptionCallback },
    { BUTTON, SEARCH, OptionCallback },
    { BUTTON, BOTH_SCREENS, OptionCallback },
    { BUTTON, REMOVE_MANPAGE, OptionCallback },
    { BUTTON, OPEN_MANPAGE, OptionCallback },
    { BUTTON, SHOW_VERSION, OptionCallback },
    { SEPARATOR },
    { BUTTON, QUIT, OptionCallback },
    NULL
  };

  static MenuDescription sectionsMenu[] = {
    { LABEL, "mxmanSections" },
    { SEPARATOR },
    NULL
  };

  static MenuDescription menuBarDesc[] = {
    { PULLDOWN, OPTION_MENU, NULL, NULL, optionsMenu },
    { RADIOPULLDOWN, SECTION_MENU, NULL, NULL, sectionsMenu },
    NULL
  };

#endif
  Arg arglist[MANPAGEARGS];	/* An argument list for widget creation */
  Cardinal num_args;		/* The number of arguments in the list. */
  Widget top, pane, hpane, sections;	/* Widgets */
  ManPageWidgets * mpw = &(man_globals->manpagewidgets);

  num_args = (Cardinal) 0;
  XtSetArg(arglist[num_args], XtNwidth, default_width);
  num_args++; 
  XtSetArg(arglist[num_args], XtNheight, default_height);
  num_args++; 

  top = XtCreatePopupShell(name, topLevelShellWidgetClass, initial_widget,
			   arglist, num_args);

  man_globals->This_Manpage = top; /* pointer to root widget of Manualpage. */
  num_args = 0;
  if (full_instance)
    XtSetArg(arglist[num_args], XtNiconPixmap,
	     XCreateBitmapFromData( XtDisplay(top), XtScreen(top)->root,
				   (char *)icon_open_bits, icon_open_width,
				   icon_open_height));
  else 
    XtSetArg(arglist[num_args], XtNiconPixmap,
	     XCreateBitmapFromData( XtDisplay(top), XtScreen(top)->root,
				   (char *)icon_help_bits, icon_help_width,
				   icon_help_height));
  num_args++;
  XtSetValues(top, arglist, num_args);

#ifdef MOTIF

  /* (7/9/93:hajadi)

                   top (shell)	
                +---------------+ -> mainWindow
                |[...          ]--->   menuBar
                |+-------------+--->   form
                ||[...        ]---->     label
                |+-------------+|
                ||             ---->     pane
                || directory   ||
                ||             ||
                || manpage     ||
                ||             ||
                |+-------------+|
                +---------------+

  */

  mainWindow = XmCreateMainWindow( top, "mainWindow", NULL, (Cardinal) 0 );
  XtManageChild( mainWindow );

  /* fix the callback data, before creating menu bar */
  for ( i=2;i<12;i++ ) {
    if ( i!=10 ) /* skip separator */
      optionsMenu[ i ].data = (XtPointer) man_globals;
  }
  menuBar = createMenu( MENUBAR, "menuBar", mainWindow, menuBarDesc, NULL );
  form = XmCreateForm( mainWindow, "form", NULL, (Cardinal) 0 );
  XtManageChild( form );
  
  XtVaSetValues( mainWindow,
    XmNmenuBar, menuBar,	
    XmNworkWindow, form,
    NULL );

  num_args = 0;
  XtSetArg( arglist[num_args], XmNtopAttachment, XmATTACH_FORM ); num_args++;
  XtSetArg( arglist[num_args], XmNleftAttachment, XmATTACH_FORM ); num_args++;
  XtSetArg( arglist[num_args], XmNrightAttachment, XmATTACH_FORM ); num_args++;
  man_globals->label = XtCreateManagedWidget(MANNAME, xmLabelWidgetClass,
			   form, arglist, num_args);

  XtSetArg( arglist[num_args], XmNbottomAttachment, XmATTACH_FORM ); num_args++;
  pane = XtCreateManagedWidget("Manpage_Vpane", xmPanedWindowWidgetClass, form, 
	   arglist, num_args);

#else
  pane = XtCreateManagedWidget("Manpage_Vpane", panedWidgetClass, top, NULL, 
			       (Cardinal) 0);

/* Create menu bar. */

  hpane = XtCreateManagedWidget("horizPane", panedWidgetClass,
				  pane, NULL, (Cardinal) 0);
  num_args = 0;
  XtSetArg(arglist[num_args], XtNmenuName, OPTION_MENU); num_args++;
  (void) XtCreateManagedWidget("options", menuButtonWidgetClass,
				  hpane, arglist, num_args);

  CreateOptionMenu(man_globals, top);

  num_args = 0;
  XtSetArg(arglist[num_args], XtNmenuName, SECTION_MENU); num_args++;
  sections = XtCreateManagedWidget("sections", menuButtonWidgetClass,
				   hpane, arglist, num_args);
#endif

#ifdef MOTIF
  man_globals->option_menu = XtNameToWidget( menuBar, OPTION_MENU );
  if ( !man_globals->option_menu ) {
    fprintf( stderr, "NULL widget.\n" );
    exit( -1 );
  }
  /* why did i do this ?  bonus if you can find the answer 8-) */ 
  XtVaGetValues( man_globals->option_menu,
      XmNsubMenuId, &pulldown,
      NULL );
    
  CreateOptionMenu( man_globals, pulldown );

  sections = XtNameToWidget( menuBar, SECTION_MENU );

  xms = XmStringCreateSimple( SHOW_BOTH );
  XtSetArg(arglist[0], XmNlabelString, xms);
#else
  XtSetArg(arglist[0], XtNlabel, SHOW_BOTH);
#endif
  XtSetValues(man_globals->both_screens_entry, arglist, (Cardinal) 1);

#ifdef MOTIF
  /* done with xms, free it */
  XmStringFree( xms );
#endif

  /* adjust menus according to full manpage, or just help window */

  if (full_instance) {
    MakeSearchWidget(man_globals, top);

#ifdef MOTIF
    XtVaGetValues( sections,
      XmNsubMenuId, &pulldown,
      NULL );
    CreateSectionMenu(man_globals, pulldown);
#else

    CreateSectionMenu(man_globals, top);
#endif
    MakeSaveWidgets(man_globals, top);
  } else {
    XtSetSensitive(sections, FALSE);       
    XtSetArg(arglist[0], XtNsensitive, FALSE);
    XtSetValues(man_globals->dir_entry, arglist, ONE);
    XtSetValues(man_globals->manpage_entry, arglist, ONE);
    XtSetValues(man_globals->help_entry, arglist, ONE);
    XtSetValues(man_globals->search_entry, arglist, ONE);
    XtSetValues(man_globals->both_screens_entry, arglist, ONE);
  }

#ifndef MOTIF
  man_globals->label = XtCreateManagedWidget(MANNAME, labelWidgetClass,
					     hpane, NULL, (Cardinal) 0);
#endif

/* Create Directory */

  if (full_instance) {
    num_args = 0;
#ifdef MOTIF
    mpw->directory = XmCreateForm( pane, DIRECTORY_NAME, NULL, ZERO );
    XtManageChild( mpw->directory );
#else
    XtSetArg(arglist[num_args], XtNallowVert, TRUE);
    num_args++;
    mpw->directory = XtCreateWidget(DIRECTORY_NAME, viewportWidgetClass,
				    pane, arglist, num_args);
#endif
    
    man_globals->current_directory = INITIAL_DIR;
    MakeDirectoryBox(man_globals, mpw->directory,
		     mpw->box + man_globals->current_directory, 
		     man_globals->current_directory );
    XtManageChild(mpw->box[man_globals->current_directory]);

  }


/* Create Manpage */
#ifdef MOTIF
  /* hack to put the scrlbar outside the scrlByLine widget ! */
  /*   see ScrollByL.c:CreateScollbar()   */
  form = XmCreateForm( pane, "form", NULL, 0 );
  XtManageChild( form );

  /* give it 3d appearance */
  num_args = 0;
  XtSetArg(arglist[num_args], XmNshadowThickness, 2); num_args++;
  XtSetArg(arglist[num_args], XmNleftAttachment, XmATTACH_FORM); num_args++;
  XtSetArg(arglist[num_args], XmNrightAttachment, XmATTACH_FORM); num_args++;
  XtSetArg(arglist[num_args], XmNtopAttachment, XmATTACH_FORM); num_args++;
  XtSetArg(arglist[num_args], XmNbottomAttachment, XmATTACH_FORM); num_args++;
  pane = XmCreateFrame( form, "frame", arglist, num_args );
  XtManageChild( pane );
#endif

  mpw->manpage = XtCreateWidget(MANUALPAGE, scrollByLineWidgetClass,
				pane, NULL, (Cardinal) 0);

}

/*	Function Name: StartManpage
 *	Description: Starts up a new manpage.
 *	Arguments: man_globals - the psuedo globals variable.
 *                 help - is this a help file?
 *                 page - Is there a page to display?
 *	Returns: none.
 */

static void
StartManpage(man_globals, help, page)
ManpageGlobals * man_globals;
Boolean help, page;
{
#ifdef MOTIF
  XmString xmsShowOne = XmStringCreateSimple( SHOW_ONE );
#endif
  Widget dir = man_globals->manpagewidgets.directory;
  Widget manpage = man_globals->manpagewidgets.manpage;
  Widget label = man_globals->label;
  Arg arglist[1];

/* 
 * If there is a helpfile then put up both screens if both_show is set.
 */

  if (page || help) {
    if (help) 
#ifdef MOTIF
      strcpy(man_globals->manpage_title, "Mxman Help");
#else
      strcpy(man_globals->manpage_title, "Xman Help");
#endif

    if (man_globals->both_shown) {
      XtManageChild(dir);
      man_globals->dir_shown = TRUE;

#ifdef MOTIF
      XtSetArg(arglist[0], XmNheight, resources.directory_height);
#else
      XtSetArg(arglist[0], XtNpreferredPaneSize, resources.directory_height);
#endif
      XtSetValues(dir, arglist, (Cardinal) 1);

      XtSetArg(arglist[0], XtNsensitive, FALSE);
      XtSetValues(man_globals->manpage_entry, arglist, ONE);
      XtSetValues(man_globals->dir_entry, arglist, ONE);

#ifdef MOTIF
      XtSetArg(arglist[0], XmNlabelString, xmsShowOne);
#else
      XtSetArg(arglist[0], XtNlabel, SHOW_ONE);
#endif
      XtSetValues(man_globals->both_screens_entry, arglist, ONE);
      ChangeLabel(label,
		  man_globals->section_name[man_globals->current_directory]);
    }
    else {
      ChangeLabel(label,man_globals->manpage_title);
    }
    XtManageChild(manpage);
    man_globals->dir_shown = FALSE;
  
  }
/*
 * Since no help file to display, put up directory and do not allow change
 * to manpage, show both, or help.
 */
  else {			
#ifdef MOTIF
    /* Pane->Form->Frame->manpage */
    XtManageChild(manpage);   /* managed but not shown */
    XtUnmanageChild( XtParent( XtParent( manpage ) ) );
#endif
    XtManageChild(dir);
    man_globals->dir_shown = TRUE;
    XtSetArg(arglist[0], XtNsensitive, FALSE);
    XtSetValues(man_globals->manpage_entry,        arglist, ONE);
    XtSetValues(man_globals->help_entry,           arglist, ONE);
    XtSetValues(man_globals->both_screens_entry,   arglist, ONE);
    man_globals->both_shown = FALSE;
    ChangeLabel(label,
		man_globals->section_name[man_globals->current_directory]);
  }

/*
 * Start 'er up, and change the cursor.
 */

  XtRealizeWidget( man_globals->This_Manpage );
  SaveGlobals( man_globals->This_Manpage, man_globals);
  XtMapWidget( man_globals->This_Manpage );
  AddCursor( man_globals->This_Manpage, resources.cursors.manpage);
  XtSetArg(arglist[0], XtNtransientFor, man_globals->This_Manpage);
  XtSetValues(XtParent(man_globals->standby), arglist, (Cardinal)1);
  XtSetValues(XtParent(man_globals->save), arglist, (Cardinal) 1);
  XtRealizeWidget(XtParent(man_globals->standby));
  XtRealizeWidget(XtParent(man_globals->save));
  AddCursor( XtParent(man_globals->standby), resources.cursors.top);
  AddCursor( XtParent(man_globals->save), resources.cursors.top);

/*
 * Set up ICCCM delete window.
 */
  XtOverrideTranslations
      (man_globals->This_Manpage, 
       XtParseTranslationTable ("<Message>WM_PROTOCOLS: RemoveThisManpage()"));
  (void) XSetWMProtocols (XtDisplay(man_globals->This_Manpage),
			  XtWindow(man_globals->This_Manpage),
			  &wm_delete_window, 1);

#ifdef MOTIF
  XmStringFree( xmsShowOne );
#endif
}

/*      Function Name: MenuDestroy
 *      Description: free's data associated with menu when it is destroyed.
 *      Arguments: w - menu widget.
 *                 free_me - data to free.
 *                 junk - not used.
 *      Returns: none.
 */

/* ARGSUSED */
static void
MenuDestroy(w, free_me, junk)
Widget w;
XtPointer free_me, junk;
{
  XtFree( (char *) free_me);
}

/*      Function Name:   CreateOptionMenu
 *      Description: Create the option menu.
 *      Arguments: man_globals - the manual page globals.
 *                 parent - the button that activates the menu.
 *      Returns: none.
 */

static void
CreateOptionMenu(man_globals, parent)
ManpageGlobals * man_globals;
Widget parent;
{
  Widget menu, entry;
  int i;
  static char * option_names[] = {	/* Names of the buttons. */
    DIRECTORY,
    MANPAGE,
    HELP,
    SEARCH,
    BOTH_SCREENS, 
    REMOVE_MANPAGE,
    OPEN_MANPAGE,
    SHOW_VERSION,
    QUIT
  };

#ifndef MOTIF 
  menu = XtCreatePopupShell(OPTION_MENU, simpleMenuWidgetClass, parent,
			    NULL, (Cardinal) 0);
  man_globals->option_menu = menu;
#endif
  
  for (i = 0 ; i < NUM_OPTIONS ; i++) {
#ifdef MOTIF
    /* all the work has been done using dyoung menu support             */
    /* we just need to get a hold of all the button widgets in the menu */
    /*   parent is the pulldown widget of option menu                   */
    entry = XtNameToWidget( parent, option_names[i] );
    if ( !entry ) {
      fprintf( stderr, "Error: \"%s\" is a NULL widget.\n", option_names[i] );
      exit( -1 );
    }
#else
    entry = XtCreateManagedWidget(option_names[i], smeBSBObjectClass,
				  menu, NULL, ZERO);
    XtAddCallback(entry, XtNcallback, OptionCallback, (caddr_t) man_globals);
#endif
    switch (i) {
    case 0:
	man_globals->dir_entry = entry;
	break;
    case 1:
	man_globals->manpage_entry = entry;
	break;
    case 2:
	man_globals->help_entry = entry;
	break;
    case 3:
	man_globals->search_entry = entry;
	break;
    case 4:
	man_globals->both_screens_entry = entry;
	break;
    case 5:
	man_globals->remove_entry = entry;
	break;
    case 6:
	man_globals->open_entry = entry;
	break;
    case 7:
	man_globals->version_entry = entry;
	break;
    case 8:
	man_globals->quit_entry = entry;
	break;
    default:
	break;
    }
  }
}

/*      Function Name: CreateSectionMenu
 *      Description: Create the Section menu.
 *      Arguments: man_globals - the manual page globals.
 *                 parent - the button that activates the menu.
 *      Returns: none.
 */

static void
CreateSectionMenu(man_globals, parent)
ManpageGlobals * man_globals;
Widget parent;
{
#ifdef MOTIF
  XmString xms;
#endif
  Widget menu, entry;
  int i;
  MenuStruct * menu_struct;
  Arg args[5];
  Cardinal num_args;
  char entry_name[BUFSIZ];

#ifndef MOTIF
  menu = XtCreatePopupShell(SECTION_MENU, simpleMenuWidgetClass, parent,
			    NULL, (Cardinal) 0);
#endif

  for (i = 0 ; i < sections ; i ++) {
    num_args = 0;
#ifdef MOTIF
    xms = XmStringCreateSimple( manual[i].blabel );
    XtSetArg(args[num_args], XmNlabelString, xms); num_args++;
    XtSetArg(args[num_args], XmNindicatorType, XmONE_OF_MANY); num_args++;
    if ( i==0 ) { /* The first one is on */
      XtSetArg(args[num_args], XmNset, True); num_args++;
    }
#else
    XtSetArg(args[num_args], XtNlabel, manual[i].blabel); num_args++;
#endif
    sprintf(entry_name, "section%d", i);
      
#ifdef MOTIF
    entry = XtCreateManagedWidget(entry_name, xmToggleButtonGadgetClass,
				  parent, args, num_args);
    XmStringFree( xms ); /* done with xms, free it */
#else
    entry = XtCreateManagedWidget(entry_name, smeBSBObjectClass,
				  menu, args, num_args);
#endif
    menu_struct = (MenuStruct *) XtMalloc(sizeof(MenuStruct));
    menu_struct->data = (caddr_t) man_globals;
    menu_struct->number = i;
#ifdef MOTIF
    XtAddCallback(entry, XmNvalueChangedCallback, DirPopupCallback, 
		    (XtPointer) menu_struct);
    XtAddCallback(entry, XmNdestroyCallback, MenuDestroy, 
		    (XtPointer) menu_struct);
#else
    XtAddCallback(entry, XtNcallback, DirPopupCallback, (caddr_t) menu_struct);
    XtAddCallback(entry, XtNdestroyCallback,MenuDestroy, (caddr_t)menu_struct);
#endif
  }
}

/*	Function Name: CreateList
 *	Description: this function prints a label in the directory list
 *	Arguments: section - the manual section.
 *	Returns: none
 */

static char **
CreateList(section)
{
  char ** ret_list, **current;
  int count;

  ret_list = (char **) XtMalloc( (manual[section].nentries + 1) * 
				   sizeof (char *));

  for (current = ret_list, count = 0 ; count < manual[section].nentries ;
       count++, current++)
    *current = CreateManpageName(manual[section].entries[count], section,
				 manual[section].flags);
 
  *current = NULL;		/* NULL terminate the list. */
  return(ret_list);
}

/*	Function Name: MakeDirectoryBox
 *	Description: make a directory box.
 *	Arguments: man_globals - the psuedo global structure for each manpage.
 *                 parent - this guys parent widget.
 *                 dir_disp - the directory display widget.
 *                 section - the section number.
 *	Returns: none.
 */

void
MakeDirectoryBox(man_globals,parent,dir_disp,section)
ManpageGlobals *man_globals;
Widget parent, *dir_disp;
int section;
{
  Arg arglist[10];
  Cardinal num_args;
  char * name, label_name[BUFSIZ];

  if (*dir_disp != NULL)	/* If we have one, don't make another. */
    return;

  name = manual[section].blabel;   /* Set the section name */
  sprintf(label_name,"Directory of: %s",name);
  man_globals->section_name[section] = StrAlloc(label_name);

  num_args = 0;
#ifdef MOTIF
  /* (7/8/93:hajadi)
     Motif XmList widget doesn't allow horizontal list.
     I suppose I could've used PD spreadsheet widget.  Maybe next time...
  */
  {
    int i=0;
    char** strList = CreateList(section);

    XmString *xmsList = 
      (XmString *) XtMalloc( manual[section].nentries * sizeof( XmString ) );
    if ( !xmsList ) 
      PopupWarning( man_globals, "Couldn't allocate memory!" );

    while ( strList[ i ] ) {
      xmsList[ i ] = XmStringCreateSimple( strList[ i ] );
      i++;
    }

    XtSetArg(arglist[num_args], XmNtopAttachment, XmATTACH_FORM);num_args++;
    XtSetArg(arglist[num_args], XmNbottomAttachment, XmATTACH_FORM);num_args++;
    XtSetArg(arglist[num_args], XmNleftAttachment, XmATTACH_FORM);num_args++;
    XtSetArg(arglist[num_args], XmNrightAttachment, XmATTACH_FORM);num_args++;
    XtSetArg(arglist[num_args], XmNselectionPolicy, XmSINGLE_SELECT);num_args++;
    XtSetArg(arglist[num_args], XmNitems, xmsList); num_args++;
    XtSetArg(arglist[num_args], XmNitemCount, i); num_args++;
    *dir_disp = XmCreateScrolledList( parent, DIRECTORY_NAME, 
				      arglist, num_args ); 

    XtAddCallback(*dir_disp, XmNsingleSelectionCallback,
		DirectoryHandler, (XtPointer) man_globals);

    /* release memory used by XmString's */
    while ( i>0 ) {
      XmStringFree( xmsList[ --i ] );
    }
    XtFree( (XtPointer) xmsList );
      
  } 
#else
  XtSetArg(arglist[num_args], XtNlist, CreateList(section)); num_args++;
  XtSetArg(arglist[num_args], XtNfont, resources.fonts.directory); num_args++;
  
  *dir_disp = XtCreateWidget(DIRECTORY_NAME, listWidgetClass, parent,
			     arglist, num_args);
  
  XtAddCallback(*dir_disp, XtNcallback,
		DirectoryHandler, (caddr_t) man_globals);
#endif
}

/*	Function Name: MakeSaveWidgets.
 *	Description: This functions creates two popup widgets, the please 
 *                   standby widget and the would you like to save widget.
 *	Arguments: man_globals - the psuedo globals structure for each man page
 *                 parent - the realized parent for both popups.
 *	Returns: none.
 */
#ifdef MOTIF
/* stub callback to call SaveFormattedPage handler. */
static void saveFormattedPage( Widget w, XtPointer p1, XtPointer p2 )
{
  Cardinal npar = 1; String par = "S";
  SaveFormattedPage( w, NULL, &par, &npar );
}
#endif

void
MakeSaveWidgets(man_globals, parent)
ManpageGlobals *man_globals;
Widget parent;
{
  Widget shell, dialog; /* misc. widgets. */
  Arg warg[1];
  Cardinal n = 0;

/* make the please stand by popup widget. */
#ifdef MOTIF
  man_globals->standby = XmCreateWorkingDialog( parent, 
						"pleaseStandBy", 
						NULL, (Cardinal) 0 );
  /* Keep the msg, but remove all other widgets from that dialog. */
  XtUnmanageChild( XmMessageBoxGetChild( man_globals->standby,
					 XmDIALOG_CANCEL_BUTTON ) );
  XtUnmanageChild( XmMessageBoxGetChild( man_globals->standby,
					 XmDIALOG_HELP_BUTTON ) );
  XtUnmanageChild( XmMessageBoxGetChild( man_globals->standby,
					 XmDIALOG_OK_BUTTON ) );
  XtUnmanageChild( XmMessageBoxGetChild( man_globals->standby,
					 XmDIALOG_SEPARATOR ) );

  /* save dialog */

  man_globals->save = XmCreateQuestionDialog( parent,
					      "likeToSave",
					      NULL, (Cardinal) 0 );
  XtUnmanageChild( XmMessageBoxGetChild( man_globals->save,
					 XmDIALOG_HELP_BUTTON ) );
  XtAddCallback( man_globals->save, XmNokCallback, saveFormattedPage, NULL );
#else
  if (XtIsRealized(parent)) {
      XtSetArg(warg[0], XtNtransientFor, parent);	n++;
  }
  shell = XtCreatePopupShell( "pleaseStandBy", transientShellWidgetClass,
			      parent, warg, (Cardinal) n);

  man_globals->standby = XtCreateManagedWidget("label", labelWidgetClass, 
					       shell, NULL, (Cardinal) 0);

  man_globals->save = XtCreatePopupShell("likeToSave",
					 transientShellWidgetClass,
					 parent, warg, n);

  dialog = XtCreateManagedWidget("dialog", dialogWidgetClass, 
				 man_globals->save, NULL, (Cardinal) 0);

  XawDialogAddButton(dialog, FILE_SAVE, NULL, NULL);
  XawDialogAddButton(dialog, CANCEL_FILE_SAVE, NULL, NULL);

  if (XtIsRealized(parent)) {
      XtRealizeWidget(shell);
      AddCursor(shell,resources.cursors.top);
      XtRealizeWidget(man_globals->save);
      AddCursor(man_globals->save, resources.cursors.top);
  }
#endif

}

/*      Function Name: FormUpWidgets
 *      Description: Sizes widgets to look nice.
 *      Arguments: parent - the common parent of all the widgets.
 *                 full_size - array of widget names that will he full size.
 *                 half_size - array of widget names that will he half size.
 *      Returns: none
 */

#ifndef MOTIF
void
FormUpWidgets(parent, full_size, half_size)
Widget parent;
char ** full_size, ** half_size;
{
  Widget * full_widgets, * half_widgets, *temp, long_widget;
  Dimension longest, length, b_width;
  int interior_dist;
  Arg arglist[2];
    
  full_widgets = ConvertNamesToWidgets(parent, full_size);
  half_widgets = ConvertNamesToWidgets(parent, half_size);
  
  long_widget = NULL;
  longest = 0;
  XtSetArg(arglist[0], XtNwidth, &length);
  XtSetArg(arglist[1], XtNborderWidth, &b_width);

/*
 * Find Longest widget.
 */

  for ( temp = full_widgets ; *temp != (Widget) NULL ; temp++) {
    XtGetValues(*temp, arglist, (Cardinal) 2);
    length += 2 * b_width;
    if (length > longest) {
      longest = length;
      long_widget = *temp;
    }
  }

  if (long_widget == (Widget) NULL) {          /* Make sure we found one. */
    PopupWarning(GetGlobals(parent), 
		 "Could not find longest widget, aborting...");
    XtFree((char *)full_widgets);
    XtFree((char *)half_widgets);
    return;
  }

/*
 * Set all other full_widgets to this length.
 */

  for ( temp = full_widgets ; *temp != (Widget) NULL ; temp++ )
    if ( long_widget != *temp) {
      Dimension width, border_width;

      XtSetArg(arglist[0], XtNborderWidth, &border_width);
      XtGetValues(*temp, arglist, (Cardinal) 1);
    
      width = longest - 2 * border_width;
      XtSetArg(arglist[0], XtNwidth, width);
      XtSetValues(*temp, arglist, (Cardinal) 1);
    }

/*
 * Set all the half widgets to the right length.
 */

  XtSetArg(arglist[0], XtNdefaultDistance, &interior_dist);
  XtGetValues(parent, arglist, (Cardinal) 1);
  
  for ( temp = half_widgets ; *temp != (Widget) NULL ; temp++) {
    Dimension width, border_width;

    XtSetArg(arglist[0], XtNborderWidth, &border_width);
    XtGetValues(*temp, arglist, (Cardinal) 1);
    
    width = (int)(longest - interior_dist)/2 - 2 * border_width;
    XtSetArg(arglist[0], XtNwidth, width);
    XtSetValues(*temp, arglist, (Cardinal) 1);
  }

  XtFree((char *)full_widgets);
  XtFree((char *)half_widgets);
}
#endif /* MOTIF */
  
/*      Function Name: ConvertNamesToWidgets
 *      Description: Convers a list of names into a list of widgets.
 *      Arguments: parent - the common parent of these widgets.
 *                 names - an array of widget names.
 *      Returns: an array of widget id's.
 */

static Widget *
ConvertNamesToWidgets(parent, names)
Widget parent;
char ** names;
{
  char ** temp;
  Widget * ids, * temp_ids;
  int count;

  for (count = 0, temp = names; *temp != NULL ; count++, temp++);

  ids = (Widget *) XtMalloc( (count + 1) * sizeof(Widget));

  
  for ( temp_ids = ids; *names != NULL ; names++, temp_ids++) {
    *temp_ids = XtNameToWidget(parent, *names);
    if (*temp_ids == NULL) {
      char error_buf[BUFSIZ];
    
      sprintf(error_buf, "Could not find widget named '%s'", *names);
      PrintError(error_buf);
      XtFree((char *)ids);
      return(NULL);
    }
  }
  
  *temp_ids = (Widget) NULL;
  return(ids);
}
    
