/*
 * Copyright 1990 by Baylor College of Medicine ALL RIGHTS RESERVED. 
 *
 * This program is subject to a license agreement between 
 * Baylor College of Medicine and MIT. Any use inconsistent with
 * said license and any use by persons other than the faculty, 
 * students and staff at MIT or any use on a computer not operated 
 * as part of the Athena Computing Environment (ACE) is expressly 
 * prohibited.
 */
/*******************************************************************************
* SYSTEM...: Virtual Notebook System
*
* MODULE...: print_popup.c
*
* PURPOSE..:
*   Provides the user interface pop-up window for the vns printing facility
*
* TAG: PSPU
*
* REVISIONS:
*   Ross Dargahi                February 1990
*
* COMMENTS:
*   This module is far too big & should be broken up!! Ross D.
*
*******************************************************************************/

#define PRINT_POPUP_C    /*define source name for includes*/

/*******************************************************************************
Include Files
*******************************************************************************/

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/CoreP.h>
#include <X11/Shell.h>
#include <Xm/Form.h>
#include <Xm/Frame.h>
#include <Xm/LabelG.h>
#include <Xm/List.h>
#include <Xm/PushBG.h>
#include <Xm/RowColumn.h>
#include <Xm/Scale.h>
#include <Xm/TextF.h>
#include <Xm/ToggleBG.h>

#include <srvlib.h>
#include <pagelist.h>
#include <page_to_ps.h>
/*#include "../newps/page_to_ps.h"*/
#include <printer.h>

/*******************************************************************************
Private Defines
*******************************************************************************/

#define PSPU_MAXCOPIES       99     /*maximum allowed value for # copies*/
#define PSPU_MAXMARGIN       99.99  /*maximum allowed value for a margin*/
#define PSPU_MAXPRINTERS     32     /*maximum number of printers allowed*/

/*******************************************************************************
Private Data Structures
*******************************************************************************/

typedef struct setGetFunc_s  /*ps state variable set & get function pointers*/
{
  void  (*set)();  /*set value function pointer*/
  union
   {
      float (*getf)();    /*get float value function pointer*/
      char  *(*getcp)();  /*get char * value function pointer*/
   } type;
} PSPUsetGetFunc_s; 


typedef enum showObj_e  /*showable object list*/
{
  PSPU_ALINK,    /*action link*/
  PSPU_AUDIO,    /*audio link*/
  PSPU_GRID,     /*page grid*/
  PSPU_IMAGE,    /*images*/
  PSPU_OUTLINE,  /*object outlines*/
  PSPU_PLINK,    /*page links*/
  PSPU_TEXT      /*text*/
} PSPU_SHOWOBJ_E;

/*******************************************************************************
Private Function Prototypes
*******************************************************************************/

static int  badFloat();
static int  badInt();
static int  badText();
static void colourToggleCallback();
static void createColourToggle();
static void createCopiesTxt();
static void createMarginGroup();
static void createOptionButtons();
static void createOptionsPopup();
static void createOutputOptionsGroup();
static void createOutputOptsRadioGrp();
static void createOutputOptsTxt();
static void createPageOrientationGroup();
static void createPageScaleSlider();
static void createPaperOptionsGroup();
static void createPhysicalMarginGroup();
static void createPrintLabel();
static void createPrintMethodGroup();
static void createPrintOptionsGroup();
static void createPrinterOptionsGroup();
static void createPrintPopup();
static void createShowObjGroup();
static void createSitePrinterGroup();
static void createUniqueFnameToggle();
static void createUserMarginGroup();
static char *getDefaultPrinter();
static void optionPopupOkButtonCb();
static void printButtonCallBack();
static void printCopiesChangedCallback();
static void printMarginChangedCallback();
static void printMethodCallback();
static void printNamesCallback();
static void printPopupCancelButtonCb();
static void printPopupOptionButtonCb();
static void printOrientationCallback();
static void printOutputCallback();
static void printScaleCallback();
static void setPrintMethod();
static void setTextFloatField();
static void showObjCallback();
static void sitePrinterCallback();
static void uniqueFnameToggleCallback();

/*******************************************************************************
Private Global Declarations
*******************************************************************************/

static Widget    optionsPopup;  /*printing options widget*/
static PRINTER_S printers[32];  /*array of printers parameters*/
static Widget    printPopup;    /*print popup widget*/

static struct _print_context /*printing context*/
{
  SrvContext *srv;  /*server connection id*/
  int        nid;  /*notebook id*/
  int        pid;  /*page id*/
  char       *sitefile; /* site printer file */
} pc;

/*******************************************************************************
****************************    PUBLIC FUNCTIONS    ****************************
*******************************************************************************/

void VtPrint(parent, srv, nid, pid, title, sitefile)

Widget      parent;  /*parent widget to grow off of*/
SrvContext  *srv;    /*database server context*/
int         nid;     /*notebook id of page to print*/
int         pid;     /*page id of page to print*/
char        *title;  /*title of the page to print*/
char        *sitefile; /* site printer file */

/*create/display print & options popup windows and allow printing*/

{
  static Boolean PrintPopupCreated = FALSE; /*T:print popup created*/

  XmString aLabel;    /*compound string to display page title*/
  char     buf[256];  /*buffer for the page title*/
  int      proc_id;   /*current users pid*/
  Widget   pageLabel; /*popup page title widget*/

  /* set the site printer file path */
  pc.sitefile = strdup(sitefile);

  /*create the popups if not done before*/

  if (!PrintPopupCreated)  
   {
     init_ps(); /*initialize the page to postscript driver*/
     createPrintPopup(parent);  /*create the print popup*/
     createOptionsPopup(parent);  /*create the options popup*/
     PrintPopupCreated = TRUE;
   }
 
  /*setup the page context for printing*/
 
  proc_id = getpid();
  pc.srv = srv;
  pc.nid = nid;
  pc.pid = pid;

  /*set the current page field*/

  pageLabel = XtNameToWidget(printPopup,"*printlabel");
  sprintf(buf,"Current Page:   %s",title);
  aLabel = XmStringCreateLtoR(buf, XmSTRING_DEFAULT_CHARSET);
  XtVaSetValues(pageLabel, XmNlabelString, aLabel, NULL);
  XmStringFree(aLabel);

  XtManageChild(printPopup);

} /*VtPrint*/

/*******************************************************************************
****************************    PRIVATE FUNCTIONS    ***************************
*******************************************************************************/

static int badFloat(text)

char *text;  /*text to check*/

/*checks if a string is a correct ascii representation of an floating number*/

{
  char  aChar;     /*current character in text string*/
  short decPoint;  /*T:decimal point found*/
  short lcv;       /*Loop control variable*/
  int   len;       /*Length of text string*/

  decPoint = False;

  if ((len = strlen(text)) == 0)
     return(-1);
  else
     for (lcv = 0; lcv < len; lcv++)
        if ((aChar = *(text + lcv)) == '.')
         {
           if (decPoint)  /*already have a decimal point*/
              return(-1);
           else
              decPoint = True;
         }
        else if (aChar < '0' || aChar > '9')
           return(-1);

  return(0);

} /*badFloat*/

/******************************************************************************/
static int badInt(text)

char *text;  /*text to check*/

/*checks if a string is a correct ascii representation of an integer number*/

{
  char  aChar;     /*current character in text string*/
  short lcv;       /*Loop control variable*/
  int   len;       /*Length of text string*/

  if ((len = strlen(text)) == 0)
     return(-1);
  else
     for (lcv = 0; lcv < len; lcv++)
        if ((aChar = *(text+lcv)) < '0' || aChar > '9')
           return(-1);

  return(0);

} /*badInt*/

/******************************************************************************/
static int badText(text, except)

char *text;   /*text to check*/
char *except; /*aharacters not permitted in text*/

/*checks if a string contains any illegal characters <except>*/

{
  if (strcspn(text, except) == strlen(text))
     return(0);
  else
     return(-1);

} /*badText*/

/******************************************************************************/
static void colourToggleCallback(refWidget, dummy, reason)

Widget                       refWidget;  /*widget invoking the callback*/
XtPointer                    dummy;      /*user data*/
XmToggleButtonCallbackStruct *reason;    /*reason affected*/

/*callback function for the print in colour toggle*/

{
  set_color(reason->set);

} /*colourToggleCallback*/

/******************************************************************************/
static void createColourToggle(parent)

Widget parent; 

/*creates the toggle button that allows the selection of colour on those
printer devices that allow colour or when file mode is selected*/

{
  XmString aLabel;
  Widget   colourToggleFrame;
  Widget   colourToggle;

  colourToggleFrame = XtVaCreateManagedWidget("colourtoggleframe",
                          xmFrameWidgetClass, parent,
                          XmNshadowType, XmSHADOW_ETCHED_IN,
                          XmNtopAttachment, XmATTACH_FORM,
                          XmNleftAttachment, XmATTACH_WIDGET,
                          XmNleftWidget, XtNameToWidget(optionsPopup, 
                                                    "*outputradiogroupframe"),
                          XmNleftOffset, 10,
                          XmNrightAttachment, XmATTACH_FORM,
                          XmNrightOffset, 10,
                          NULL);

  aLabel = XmStringCreateLtoR("Print In Colour", XmSTRING_DEFAULT_CHARSET);
  colourToggle = XtVaCreateManagedWidget("printcolour",
                          xmToggleButtonGadgetClass, colourToggleFrame,
                          XmNlabelString, aLabel,
                          XmNset, False,
                          NULL);
  XtAddCallback(colourToggle, XmNvalueChangedCallback, colourToggleCallback, 
                NULL);
  XmStringFree(aLabel);

} /*createColourToggle*/

/******************************************************************************/
static void createCopiesTxt(parent)

Widget parent;

/*create the # copies label and text field widgets for inclusion in the output
group*/

{
  XmString aLabel;
  char     asciiValue[8];  /*ascii rep of current # copies*/
  Widget   copiesField;
  Widget   copiesForm;
  Widget   copiesFrame;
  Widget   copiesLabel;
  Widget   offsetWidget;   /*widget to offset copies field from in form*/

  offsetWidget = XtNameToWidget(optionsPopup, "*colourtoggleframe");

  copiesFrame = XtVaCreateManagedWidget("copiesframe",
                 xmFrameWidgetClass, parent,
                 XmNshadowType, XmSHADOW_ETCHED_IN,
                 XmNmarginWidth, 5,
                 XmNmarginHeight, 5,
                 XmNtopAttachment, XmATTACH_WIDGET,
                 XmNtopWidget, XtNameToWidget(optionsPopup, 
                                              "*uniquetoggleframe"),
                 XmNtopOffset, 10,
                 XmNleftAttachment, XmATTACH_WIDGET,
                 XmNleftWidget, XtNameToWidget(optionsPopup, 
                                               "*outputradiogroupframe"),
                 XmNleftOffset, 10,
                 XmNrightAttachment, XmATTACH_FORM,
                 XmNrightOffset, 10,
                 NULL);

  copiesForm = XtVaCreateManagedWidget("copiesform",
                 xmFormWidgetClass, copiesFrame, 
                 XmNallowOverlap, False,
                 XmNwidth, 100,
                 XmNverticalSpacing, 5,
                 XmNhorizontalSpacing, 0,
                 NULL);

  sprintf(asciiValue, "%d", get_copies());
  copiesField = XtVaCreateManagedWidget("copiesfield",
                 xmTextFieldWidgetClass, copiesForm,
                 XmNmaxLength, 2,
                 XmNcolumns, 2,
                 XtNvalue, asciiValue,
                 XmNtopAttachment, XmATTACH_FORM,
                 XmNleftAttachment, XmATTACH_FORM,
                 NULL);
  XtAddCallback(copiesField, XmNlosingFocusCallback, printCopiesChangedCallback,
                NULL);
 
  aLabel = XmStringCreateLtoR("Copies", XmSTRING_DEFAULT_CHARSET);
  copiesLabel = XtVaCreateManagedWidget("filenamelabel",
                 xmLabelGadgetClass, copiesForm,
                 XmNalignment, XmALIGNMENT_BEGINNING,
                 XmNlabelString, aLabel,
                 XmNtopAttachment, XmATTACH_FORM,
                 XmNtopOffset, 10,
                 XmNleftAttachment, XmATTACH_WIDGET,
                 XmNleftWidget, copiesField,
                 NULL);
  XmStringFree(aLabel);

} /*createCopiesTxt*/

/******************************************************************************/
static void createMarginGroup()

/*Creates the frame and form for the user and printer margin groups and calls
the functions that create the user and printer margins*/

{
  Widget marginGrpForm;
  Widget marginGrpFrame;

  marginGrpFrame = XtVaCreateManagedWidget("margingrpframe",
                          xmFrameWidgetClass, optionsPopup,
                          XmNshadowType, XmSHADOW_ETCHED_IN,
                          XmNmarginWidth, 10,
                          XmNmarginHeight, 10,
                          XmNtopAttachment, XmATTACH_WIDGET,
                          XmNtopWidget, XtNameToWidget(optionsPopup, 
                                                       "*printeroptsgrpframe"),
                          XmNtopOffset, 10,
                          XmNleftAttachment, XmATTACH_FORM, 
                          XmNleftOffset, 10,
                          XmNrightAttachment, XmATTACH_FORM, 
                          XmNrightOffset, 10,
                          NULL);
  
  marginGrpForm = XtVaCreateManagedWidget("margingrpform",
                          xmFormWidgetClass, marginGrpFrame, 
                          XmNallowOverlap, False,
                          XmNverticalSpacing, 5,
                          XmNhorizontalSpacing, 0,
                          NULL);

  createUserMarginGroup(marginGrpForm);  /*user margins*/
  createPhysicalMarginGroup(marginGrpForm);  /*device margins*/

} /*createMarginGroup*/

/******************************************************************************/
static void createOptionButtons()

/*Creates the button controls that control the print options dialog. These are 
the ok, print, print test, and help buttons.*/

{
  Widget    aButton;           /*one of the buttons*/
  Widget    buttonGroupForm;   /*form for the buttons in the group*/
  Widget    buttonGroupFrame;  /*frame for the button group*/
  XmString  buttonLabel;       /*label for a button*/
  Dimension buttonWidth;       /*width of the buttons*/
  Widget    helpButton;        /*the help button*/
  Widget    printButton;       /*the print button (used in form layout)*/

  buttonWidth = 70;  /*make all the buttons the same size*/

  /*create the button group frame and forms*/

  buttonGroupFrame = XtVaCreateManagedWidget("buttongroupframe",
                                    xmFrameWidgetClass, optionsPopup,
                                    XmNshadowType, XmSHADOW_ETCHED_IN,
                                    XmNtopAttachment, XmATTACH_WIDGET,
                                    XmNtopWidget, XtNameToWidget(optionsPopup,
                                                            "*margingrpframe"),
                                    XmNtopOffset, 10,
                                    XmNleftAttachment, XmATTACH_FORM, 
                                    XmNleftOffset, 10,
                                    XmNrightAttachment, XmATTACH_FORM, 
                                    XmNrightOffset, 10,
                                    XmNbottomAttachment, XmATTACH_FORM,
                                    XmNbottomOffset, 10,
                                    NULL);

  buttonGroupForm = XtVaCreateManagedWidget("buttongroupform",
                                    xmFormWidgetClass, buttonGroupFrame,
                                    XmNallowOverlap, False,
                                    XmNhorizontalSpacing, 10,
                                    XmNverticalSpacing, 10,
                                    XmNheight, 55,
                                    NULL);

  /*create the ok button and add its callback to it*/

  buttonLabel = XmStringCreateLtoR("Ok", XmSTRING_DEFAULT_CHARSET);
  aButton = XtVaCreateManagedWidget("okbutton",
                                    xmPushButtonGadgetClass, buttonGroupForm,
                                    XmNlabelString, buttonLabel,
                                    XmNshowAsDefault, True,
                                    XmNdefaultButtonShadowThickness, 2,
                                    XmNwidth, buttonWidth,
                                    XmNtopAttachment, XmATTACH_FORM,
                                    XmNleftAttachment, XmATTACH_FORM,
                                    NULL);
  XtVaSetValues(optionsPopup,
                XmNdefaultButton, aButton,
                NULL);
  XtAddCallback(aButton, XmNactivateCallback, optionPopupOkButtonCb, NULL);
  XmStringFree(buttonLabel);

  /*create the print button*/

  buttonLabel = XmStringCreateLtoR("Print", XmSTRING_DEFAULT_CHARSET);
  printButton = XtVaCreateManagedWidget("printbutton",
                                    xmPushButtonGadgetClass, buttonGroupForm,
                                    XmNlabelString, buttonLabel,
                                    XmNdefaultButtonShadowThickness, 2,
                                    XmNwidth, buttonWidth,
                                    XmNtopAttachment, XmATTACH_FORM,
                                    XmNleftAttachment, XmATTACH_WIDGET,
                                    XmNleftWidget, aButton,
                                    NULL);
  XtAddCallback(printButton, XmNactivateCallback, printButtonCallBack, 
                (XtPointer)NULL);
  XmStringFree(buttonLabel);

  /*create the help button and add its callback to it*/

  buttonLabel = XmStringCreateLtoR("Help", XmSTRING_DEFAULT_CHARSET);
  helpButton = XtVaCreateManagedWidget("helpbutton",
                                    xmPushButtonGadgetClass, buttonGroupForm,
                                    XmNlabelString, buttonLabel,
                                    XmNdefaultButtonShadowThickness, 2,
                                    XmNwidth, buttonWidth,
                                    XmNsensitive, False,
                                    XmNtopAttachment, XmATTACH_FORM,
                                    XmNrightAttachment, XmATTACH_FORM,
                                    NULL);
  XmStringFree(buttonLabel);

  /*create the print test button and add its callback to it*/
/*
  buttonLabel = XmStringCreateLtoR("Print Test", XmSTRING_DEFAULT_CHARSET);
  aButton = XtVaCreateManagedWidget("testbutton",
                                    xmPushButtonGadgetClass, buttonGroupForm,
                                    XmNlabelString, buttonLabel,
                                    XmNdefaultButtonShadowThickness, 2,
                                    XmNwidth, buttonWidth,
                                    XmNsensitive, False,
                                    XmNtopAttachment, XmATTACH_FORM,
                                    XmNrightAttachment, XmATTACH_WIDGET,
                                    XmNrightWidget, helpButton,
                                    NULL);
  XmStringFree(buttonLabel);
*/
} /*CreateOptionButtons*/

/******************************************************************************/
static void createOptionsPopup(parent)

Widget parent;

/*construct the printing options popup. This is a dialog form that will not
allow any interaction by the invoking application until the dialog is responded
to.*/

{
  XmString  dialogTitle;
  XmString  listItem;

  optionsPopup = XmCreateFormDialog(parent, "optionspopup", NULL, 0);
  dialogTitle = XmStringCreateLtoR("VNS Printing Options", 
                                   XmSTRING_DEFAULT_CHARSET);
  XtVaSetValues(optionsPopup,
                XmNdialogTitle, dialogTitle,
                XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
                XmNnoResize, True,
                NULL);
  XmStringFree(dialogTitle);

  createPrintOptionsGroup(); /*method, orientation, objects to print, scale*/
  createPrinterOptionsGroup();  /*printer, paper, colour, copies, dest, file*/
  createMarginGroup();  /*user & printer*/
  createOptionButtons();  /*ok, print, print test, help*/

  listItem = XmStringCreateLtoR(printers[0].pname, XmSTRING_DEFAULT_CHARSET);
  XmListSelectItem(XtNameToWidget(optionsPopup,"*siteprinterlist"), listItem, 
                   True);
  XmStringFree(listItem);

} /*createOptionsPopup*/

/******************************************************************************/
static void createOutputOptionsGroup(parent)

Widget parent;  /*parent widget*/

/*creates the output options group which includes the output destination, colour
toggle, # copies, printer name field, & file name field*/

{
  XmString aLabel;       
  Widget   outputOptionsGrpForm;
  Widget   outputOptionsGrpFrame;
  Widget   outputOptionsGrpLabel;

  aLabel = XmStringCreateLtoR("Output To:", XmSTRING_DEFAULT_CHARSET);
  outputOptionsGrpLabel = XtVaCreateManagedWidget("outputoptionsgrplabel",
                          xmLabelGadgetClass, parent,
                          XmNalignment, XmALIGNMENT_BEGINNING,
                          XmNlabelString, aLabel,
                          XmNtopAttachment, XmATTACH_FORM,
                          XmNtopOffset, 5,
                          XmNleftAttachment, XmATTACH_WIDGET,
                          XmNleftWidget, XtNameToWidget(optionsPopup, 
                                                        "*papergroupframe"),
                          XmNleftOffset, 10,
                          NULL);
  XmStringFree(aLabel);

  outputOptionsGrpFrame = XtVaCreateManagedWidget("outputoptionsgrpframe",
                          xmFrameWidgetClass, parent,
                          XmNshadowType, XmSHADOW_ETCHED_IN,
                          XmNmarginWidth, 10,
                          XmNmarginHeight, 10,
                          XmNtopAttachment, XmATTACH_WIDGET,
                          XmNtopWidget, outputOptionsGrpLabel,
                          XmNrightAttachment, XmATTACH_FORM, 
                          XmNleftAttachment, XmATTACH_WIDGET,
                          XmNleftWidget, XtNameToWidget(optionsPopup, 
                                                        "*papergroupframe"),
                          XmNleftOffset, 10,
                          NULL);
  
  outputOptionsGrpForm = XtVaCreateManagedWidget("outputoptionsgrpform",
                          xmFormWidgetClass, outputOptionsGrpFrame, 
                          XmNallowOverlap, False,
                          XmNverticalSpacing, 5,
                          XmNhorizontalSpacing, 0,
                          NULL);

  createOutputOptsRadioGrp(outputOptionsGrpForm);  /*destination panel*/
  createColourToggle(outputOptionsGrpForm);  /*colour toggle*/
  createUniqueFnameToggle(outputOptionsGrpForm);  /*unique file name toggle*/
  createCopiesTxt(outputOptionsGrpForm);  /*# copies field*/
  createOutputOptsTxt(outputOptionsGrpForm);  /*printer & file fields*/

} /*createOutputOptionsGroup*/

/******************************************************************************/
static void createOutputOptsRadioGrp(parent)

Widget parent;

/*creates output options radio group which allows the selection of output
direction to a file, a printer, or both a file and a printer*/

{
  Widget    aToggle;                /*one of the buttons*/
  Widget    outputRadioGroupRC;     /*form for the buttons in the group*/
  Widget    outputRadioGroupForm;   /*frame for the button group*/
  Widget    outputRadioGroupFrame;  /*frame for the button group*/
  Widget    outputRadioGroupLabel;  /*frame for the button group*/
  XmString  aLabel;                 /*label for a button*/

  outputRadioGroupFrame = XtVaCreateManagedWidget("outputradiogroupframe",
                    xmFrameWidgetClass, parent,
                    XmNshadowType, XmSHADOW_ETCHED_IN,
                    XmNtopAttachment, XmATTACH_FORM,
                    XmNleftAttachment, XmATTACH_FORM,
                    NULL);

  outputRadioGroupRC = XtVaCreateManagedWidget("outputradiogrouprc",
                    xmRowColumnWidgetClass, outputRadioGroupFrame, 
                    XmNorientation, XmVERTICAL,
                    XmNnumColumns, 1,
                    XmNpacking, XmPACK_COLUMN,
                    XmNradioBehavior, True,
                    XmNradioAlwaysOne, True,
                    NULL);

  aLabel = XmStringCreateLtoR("Printer", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("outputprinter",
                    xmToggleButtonGadgetClass, outputRadioGroupRC,
                    XmNlabelString, aLabel,
                    XmNindicatorType, XmONE_OF_MANY,
                    XmNset, (get_outputTo() == P_PRINTER) ? True : False,
                    NULL);
  XtAddCallback(aToggle, XmNvalueChangedCallback, printOutputCallback, 
                P_PRINTER);
  XmStringFree(aLabel);

  aLabel = XmStringCreateLtoR("File", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("outputfile",
                    xmToggleButtonGadgetClass, outputRadioGroupRC,
                    XmNlabelString, aLabel,
                    XmNset, (get_outputTo() == P_FILE) ? True : False,
                    NULL);
  XtAddCallback(aToggle, XmNvalueChangedCallback, printOutputCallback, 
                P_FILE);
  XmStringFree(aLabel);

  aLabel = XmStringCreateLtoR("Printer & File", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("outputprinterfile",
                    xmToggleButtonGadgetClass, outputRadioGroupRC,
                    XmNlabelString, aLabel,
                    XmNset, (get_outputTo() == P_BOTH) ? True : False,
                    NULL);
  XtAddCallback(aToggle, XmNvalueChangedCallback, printOutputCallback, 
                P_BOTH);
  XmStringFree(aLabel);

}  /*createOutputOptsRadioGrp*/

/******************************************************************************/
static void createOutputOptsTxt(parent)

Widget parent;

/*create the filename & printer name label and text field widgets for inclusion
in the output group*/

{
  static   PSPUsetGetFunc_s fileNameInfo;      /*ps contxt get & set func ptrs*/
  static   PSPUsetGetFunc_s printerNameInfo;   /*ps contxt get & set func ptrs*/

  Widget   aField;
  XmString aLabel;
  Widget   aNameLabel;
  Widget   offsetWidget;  /*offset widget in the form*/

  offsetWidget = XtNameToWidget(optionsPopup, "*copiesframe");

  aLabel = XmStringCreateLtoR("File Name:", XmSTRING_DEFAULT_CHARSET);
  aNameLabel = XtVaCreateManagedWidget("filenamelabel",
                       xmLabelGadgetClass, parent,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNtopAttachment, XmATTACH_WIDGET,
                       XmNtopWidget, offsetWidget,
                       XmNtopOffset, 15,
                       XmNleftAttachment, XmATTACH_FORM,
                       NULL);
  XmStringFree(aLabel);

  aField = XtVaCreateManagedWidget("filenamefield",
                       xmTextFieldWidgetClass, parent,
                       XmNmaxLength, 15,
                       XmNtopAttachment, XmATTACH_WIDGET,
                       XmNtopWidget, offsetWidget,
                       XmNtopOffset, 10,
                       XmNleftAttachment, XmATTACH_WIDGET,
                       XmNleftWidget, aNameLabel,
                       XmNleftOffset, 30,
                       XmNrightAttachment, XmATTACH_FORM,
                       XmNrightOffset, 10,
                       NULL);
  fileNameInfo.set = set_fileName;
  fileNameInfo.type.getcp = (char *(*)())get_fileName; 
  XtAddCallback(aField, XmNlosingFocusCallback, printNamesCallback, 
                &fileNameInfo);
 
  aLabel = XmStringCreateLtoR("Printer Name:", XmSTRING_DEFAULT_CHARSET);
  aNameLabel = XtVaCreateManagedWidget("printernamelabel",
                       xmLabelGadgetClass, parent,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNtopAttachment, XmATTACH_WIDGET,
                       XmNtopWidget, aField,
                       XmNtopOffset, 15,
                       XmNleftAttachment, XmATTACH_FORM,
                       NULL);
  XmStringFree(aLabel);

  aField = XtVaCreateManagedWidget("printernamefield",
                       xmTextFieldWidgetClass, parent,
                       XmNmaxLength, 15,
                       XmNtopAttachment, XmATTACH_WIDGET,
                       XmNtopWidget, aField, /*filenamefield*/
                       XmNtopOffset, 10,
                       XmNleftAttachment, XmATTACH_WIDGET,
                       XmNleftWidget, aNameLabel,
                       XmNleftOffset, 10,
                       XmNrightAttachment, XmATTACH_FORM,
                       XmNrightOffset, 10,
                       NULL);
  printerNameInfo.set = set_printer;
  printerNameInfo.type.getcp = (char *(*)())get_printer; 
  XtAddCallback(aField, XmNlosingFocusCallback, printNamesCallback, 
                &printerNameInfo);

} /*createOutputOptsTxt*/

/******************************************************************************/
static void createPageOrientationGroup(parent)

Widget parent;

/*creates the radio group which allows the selection of printing page 
orientation*/

{
  Widget    aToggle;                
  Widget    orientationGroupRC;    
  Widget    orientationGroupForm; 
  Widget    orientationGroupFrame;
  Widget    orientationGroupLabel;
  XmString  aLabel;

  aLabel = XmStringCreateLtoR("Page Orientation:", XmSTRING_DEFAULT_CHARSET);
  orientationGroupLabel = XtVaCreateManagedWidget("orientationgrouplabel",
                    xmLabelGadgetClass, parent,
                    XmNalignment, XmALIGNMENT_BEGINNING,
                    XmNlabelString, aLabel,
                    XmNtopAttachment, XmATTACH_FORM,
                    XmNtopOffset, 5,
                    XmNleftAttachment, XmATTACH_POSITION,
                    XmNleftPosition, 40,
                    NULL);
  XmStringFree(aLabel);

  orientationGroupFrame = XtVaCreateManagedWidget("orientationgroupframe",
                    xmFrameWidgetClass, parent,
                    XmNshadowType, XmSHADOW_ETCHED_IN,
                    XmNtopAttachment, XmATTACH_WIDGET,
                    XmNtopWidget, orientationGroupLabel,
                    XmNleftAttachment, XmATTACH_POSITION,
                    XmNleftPosition, 40,
                    NULL);

  orientationGroupRC = XtVaCreateManagedWidget("orientationgrouprc",
                    xmRowColumnWidgetClass, orientationGroupFrame, 
                    XmNorientation, XmVERTICAL,
                    XmNnumColumns, 1,
                    XmNpacking, XmPACK_COLUMN,
                    XmNradioBehavior, True,
                    XmNradioAlwaysOne, True,
                    NULL);

  /*each toggle sets its value by calling the necessary ps convenience function
   *and setting its value based upon the result*/

  aLabel = XmStringCreateLtoR("Portrait", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("orientationportrait",
                    xmToggleButtonGadgetClass, orientationGroupRC,
                    XmNlabelString, aLabel,
                    XmNindicatorType, XmONE_OF_MANY,
                    XmNset, (get_orientation() == P_PORTRAIT) ? True : False,
                    NULL);
  XmStringFree(aLabel);
  XtAddCallback(aToggle, XmNvalueChangedCallback, printOrientationCallback, 
                P_PORTRAIT);

  aLabel = XmStringCreateLtoR("Landscape", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("orientationlandscape",
                    xmToggleButtonGadgetClass, orientationGroupRC,
                    XmNlabelString, aLabel,
                    XmNset, (get_orientation() == P_LANDSCAPE) ? True : False,
                    NULL);
  XmStringFree(aLabel);
  XtAddCallback(aToggle, XmNvalueChangedCallback, printOrientationCallback, 
                P_LANDSCAPE);

  aLabel = XmStringCreateLtoR("Automatic", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("orientationposter",
                    xmToggleButtonGadgetClass, orientationGroupRC,
                    XmNlabelString, aLabel,
                    XmNset, (get_orientation() == P_AUTO) ? True : False,
                    NULL);
  XmStringFree(aLabel);
  XtAddCallback(aToggle, XmNvalueChangedCallback, printOrientationCallback, 
                P_AUTO);

} /*createPageOrientationGroup*/

/******************************************************************************/
static void createPageScaleSlider(parent)

Widget parent;

/*sets up the slider bar that allows the user to set the scale at which to print
the page.*/

{
  XmString  aLabel;      
  Widget    aScale;
  Widget    scaleLabel; 
  Widget    scaleScale;

  aLabel = XmStringCreateLtoR("Page Scale (%)", XmSTRING_DEFAULT_CHARSET);
  scaleScale = XtVaCreateManagedWidget("scalescale",
                  xmScaleWidgetClass, parent,
                  XmNmaximum, 500,
                  XmNminimum, 1,
                  XmNvalue, get_scale(),
                  XmNorientation, XmHORIZONTAL,
                  XmNprocessingDirection, XmMAX_ON_RIGHT,
                  XmNshowValue, True,
                  XmNtitleString, aLabel,
                  XmNtopAttachment, XmATTACH_WIDGET,
                  XmNtopWidget, XtNameToWidget(optionsPopup, 
                                                 "*methodgroupframe"),
                  XmNtopOffset, 10,
                  XmNleftAttachment, XmATTACH_FORM,
                  XmNleftOffset, 5,
                  XmNrightAttachment, XmATTACH_WIDGET,
                  XmNrightWidget, XtNameToWidget(optionsPopup, 
                                                 "*showgroupframe"),
                  XmNrightOffset, 10,
                  NULL);
  XmStringFree(aLabel);
  XmScaleSetValue(scaleScale, get_scale());
  XtAddCallback(scaleScale, XmNvalueChangedCallback, printScaleCallback, 
                NULL);
 
} /*createPageScaleSlider*/

/******************************************************************************/
static void createPaperOptionsGroup(parent)

Widget parent;

/*creates the radio group that allows the selection of the paper medium to print
on*/

{
  Widget    aToggle;
  Widget    paperGroupRC;
  Widget    paperGroupForm;
  Widget    paperGroupFrame;
  Widget    paperGroupLabel;
  XmString  aLabel;

  aLabel = XmStringCreateLtoR("Paper Type:", XmSTRING_DEFAULT_CHARSET);
  paperGroupLabel = XtVaCreateManagedWidget("papergrouplabel",
                     xmLabelGadgetClass, parent,
                     XmNalignment, XmALIGNMENT_BEGINNING,
                     XmNlabelString, aLabel,
                     XmNtopAttachment, XmATTACH_FORM,
                     XmNtopOffset, 5,
                     XmNleftAttachment, XmATTACH_WIDGET,
                     XmNleftWidget, XtNameToWidget(optionsPopup, 
                                                   "*siteprinterframe"),
                     XmNleftOffset, 10,
                     NULL);
  XmStringFree(aLabel);

  paperGroupFrame = XtVaCreateManagedWidget("papergroupframe",
                     xmFrameWidgetClass, parent,
                     XmNshadowType, XmSHADOW_ETCHED_IN,
                     XmNtopAttachment, XmATTACH_WIDGET,
                     XmNtopWidget, paperGroupLabel,
                     XmNleftAttachment, XmATTACH_WIDGET,
                     XmNleftWidget, XtNameToWidget(optionsPopup, 
                                                   "*siteprinterframe"),
                     XmNleftOffset, 10,
                     NULL);

  paperGroupRC = XtVaCreateManagedWidget("papergrouprc",
                     xmRowColumnWidgetClass, paperGroupFrame, 
                     XmNorientation, XmVERTICAL,
                     XmNnumColumns, 1,
                     XmNpacking, XmPACK_COLUMN,
                     XmNradioBehavior, True,
                     XmNradioAlwaysOne, True,
                     NULL);

  /*each toggle sets its value by calling the necessary ps convenience function
   *and setting its value based upon the result*/

  aLabel = XmStringCreateLtoR("U.S. Letter", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("paperusletter",
                     xmToggleButtonGadgetClass, paperGroupRC,
                     XmNlabelString, aLabel,
                     XmNindicatorType, XmONE_OF_MANY,
                     XmNset, (get_papertype() == P_US_LETTER) ? True : False,
                     NULL);
  XmStringFree(aLabel);

  aLabel = XmStringCreateLtoR("U.S. Legal", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("paperuslegal",
                     xmToggleButtonGadgetClass, paperGroupRC,
                     XmNlabelString, aLabel,
                     XmNsensitive, False,
                     XmNset, (get_papertype() == P_US_LEGAL) ? True : False,
                     NULL);
  XmStringFree(aLabel);

  aLabel = XmStringCreateLtoR("A4 Letter", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("papera4letter",
                     xmToggleButtonGadgetClass, paperGroupRC,
                     XmNlabelString, aLabel,
                     XmNsensitive, False,
                     XmNset, (get_papertype() == P_A4_LETTER) ? True : False,
                     NULL);
  XmStringFree(aLabel);

  aLabel = XmStringCreateLtoR("A4 Special", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("papera4special",
                     xmToggleButtonGadgetClass, paperGroupRC,
                     XmNlabelString, aLabel,
                     XmNsensitive, False,
                     XmNset, (get_papertype() == P_A4_SPECIAL) ? True : False,
                     NULL);
  XmStringFree(aLabel);

} /*createPaperOptionsGroup*/

/******************************************************************************/
static void createPhysicalMarginGroup(parent)

Widget parent;

/*creates the printer margin group otherwise known as the physical margin 
group. This is the page area upon which the printer can actually print*/

{

  static PSPUsetGetFunc_s lInfo;  /*left usr margin info*/
  static PSPUsetGetFunc_s rInfo;  /*right usr margin info*/
  static PSPUsetGetFunc_s tInfo;  /*top usr margin info*/
  static PSPUsetGetFunc_s bInfo;  /*bottom usr margin info*/

  char      asciiMarginVal[8];  /*ascii rep of margin value*/
  Widget    physMarginRC;      
  Widget    physMarginField;  
  Widget    physLMarginField;
  Widget    physRMarginField;
  Widget    physMarginForm;
  Widget    physMarginFrame;
  Widget    physMarginLabel;
  XmString  aLabel;

  aLabel = XmStringCreateLtoR("Printer Margins (Inches):", 
                              XmSTRING_DEFAULT_CHARSET);
  physMarginLabel = XtVaCreateManagedWidget("physmarginlabel",
                       xmLabelGadgetClass, parent,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNtopAttachment, XmATTACH_FORM,
                       XmNtopOffset, 5,
                       XmNrightAttachment, XmATTACH_FORM,
                       XmNrightOffset, 99,
                       NULL);
  XmStringFree(aLabel);

  physMarginFrame = XtVaCreateManagedWidget("physmarginframe",
                       xmFrameWidgetClass, parent,
                       XmNshadowType, XmSHADOW_ETCHED_IN,
                       XmNtopAttachment, XmATTACH_WIDGET,
                       XmNtopWidget, physMarginLabel,
                       XmNrightAttachment, XmATTACH_FORM,
                       XmNrightOffset, 5,
                       NULL);

  physMarginForm = XtVaCreateManagedWidget("physmarginform",
                        xmFormWidgetClass, physMarginFrame,
                        XmNallowOverlap, False,
                        XmNverticalSpacing, 5,
                        XmNhorizontalSpacing, 0,
                        NULL);

  /*left margin text field and label*/

  aLabel = XmStringCreateLtoR("Left:", XmSTRING_DEFAULT_CHARSET);
  physMarginLabel = XtVaCreateManagedWidget("physleftmarginlabel",
                       xmLabelGadgetClass, physMarginForm,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNtopAttachment, XmATTACH_FORM,
                       XmNtopOffset, 10,
                       XmNleftAttachment, XmATTACH_FORM,
                       XmNleftOffset, 5,
                       NULL);
  XmStringFree(aLabel);

  sprintf(asciiMarginVal, "%.2f", get_physLMargin());
  physLMarginField = XtVaCreateManagedWidget("physleftmarginfield",
                       xmTextFieldWidgetClass, physMarginForm,
                       XmNmaxLength, 6,
                       XmNcolumns, 6,
                       XtNvalue, asciiMarginVal,
                       XmNtopAttachment, XmATTACH_FORM,
                       XmNtopOffset, 5,
                       XmNleftAttachment, XmATTACH_WIDGET,
                       XmNleftWidget, physMarginLabel,
                       XmNleftOffset, 10,
                       NULL);
  lInfo.set = set_physLMargin;
  lInfo.type.getf = (float (*)())get_physLMargin; 
  XtAddCallback(physLMarginField, XmNlosingFocusCallback,
                printMarginChangedCallback, &lInfo);
 
  /*right margin text field and label*/

  aLabel = XmStringCreateLtoR("Right:", XmSTRING_DEFAULT_CHARSET);
  physMarginLabel = XtVaCreateManagedWidget("physrightmarginlabel",
                       xmLabelGadgetClass, physMarginForm,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNbottomAttachment, XmATTACH_FORM,
                       XmNbottomOffset, 10,
                       XmNleftAttachment, XmATTACH_FORM,
                       XmNleftOffset, 5,
                       NULL);
  XmStringFree(aLabel);

  sprintf(asciiMarginVal, "%.2f", get_physRMargin());
  physRMarginField = XtVaCreateManagedWidget("physrightmarginfield",
                       xmTextFieldWidgetClass, physMarginForm,
                       XmNmaxLength, 6,
                       XmNcolumns, 6,
                       XtNvalue, asciiMarginVal,
                       XmNtopAttachment, XmATTACH_WIDGET,
                       XmNtopWidget, physLMarginField,
                       XmNbottomAttachment, XmATTACH_FORM,
                       XmNbottomOffset, 5,
                       XmNleftAttachment, XmATTACH_WIDGET,
                       XmNleftWidget, physMarginLabel,
                       XmNleftOffset, 5,
                       NULL);
  rInfo.set = set_physRMargin;
  rInfo.type.getf = (float (*)())get_physRMargin; 
  XtAddCallback(physRMarginField, XmNlosingFocusCallback, 
                printMarginChangedCallback, &rInfo);

  /*bottom margin text field and label*/

  aLabel = XmStringCreateLtoR("Bottom:", XmSTRING_DEFAULT_CHARSET);
  physMarginLabel = XtVaCreateManagedWidget("physbottommarginlabel",
                       xmLabelGadgetClass, physMarginForm,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNbottomAttachment, XmATTACH_FORM,
                       XmNbottomOffset, 10,
                       XmNleftAttachment, XmATTACH_WIDGET,
                       XmNleftWidget, physRMarginField,
                       XmNleftOffset, 5,
                       NULL);
  XmStringFree(aLabel);

  sprintf(asciiMarginVal, "%.2f", get_physBMargin());
  physMarginField = XtVaCreateManagedWidget("physbottommarginfield",
                       xmTextFieldWidgetClass, physMarginForm,
                       XmNmaxLength, 6,
                       XmNcolumns, 6,
                       XtNvalue, asciiMarginVal,
                       XmNbottomAttachment, XmATTACH_FORM,
                       XmNbottomOffset, 5,
                       XmNleftAttachment, XmATTACH_WIDGET,
                       XmNleftWidget, physMarginLabel,
                       XmNrightAttachment, XmATTACH_FORM,
                       XmNrightOffset, 5,
                       NULL);
  bInfo.set = set_physBMargin;
  bInfo.type.getf = (float (*)())get_physBMargin; 
  XtAddCallback(physMarginField, XmNlosingFocusCallback, 
                printMarginChangedCallback, &bInfo);

  /*top margin text field and label*/

  aLabel = XmStringCreateLtoR("Top:", XmSTRING_DEFAULT_CHARSET);
  physMarginLabel = XtVaCreateManagedWidget("phystopmarginlabel",
                       xmLabelGadgetClass, physMarginForm,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNtopAttachment, XmATTACH_FORM,
                       XmNtopOffset, 10,
                       XmNleftAttachment, XmATTACH_WIDGET,
                       XmNleftWidget, physLMarginField,
                       XmNleftOffset, 5,
                       NULL);
  XmStringFree(aLabel);

  sprintf(asciiMarginVal, "%.2f", get_physTMargin());
  physMarginField = XtVaCreateManagedWidget("phystopmarginfield",
                       xmTextFieldWidgetClass, physMarginForm,
                       XmNmaxLength, 6,
                       XmNcolumns, 6,
                       XtNvalue, asciiMarginVal,
                       XmNtopAttachment, XmATTACH_FORM,
                       XmNtopOffset, 5,
                       XmNrightAttachment, XmATTACH_FORM,
                       XmNrightOffset, 5,
                       NULL);
  tInfo.set = set_physTMargin;
  tInfo.type.getf = (float (*)())get_physTMargin; 
  XtAddCallback(physMarginField, XmNlosingFocusCallback, 
                printMarginChangedCallback, &tInfo);

} /*createPhysicalMarginGroup*/

/******************************************************************************/
static void createPrintButtons()

/*Creates the button controls that control the print dialog. These are the 
  print, cancel, options, and help buttons.*/

{
  Widget    aButton;           /*one of the buttons*/
  Widget    buttonGroupForm;   /*form for the buttons in the group*/
  Widget    buttonGroupFrame;  /*frame for the button group*/
  XmString  buttonLabel;       /*label for a button*/
  Dimension buttonWidth;       /*width of the buttons*/
  Widget    optionButton;      /*the help button*/
  Widget    printButton;       /*the print button (used in form layout)*/

  buttonWidth = 70;

  /*create the button group frame and forms*/

  buttonGroupFrame = XtVaCreateManagedWidget("printbuttongroupframe",
                                    xmFrameWidgetClass, printPopup,
                                    XmNshadowType, XmSHADOW_ETCHED_IN,
                                    XmNtopAttachment, XmATTACH_WIDGET,
                                    XmNtopWidget, XtNameToWidget(printPopup,
                                                            "*printlabelframe"),
                                    XmNtopOffset, 10,
                                    XmNleftAttachment, XmATTACH_FORM, 
                                    XmNleftOffset, 10,
                                    XmNrightAttachment, XmATTACH_FORM, 
                                    XmNrightOffset, 10,
                                    XmNbottomAttachment, XmATTACH_FORM,
                                    XmNbottomOffset, 10,
                                    NULL);

  buttonGroupForm = XtVaCreateManagedWidget("printbuttongroupform",
                                    xmFormWidgetClass, buttonGroupFrame,
                                    XmNallowOverlap, False,
                                    XmNhorizontalSpacing, 10,
                                    XmNverticalSpacing, 10,
                                    XmNheight, 55,
                                    NULL);

  /*create the print button*/

  buttonLabel = XmStringCreateLtoR("Print", XmSTRING_DEFAULT_CHARSET);
  printButton = XtVaCreateManagedWidget("printprintbutton",
                                    xmPushButtonGadgetClass, buttonGroupForm,
                                    XmNlabelString, buttonLabel,
                                    XmNshowAsDefault, True,
                                    XmNdefaultButtonShadowThickness, 2,
                                    XmNwidth, buttonWidth,
                                    XmNtopAttachment, XmATTACH_FORM,
                                    XmNleftAttachment, XmATTACH_FORM,
                                    NULL);
  XtVaSetValues(printPopup,
                XmNdefaultButton, printButton,
                NULL);
  XtAddCallback(printButton, XmNactivateCallback, printButtonCallBack, 
                (XtPointer)NULL);
  XmStringFree(buttonLabel);

  /*create the cancel button and add its callback to it*/

  buttonLabel = XmStringCreateLtoR("Cancel", XmSTRING_DEFAULT_CHARSET);
  aButton = XtVaCreateManagedWidget("printcancelbutton",
                                    xmPushButtonGadgetClass, buttonGroupForm,
                                    XmNlabelString, buttonLabel,
                                    XmNdefaultButtonShadowThickness, 2,
                                    XmNwidth, buttonWidth,
                                    XmNtopAttachment, XmATTACH_FORM,
                                    XmNleftAttachment, XmATTACH_WIDGET,
                                    XmNleftWidget, printButton,
                                    NULL);
  XtAddCallback(aButton, XmNactivateCallback, printPopupCancelButtonCb, NULL);
  XmStringFree(buttonLabel);

  /*create the options button and add its callback to it*/

  buttonLabel = XmStringCreateLtoR("Options", XmSTRING_DEFAULT_CHARSET);
  optionButton = XtVaCreateManagedWidget("printoptionbutton",
                                    xmPushButtonGadgetClass, buttonGroupForm,
                                    XmNlabelString, buttonLabel,
                                    XmNdefaultButtonShadowThickness, 2,
                                    XmNwidth, buttonWidth,
                                    XmNsensitive, True,
                                    XmNtopAttachment, XmATTACH_FORM,
                                    XmNleftAttachment, XmATTACH_WIDGET,
                                    XmNleftWidget, aButton,
                                    NULL);
  XtAddCallback(optionButton, XmNactivateCallback, printPopupOptionButtonCb, 
                (XtPointer)NULL);
  XmStringFree(buttonLabel);

  /*create the help button and add its callback to it*/

  buttonLabel = XmStringCreateLtoR("Help", XmSTRING_DEFAULT_CHARSET);
  aButton = XtVaCreateManagedWidget("printhelpbutton",
                                    xmPushButtonGadgetClass, buttonGroupForm,
                                    XmNlabelString, buttonLabel,
                                    XmNdefaultButtonShadowThickness, 2,
                                    XmNwidth, buttonWidth,
                                    XmNsensitive, False,
                                    XmNtopAttachment, XmATTACH_FORM,
                                    XmNleftAttachment, XmATTACH_WIDGET,
                                    XmNleftWidget, optionButton,
                                    XmNrightAttachment, XmATTACH_FORM,
                                    XmNrightOffset, 10,
                                    NULL);
  XmStringFree(buttonLabel);

} /*CreatePrintButtons*/

/******************************************************************************/
static void createPrintLabel()

/*creates the current page label that appears in the print dialog box*/

{
  Widget labelFrame;
  Widget printLabel;

  labelFrame = XtVaCreateManagedWidget("printlabelframe",
                                    xmFrameWidgetClass, printPopup,
                                    XmNshadowType, XmSHADOW_ETCHED_IN,
                                    XmNtopAttachment, XmATTACH_FORM,
                                    XmNtopOffset, 10,
                                    XmNleftAttachment, XmATTACH_FORM, 
                                    XmNleftOffset, 10,
                                    XmNrightAttachment, XmATTACH_FORM, 
                                    XmNrightOffset, 10,
                                    NULL);

  printLabel = XtVaCreateManagedWidget("printlabel",
                       xmLabelGadgetClass, labelFrame,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNtopAttachment, XmATTACH_FORM,
                       XmNtopOffset, 5,
                       XmNleftAttachment, XmATTACH_FORM,
                       XmNleftOffset, 5,
                       NULL);

} /*createPrintLabel*/

/******************************************************************************/
static void createPrintMethodGroup(parent)

Widget parent;

/*creates the printing method group. This group allows the user to select the
printing method to utilize in the printing job. Available methods are: clip to
page, fit to page, and poster page*/

{
  Widget    aToggle;
  Widget    methodGroupRC;
  Widget    methodGroupForm;
  Widget    methodGroupFrame;
  Widget    methodGroupLabel;
  XmString  aLabel;

  aLabel = XmStringCreateLtoR("Printing Method:", XmSTRING_DEFAULT_CHARSET);
  methodGroupLabel = XtVaCreateManagedWidget("methodgrouplabel",
                       xmLabelGadgetClass, parent,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNtopAttachment, XmATTACH_FORM,
                       XmNtopOffset, 5,
                       XmNleftAttachment, XmATTACH_FORM,
                       XmNleftOffset, 5,
                       NULL);
  XmStringFree(aLabel);

  methodGroupFrame = XtVaCreateManagedWidget("methodgroupframe",
                       xmFrameWidgetClass, parent,
                       XmNshadowType, XmSHADOW_ETCHED_IN,
                       XmNtopAttachment, XmATTACH_WIDGET,
                       XmNtopWidget, methodGroupLabel,
                       XmNleftAttachment, XmATTACH_FORM,
                       XmNleftOffset, 5,
                       NULL);

  methodGroupRC = XtVaCreateManagedWidget("methodgrouprc",
                       xmRowColumnWidgetClass, methodGroupFrame, 
                       XmNorientation, XmVERTICAL,
                       XmNnumColumns, 1,
                       XmNpacking, XmPACK_COLUMN,
                       XmNradioBehavior, True,
                       XmNradioAlwaysOne, True,
                       NULL);

  /*each toggle sets its value by calling the necessary ps convenience function
   *and setting its value based upon the result*/

  aLabel = XmStringCreateLtoR("Clip Page", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("methodclippage",
                       xmToggleButtonGadgetClass, methodGroupRC,
                       XmNlabelString, aLabel,
                       XmNindicatorType, XmONE_OF_MANY,
                       XmNset, (get_method() == P_CLIP_PAGE) ? True : False,
                       NULL);
  XmStringFree(aLabel);
  XtAddCallback(aToggle, XmNvalueChangedCallback, printMethodCallback, 
                P_CLIP_PAGE);

  aLabel = XmStringCreateLtoR("Fit To Page", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("methodfittopage",
                       xmToggleButtonGadgetClass, methodGroupRC,
                       XmNlabelString, aLabel,
                       XmNset, (get_method() == P_FIT_TO_PAGE) ? True : False,
                       NULL);
  XmStringFree(aLabel);
  XtAddCallback(aToggle, XmNvalueChangedCallback, printMethodCallback, 
                P_FIT_TO_PAGE);

  aLabel = XmStringCreateLtoR("Poster Page", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("posterpage",
                       xmToggleButtonGadgetClass, methodGroupRC,
                       XmNlabelString, aLabel,
                       XmNset, (get_method() == P_POSTER) ? True : False,
                       NULL);
  XmStringFree(aLabel);
  XtAddCallback(aToggle, XmNvalueChangedCallback, printMethodCallback, 
                P_POSTER);

} /*createPrintMethodGroup*/


/******************************************************************************/
static void createPrintOptionsGroup()

/*creates the print options group which includes the method radio group, the
orientation method group, the objects to be shown group, and the page scale
slider*/

{
  Widget printOptsGrpForm;
  Widget printOptsGrpFrame;

  printOptsGrpFrame = XtVaCreateManagedWidget("printoptsgrpframe",
                          xmFrameWidgetClass, optionsPopup,
                          XmNshadowType, XmSHADOW_ETCHED_IN,
                          XmNmarginWidth, 10,
                          XmNmarginHeight, 10,
                          XmNtopAttachment, XmATTACH_FORM,
                          XmNtopOffset, 10,
                          XmNleftAttachment, XmATTACH_FORM, 
                          XmNleftOffset, 10,
                          XmNrightAttachment, XmATTACH_FORM, 
                          XmNrightOffset, 10,
                          NULL);
  
  printOptsGrpForm = XtVaCreateManagedWidget("printoptsgrpform",
                          xmFormWidgetClass, printOptsGrpFrame, 
                          XmNallowOverlap, False,
                          XmNverticalSpacing, 5,
                          XmNhorizontalSpacing, 0,
                          NULL);

  createPrintMethodGroup(printOptsGrpForm); 
  createPageOrientationGroup(printOptsGrpForm);  
  createShowObjGroup(printOptsGrpForm);
  createPageScaleSlider(printOptsGrpForm);

} /*createPrintOptionsGroup*/

/******************************************************************************/
static void createPrinterOptionsGroup()

/*creates the printer options group which includes the site printer list, the
paper options group, and the output options group.*/

{
  Widget printerOptsGrpForm;
  Widget printerOptsGrpFrame;

  printerOptsGrpFrame = XtVaCreateManagedWidget("printeroptsgrpframe",
                          xmFrameWidgetClass, optionsPopup,
                          XmNshadowType, XmSHADOW_ETCHED_IN,
                          XmNmarginWidth, 10,
                          XmNmarginHeight, 10,
                          XmNtopAttachment, XmATTACH_WIDGET,
                          XmNtopWidget, XtNameToWidget(optionsPopup, 
                                                       "*printoptsgrpframe"),
                          XmNtopOffset, 10,
                          XmNleftAttachment, XmATTACH_FORM, 
                          XmNleftOffset, 10,
                          XmNrightAttachment, XmATTACH_FORM, 
                          XmNrightOffset, 10,
                          NULL);
  
  printerOptsGrpForm = XtVaCreateManagedWidget("printeroptsgrpform",
                          xmFormWidgetClass, printerOptsGrpFrame, 
                          XmNallowOverlap, False,
                          XmNverticalSpacing, 5,
                          XmNhorizontalSpacing, 0,
                          NULL);

  createSitePrinterGroup(printerOptsGrpForm);
  createPaperOptionsGroup(printerOptsGrpForm);
  createOutputOptionsGroup(printerOptsGrpForm);

} /*createPrinterOptionsGroup*/

/******************************************************************************/
static void createPrintPopup(parent)

Widget parent;

/*construct the printing popup window*/

{
  XmString  dialogTitle;
  XmString  listItem;

  /*the print popup window is a form dialog that forces the user to complete
   *dialog interaction before continuing with other application actions*/

  printPopup = XmCreateFormDialog(parent, "printpopup", NULL, 0);
  dialogTitle = XmStringCreateLtoR("VNS Printing", XmSTRING_DEFAULT_CHARSET);
  XtVaSetValues(printPopup,
                XmNdialogTitle, dialogTitle,
                XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
                XmNnoResize, True,
                NULL);
  XmStringFree(dialogTitle);

  createPrintLabel(printPopup);  /*create the current page label*/
  createPrintButtons(printPopup);  /*create the dialog buttons*/

} /*createPrintPopup*/

/******************************************************************************/
static void createShowObjGroup(parent)

Widget parent;

/*creates the toggle button group that permits the user to select which objects
to print and whether to print object outlines and page grids*/

{
  Widget    aToggle;
  Widget    showGroupRC;
  Widget    showGroupFrame;
  Widget    showGroupLabel;
  XmString  aLabel;

  /*create the button group frame and forms*/

  aLabel = XmStringCreateLtoR("Show:", XmSTRING_DEFAULT_CHARSET);
  showGroupLabel = XtVaCreateManagedWidget("showgrouplabel",
                          xmLabelGadgetClass, parent,
                          XmNalignment, XmALIGNMENT_BEGINNING,
                          XmNlabelString, aLabel,
                          XmNtopAttachment, XmATTACH_FORM,
                          XmNtopOffset, 5,
                          XmNrightAttachment, XmATTACH_FORM,
                          XmNrightOffset, 90,
                          NULL);
  XmStringFree(aLabel);

  showGroupFrame = XtVaCreateManagedWidget("showgroupframe",
                          xmFrameWidgetClass, parent,
                          XmNshadowType, XmSHADOW_ETCHED_IN,
                          XmNtopAttachment, XmATTACH_WIDGET,
                          XmNtopWidget, showGroupLabel,
                          XmNrightAttachment, XmATTACH_FORM,
                          XmNrightOffset, 5, 
                          NULL);

  showGroupRC = XtVaCreateManagedWidget("showgrouprc",
                          xmRowColumnWidgetClass, showGroupFrame, 
                          XmNorientation, XmVERTICAL,
                          XmNnumColumns, 1,
                          XmNpacking, XmPACK_COLUMN,
                          NULL);

  /*each toggle sets its value by calling the necessary ps convenience function
   *and setting its value based upon the result*/

  aLabel = XmStringCreateLtoR("Text", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("showtext",
                          xmToggleButtonGadgetClass, showGroupRC,
                          XmNlabelString, aLabel,
                          XmNset, get_show_text(),
                          NULL);
  XmStringFree(aLabel);
  XtAddCallback(aToggle, XmNvalueChangedCallback, showObjCallback, 
                PSPU_TEXT);

  aLabel = XmStringCreateLtoR("Images", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("showimages",
                          xmToggleButtonGadgetClass, showGroupRC,
                          XmNlabelString, aLabel,
                          XmNset, get_show_images(),
                          NULL);
  XmStringFree(aLabel);
  XtAddCallback(aToggle, XmNvalueChangedCallback, showObjCallback, 
                PSPU_IMAGE);

  aLabel = XmStringCreateLtoR("Action Links", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("showactionlinks",
                          xmToggleButtonGadgetClass, showGroupRC,
                          XmNlabelString, aLabel,
                          XmNset, get_show_alinks(),
                          NULL);
  XmStringFree(aLabel);
  XtAddCallback(aToggle, XmNvalueChangedCallback, showObjCallback, 
                PSPU_ALINK);

/* ******** AUDIO LINKS ARE NOT CURRENTLY SUPPORTED ********

  aLabel = XmStringCreateLtoR("Audio Links", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("showaudioinks",
                          xmToggleButtonGadgetClass, showGroupRC,
                          XmNlabelString, aLabel,
                          XmNset, get_show_audios(),
                          NULL);
  XmStringFree(aLabel);  
  XtAddCallback(aToggle, XmNvalueChangedCallback, showObjCallback, 
                PSPU_AUDIO);
*************************************************************/

  aLabel = XmStringCreateLtoR("Page Links", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("showpagelinks",
                          xmToggleButtonGadgetClass, showGroupRC,
                          XmNlabelString, aLabel,
                          XmNset, get_show_plinks(),
                          NULL);
  XmStringFree(aLabel);
  XtAddCallback(aToggle, XmNvalueChangedCallback, showObjCallback, 
                PSPU_PLINK);

  aLabel = XmStringCreateLtoR("Page Grid", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("showpagegrid",
                          xmToggleButtonGadgetClass, showGroupRC,
                          XmNlabelString, aLabel,
                          XmNset, get_show_grid(),
                          NULL);
  XmStringFree(aLabel);
  XtAddCallback(aToggle, XmNvalueChangedCallback, showObjCallback, 
                PSPU_GRID);

  aLabel = XmStringCreateLtoR("Object Outlines", XmSTRING_DEFAULT_CHARSET);
  aToggle = XtVaCreateManagedWidget("showobjectoutlines",
                          xmToggleButtonGadgetClass, showGroupRC,
                          XmNlabelString, aLabel,
                          XmNset, get_show_outline(),
                          NULL);
  XmStringFree(aLabel);
  XtAddCallback(aToggle, XmNvalueChangedCallback, showObjCallback, 
                PSPU_OUTLINE);

} /*createShowObjGroup*/

/******************************************************************************/
static void createSitePrinterGroup(parent)

Widget parent;

/*sets up the site printer list by calling functions to read in the site
printer file and creating a list from that file. Also a user defined printer
option is added to the list to allow users to define their own printers*/

{
  Arg       arg[4];            /*arg list for setting up a scrolled list*/
  XmString  aLabel;
  int       lcv;
  XmString  listItem;          /*list item*/
  int       noPrinters;        /*number of printers read in*/
  Widget    sitePrinterRC;   
  Widget    sitePrinterForm;
  Widget    sitePrinterFrame;
  Widget    sitePrinterLabel;
  Widget    sitePrinterList;

  aLabel = XmStringCreateLtoR("Printer In Use:", XmSTRING_DEFAULT_CHARSET);
  sitePrinterLabel = XtVaCreateManagedWidget("siteprinterlabel",
                       xmLabelGadgetClass, parent,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNtopAttachment, XmATTACH_FORM,
                       XmNtopOffset, 5,
                       XmNleftAttachment, XmATTACH_FORM,
                       XmNleftOffset, 5,
                       NULL);
  XmStringFree(aLabel);

  sitePrinterFrame = XtVaCreateManagedWidget("siteprinterframe",
                       xmFrameWidgetClass, parent,
                       XmNshadowType, XmSHADOW_ETCHED_IN,
                       XmNtopAttachment, XmATTACH_WIDGET,
                       XmNtopWidget, sitePrinterLabel,
                       XmNleftAttachment, XmATTACH_FORM,
                       XmNleftOffset, 5,
                       NULL);
  
  lcv = 0;
  XtSetArg(arg[lcv], XmNlistSizePolicy, XmCONSTANT); lcv++;
  XtSetArg(arg[lcv], XmNselectionPolicy, XmBROWSE_SELECT); lcv++;
  XtSetArg(arg[lcv], XmNvisibleItemCount, 10); lcv++;
  XtSetArg(arg[lcv], XmNscrollBarDisplayPolicy, XmAS_NEEDED); lcv++;
  XtSetArg(arg[lcv], XmNwidth, 120); lcv++;

  sitePrinterList = XmCreateScrolledList(sitePrinterFrame, "siteprinterlist",
                                         arg, lcv);
  XtAddCallback(sitePrinterList, XmNbrowseSelectionCallback, 
                sitePrinterCallback, NULL);

  /*this is hopefully a temporary fix on loading site printers. this
   *implementation is to say the least rather cheap/hackish*/

  PRNloadPrinters(&noPrinters, PSPU_MAXPRINTERS, printers, pc.sitefile);

  /*Add the USER DEFINED printer to the list. This allows the user to specify
   *a printer name and other parameters*/

  strcpy(printers[noPrinters].pname, "USER DEFINED");
  printers[noPrinters].tMargin = 0;
  printers[noPrinters].bMargin = 0;
  printers[noPrinters].lMargin = 0;
  printers[noPrinters].rMargin = 0;
  printers[noPrinters].colour = 1;

  /*set default physical margins to first printer in the list*/
 
  set_physTMargin(printers[0].tMargin);
  set_physBMargin(printers[0].bMargin);
  set_physLMargin(printers[0].lMargin);
  set_physRMargin(printers[0].rMargin);

  /*load the list*/
 
  for (lcv = 0; lcv < noPrinters; lcv++)
   {
     listItem = XmStringCreateLtoR(printers[lcv].pname,
                                   XmSTRING_DEFAULT_CHARSET);
     XmListAddItem(sitePrinterList, listItem, 0); 
     XmStringFree(listItem);
   }

       listItem = XmStringCreateLtoR(printers[lcv].pname,
                                   XmSTRING_DEFAULT_CHARSET);
     XmListAddItem(sitePrinterList, listItem, 0);
     XmStringFree(listItem);


  XtManageChild(sitePrinterList);

} /*createSitePrinterGroup*/

/******************************************************************************/
static void createUniqueFnameToggle(parent)

Widget parent; 

/*creates the toggle button that allows the selection of colour on those
printer devices that allow colour or when file mode is selected*/

{
  XmString aLabel;
  Widget   uniqueToggleFrame;
  Widget   uniqueToggle;

  uniqueToggleFrame = XtVaCreateManagedWidget("uniquetoggleframe",
                          xmFrameWidgetClass, parent,
                          XmNshadowType, XmSHADOW_ETCHED_IN,
                          XmNtopAttachment, XmATTACH_WIDGET,
                          XmNtopWidget, XtNameToWidget(optionsPopup, 
                                                    "*colourtoggleframe"),
                          XmNleftAttachment, XmATTACH_WIDGET,
                          XmNleftWidget, XtNameToWidget(optionsPopup, 
                                                    "*outputradiogroupframe"),
                          XmNleftOffset, 10,
                          XmNrightAttachment, XmATTACH_FORM,
                          XmNrightOffset, 10,
                          NULL);

  aLabel = XmStringCreateLtoR("Unique File Names", XmSTRING_DEFAULT_CHARSET);
  uniqueToggle = XtVaCreateManagedWidget("printunique",
                          xmToggleButtonGadgetClass, uniqueToggleFrame,
                          XmNlabelString, aLabel,
                          XmNset, get_uniqueFname(),
                          NULL);
  XtAddCallback(uniqueToggle, XmNvalueChangedCallback, 
                uniqueFnameToggleCallback, NULL);
  XmStringFree(aLabel);

} /*createUniqueFnameToggle*/

/******************************************************************************/
static void createUserMarginGroup(parent)

Widget parent;

/*creates the fields for the user margin group. these are the margins that the
user specifies for the printed page*/

{
  static PSPUsetGetFunc_s lInfo;  /*left usr margin info*/
  static PSPUsetGetFunc_s rInfo;  /*right usr margin info*/
  static PSPUsetGetFunc_s tInfo;  /*top usr margin info*/
  static PSPUsetGetFunc_s bInfo;  /*bottom usr margin info*/

  char      asciiMarginVal[8];  /*ascii rep of margin value*/
  Widget    userMarginRC;       
  Widget    userMarginField;   
  Widget    userLMarginField; 
  Widget    userRMarginField;
  Widget    userMarginForm; 
  Widget    userMarginFrame;
  Widget    userMarginLabel;
  XmString  aLabel;

  aLabel = XmStringCreateLtoR("User Margins (Inches):", 
                       XmSTRING_DEFAULT_CHARSET);
  userMarginLabel = XtVaCreateManagedWidget("usermarginlabel",
                       xmLabelGadgetClass, parent,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNtopAttachment, XmATTACH_FORM,
                       XmNtopOffset, 5,
                       XmNleftAttachment, XmATTACH_FORM,
                       XmNleftOffset, 5,
                       NULL);
  XmStringFree(aLabel);

  userMarginFrame = XtVaCreateManagedWidget("usermarginframe",
                       xmFrameWidgetClass, parent,
                       XmNshadowType, XmSHADOW_ETCHED_IN,
                       XmNtopAttachment, XmATTACH_WIDGET,
                       XmNtopWidget, userMarginLabel,
                       XmNbottomAttachment, XmATTACH_FORM,
                       XmNbottomOffset, 5,
                       XmNleftAttachment, XmATTACH_FORM,
                       XmNleftOffset, 5,
                       NULL);

  userMarginForm = XtVaCreateManagedWidget("usermarginform",
                       xmFormWidgetClass, userMarginFrame,
                       XmNallowOverlap, False,
                       XmNverticalSpacing, 5,
                       XmNhorizontalSpacing, 0,
                       NULL);

  /*left margin text field and label*/

  aLabel = XmStringCreateLtoR("Left:", XmSTRING_DEFAULT_CHARSET);
  userMarginLabel = XtVaCreateManagedWidget("userleftmarginlabel",
                       xmLabelGadgetClass, userMarginForm,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNtopAttachment, XmATTACH_FORM,
                       XmNtopOffset, 10,
                       XmNleftAttachment, XmATTACH_FORM,
                       XmNleftOffset, 5,
                       NULL);
  XmStringFree(aLabel);

  sprintf(asciiMarginVal, "%.2f", get_left_margin());
  userLMarginField = XtVaCreateManagedWidget("userleftmarginfield",
                       xmTextFieldWidgetClass, userMarginForm,
                       XmNmaxLength, 6,
                       XmNcolumns, 6,
                       XtNvalue, asciiMarginVal,
                       XmNtopAttachment, XmATTACH_FORM,
                       XmNtopOffset, 5,
                       XmNleftAttachment, XmATTACH_WIDGET,
                       XmNleftWidget, userMarginLabel,
                       XmNleftOffset, 10,
                       NULL);
  lInfo.set = set_left_margin;
  lInfo.type.getf = (float (*)())get_left_margin; 
  XtAddCallback(userLMarginField, XmNlosingFocusCallback, 
                printMarginChangedCallback, &lInfo);
 
  /*right margin text field and label*/

  aLabel = XmStringCreateLtoR("Right:", XmSTRING_DEFAULT_CHARSET);
  userMarginLabel = XtVaCreateManagedWidget("userrightmarginlabel",
                       xmLabelGadgetClass, userMarginForm,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNbottomAttachment, XmATTACH_FORM,
                       XmNbottomOffset, 10,
                       XmNleftAttachment, XmATTACH_FORM,
                       XmNleftOffset, 5,
                       NULL);
  XmStringFree(aLabel);

  sprintf(asciiMarginVal, "%.2f", get_right_margin());
  userRMarginField = XtVaCreateManagedWidget("userrightmarginfield",
                       xmTextFieldWidgetClass, userMarginForm,
                       XmNmaxLength, 6,
                       XmNcolumns, 6,
                       XtNvalue, asciiMarginVal,
                       XmNtopAttachment, XmATTACH_WIDGET,
                       XmNtopWidget, userLMarginField,
                       XmNbottomAttachment, XmATTACH_FORM,
                       XmNbottomOffset, 5,
                       XmNleftAttachment, XmATTACH_WIDGET,
                       XmNleftWidget, userMarginLabel,
                       XmNleftOffset, 5,
                       NULL);
  rInfo.set = set_right_margin;
  rInfo.type.getf = (float (*)())get_right_margin; 
  XtAddCallback(userRMarginField, XmNlosingFocusCallback, 
                printMarginChangedCallback, &rInfo);

  /*bottom margin text field and label*/

  aLabel = XmStringCreateLtoR("Bottom:", XmSTRING_DEFAULT_CHARSET);
  userMarginLabel = XtVaCreateManagedWidget("userbottommarginlabel",
                       xmLabelGadgetClass, userMarginForm,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNbottomAttachment, XmATTACH_FORM,
                       XmNbottomOffset, 10,
                       XmNleftAttachment, XmATTACH_WIDGET,
                       XmNleftWidget, userRMarginField,
                       XmNleftOffset, 5,
                       NULL);
  XmStringFree(aLabel);

  sprintf(asciiMarginVal, "%.2f", get_bot_margin());
  userMarginField = XtVaCreateManagedWidget("userbottommarginfield",
                       xmTextFieldWidgetClass, userMarginForm,
                       XmNmaxLength, 6,
                       XmNcolumns, 6,
                       XtNvalue, asciiMarginVal,
                       XmNbottomAttachment, XmATTACH_FORM,
                       XmNbottomOffset, 5,
                       XmNleftAttachment, XmATTACH_WIDGET,
                       XmNleftWidget, userMarginLabel,
                       XmNrightAttachment, XmATTACH_FORM,
                       XmNrightOffset, 5,
                       NULL);
  bInfo.set = set_bot_margin;
  bInfo.type.getf = (float (*)())get_bot_margin; 
  XtAddCallback(userMarginField, XmNlosingFocusCallback, 
                printMarginChangedCallback, &bInfo);

  /*top margin text field and label*/

  aLabel = XmStringCreateLtoR("Top:", XmSTRING_DEFAULT_CHARSET);
  userMarginLabel = XtVaCreateManagedWidget("usertopmarginlabel",
                       xmLabelGadgetClass, userMarginForm,
                       XmNalignment, XmALIGNMENT_BEGINNING,
                       XmNlabelString, aLabel,
                       XmNtopAttachment, XmATTACH_FORM,
                       XmNtopOffset, 10,
                       XmNleftAttachment, XmATTACH_WIDGET,
                       XmNleftWidget, userLMarginField,
                       XmNleftOffset, 5,
                       NULL);
  XmStringFree(aLabel);

  sprintf(asciiMarginVal, "%.2f", get_top_margin());
  userMarginField = XtVaCreateManagedWidget("usertopmarginfield",
                       xmTextFieldWidgetClass, userMarginForm,
                       XmNmaxLength, 6,
                       XmNcolumns, 6,
                       XtNvalue, asciiMarginVal,
                       XmNtopAttachment, XmATTACH_FORM,
                       XmNtopOffset, 5,
                       XmNrightAttachment, XmATTACH_FORM,
                       XmNrightOffset, 5,
                       NULL);
  tInfo.set = set_top_margin;
  tInfo.type.getf = (float (*)())get_top_margin; 
  XtAddCallback(userMarginField, XmNlosingFocusCallback, 
                printMarginChangedCallback, &tInfo);

} /*createUserMarginGroup*/

/******************************************************************************/
static char *getDefaultPrinter()

/*checks the environment for a printer specification, otherwise uses the ps
as its default*/

{
  char *printer;
  extern char *getenv();

  if (printer = getenv("VNSPRINTER"))
     return(printer);
  else if (printer = getenv("PRINTER"))
     return(printer);
  else
     return(XtNewString("ps"));

} /*getDefaultPrinter*/

/******************************************************************************/
static void optionPopupOkButtonCb(wd)

Widget wd;

/*Callback for selection the Ok button. Simply pops down the options panel*/

{
  XtUnmanageChild(optionsPopup);

} /*optionPopupOkButtonCb*/

/******************************************************************************/
static void printButtonCallBack(wd)

Widget wd;

/*Callback for selection the print button*/

{
  PLL_LISTDATA_S data;
  char *handle;

  if (XtIsManaged(optionsPopup))
     VtWatchOn(optionsPopup); /*activate watch cursor*/

  VtWatchOn(printPopup); /*activate watch cursor*/

  /*set the db & x servers*/

  set_xDisplay(XtDisplay(printPopup));
  set_dbServerId(pc.srv);

  /*build page list for the printing routine*/

  handle = PLLcreate();
  data.nid = pc.nid;
  data.pid = pc.pid;
  PLLinsert(handle, PLL_PAGE, &data, PLL_FIRST, 1);

  /*print the page and then kill the page list*/

  PSprint(handle); 
  PLLkillList(&handle);  

  if (XtIsManaged(optionsPopup))
     VtWatchOff(optionsPopup); /*deactivate watch cursor*/

  VtWatchOff(printPopup); /*deactivate watch cursor*/

  XtUnmanageChild(optionsPopup);
  XtUnmanageChild(printPopup);

} /*printButtonCallBack*/

/******************************************************************************/
static void printCopiesChangedCallback(refWidget, dummy, callData)

Widget           refWidget;
XtPointer        dummy; 
XmTextVerifyPtr  callData;

/*call back for copies text field. Ensures a valid integer # is entered for the
field. This function is invoked by the XmNlosingFocusCallback*/

{
  char asciiValue[16];  /*ascii margin value*/
  char *text;

  if (badInt((text = XmTextFieldGetString(refWidget))) || 
             atoi(text) > PSPU_MAXCOPIES || atoi(text) < 1)
   {
     /*reset the widget back to its old value*/

     sprintf(asciiValue, "%d", get_copies());
     XBell(XtDisplay(optionsPopup),75); /*alert the user*/
   }
  else
   {
     int newVal;

     sscanf(text, "%d", &newVal);
     set_copies(newVal);
     sprintf(asciiValue, "%d", get_copies());
   }

  XmTextFieldSetString(refWidget, asciiValue);
  callData->doit = True;
   
} /*printCopiesChangedCallback*/

/******************************************************************************/
static void printMarginChangedCallback(refWidget, marginFuncs, callData)

Widget           refWidget;
PSPUsetGetFunc_s *marginFuncs;
XmTextVerifyPtr  callData;

/*call back for user margin and device margin text fields. Ensures that the 
text entered is a valid floating point number. This function is invoked by
the XmNlosingFocusCallback*/

{
  char asciiValue[16];  /*ascii margin value*/
  char *text;

  if (badFloat((text = XmTextFieldGetString(refWidget))) || 
               atof(text) > PSPU_MAXMARGIN)
   {
     /*reset the widget back to its old value*/

     sprintf(asciiValue, "%.2f", (*marginFuncs->type.getf)());
     XBell(XtDisplay(optionsPopup),75); /*alert the user*/
   }
  else
   {
     float newVal;  /*new margin value*/

     /*set the new value in the printing context and format it for screen
      *display*/

     sscanf(text, "%f", &newVal);
     (*marginFuncs->set)(newVal);
     sprintf(asciiValue, "%.2f", (*marginFuncs->type.getf)());
   }

  XmTextFieldSetString(refWidget, asciiValue);
  callData->doit = True; /*allow the widget action to continue*/
   
} /*printMarginChangedCallback*/

/******************************************************************************/
static void printMethodCallback(refWidget, method, callData)

Widget                       refWidget;
P_Method                     method;     /*new printing method*/
XmToggleButtonCallbackStruct *callData;  /*toggle button callback struct*/

/*Callback routine for setting the printing method*/

{
  if (callData->set)  /*see if the radio toggle is set*/
     set_method(method);

} /*printMethodCallback*/

/******************************************************************************/
static void printNamesCallback(refWidget, nameFuncs, callData)

Widget           refWidget;
PSPUsetGetFunc_s *nameFuncs;  /*pointer to print context get & set funcs*/
XmTextVerifyPtr  callData;    /*text callback structure*/

/*callback for printer name and file name fields. chechs to see that the fields
do not contain any invalid characters*/

{
  char asciiValue[64];  /*ascii margin value*/
  char *text;           /*text in the field*/

  if (badText((text = XmTextFieldGetString(refWidget)), 
               "~`!@#$%^&*()-+={}[];:'|,<>?/\"\\ "))
   {
     /*reset the widget back to its old value*/

     text = (*nameFuncs->type.getcp)();
     XmTextFieldSetString(refWidget, text);
     XBell(XtDisplay(optionsPopup),75); /*alert the user*/
   }
  else  /*all is ok*/
     (*nameFuncs->set)(text);

  callData->doit = True;
   
} /*printNamesCallback*/

/******************************************************************************/
static void printOrientationCallback(refWidget, orientation, callData)

Widget                       refWidget;
P_Orientation                orientation;  /*new page orientation*/
XmToggleButtonCallbackStruct *callData;    /*toggle button callback struct*/

/*Callback routine for setting the page orientation*/

{
  if (callData->set)  /*see if the radio toggle is set*/
     set_orientation(orientation);

} /*printOrientationCallback*/

/******************************************************************************/
static void printOutputCallback(refWidget, outputTo, callData)

Widget                       refWidget;
P_Output                     outputTo;
XmToggleButtonCallbackStruct *callData;  /*toggle button callback struct*/

/*Callback routine for setting the page orientation*/

{
  if (callData->set)
     set_outputTo(outputTo);

} /*printOrientationCallback*/

/******************************************************************************/
static void printPopupCancelButtonCb(wd)

Widget wd;

/*Callback for selection the Cancel button. Simply pops down the print panel*/

{
  XtUnmanageChild(optionsPopup);
  XtUnmanageChild(printPopup);

} /*printPopupCancelButtonCb*/

/******************************************************************************/
static void printPopupOptionButtonCb(wd)

Widget wd;

/*Callback for print popup option button.*/ 

{

  XtManageChild(optionsPopup);

} /*printPopupCancelButtonCb*/

/******************************************************************************/
static void printScaleCallback(refWidget, dummy, callData)

Widget                refWidget;
XtPointer             dummy;
XmScaleCallbackStruct *callData;

/*Callback routine for setting the page scale*/

{
  set_scale(callData->value);

} /*printScaleCallback*/

/******************************************************************************/
static void setTextFloatField(widgetPath, setFunc, value, precision)

char  *widgetPath;   /*name of widget to set*/
float (*setFunc)();  /*function to set ps field*/
float value;         /*value to set*/
short precision;     /*precision*/

/*given <value> and <precision>, sets a text widget and postscript field to
that value*/

{
  char asciiValue[16];

  sprintf(asciiValue, "%.*f", precision, value);
  XmTextFieldSetString(XtNameToWidget(optionsPopup, widgetPath), asciiValue);
  (*setFunc)(value);

} /*setTextFloatField*/

/******************************************************************************/
static void showObjCallback(refWidget, objType, reason)

Widget                       refWidget;   /*widget invoking the callback*/
PSPU_SHOWOBJ_E               objType;     /*type of objected affected*/
XmToggleButtonCallbackStruct *reason;     /*reason affected*/

/*callback for the show object toggle group*/

{
  static void (*jumpTable[])() =  /*vector table for show object set/unset*/
   {                              /*functions*/
     set_show_alinks,   /*set function for action links*/
     set_show_audios,   /*set function for audio links*/
     set_show_grid,     /*set function for page grid*/
     set_show_images,   /*set function for images*/
     set_show_outline,  /*set function for object outlines*/
     set_show_plinks,   /*set function for page links*/
     set_show_text      /*set funtions for text objects*/
   };

  (*jumpTable[(int)objType])(reason->set);

} /*showObjCallback*/

/******************************************************************************/
static void sitePrinterCallback(refWidget, dummy, callData)

Widget               refWidget;
XtPointer            dummy;
XmListCallbackStruct *callData;

/*callback for the site printer list widget. Sets up the necessary parameters
for the specified printer - device margins, colour etc*/

{
  Widget printerNameWd;
  int    pos;

  pos = callData->item_position - 1;

  if (printers[pos].colour)
     XtVaSetValues(XtNameToWidget(optionsPopup, "*printcolour"), 
                   XmNsensitive, True,
                   NULL);
  else
   {
     XtVaSetValues(XtNameToWidget(optionsPopup, "*printcolour"), 
                   XmNsensitive, False,
                   XmNset, False,
                   NULL);
   }

  if (strcmp(printers[pos].pname, "USER DEFINED") == 0)  /*user-defined seled*/
   {
     /*allow the user to enter a printer name and decide whether it can support
      *colour printing*/

     XmTextFieldSetEditable((printerNameWd = 
                   XtNameToWidget(optionsPopup, "*printernamefield")), True);
     XmTextFieldSetString(printerNameWd, ""); 
     XmTextFieldShowPosition(printerNameWd, 0);
     XtVaSetValues(printerNameWd,
                   XmNsensitive, True,
                   NULL);
   }
  else
   {
     XmTextFieldSetEditable((printerNameWd = 
                   XtNameToWidget(optionsPopup, "*printernamefield")), False);
     XmTextFieldSetString(printerNameWd, printers[pos].pname); 
     set_printer(printers[pos].pname);
     XmTextFieldShowPosition(printerNameWd, 0);
     XtVaSetValues(printerNameWd,
                   XmNsensitive, False,
                   NULL);
   }

  /*set the printer margins up*/

  setTextFloatField("*physleftmarginfield", set_physLMargin, 
                    printers[pos].lMargin, 2);
  setTextFloatField("*physrightmarginfield", set_physRMargin, 
                    printers[pos].rMargin, 2);
  setTextFloatField("*phystopmarginfield", set_physTMargin, 
                    printers[pos].tMargin, 2);
  setTextFloatField("*physbottommarginfield", set_physBMargin, 
                    printers[pos].bMargin, 2);

} /*sitePrinterCallback*/

/******************************************************************************/
static void uniqueFnameToggleCallback(refWidget, dummy, reason)

Widget                       refWidget;  /*widget invoking the callback*/
XtPointer                    dummy;      /*user data*/
XmToggleButtonCallbackStruct *reason;    /*reason affected*/

/*callback function for the unique file name toggle*/

{
  set_uniqueFname(reason->set);

} /*colourToggleCallback*/

/*******************************************************************************
Private undefines
*******************************************************************************/

#undef PSPU_MAXCOPIES
#undef PSPU_MAXMARGIN
#undef PSPU_MAXPRINTERS
#undef PSPU_SITEPRINTERFILE
#undef PRINT_POPUP_C

