/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Microsoft Corporation, 1989                                 */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
#pragma  pagesize(55)
/**************************************************************************
 *
 * SOURCE FILE NAME =  DEVMODE.C
 *
 * DESCRIPTIVE NAME =  PLOTTER DRIVER SOURCE
 *
 *
 * VERSION = V2.0
 *
 * DATE        09/18/88
 *
 * DESCRIPTION This file contains the functions for the Job and Printer
 *             properties dialogs.
 *
 *
 * FUNCTIONS   save_profile         save_profile
 *             check_menuitem       This function checks or unchecks a menuitem
 *             check_pen            Set the check status in the PenColor
 *             check_pens           Check the currently selected pens
 *             clear_entries        Gray all items in the PenColor,
 *             display_carousel     display_carousel
 *             display_colors       Determine the allowable colors and
 *             display_paper_size   display_paper_size
 *             display_pen          display_pen
 *             display_pens         display_pens
 *             get_group            get_group
 *             get_string           get_string
 *             init_dialog          init_dialog
 *             list_pen_options     list_pen_options
 *             list_pen_priority    list_pen_priority
 *             main_dialog_command  main_dialog_command
 *             reset_entries        reset_entries
 *             update_menu          update_menu
 *             help_dialog_proc     help_dialog_proc
 *             main_dialog_proc     main_dialog_proc
 *             options_dialog_proc  options_dialog_proc
 *             priority_dialog_proc priority_dialog_proc
 *             DevPostDeviceModes   DevPostDeviceModes
 *             EA_GetVersion        EA_GetVersion
 *             szStrCopy            szStrCopy
 *             SetHelpStubHook()    SetHelpStubHook()
 *             InitializeHelp       InitializeHelp
 *             ReleaseHelpStubHook  ReleaseHelpStubHook
 *             CleanUpHelpStubHook  CleanUpHelpStubHook
 *             HelpStubHook         HelpStubHook
 *             get_module_dir       Return size of the directory path
 *             HelpErrorFilter      HelpErrorFilter
 *
 *
 *
 *
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/
#define  INCL_DOSMODULEMGR             /* DosLoadModule prototype           */
#define  INCL_DOSFILEMGR               /* DosQPathInfo DCR1399              */
#define  INCL_WINWINDOWMGR
#define  INCL_WINMESSAGEMGR
#define  INCL_WINDIALOGS
#define  INCL_WINSTATICS
#define  INCL_WINBUTTONS
#define  INCL_WINEDITCTLS
#define  INCL_WINLISTBOXES
#define  INCL_WINMENUS
#define  INCL_WINSCROLLBARS
#define  INCL_WINFRAMEMGR
#define  INCL_WINFRAMECTLS
#define  INCL_WINRECTANGLES
#define  INCL_WINSHELLDATA
#define  INCL_WINENTRYFIELDS
#define  INCL_WINSTDDLGS               // @MJH
#define  INCL_WINHELP                  /* DCR 1476                          */
#define  INCL_DOSPROCESS               /* DCR 1476                          */
#define  INCL_WINHOOKS                 /* DCR 1476                          */
#define  INCL_DOSMISC                  /* DCR 1476                          */
#define  INCL_WINSYS                   /* Presprarm  stuff                  */
#define  INCL_GPIPRIMITIVES
#define  INCL_GPILCIDS
#define  INCL_GPILOGCOLORTABLE         // @MARK
#define  INCL_DEV

/*LISTOFF                                                                   */
                              /* for PPC.EXE                                */

#define USERINTERFACE                   /* incl gpi stuff not ddi stuff     */
#include "plotters.h"

#include "error.h"
#include "profile.h"
#include "devmode.h"
#include "dialog.h"
#include "utils.h"
#include "color.h"
#include "forms.h"                    // @MJH
#include <pmhelp.h>                    /* DCR 1476                          */

/*LISTON                                                                    */
                              /* for PPC.EXE                                */
/*
** OSDD DCR 1476 - Integrate 1.2 Help Manager
*/

#define  VQMAXMSGSTRING 256            /* Maximum msg box string length     */
#define  RES_FLAG      0xFFFF0000
#define  HELPFILENAME  "\\PLOTTERS.HLP"
BOOL HelpStubHookIsSet = FALSE;        /* for new help                      */
HWND hwndHelp = 0;
BOOL HelpAlreadyInitialized = FALSE;   /* for new help                      */
CHAR szHelpTitle[VQMAXMSGSTRING+1] = { 0 } ;
                                       /* KEEP THIS INITIALIZED or compile
                                          error!!!                          */
HWND hwndMain = 0;                     /* KEEP INITIALIZED. Main window
                                          handle need for help instance.    */

/*
** HELPINIT -- help manager initialization structure
*/

static HELPINIT hmiHelpData =
{
  sizeof(HELPINIT),
  0L,
  (PSZ)NULL,
  (PHELPTABLE)
  (MAIN_HELPTABLE|RES_FLAG),
  (HMODULE)NULL,
  (HMODULE)NULL,
  (USHORT)NULL,
  (USHORT)NULL,
  (PSZ)NULL,
  CMIC_HIDE_PANEL_ID,
  (PSZ)HELPFILENAME
} ;

/* GpiQueryTextBox return structure */

typedef struct _TEXTBOX {              /* txtbox */
    POINTL ptlTopLeft;
    POINTL ptlBottomLeft;
    POINTL ptlTopRight;
    POINTL ptlBottomRight;
    POINTL ptlConcat;
} TEXTBOX;


#define  MSGBUFSIZE    80
#define  MAX_PATH_SIZE 256             // size of driver name DCR1399
#define  EA_NAME_VERSION ".VERSION"    // attribute name DCR1399
#define  SIZE_EA_NAME_VERSION (sizeof(EA_NAME_VERSION) - 1)  // DCR1399
#define  MAX_VERNAME_SIZE 128          // length of version name DCR1399


//LOCAL SHORT DefColorMenu[MAX_COLORS+2] =
//{
//  YELLOW,         ORANGE,         RED,            GREEN,          RED_VIOLET,
//  AQUA,           VIOLET,         BLUE,           BROWN,          BLACK,
//  WHITE,          GRAY,           DARKBLUE,       DARKRED,        DARKPINK,
//  DARKGREEN,      DARKCYAN,       DARKGRAY,       LIGHTGRAY,      REDGRAY,
//  GREENGRAY,      BLUEGRAY,       NO_COLOR,       0
//} ;

LOCAL SHORT DefPenColorMenu[MAX_PENCOLORMENU+1] =
{
  SELECT_PEN_COLOR, NO_COLOR,       0
} ;

LOCAL SHORT DefTypeMenu[MAX_PEN_TYPES+1] =
{
  P3,             P7,             T3,             T6,             V25,
  V35,            V50,            V70,            R3,             D018,
  D025,           D035,           D050,           D070,           D100,
  D012,           0               // Added another pen size
                                  // This should not be sorted!
} ;

LOCAL SHORT DefOptionsMenu[MAX_PEN_OPTIONS+1] =
{
  SPEED,          FORCE,          ACCELERATION,   USAGE,          0
} ;

/*
**      Color/Pen type compatability matrix.  This specifies which
**  colors are available for each type of pen.
*/

//LOCAL SHORT ColorSupport[MAX_PEN_TYPES][MAX_COLORS] =
//{
//
///*
//** Each horz entry coresponds to the entries in ColorList[MAX_COLORS]  array
//** YEL OR RED GR RED_V AQUA VIO BL BR BL WH GR DBL DKRED DKPK DKGR DKCY DKGR
//*/
//
//  {
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1
//  } ,                                  /* P3                                */
//  {
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1
//  } ,                                  /* P7                                */
//  {
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1
//  } ,                                  /* T3                                */
//  {
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1
//  } ,                                  /* T6                                */
//  {
//    0,              0,              0,              0,              0,
//    0,              0,              0,              0,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1
//  } ,                                  /* V25                               */
//  {
//    1,              1,              1,              1,              0,
//    0,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1
//  } ,                                  /* V35                               */
//  {
//    0,              0,              0,              0,              0,
//    0,              0,              0,              0,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1
//  } ,                                  /* V50                               */
//  {
//    1,              1,              1,              1,              0,
//    0,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1
//  } ,                                  /* V70                               */
//  {
//    0,              0,              1,              1,              0,
//    0,              0,              0,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1
//  } ,                                  /* R3                                */
//  {
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1
//  } ,                                  /* 0.18                              */
//  {
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1
//  } ,                                  /* 0.25                              */
//  {
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1
//  } ,                                  /* 0.35                              */
//  {
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1
//  } ,                                  /* 0.50                              */
//  {
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1
//  } ,                                  /* 0.70                              */
//  {
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1,              1,              1,              1,
//    1,              1
//  }                                    /* 1.00                              */
//} ;

/*
** The following FEAL_VER/GEAL_VER structure are used to get
** EA .VERSION of pscript driver file     DCR1399
*/
/*
** CSet/2 Conversion: changed FEAL_VER and GEAL_VER to match what is
**                    used in Postscript. -- Jim R
*/

#pragma  pack          (1)
typedef struct _FEAL_VER
{
  ULONG cbList;                        /* size of the structure             */
  ULONG oNextEntryOffset;              /*                                   */
  BYTE  fEA;                           /*                                   */
  BYTE  cbName;                        /*                                   */
  USHORT cbValue;                      /*                                   */
  CHAR szEAName[SIZE_EA_NAME_VERSION+1];/* fixed size EA name               */
  USHORT usEAT_Type;                   /* Type of the EA                    */
  USHORT usCodePage;                   /* code page field                   */
  USHORT usValueCount;                 /* total fileds                      */
  USHORT usVerASCIIType;               /* type of EAT assume ANSI           */
  USHORT usSizeVerName;                /* name of version name              */
  CHAR szVersionName[MAX_VERNAME_SIZE];/* name of the version               */
} FEAL_VER;
#pragma pack()

/*
** CSet/2 Conversion: Jim R
** The GEAL_VER must be packed on 4-byte boundaries so that it can be used
** with DosQueryPathInfo
*/
#pragma pack(4)
typedef struct _GEAL_VER
{
  ULONG cbList;
  ULONG oNextEntryOffset;
  BYTE cbName;
  CHAR szEAName[SIZE_EA_NAME_VERSION+1];
} GEAL_VER;
#pragma  pack()

/*
** local routine to retreive the driver's EA version  DCR1399
*/

VOID EA_GetVersion(PSZ);
                                       /* DCR1399                           */
VOID szStrCopy(PSZ,PSZ,SHORT);         /* DCR1399                           */
LOCAL char  ApplNam[] = "PM_SPOOLER_DD";
LOCAL VOID  check_menuitem(HWND,USHORT,BOOL);
LOCAL VOID  check_pen(PDEVMODE,BOOL);
LOCAL VOID  check_pens(PDEVMODE);
LOCAL VOID  clear_entries(PDEVMODE);
LOCAL VOID  display_carousel(PDEVMODE,HWND);
LOCAL VOID  display_colors(PDEVMODE);
LOCAL VOID  display_paper_size(PDEVMODE,HWND);
LOCAL VOID  display_pen(PDEVMODE,HWND,SHORT);
LOCAL VOID  display_pens(PDEVMODE,HWND);
LOCAL SHORT get_group(SHORT);
LOCAL PSZ   get_string(PDEVMODE,SHORT);
LOCAL VOID  init_dialog(PDEVMODE,HWND);
LOCAL VOID  list_pen_options(PDEVMODE,HWND);
LOCAL VOID  list_pen_priority(PDEVMODE,HWND);
LOCAL ULONG main_dialog_command(PDEVMODE,HWND,USHORT,MPARAM,MPARAM);

LOCAL VOID  reset_entries(PDEVMODE);
LOCAL VOID  save_profile (PPROFILEINFO pSetup, PSZ pszAppName);        // @MJH
LOCAL VOID  update_menu(PDEVMODE,PMENUSTAT);
LOCAL ULONG GetMeasureIteminfo( HPS, HWND, PCH, SHORT );

/*
** OSDD DCR 1476 - Integrate 1.2 Help Manager
*/

VOID InitializeHelp(VOID);
BOOL SetHelpStubHook(VOID);
VOID ReleaseHelpStubHook(VOID);
VOID CleanUpHelpStubHook(USHORT);
INT  HelpStubHook(HAB,USHORT,USHORT,USHORT,PRECTL);
PSZ           get_module_dir(PSZ);
BOOL          HelpErrorFilter(ULONG,PSZ);
BOOL(*pfnWinDestroyHelpInstance)(HWND hwndHelpInstance)= NULL;
HWND(*pfnWinCreateHelpInstance)(HAB hab,PHELPINIT
                                            phinitHMInitStructure)= NULL;
BOOL(*pfnWinAssociateHelpInstance)(HWND hwndHelpInstance,HWND
                                               hwndApp)= NULL;

#define ENABLE_WINDOW(hwnd,id,flag) WinEnableWindow (WinWindowFromID (hwnd, id), flag)
VOID
SwitchBetween_RGB_Carousel (HWND hwnd, HWND hMenu, PDEVMODE pDevMode, BOOL fUseRGB)
{
   BOOL   fEnableWindow;

   // All of the         will be disabled if we are going into RGB mode
   fEnableWindow = (fUseRGB) ? FALSE : TRUE;

   ENABLE_WINDOW (hwnd, COLORSORT,       fEnableWindow);
   ENABLE_WINDOW (hwnd, HPGL2_RASTER,    !fEnableWindow);
   ENABLE_WINDOW (hwnd, GEC,             fEnableWindow);
   ENABLE_WINDOW (hwnd, SELECT_ALL,      fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_PEN1,   fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_PEN2,   fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_PEN3,   fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_PEN4,   fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_PEN5,   fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_PEN6,   fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_PEN7,   fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_PEN8,   fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_COLOR1, fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_COLOR2, fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_COLOR3, fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_COLOR4, fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_COLOR5, fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_COLOR6, fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_COLOR7, fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_COLOR8, fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_TYPE1,  fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_TYPE2,  fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_TYPE3,  fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_TYPE4,  fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_TYPE5,  fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_TYPE6,  fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_TYPE7,  fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL_TYPE8,  fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSELNUM,     fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSEL,        fEnableWindow);
   ENABLE_WINDOW (hwnd, ACTIVE_CAROUSEL, fEnableWindow);
   ENABLE_WINDOW (hwnd, PENTEXT,         fEnableWindow);
   ENABLE_WINDOW (hwnd, COLORTEXT,       fEnableWindow);
   ENABLE_WINDOW (hwnd, TYPETEXT,        fEnableWindow);
   ENABLE_WINDOW (hwnd, CAROUSELTEXT,    fEnableWindow);

   // Set the "carousel" menu item to enabled/disabled
   WinSendMsg (hMenu, MM_SETITEMATTR,
               MPFROM2SHORT (IDM_CAROUSEL, TRUE),
               MPFROM2SHORT (MIA_DISABLED, fEnableWindow ? 0 : MIA_DISABLED));

   // Change the get back to button's text
   if (fUseRGB)
      WinSetDlgItemText (hwnd, RGB_OR_CAROUSEL_MODE,
                         get_string (pDevMode, CAROUSEL_MODE));
   else
      WinSetDlgItemText (hwnd, RGB_OR_CAROUSEL_MODE,
                         get_string (pDevMode, RGB_MODE));
}

/***************************************************************************/
/***************************************************************************/
VOID
build_app_name (PSZ pszDriverName,
                PSZ pszDeviceName,
                PSZ pszLogAddress,
                PSZ pszAppName)
{
  /*
  ** build new app name
  */
  strcpy (pszAppName,PM_DD);                            /* copy PM_DD_       */
  strcpy (pszAppName+strlen (pszAppName),pszLogAddress);/* copy printer name */
  strcpy (pszAppName+strlen (pszAppName),",");          /* copy ","          */
  strcpy (pszAppName+strlen (pszAppName),APP_NAME);     /* driver name       */
  strcpy (pszAppName+strlen (pszAppName),".");          /* copy "."          */
  strcpy (pszAppName+strlen (pszAppName),pszDeviceName);/* copy device name  */
}

/***************************************************************************
 *
 * FUNCTION NAME = save_profile
 *
 *
 * DESCRIPTION   = save_profile
 *
 *                 save_profile Save the setup data in
 *                 os2sys.ini.  This is placed in a
 *                 private section of the file
 *                 ("PLOTTERS") and the record is
 *                 identified by
 *                 pszDeviceName.pszLogAddress (for
 *                 example "IBM6180.PLOTTER1").
 *
 *
 *
 *
 *
 *
 * INPUT         = pszDriverName;
 *                 pszDeviceName;
 *                 pszLogAddress;
 *
 *
 *
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID save_profile (PPROFILEINFO pSetup, PSZ pszAppName)
{
  PrfWriteProfileData((HINI)HINI_SYSTEMPROFILE, pszAppName, PRINTER_INFO,
                      pSetup,(ULONG)sizeof(PROFILEINFO));
}

/***************************************************************************
 *
 * FUNCTION NAME = check_menuitem
 *
 *
 * DESCRIPTION   = This function checks or unchecks a menuitem
 *                 in a menu.  If Status is TRUE, then the
 *                 menuitem is checked.  If status is FALSE,
 *                 then the menuitem is unchecked
 *
 *
 *
 *
 * INPUT         =  hMenu;
 *                  Id;
 *                  bStatus;
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID check_menuitem(HWND hMenu,USHORT Id,BOOL bStatus)

/*
**     This function checks or unchecks a menuitem in a menu.  If Status is
**   TRUE, then the menuitem is checked.  If status is FALSE, then the
**   menuitem is unchecked
*/

{
  WinSendMsg(hMenu,MM_SETITEMATTR,MPFROM2SHORT(Id,TRUE),
             (MPARAM)(bStatus? MAKELONG(MIA_CHECKED,MIA_CHECKED) :
                               MAKELONG(MIA_CHECKED,0)));
}

/***************************************************************************
 *
 * FUNCTION NAME =  check_pen
 *
 *
 * DESCRIPTION   =  Set the check status in the PenColor
 *                  and Type menu to bStatus.  The
 *                  operation is done only if a single pen
 *                  is selected in the carousel
 *                  configuration list box since this is
 *                  the only time the items in these two
 *                  popup menus will be checked.
 *
 *
 *
 *
 *
 *
 *
 *
 * INPUT         = pDevMode,bStatus
 *
 *
 *
 *
 *
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID  check_pen(PDEVMODE pDevMode,BOOL bStatus)

/*
**     Set the check status in the PenColor and Type menu to bStatus.
**   The operation is done only if a single pen is selected in the
**   carousel configuration list box since this is the only time the items
**   in these two popup menus will be checked.
*/

{

  if (pDevMode->nPensSelected == 1)
  {

    //SHORT MenuItem = (pDevMode->CurColor == 0)?NO_COLOR:YELLOW+
    //                                                    pDevMode->CurColor-1;
    //check_menuitem(pDevMode->hMenu,MenuItem,bStatus);

    if (pDevMode->CurColor != 0)
      check_menuitem(pDevMode->hMenu,P3+pDevMode->CurType,bStatus);
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = check_pens
 *
 *
 * DESCRIPTION   = Check the currently selected pens
 *                 to see if we need to enable or
 *                 disable the menu items.
 *
 *
 * INPUT         = pDevMode
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID check_pens(PDEVMODE pDevMode)

/*
**     Check the currently selected pens to see if we need to enable
**   or disable the menu items.
*/

{
  LONG  lIndex;
  LONG  lPen;
  LONG  lPenCount = 0;


  for (lIndex = 0; lIndex < pDevMode->DeviceInfo.PensInCarousel; lIndex++)
  {
    if (pDevMode->bPenSelected[lIndex])
    {
      lPen = lIndex;
      ++lPenCount;
    }
  }

  if (pDevMode->nPensSelected == 1)
  {
    if (pDevMode->CurColor)
    {
      //check_menuitem(pDevMode->hMenu,
      //               YELLOW+pDevMode->CurColor-1,
      //               FALSE);
      check_menuitem(pDevMode->hMenu,
                     P3+pDevMode->CurType,
                     FALSE);
    }

    //else
    //  check_menuitem(pDevMode->hMenu,
    //                 NO_COLOR,
    //                 FALSE);
  }

  if (lPenCount == 1)
  {
    pDevMode->CurColor = pDevMode->pSetup->Carousel
       [pDevMode->pSetup->CurrentCarousel].Pen[lPen].Color;
    pDevMode->CurType = pDevMode->pSetup->Carousel
       [pDevMode->pSetup->CurrentCarousel].Pen[lPen].Type;

    if (pDevMode->CurColor)
    {
      //check_menuitem(pDevMode->hMenu,
      //               YELLOW+pDevMode->CurColor-1,
      //               TRUE);
      check_menuitem(pDevMode->hMenu,
                     P3+pDevMode->CurType,
                     TRUE);
    }

    //else
    //  check_menuitem(pDevMode->hMenu,NO_COLOR,TRUE);
  }

  if ((!lPenCount && pDevMode->nPensSelected) || (lPenCount &&
     !pDevMode->nPensSelected))
  {
    SHORT Option = lPenCount ? 0 : MIA_DISABLED;

    WinEnableWindowUpdate(pDevMode->hMenu,FALSE);
    WinSendMsg(pDevMode->hMenu,MM_SETITEMATTR,
               MPFROM2SHORT(IDM_PENCOLOR,TRUE),
               MPFROM2SHORT(MIA_DISABLED,Option));
    WinSendMsg(pDevMode->hMenu,MM_SETITEMATTR,
               MPFROM2SHORT(IDM_PENTYPE,TRUE),
               MPFROM2SHORT(MIA_DISABLED,Option));
    WinSendMsg(pDevMode->hMenu,MM_SETITEMATTR,
               MPFROM2SHORT(IDM_OPTIONS,TRUE),
               MPFROM2SHORT(MIA_DISABLED,Option));

    if (lPenCount)
      reset_entries(pDevMode);
    else
      clear_entries(pDevMode);
    WinShowWindow(pDevMode->hMenu,TRUE);
  }
  pDevMode->nPensSelected = lPenCount;
}

/***************************************************************************
 *
 * FUNCTION NAME = clear_entries
 *
 *
 * DESCRIPTION   = Gray all items in the PenColor,
 *                 Type, and Options menues.  This is
 *                 required either when a new
 *                 carousel is selected or the user
 *                 does not have a pen selected in
 *                 the carousel configuration list
 *                 box.
 *
 *
 *
 *
 *
 *
 *
 *
 * INPUT         = pDevMode
 *
 *
 *
 *
 *
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID clear_entries(PDEVMODE pDevMode)

/*
**     Gray all items in the PenColor, Type, and Options menues.
**  This is required either when a new carousel is selected or the user
**  does not have a pen selected in the carousel configuration list box.
*/

{
  LONG lIndex;


  //for (lIndex = 0; pDevMode->ColorMenu[lIndex].MenuItem; lIndex++)
  //  pDevMode->ColorMenu[lIndex].bStatus = 0;

  for (lIndex = 0; pDevMode->PenColorMenu[lIndex].MenuItem; lIndex++)
    pDevMode->PenColorMenu[lIndex].bStatus = 0;

  for (lIndex = 0; pDevMode->TypeMenu[lIndex].MenuItem; lIndex++)
    pDevMode->TypeMenu[lIndex].bStatus = 0;

  for (lIndex = 0; pDevMode->OptionsMenu[lIndex].MenuItem; lIndex++)
    pDevMode->OptionsMenu[lIndex].bStatus = 0;
  //update_menu(pDevMode,pDevMode->ColorMenu);
  update_menu(pDevMode,pDevMode->PenColorMenu);
  update_menu(pDevMode,pDevMode->TypeMenu);
  update_menu(pDevMode,pDevMode->OptionsMenu);
}

/***************************************************************************
 *
 * FUNCTION NAME = display_carousel
 *
 *
 * DESCRIPTION   = display_carousel
 *                 Display the currently selected
 *                 carousel information in the static
 *                 fields.
 *
 *
 *
 * INPUT         = pDevMode,hWnd
 *
 *
 *
 *
 *
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID display_carousel(PDEVMODE pDevMode,HWND hWnd)

/*
**      Display the currently selected carousel information
**  in the static fields.
*/

{
  LONG lIndex;


  for (lIndex = 0; lIndex < pDevMode->DeviceInfo.PensInCarousel; lIndex++)
  {
    WinSendDlgItemMsg(hWnd,
                      CAROUSEL_PEN1+lIndex,
                      BM_SETCHECK,
                      (MPARAM)FALSE,
                      0L);
    pDevMode->bPenSelected[lIndex] = FALSE;
  }
  WinSendDlgItemMsg(hWnd,
                    ACTIVE_CAROUSEL,
                    BM_SETCHECK,
                    (MPARAM)pDevMode->pSetup->bActiveCarousel
                       [pDevMode->pSetup->CurrentCarousel],
                    (MPARAM)NULL);
  WinSetDlgItemShort(hWnd,
                     CAROUSELNUM,
                     pDevMode->pSetup->CurrentCarousel+1,
                     TRUE);
  pDevMode->bSelectAll = FALSE;
  WinSetDlgItemText(hWnd,SELECT_ALL,
                    get_string(pDevMode,
                               SELECT_ALL));
  display_pens(pDevMode,hWnd);
  check_menuitem(pDevMode->hMenu,
                 SEL_CAROUSEL1+pDevMode->pSetup->CurrentCarousel,
                 TRUE);
}

/***************************************************************************
 *
 * FUNCTION NAME = display_colors
 *
 *
 * DESCRIPTION   = Determine the allowable colors and
 *                 types that can be selected in the
 *                 PenColor and Type popup menus.  On
 *                 entry, the menu status table for the
 *                 PenColor menu is set all true
 *                 (indicating any pen can be selected).
 *                 The Type menu status table is
 *                 initialized according to the pen
 *                 types supported by the current
 *                 plotter.  Then, each pen that is
 *                 selected in the carousel
 *                 configuration list box is examined.
 *                 If there is no pen in the stall, no
 *                 operation is performed.  Otherwise,
 *                 all PenColor menu items that the
 *                 selected pen type does not support
 *                 are grayed.  Likewise, all Type menu
 *                 items that do not support the color
 *                 of the given pen are grayed.  Finally
 *                 the update menu function is called
 *                 for the PenColor and Type popup
 *                 menus.
 *
 *
 *
 *
 *
 *
 * INPUT         = (pDevMode)
 *
 *
 *
 *
 *
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID display_colors(PDEVMODE pDevMode)

/*
**      Determine the allowable colors and types that can be
**   selected in the PenColor and Type popup menus.  On entry, the menu status
**   table for the PenColor menu is set all true (indicating any pen can be
**   selected). The Type menu status table is initialized according to the pen
**   types supported by the current plotter.  Then, each pen that is selected
**   in the carousel configuration list box is examined.  If there is no pen in
**   the stall, no  operation is performed.  Otherwise, all PenColor menu items
**   that the selected pen type does not support are grayed.  Likewise, all Type
**   menu items that do not support the color of the given pen are grayed.
**   Finally the update menu function is called for the PenColor and Type
**   popup menus.
*/

{
  LONG  lIndex;


  //for (Index = 0; pDevMode->ColorMenu[Index].MenuItem; Index++)
  //  pDevMode->ColorMenu[Index].bStatus = 1;

  for (lIndex = 0; pDevMode->PenColorMenu[lIndex].MenuItem; lIndex++)
    pDevMode->PenColorMenu[lIndex].bStatus = 1;

  for (lIndex = 0; pDevMode->TypeMenu[lIndex].MenuItem; lIndex++)
    pDevMode->TypeMenu[lIndex].bStatus = pDevMode->DeviceInfo.PenTypeSupport
       [lIndex];

//for (Pen = 0; Pen < pDevMode->DeviceInfo.PensInCarousel; Pen++)
//{
//  if (pDevMode->bPenSelected[Pen] && pDevMode->pSetup->Carousel
//      [pDevMode->pSetup->CurrentCarousel].Pen[Pen].Color != 0)
//  {
//    for (Index = 0; Index < MAX_COLORS; Index++)
//      pDevMode->ColorMenu[Index].bStatus &= ColorSupport
//         [pDevMode->pSetup->Carousel[pDevMode->pSetup->CurrentCarousel].Pen
//         [Pen].Type][Index];
//
//    for (Index = 0; Index < MAX_PEN_TYPES; Index++)
//      pDevMode->TypeMenu[Index].bStatus &= ColorSupport[Index]
//         [pDevMode->pSetup->Carousel[pDevMode->pSetup->CurrentCarousel].Pen
//         [Pen].Color-1];
//  }
//}
  //update_menu(pDevMode,pDevMode->ColorMenu);
  update_menu(pDevMode,pDevMode->PenColorMenu);
  update_menu(pDevMode,pDevMode->TypeMenu);
}

/***************************************************************************
 *
 * FUNCTION NAME = display_paper_size
 *
 *
 * DESCRIPTION   = display_paper_size
 *
 *                 Display the current paper size in the main
 *                 dialog box.  If the paper size is A thru E
 *                 or A4 thru A0, the dialog elements for the
 *                 determination of the roll length are
 *                 hidden and the current paper size is shown
 *                 via static text.  If the paper size is
 *                 either 24 or 36 inch roll, the paper size
 *                 static message is hidden and the dialog
 *                 elements for the roll length are shown.
 *                 If roll feed is selected, the input focus
 *                 of the main dialog is set on the roll
 *                 length input box.  The current paper size
 *                 is then checked in the popup menu.
 *
 *
 * INPUT         = (pDevMode,hWnd)
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID display_paper_size(PDEVMODE pDevMode,HWND hWnd)

/*
**              Display the current paper size in the main dialog box.
**  If the paper size is A thru E or A4 thru A0, the dialog elements for the
**  determination of the roll length are hidden and the current paper size is
**  shown via static text.  If the paper size is either 24 or 36 inch roll, the
**  paper size static message is hidden and the dialog elements for the roll
**  length are shown.  If roll feed is selected, the input focus of the main
**  dialog is set on the roll length input box.  The current paper size is
**  then checked in the popup menu.
*/

{
  HWND hRollScroll = WinWindowFromID(hWnd,ROLL_SCROLL);
  HWND hRollText1 = WinWindowFromID(hWnd,ROLL_TEXT1);
  HWND hRollText2 = WinWindowFromID(hWnd,ROLL_TEXT2);
  HWND hRollLength = WinWindowFromID(hWnd,ROLL_LENGTH);
  HWND hMediaSize = WinWindowFromID(hWnd,MEDIA_SIZE);

  USHORT Loop = 0;
  USHORT fsMediaSize;
  USHORT Form = (USHORT)WinSendDlgItemMsg(hWnd,FORMNAME,
                                          LM_QUERYSELECTION,0L,0L)+1;
  fsMediaSize = pDevMode->DeviceInfo.fsMediaSizeSupport;

  for (Loop = 0; Form; Loop++)
  {
    /*
    ** If the bit is 1,  the size is supported
    */
    if (fsMediaSize&(1 << Loop))
      --Form;
  }

  // Save the current form
  pDevMode->pSetup->usFlags &= ~FL_USERDEFINEDFORMS;     // @MJH
  pDevMode->pSetup->Size = Loop-1;

  if (!IsRollPaper(pDevMode->pSetup->Size))
  {
    WinShowWindow(hRollScroll,FALSE);
    WinShowWindow(hRollText1,FALSE);
    WinShowWindow(hRollText2,FALSE);
    WinShowWindow(hRollLength,FALSE);
    WinSetDlgItemText(hWnd,MEDIA_SIZE,
                      get_string(pDevMode,SIZE_A+pDevMode->pSetup->Size));
    WinShowWindow(hMediaSize,TRUE);
  }
  else
  {
    WinShowWindow(hMediaSize,FALSE);

    if (pDevMode->pSetup->Size == 10)
    {
      WinSetDlgItemText(hWnd,ROLL_TEXT2,
                        get_string(pDevMode,ROLL_24));

      if (pDevMode->pSetup->Roll24 > 500 ||
          pDevMode->pSetup->Roll24 < 1)
          pDevMode->pSetup->Roll24 = 24;
      WinSetDlgItemShort(hWnd,ROLL_LENGTH,
                         pDevMode->pSetup->Roll24,TRUE);
    }
    else
    {
      WinSetDlgItemText(hWnd,ROLL_TEXT2,
                        get_string(pDevMode,ROLL_36));

      if (pDevMode->pSetup->Roll36 > 500 ||
          pDevMode->pSetup->Roll36 < 1)
          pDevMode->pSetup->Roll36 = 36;
      WinSetDlgItemShort(hWnd,ROLL_LENGTH,
                         pDevMode->pSetup->Roll36,TRUE);
    }
    WinShowWindow(hRollText1,TRUE);
    WinShowWindow(hRollText2,TRUE);
    WinShowWindow(hRollScroll,TRUE);
    WinShowWindow(hRollLength,TRUE);
    WinUpdateWindow(hRollLength);
  }
}

/***************************************************************************
 *
 * FUNCTION NAME =  display_pen
 *
 *
 * DESCRIPTION   =  display_pen
 *                  This function will display a pen
 *                  description for the given Pen in the
 *                  carousel text fields.  The pen
 *                  description consists of the pen
 *                  color and the pen type.
 *
 *
 * INPUT         = (pDevMode,hWnd,Pen)
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID display_pen(PDEVMODE pDevMode,HWND hWnd,SHORT Pen)

/*
**     This function will display a pen description for the given Pen in the
**  carousel text fields.  The pen description consists of the pen color and
**  the pen type.
*/

{
  SHORT Color = pDevMode->pSetup->Carousel[pDevMode->pSetup->CurrentCarousel].
     Pen[Pen].Color;

  WinSetDlgItemText(hWnd,CAROUSEL_COLOR1+Pen,
                    Color?get_string(pDevMode,
                                     YELLOW+Color-1):(PSZ)" ");
  WinSetDlgItemText(hWnd,CAROUSEL_TYPE1+Pen,
                    Color?get_string(pDevMode,
                                     P3+pDevMode->pSetup->Carousel
                                        [pDevMode->pSetup->CurrentCarousel].
                                        Pen[Pen].Type):(PSZ)" ");
}

/***************************************************************************
 *
 * FUNCTION NAME = display_pens
 *
 *
 * DESCRIPTION   = display_pens
 *                 This function will reset the contents of
 *                 the carousel configuration list box for
 *                 the current carousel.  Since the
 *                 display_pen function inserts its pen
 *                 description at the specified position, a
 *                 dummy string must be created for the
 *                 duration of the carousel configuration
 *                 construction.  Once completed, this string
 *                 is deleted.  If any pens were selected
 *                 prior to this construction, the check
 *                 marks must be removed from the PenColor
 *                 and Type menus and the PenColor, Type, and
 *                 Options popup menus must be grayed.
 *
 * INPUT         = (pDevMode,hWnd)
 *
 *
 *
 *
 *
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID display_pens(PDEVMODE pDevMode,HWND hWnd)

/*
**     This function will reset the contents of the carousel configuration list
**   box for the current carousel.  Since the display_pen function inserts its
**   pen description at the specified position, a dummy string must be created
**   for the duration of the carousel configuration construction.  Once
**   completed, this string is deleted.  If any pens were selected prior to this
**   construction, the check marks must be removed from the PenColor and Type
**   menus and the PenColor, Type, and Options popup menus must be grayed.
*/

{
  LONG lIndex;


  for (lIndex = 0; lIndex < pDevMode->DeviceInfo.PensInCarousel; lIndex++)
    display_pen(pDevMode,
                hWnd,
                lIndex);

  if (pDevMode->nPensSelected)
  {
    WinEnableWindowUpdate(pDevMode->hMenu,FALSE);
    check_pen(pDevMode,FALSE);
    WinSendMsg(pDevMode->hMenu,MM_SETITEMATTR,
               MPFROM2SHORT(IDM_PENCOLOR,TRUE),
               MPFROM2SHORT(MIA_DISABLED,MIA_DISABLED));
    WinSendMsg(pDevMode->hMenu,
               MM_SETITEMATTR,
               MPFROM2SHORT(IDM_PENTYPE,TRUE),
               MPFROM2SHORT(MIA_DISABLED,MIA_DISABLED));
    WinSendMsg(pDevMode->hMenu,
               MM_SETITEMATTR,
               MPFROM2SHORT(IDM_OPTIONS,TRUE),
               MPFROM2SHORT(MIA_DISABLED,MIA_DISABLED));
    WinShowWindow(pDevMode->hMenu,TRUE);
    pDevMode->nPensSelected = 0;
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = get_group
 *
 *
 * DESCRIPTION   = get_group
 *
 *                 This function returns the group in which
 *                 a pen is classified from its given type.
 *                 (Example:  P3 and P7 are paper pens, T3
 *                 and T6 are transparency pens, etc.)
 *
 *
 *
 * INPUT         = (Type)
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL SHORT get_group(SHORT Type)

/*
**   This function returns the group in which a pen is classified from its
**   given type.  (Example:  P3 and P7 are paper pens, T3 and T6 are
**   transparency pens, etc.)
*/

{
  SHORT Result;

  Type += P3;

  if (WITHIN(Type,P3,P7))
    Result = PAPER;
  else
    if (WITHIN(Type,T3,T6))
      Result = TRANSPARENCY;
    else
      if (Type == R3)
        Result = ROLLERBALL;
      else
        if (WITHIN(Type,V25,V70))
          Result = DISPOSABLE;
        else
          Result = REFILLABLE;
  return (Result);
}

/***************************************************************************
 *
 * FUNCTION NAME = get_string
 *
 *
 * DESCRIPTION   = get_string
 *
 *                 Load string number Message from the
 *                 resources file and place in the
 *                 message buffer in the DEVMODE
 *                 structure.  Returns the address of the
 *                 string buffer in DEVMODE.
 *
 *
 *
 * INPUT         = (pDevMode,Message)
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL PSZ get_string(PDEVMODE pDevMode,SHORT Message)

/*
**      Load string number Message from the resources file and place in the
**   message buffer in the DEVMODE structure.
**   Returns the address of the string buffer in DEVMODE.
*/

{
  WinLoadString(pDevMode->hAB,get_mod_handle(),
                Message,MSGBUFSIZE,
                pDevMode->MessageBuffer);
  return (pDevMode->MessageBuffer);
}

/***************************************************************************
 *
 * FUNCTION NAME = init_dialog
 *
 *
 * DESCRIPTION   = init_dialog
 *                 Initializes the main dialog box.
 *                 This is done upon entry and when the
 *                 user changes the current plotter.
 *                 It performs the following duties:
 *
 *
 *                 Set window caption to the current
 *                 plotter and check it in the Plotter
 *                 menu.  Check the current and active
 *                 carousels; display the current carousel
 *                 above the carousel configuration list
 *                 box.  Initialize the paper feed
 *                 selections and options.  Initialize the
 *                 orientation selections.  Display the
 *                 current paper size.  Disable the
 *                 PenColor, Type, and Options popup
 *                 menus.  Construct the carousel
 *                 configuration list box.  Determine
 *                 paper size support and update the Size
 *                 popup menu.
 *
 *
 *
 *
 * INPUT         = pDevMode,hWnd
 *
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID init_dialog(PDEVMODE pDevMode,HWND hWnd)

/*
**      Initializes the main dialog box.  This is done upon entry
**   and when the user changes the current plotter.  It performs the following
**   duties:
**      - Set window caption to the current plotter and check it in the Plotter
**        menu.
**      - Check the current and active carousels; display the current carousel
**        above the carousel configuration list box.
**      - Initialize the paper feed selections and options.
**      - Initialize the orientation selections.
**      - Display the current paper size.
**      - Disable the PenColor, Type, and Options popup menus.
**      - Construct the carousel configuration list box.
**      - Determine paper size support and update the Size popup menu.
*/

{
  SHORT  Index;
  SHORT  Item;
  SHORT  ItemSave;
  USHORT fsMediaSupported;
  SHORT  UserIndex;

  for (Index = 0; Index < MAX_CAROUSELS; Index++)
  {
    check_menuitem(pDevMode->hMenu,
                   ACTIVE_CAROUSEL1+Index,
                   pDevMode->pSetup->bActiveCarousel[Index]);
    check_menuitem(pDevMode->hMenu,
                   SEL_CAROUSEL1+Index,
                   Index == pDevMode->pSetup->CurrentCarousel);
  }
  display_carousel(pDevMode,
                   hWnd);
  WinSendDlgItemMsg(hWnd,
                    MANUAL,
                    BM_SETCHECK,
                    (MPARAM)(pDevMode->pSetup->PaperFeed?FALSE:TRUE),
                    0L);
  WinSendDlgItemMsg(hWnd,
                    AUTOMATIC,
                    BM_SETCHECK,
                    (MPARAM)(pDevMode->pSetup->PaperFeed?TRUE:FALSE),
                    0L);

  if (pDevMode->pSetup->PaperFeed)
    WinEnableWindow(WinWindowFromID(hWnd,
                                    PRELOADED),
                    FALSE);
  WinSendDlgItemMsg(hWnd,
                    PRELOADED,
                    BM_SETCHECK,
                    (MPARAM)pDevMode->pSetup->bPreloaded,
                    (MPARAM)0L);
  WinSendDlgItemMsg(hWnd,
                    GEC,
                    BM_SETCHECK,
                    (MPARAM)pDevMode->pSetup->bGECOption,
                    0L);
  WinShowWindow(WinWindowFromID(hWnd,
                                GEC),
                pDevMode->DeviceInfo.GECSupport);

  WinSendDlgItemMsg(hWnd,
                    COLORSORT,
                    BM_SETCHECK,
                    (MPARAM)pDevMode->pSetup->bColorSort,
                    0L);

  WinSendDlgItemMsg(hWnd,
                    HPGL2_RASTER,
                    BM_SETCHECK,
                    (MPARAM)(!(pDevMode->pSetup->usFlags & FL_RASTER)),
                    0L);
  WinShowWindow(WinWindowFromID(hWnd,
                   HPGL2_RASTER),
                   (PlotterClass[pDevMode->Plotter].usHPGLCaps & HPGL2));


  /*  Initialize DRAFT button; Draft mode not implemented
  **
  **   WinSendDlgItemMsg (hWnd,DRAFT,BM_SETCHECK,(MPARAM)
  **     pDevMode->pSetup->bDraft,0L);
  */

  WinSendDlgItemMsg(hWnd,
                    PORTRAIT,
                    BM_SETCHECK,
                    (MPARAM)(pDevMode->pSetup->Orientation?FALSE:TRUE),
                    0L);
  WinSendDlgItemMsg(hWnd,
                    LANDSCAPE,
                    BM_SETCHECK,
                    (MPARAM)(pDevMode->pSetup->Orientation?TRUE:FALSE),
                    0L);

  clear_entries(pDevMode);

  // Clear out all of the entries in the listbox
  WinSendDlgItemMsg(hWnd,
                    FORMNAME,
                    LM_DELETEALL,
                    0L,
                    0L);

  // now, add them if they are supported
  fsMediaSupported = pDevMode->DeviceInfo.fsMediaSizeSupport;

  for (Index = 0, Item = 0; Index < MAX_MEDIA_SIZES; Index++)
  {
    if (fsMediaSupported & (1 << Index))
    {
      // and the entry
      WinSendDlgItemMsg(hWnd,
                        FORMNAME,
                        LM_INSERTITEM,
                        (MPARAM)LIT_END,
                        (MPARAM)get_string(pDevMode,
                                           SIZE_A+Index));

      // Remember the index of the selected item (in pDevMode)
      if ((!(pDevMode->pSetup->usFlags & FL_USERDEFINEDFORMS)) &&
          Index == pDevMode->pSetup->Size)
        ItemSave = Item;

      ++Item;
    }
  }

  // Append the user defined forms to the list box
  // Also if the FL_USERDEFINEDFORMS bit is set then use that index
  UserIndex = add_user_forms_to_list (pDevMode, WinWindowFromID (hWnd, FORMNAME));
  if (pDevMode->pSetup->usFlags & FL_USERDEFINEDFORMS)
     ItemSave = UserIndex;

  // Select the remembered item
  WinSendDlgItemMsg(hWnd,
                    FORMNAME,
                    LM_SELECTITEM,
                    (MPARAM)ItemSave,
                    (MPARAM)TRUE);
  WinSendDlgItemMsg(hWnd,
                    FORMNAME,
                    LM_SETTOPINDEX,
                    (MPARAM)ItemSave,
                    (MPARAM)0L);

  // uncollated copies
  WinSendMsg (WinWindowFromID (hWnd, UNCOLLATED_COPIES),
              SPBM_SETCURRENTVALUE,
              (MPARAM)((pDevMode->pSetup->usFlags & FL_UNCOLLATEDMASK)+1),
              (MPARAM)NULL);

  if (pDevMode->pSetup->usFlags & FL_USERDEFINEDFORMS)
     display_user_form_paper_size (pDevMode,
                                   hWnd,
                                   (PUSERFORMINFO)WinSendDlgItemMsg (hWnd,
                                                        FORMNAME,
                                                        LM_QUERYITEMHANDLE,
                                                        MPFROMSHORT (UserIndex),
                                                        (MPARAM)0));
  else
     display_paper_size(pDevMode, hWnd);
}

/***************************************************************************
 *
 * FUNCTION NAME = list_pen_options
 *
 *
 * DESCRIPTION   = list_pen_options
 *
 *                 Display (in the pen options dialog box)
 *                 the value for the given option for each
 *                 pen selected from the carousel
 *                 configuration list box.  The pen options
 *                 available are:  Speed, Force, and
 *                 Acceleration.  Speed and acceleration are
 *                 true values while force is an index in a
 *                 table of values that is dependent upon the
 *                 current plotter.
 *
 *
 *
 * INPUT         = (pDevMode,hWnd)
 *
 *
 *
 *
 *
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID list_pen_options(PDEVMODE pDevMode,HWND hWnd)

/*
**      Display (in the pen options dialog box) the value for the
**   given option for each pen selected from the carousel configuration list
**   box. The pen options available are: Speed, Force, and Acceleration.  Speed
**   and acceleration are true values while force is an index in a table of
**   values that is dependent upon the current plotter.
*/

{
  SHORT Index,Value;
  char PenOpt[8];


  for (Index = 0; Index < pDevMode->nPensSelected; Index++)
  {
    if (pDevMode->PenOption == 1)
      Value = pDevMode->DeviceInfo.ForceValue[pDevMode->PenValue[Index]-1];
    else
      Value = pDevMode->PenValue[Index];

    int_to_str((LONG)Value,PenOpt,1);
    WinSetDlgItemText(hWnd,CAROUSEL_VAR1+Index,PenOpt);
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = list_pen_priority
 *
 *
 * DESCRIPTION   = list_pen_priority
 *
 *                 Display (in the pen priority dialog box)
 *                 the priority for each pen selected from
 *                 the carousel configuration list box.  The
 *                 possible priorities are:  NONE, LINE,
 *                 FILL, and TEXT
 *
 *
 *
 *
 * INPUT         = pDevMode,hWnd
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID list_pen_priority(PDEVMODE pDevMode,HWND hWnd)

/*
**         Display (in the pen priority dialog box) the priority for
**   each pen selected from the carousel configuration list box.  The possible
**   priorities are: NONE, LINE, FILL, and TEXT
*/

{
  SHORT PenOffset;


  for (PenOffset = 0; PenOffset < pDevMode->nPensSelected; PenOffset++)
    WinSetDlgItemText(hWnd,CAROUSEL_VAR1+PenOffset,
                      get_string(pDevMode,
                                 USE_NONE+pDevMode->PenPriority[PenOffset]));
}

/***************************************************************************
 *
 * FUNCTION NAME = main_dialog_command
 *
 *
 * DESCRIPTION   = main_dialog_command
 *
 *                 Handle the user interface with the
 *                 main dialog box.  This dialog box can
 *                 only be enabled by the exported
 *                 function DeviceMode.  Seems we return
 *                 TRUE if we process something, else
 *                 FALSE.
 *
 *
 * INPUT         = pDevMode,hWnd,Msg,mParam1,mParam2
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = Handled
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL ULONG main_dialog_command(PDEVMODE pDevMode,HWND hWnd,USHORT
                                             Msg,MPARAM mParam1,MPARAM mParam2
)

/*
**      Handle the user interface with the main dialog box.  This
**   dialog box can only be enabled by the exported function DeviceMode.
**      Seems we return TRUE if we process something,  else FALSE.
*/

{
  ULONG  Handled = TRUE;
  USHORT Cmd = LOUSHORT(mParam1);
  LONG   ulValue;

  if (Cmd == DID_OK)
  {
    /*
    ** if we have a help instance destroy it.     DCR 1476
    */
    WinAssociateHelpInstance(NULLHANDLE, WinQueryActiveWindow(HWND_DESKTOP));

    if (HelpAlreadyInitialized)
    {
      WinDestroyHelpInstance(hwndHelp);
      hwndHelp = (HWND)NULL;
      HelpAlreadyInitialized = FALSE;
      HelpStubHookIsSet = FALSE;
    }
    ReleaseHelpStubHook();

    if (IsRollPaper(pDevMode->pSetup->Size))    /* Roll Feed */
      if (pDevMode->pSetup->Size == 10)
        WinQueryDlgItemShort(hWnd,ROLL_LENGTH,
                             &pDevMode->pSetup->Roll24,
                             FALSE);
      else
        WinQueryDlgItemShort(hWnd,ROLL_LENGTH,
                             &pDevMode->pSetup->Roll36,
                             FALSE);
    pDevMode->pSetup->Orientation = WinSendDlgItemMsg(hWnd,
                                                      LANDSCAPE,
                                                      BM_QUERYCHECK,
                                                      0L,
                                                      0L)?1:0;
    pDevMode->pSetup->bPreloaded = (BOOL)WinSendDlgItemMsg(hWnd,
                                                           PRELOADED,
                                                           BM_QUERYCHECK,
                                                           0L,
                                                           0L);
    pDevMode->pSetup->bGECOption = (BOOL)WinSendDlgItemMsg(hWnd,
                                                           GEC,
                                                           BM_QUERYCHECK,
                                                           0L,
                                                           0L);

    /*
    ** Query DRAFT Button -- Draft mode not implemented
    **
    **       pDevMode->pSetup->bDraft = (BOOL)WinSendDlgItemMsg (hWnd,
    **         DRAFT,BM_QUERYCHECK,0L,0L);
    */

    pDevMode->pSetup->bColorSort = (BOOL)WinSendDlgItemMsg(hWnd,
                                                           COLORSORT,
                                                           BM_QUERYCHECK,
                                                           0L,
                                                           0L);

    // HPGL2
    // Clear out the old value
    pDevMode->pSetup->usFlags &= ~FL_RASTER;
    pDevMode->pSetup->usFlags |= (WinSendDlgItemMsg(hWnd,
                                                           HPGL2_RASTER,
                                                           BM_QUERYCHECK,
                                                           0L,
                                                           0L) ? 0 : FL_RASTER);

    // begin @MJH

    // clear out the old value
    pDevMode->pSetup->usFlags &= ~FL_UNCOLLATEDMASK;

    // find out the new value
    WinSendMsg (WinWindowFromID (hWnd, UNCOLLATED_COPIES),
                SPBM_QUERYVALUE,
                MPFROMP (&ulValue),
                MPFROM2SHORT (0, SPBQ_DONOTUPDATE));

    // save it
    pDevMode->pSetup->usFlags |= ((USHORT)ulValue & FL_UNCOLLATEDMASK) - 1;

    // delete any user forms from the list
    delete_user_forms_from_list (pDevMode, WinWindowFromID (hWnd, FORMNAME));

    // end   @MJH

    pDevMode->pSetup->Version = JOBPROP_VERSION;                     // @MJH3
    WinShowWindow(pDevMode->hMenu,FALSE);
    WinDismissDlg(hWnd,TRUE);
  }
  else if (Cmd == DID_CANCEL)
  {
    /*
    ** if we have a help instance destroy it.     DCR 1476
    */
    WinAssociateHelpInstance(NULLHANDLE, WinQueryActiveWindow(HWND_DESKTOP));

    if (HelpAlreadyInitialized)
    {
      WinDestroyHelpInstance(hwndHelp);
      hwndHelp = (HWND)NULL;
      HelpAlreadyInitialized = FALSE;
      HelpStubHookIsSet = FALSE;
    }
    ReleaseHelpStubHook();

    // begin @MJH

    // delete any user forms from the list
    delete_user_forms_from_list (pDevMode, WinWindowFromID (hWnd, FORMNAME));

    // end @MJH

    pDevMode->bCancel = TRUE;
    WinShowWindow(pDevMode->hMenu,FALSE);
    WinDismissDlg(hWnd,TRUE);
  }
  else if (Cmd >= SEL_CAROUSEL1 &&
           Cmd < SEL_CAROUSEL1+MAX_CAROUSELS)
  {
    SHORT Carousel = Cmd-SEL_CAROUSEL1;

    if (Carousel != pDevMode->pSetup->CurrentCarousel)
    {
      check_menuitem(pDevMode->hMenu,
                     SEL_CAROUSEL1+pDevMode->pSetup->CurrentCarousel,
                     FALSE);
      pDevMode->pSetup->CurrentCarousel = Carousel;
      display_carousel(pDevMode,hWnd);
    }
  }
  else if (Cmd >= ACTIVE_CAROUSEL1 && Cmd < ACTIVE_CAROUSEL1+MAX_CAROUSELS)
  {
    SHORT nCarouselsActive = 0,Index,Carousel = Cmd-ACTIVE_CAROUSEL1;
    BOOL bSet;

    for (Index = 0; Index < MAX_CAROUSELS; Index++)
      if (pDevMode->pSetup->bActiveCarousel[Index])
        nCarouselsActive++;

    if (!(bSet = pDevMode->pSetup->bActiveCarousel[Carousel]) ||
        (bSet&& nCarouselsActive > 1))
    {
      check_menuitem(pDevMode->hMenu,
                     ACTIVE_CAROUSEL1+Carousel,
                     pDevMode->pSetup->bActiveCarousel[Carousel] ^= 1?
                        TRUE:FALSE);

      if (Carousel == pDevMode->pSetup->CurrentCarousel)
        WinSendDlgItemMsg(hWnd,
                          ACTIVE_CAROUSEL,
                          BM_SETCHECK,
                          (MPARAM)pDevMode->pSetup->bActiveCarousel
                             [Carousel],
                          (MPARAM)NULL);
    }
  }
  else if (Cmd == RESET)
  {
    WinEnableWindow (WinWindowFromID (hWnd, DID_OK), TRUE);
    get_defaults (pDevMode->Plotter, pDevMode->pSetup);
    init_dialog (pDevMode, hWnd);

    // begin @MJH
    SwitchBetween_RGB_Carousel (hWnd,
                                pDevMode->hMenu,
                                pDevMode,
                                pDevMode->pSetup->usFlags & FL_USEAPPCOLORS);
    // End @MJH
  }
  else if (Cmd == SELECT_PEN_COLOR)
  {
    WinDlgBox(HWND_DESKTOP,hWnd,
              (PFNWP)pencolor_dialog_proc,
               get_mod_handle(),
               IDD_PENCOLOR,
               pDevMode);
  }
  else if (Cmd == NO_COLOR)
  {
    SHORT Index,Color = 0;
    PPENINFO pPenInfo;

    check_pen(pDevMode,FALSE);

    if (pDevMode->CurColor == 0)
      pDevMode->CurType = 0;
    pDevMode->CurColor = Color;
    check_pen(pDevMode,TRUE);

    for (Index = 0; Index < pDevMode->DeviceInfo.PensInCarousel;
       Index++)
      if (pDevMode->bPenSelected[Index])
      {
        pPenInfo = (PPENINFO)&pDevMode->pSetup->Carousel
           [pDevMode->pSetup->CurrentCarousel].Pen[Index].Color;

        if (pPenInfo->Color == 0)
          pPenInfo->Type = 0;
        pPenInfo->Color = (UCHAR)Color;
        display_pen(pDevMode,hWnd,Index);
      }
  }
  else if (Cmd == SELECT_ALL)
  {
    SHORT Index = 0;

    pDevMode->bSelectAll = !pDevMode->bSelectAll;
    WinSetDlgItemText(hWnd,
                      SELECT_ALL,
                      get_string(pDevMode,
                             pDevMode->bSelectAll?SELECT_NONE:
                             SELECT_ALL));

    for (Index = 0; Index < pDevMode->DeviceInfo.PensInCarousel;
       Index++)
    {
      WinSendDlgItemMsg(hWnd,
                        CAROUSEL_PEN1+Index,
                        BM_SETCHECK,
                        (MPARAM)pDevMode->bSelectAll,
                        0L);
      pDevMode->bPenSelected[Index] = pDevMode->bSelectAll;
    }
    check_pens(pDevMode);
  }
  else if (Cmd >= P3 && Cmd <= D012)
  {
    SHORT Index,Type = Cmd-P3;
    PPENINFO pPenInfo;

    check_pen(pDevMode,FALSE);

    if (pDevMode->CurColor == 0)
      pDevMode->CurColor = 1;
    pDevMode->CurType = Type;
    check_pen(pDevMode,TRUE);

    for (Index = 0; Index < pDevMode->DeviceInfo.PensInCarousel;
         Index++)
      if (pDevMode->bPenSelected[Index])
      {
        pPenInfo = (PPENINFO)&pDevMode->pSetup->Carousel
           [pDevMode->pSetup->CurrentCarousel].Pen[Index].Color;
        pPenInfo->Type = (UCHAR)Type;

        if (pPenInfo->Color == 0)
          pPenInfo->Color = 1;
        display_pen(pDevMode,hWnd,Index);
      }
    display_colors(pDevMode);
  }
  else if (Cmd >= SPEED && Cmd <= ACCELERATION)
  {
    pDevMode->PenOption = Cmd-SPEED;
    WinDlgBox(HWND_DESKTOP,
              hWnd,
              (PFNWP)options_dialog_proc,
              get_mod_handle(),
              IDD_OPTIONS,
              pDevMode);
  }
  else if (Cmd == USAGE)
  {
    WinDlgBox(HWND_DESKTOP,hWnd,
              (PFNWP)priority_dialog_proc,
              get_mod_handle(),
              IDD_PRIORITY,
              pDevMode);
  }
  // begin @MJH
  else if ((Cmd == RGB_OR_CAROUSEL_MODE) &&
           ((PlotterClass[pDevMode->Plotter].usHPGLCaps & HPGL2) &&
            !(PlotterClass[pDevMode->Plotter].fsOdd & OD_HPGL2_PENPLOTTER)))
  {
    BOOL   usFlags, usUseAppColors, usValue;

    usFlags = pDevMode->pSetup->usFlags;

    // Switch the use application colors bit
    usFlags = (usFlags & FL_USEAPPCOLORS) ? (usFlags & ~FL_USEAPPCOLORS) :
                                            (usFlags |  FL_USEAPPCOLORS);
    usUseAppColors = usFlags & FL_USEAPPCOLORS;

    if (usUseAppColors)
    {
       // Switching to "RGB" mode

       // Uncheck any pens that may currently be checked!
       display_carousel (pDevMode, hWnd);

       // Now that we are in RGB mode, some things cannot be set (such as
       // color sorting), so uncheck them!
       usValue = (BOOL)WinSendDlgItemMsg(hWnd, COLORSORT, BM_QUERYCHECK, 0L, 0L);
       if (usValue)
          usFlags |= FL_SAVECOLORSORT;
       else
          usFlags &= ~FL_SAVECOLORSORT;
       WinSendDlgItemMsg (hWnd, COLORSORT, BM_SETCHECK, (MPARAM)FALSE, 0L);
    }
    else
    {
       // Switching into "Carousel" mode
       // reset the colorsorting option since it is now valid.
       usValue = (usFlags & FL_SAVECOLORSORT) ? TRUE : FALSE;
       WinSendDlgItemMsg (hWnd, COLORSORT, BM_SETCHECK, (MPARAM)usValue, 0L);
    }

    SwitchBetween_RGB_Carousel (hWnd, pDevMode->hMenu, pDevMode, usUseAppColors);

    // Save the value back...
    pDevMode->pSetup->usFlags = usFlags;
  }
  else if (Cmd == USER_DEFINED_FORMS)
  {
     SHORT    sIndex;
     ULONG    ulHandle;
     BOOL     bError = FALSE;

     pDevMode->hwndMainDlg = hWnd;

     // Remember what the user has selected...
     // First, see if an item is selected in the list box
     sIndex = (SHORT)WinSendMsg (WinWindowFromID (hWnd, FORMNAME),
                                 LM_QUERYSELECTION,
                                 MPFROMSHORT (LIT_FIRST),
                                 (MPARAM)0);
     if (LIT_NONE != sIndex)
     {
        // See if it has a handle
        ulHandle = (ULONG)WinSendDlgItemMsg (hWnd, FORMNAME,
                                             LM_QUERYITEMHANDLE,
                                             MPFROMSHORT (sIndex),
                                             (MPARAM)0);
     }

     // delete any user forms from the list
     delete_user_forms_from_list (pDevMode, WinWindowFromID (hWnd, FORMNAME));

     // let the user muck with them...
     WinDlgBox (HWND_DESKTOP,
                hWnd,
                (PFNWP)user_defined_forms_dialog_proc,
                get_mod_handle(),
                IDD_USER_DEFINED_FORMS,
                pDevMode);

     // put them back in
     add_user_forms_to_list (pDevMode, WinWindowFromID (hWnd, FORMNAME));

     if (LIT_NONE != sIndex)
     {
        if (ulHandle)
        {
           // See if it still exists
           if (user_form_exists_exists (pDevMode->hmcbHeap,
                                        (PSZ)pDevMode->achAppName,
                                        (PUSERFORMINFO)ulHandle))
              // reselect it
              WinSendMsg (WinWindowFromID (hWnd, FORMNAME),
                          LM_SELECTITEM,
                          MPFROMSHORT (sIndex),
                          (MPARAM)TRUE);
           else
              bError = TRUE;
        }
        else
        {
           // a hardcoded form size... reselect it
           WinSendMsg (WinWindowFromID (hWnd, FORMNAME),
                       LM_SELECTITEM,
                       MPFROMSHORT (sIndex),
                       (MPARAM)TRUE);
        }
     }
     else
        bError = TRUE;

     if (bError)
     {
        WinMessageBox (HWND_DESKTOP, hWnd, "Please be sure to make a selection", "Title", 0, MB_OK);

        // Clear out the form title text
        WinSetDlgItemText (hWnd, MEDIA_SIZE, "");
     }
  }
  // end @MJH
  /*
  ** help commands - DCR 1476
  */
  else if (Cmd == IDM_HOWTOGETHELP)
  {
    InitializeHelp();

    if (hwndHelp != NULLHANDLE)
      WinSendMsg(hwndHelp,
                 HM_DISPLAY_HELP,
                 (MPARAM)0,
                 (MPARAM)0);
  }
  else if (Cmd == IDM_HELPEXTENDED)
  {
    InitializeHelp();

    if (hwndHelp != NULLHANDLE)
      WinSendMsg(hwndHelp,HM_EXT_HELP,
                 (MPARAM)0,(MPARAM)0);
  }
  else if (Cmd == IDM_HELPKEYS)
  {
    InitializeHelp();

    if (hwndHelp != NULLHANDLE)
      WinSendMsg(hwndHelp,
                 HM_KEYS_HELP,
                 (MPARAM)0,
                 (MPARAM)0);
  }
  else if (Cmd == IDM_HELPINDEX)
  {
    InitializeHelp();

    if (hwndHelp != NULLHANDLE)
      WinSendMsg(hwndHelp,
                 HM_HELP_INDEX,
                 (MPARAM)0,
                 (MPARAM)0);
  }
  else
    Handled = FALSE;

  return (Handled);
}

/***************************************************************************
 *
 * FUNCTION NAME = reset_entries
 *
 *
 * DESCRIPTION   = reset_entries
 *
 *                 Update the PenColor and Type popup menus
 *                 via a call to display colors and then
 *                 determine the options supported by the
 *                 current plotter and update the Options
 *                 popup menu.
 *
 *
 *
 *
 *
 *
 *
 *
 * INPUT         = pDevMode
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID reset_entries(PDEVMODE pDevMode)

/*
**      Update the PenColor and Type popup menus via a call to
**   display colors and then determine the options supported by the current
**   plotter and update the Options popup menu.
*/

{
  SHORT Index;

  display_colors(pDevMode);

  for (Index = 0; pDevMode->OptionsMenu[Index].MenuItem; Index++)
    pDevMode->OptionsMenu[Index].bStatus =
       pDevMode->DeviceInfo.PenOptionsSupport[Index];

  update_menu(pDevMode,pDevMode->OptionsMenu);
}

/***************************************************************************
 *
 * FUNCTION NAME = update_menu
 *
 *
 * DESCRIPTION   = update_menu
 *
 *                 Set the status of a popup menu to the
 *                 menu status table given by pMenuList.
 *                 The three popup menus with menu status
 *                 tables are:  PenColor, Type, and
 *                 Options.
 *
 *
 *
 *
 *
 *
 *
 *
 * INPUT         = pDevMode,pMenuList
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

LOCAL VOID update_menu(PDEVMODE pDevMode,PMENUSTAT pMenuList)

/*
**      Set the status of a popup menu to the menu status table
**   given by pMenuList.  The three popup menus with menu status tables are:
**   PenColor, Type, and Options.
*/

{

  while (pMenuList->MenuItem)
  {
    WinSendMsg(pDevMode->hMenu,
               MM_SETITEMATTR,
               MPFROM2SHORT(pMenuList->MenuItem,TRUE),
               (MPARAM)((pMenuList->bStatus) ?
                         MAKELONG(MIA_DISABLED,0) :
                         MAKELONG(MIA_DISABLED,MIA_DISABLED)));
    ++pMenuList;
  }
}

/*
** Export Routines
*/

#ifdef   DCR1476

/***************************************************************************
 *
 * FUNCTION NAME = help_dialog_proc
 *
 *
 * DESCRIPTION   = Dialog procedure for help
 *
 *
 * INPUT         = hWnd,Msg,mParam1,mParam2
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = Handled
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

ULONG help_dialog_proc(HWND hWnd,USHORT Msg,MPARAM mParam1,MPARAM
                       mParam2)

/*
**      The HELP dialog processor.
*/

{
  ULONG Handled = FALSE;


  switch (Msg)
  {
    case  WM_INITDLG :
      {
        PDEVMODE pDevMode = (PDEVMODE)mParam2;
        SHORT Plotter = pDevMode->Plotter;

        WinSetWindowULong(hWnd,QWL_USER,(ULONG)mParam2);
        WinSetWindowText(hWnd,
                         get_string(pDevMode,pDevMode->StringId));
        break;
      }

    case  WM_COMMAND :
      if (LOUSHORT(mParam1) == DID_OK)
        WinDismissDlg(hWnd,TRUE);
      Handled = TRUE;
      break;

    default  :
      Handled = (ULONG)WinDefDlgProc(hWnd,Msg,mParam1,mParam2);
      break;
  }
  return (Handled);
}

#endif

/***************************************************************************
 *
 * FUNCTION NAME = main_dialog_proc
 *
 *
 * DESCRIPTION   = main_dialog_proc
 *
 *                 Main dialog box window procedure.  All
 *                 window functions are processed here.
 *                 WM_COMMAND type functions are passed
 *                 to the local function
 *                 main_dialog_command.
 *
 *
 *
 *
 *
 *
 *
 *
 * INPUT         = hWnd,Msg,mParam1,mParam2
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = 0 OR 1
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

ULONG main_dialog_proc(HWND hWnd,USHORT Msg,MPARAM mParam1,MPARAM
                       mParam2)

/*
**      Main dialog box window procedure.  All window functions are
**  processed here.  WM_COMMAND type functions are passed to the local
**  function main_dialog_command.
*/

{
  ULONG Handled = FALSE;
  CHAR szDrvVersion[MAX_VERNAME_SIZE]; // buffer of driver's version DCR1399


  switch (Msg)
  {
    case  WM_INITDLG :
      {
        PDEVMODE pDevMode = (PDEVMODE)mParam2;
        SHORT Index;

        /*
        ** DCR 1476
        ** Initialize help dummy hook - avoid doing WinCreateHelpInstance
        ** until the user presses F1, clicks on a help button or uses our
        ** help menu...
        */

        SetHelpStubHook();
        WinSetWindowULong(hWnd,QWL_USER,(ULONG)mParam2);

        //for (Index = 0; DefColorMenu[Index]; Index++)
        //  pDevMode->ColorMenu[Index].MenuItem = DefColorMenu[Index];

        for (Index = 0; DefPenColorMenu[Index]; Index++)
          pDevMode->PenColorMenu[Index].MenuItem = DefPenColorMenu[Index];

        for (Index = 0; DefTypeMenu[Index]; Index++)
          pDevMode->TypeMenu[Index].MenuItem = DefTypeMenu[Index];

        for (Index = 0; DefOptionsMenu[Index]; Index++)
          pDevMode->OptionsMenu[Index].MenuItem = DefOptionsMenu[Index];
        pDevMode->hMenu = WinLoadMenu(hWnd,get_mod_handle(),
                                      IDM_MAINMENU);
        pDevMode->hWnd = hWnd;
        WinSetParent(pDevMode->hMenu,hWnd,TRUE);
        WinSendMsg(hWnd,WM_UPDATEFRAME,
                   (MPARAM)(FCF_TITLEBAR|FCF_MENU|FS_DLGBORDER|WS_VISIBLE),
                   0L);
        WinSendDlgItemMsg(hWnd,ROLL_LENGTH, EM_SETTEXTLIMIT, (MPARAM)3, 0L);

        /*
        ** ROLL_SCROLL Scroll Bar
        */

        WinSendDlgItemMsg(hWnd, ROLL_SCROLL, SBM_SETSCROLLBAR,
                          MPFROMSHORT((USHORT)1), MPFROM2SHORT((USHORT)0,
                                       (USHORT)2));

        /*
        ** CAROUSEL Scroll Bar
        */
        WinSendDlgItemMsg(hWnd, CAROUSEL, SBM_SETSCROLLBAR,
                          MPFROMSHORT((USHORT)1), MPFROM2SHORT((USHORT)0,
                          (USHORT)2));
        WinSendDlgItemMsg(hWnd, CAROUSELNUM, EM_SETTEXTLIMIT, (MPARAM)2, 0L);
        WinSetWindowText(hWnd, get_string(pDevMode,pDevMode->StringId));

        for (Index = 0; Index < MAX_PENS; Index++)
        {
          WinSetDlgItemText(hWnd,CAROUSEL_COLOR1+Index,"");
          WinSetDlgItemText(hWnd,CAROUSEL_TYPE1+Index,"");
        }

        for (Index = pDevMode->DeviceInfo.PensInCarousel; Index < MAX_PENS;
           Index++)
          WinShowWindow(WinWindowFromID(hWnd, CAROUSEL_PEN1+Index),FALSE);

        pDevMode->bSelectAll = FALSE;

        WinEnableWindow(WinWindowFromID(hWnd,MANUAL),
                        pDevMode->DeviceInfo.PaperFeedSupport);
        WinEnableWindow(WinWindowFromID(hWnd,AUTOMATIC),
                        pDevMode->DeviceInfo.PaperFeedSupport);

        init_dialog(pDevMode,hWnd);

        // begin @MJH
        // Set up the "# uncollated copies" spin button
        WinSendMsg (WinWindowFromID (hWnd, UNCOLLATED_COPIES),
                    SPBM_SETLIMITS,
                    (MPARAM)16,            // max
                    (MPARAM)1);            // min
        WinSendMsg (WinWindowFromID (hWnd, UNCOLLATED_COPIES),
                    SPBM_SETCURRENTVALUE,
                    (MPARAM)((pDevMode->pSetup->usFlags & FL_UNCOLLATEDMASK)+1),
                    (MPARAM)NULL);

        // Value init in init_dialog

        // Uncollated copies are only valid in HPGL/2
        WinEnableWindow (WinWindowFromID (hWnd, UNCOLLATED_COPIES),
                         (PlotterClass[pDevMode->Plotter].usHPGLCaps & HPGL2) ? TRUE : FALSE);
        WinEnableWindow (WinWindowFromID (hWnd, UNCOLLATED_COPIES_TEXT),
                         (PlotterClass[pDevMode->Plotter].usHPGLCaps & HPGL2) ? TRUE : FALSE);

        // user defined forms are only available from printer properties
        WinEnableWindow (WinWindowFromID (hWnd, USER_DEFINED_FORMS),
                         pDevMode->bPrinterProperties);

        // end @MJH

        // begin @MJH
        // Set up the RGB color mode vs pen/carousel mode
        if (!(PlotterClass[pDevMode->Plotter].usHPGLCaps & HPGL2) ||
             (PlotterClass[pDevMode->Plotter].fsOdd & OD_HPGL2_PENPLOTTER))
        {
           // Non-HPGL/2 devices do not have RGB mode!
           WinEnableWindow (WinWindowFromID (hWnd, RGB_OR_CAROUSEL_MODE), FALSE);
           // just in case...
           pDevMode->pSetup->usFlags &= ~FL_USEAPPCOLORS;
        }
        if (pDevMode->pSetup->usFlags & FL_USEAPPCOLORS)
           WinSetDlgItemText (hWnd, RGB_OR_CAROUSEL_MODE,
                              get_string (pDevMode, RGB_MODE));
        else
           WinSetDlgItemText (hWnd, RGB_OR_CAROUSEL_MODE,
                              get_string (pDevMode, CAROUSEL_MODE));

        SwitchBetween_RGB_Carousel (hWnd,
                                    pDevMode->hMenu,
                                    pDevMode,
                                    pDevMode->pSetup->usFlags & FL_USEAPPCOLORS);


        /*
        ** EA version, and display it                                  
        */
        EA_GetVersion(&szDrvVersion[0]); // DCR1399
        WinSetDlgItemText(hWnd,          // DCR1399
                          IDD_SETUPDLG_VERSION,  // DCR1399
                          (PSZ)szDrvVersion);    // DCR1399
        WinSetFocus(HWND_DESKTOP,WinWindowFromID(hWnd,DID_OK));
        return 1;                      // Focus window is changed
        break;
      }

    /*
    ** DCR 1476
    */

    case  HM_QUERY_KEYS_HELP :
      return ((ULONG)IDH_KEYS);
    case  WM_COMMAND :
      Handled = main_dialog_command((PDEVMODE)WinQueryWindowULong(hWnd,
                                                                  QWL_USER),
                                    hWnd,
                                    Msg,
                                    mParam1,
                                    mParam2);
      break;

#if      DCR1476
    case  WM_HELP :
      {
        PDEVMODE pDevMode = (PDEVMODE)WinQueryWindowULong(hWnd,
                                                          QWL_USER);

        WinDlgBox(HWND_DESKTOP,
                  hWnd,
                  (PFNWP)help_dialog_proc,
                  get_mod_handle(),
                  IDD_HELP,
                  pDevMode);
        break;
      }
#endif
    case  WM_CONTROL :
      {
        PDEVMODE pDevMode = (PDEVMODE)WinQueryWindowULong(hWnd,
                                                          QWL_USER);

        SHORT Code = HIUSHORT(mParam1),Cmd = LOUSHORT(mParam1);

        if (Cmd == CAROUSELNUM)
        {
          if (Code == EN_CHANGE || Code == EN_KILLFOCUS)
          {
            SHORT Carousel;
            HWND hWndOK = WinWindowFromID(hWnd,DID_OK);

            WinQueryDlgItemShort(hWnd,CAROUSELNUM,&Carousel,TRUE);

            if (Carousel >= 1 && Carousel <= MAX_CAROUSELS)
            {
              WinEnableWindow(hWndOK,TRUE);

              if (Code == EN_KILLFOCUS && pDevMode->pSetup->CurrentCarousel !=
                 Carousel-1)
              {
                check_menuitem(pDevMode->hMenu,
                               SEL_CAROUSEL1+pDevMode->pSetup->CurrentCarousel,
                               FALSE);
                pDevMode->pSetup->CurrentCarousel = Carousel-1;
                display_carousel(pDevMode,hWnd);
              }
            }
            else
            {
              WinEnableWindow(hWndOK,FALSE);

              if (Code == EN_KILLFOCUS)
              {
                WinSetFocus(HWND_DESKTOP,WinWindowFromID(hWnd,CAROUSELNUM));
                Handled = TRUE;
              }
            }
          }
        }
        else if (Cmd == ROLL_LENGTH)
        {
          if (Code == EN_CHANGE || Code == EN_KILLFOCUS)
          {
            SHORT Length;
            HWND hWndOK = WinWindowFromID(hWnd,DID_OK);

            WinQueryDlgItemShort(hWnd,ROLL_LENGTH,&Length,TRUE);

            if (Length >= 1 && Length <= 500)
              WinEnableWindow(hWndOK,TRUE);
            else
            {
              WinEnableWindow(hWndOK,FALSE);

              if (Code == EN_KILLFOCUS)
              {
                WinSetFocus(HWND_DESKTOP,WinWindowFromID(hWnd,ROLL_LENGTH));
                Handled = TRUE;
              }
            }
          }
        }
        else if (Cmd >= MANUAL && Cmd <= AUTOMATIC)
        {
          if (Code == BN_CLICKED)
          {
            HWND hWndPreloaded = WinWindowFromID(hWnd,PRELOADED);

            pDevMode->pSetup->PaperFeed = Cmd-MANUAL;
            WinSendDlgItemMsg(hWnd,MANUAL,
                              BM_SETCHECK,
                              (MPARAM)(pDevMode->pSetup->PaperFeed?FALSE:
                                 TRUE),
                              0L);
            WinSendDlgItemMsg(hWnd,
                              AUTOMATIC,
                              BM_SETCHECK,
                              (MPARAM)(pDevMode->pSetup->PaperFeed?TRUE:
                                 FALSE),
                              0L);
            WinEnableWindow(hWndPreloaded,
                            pDevMode->pSetup->PaperFeed?FALSE:TRUE);
          }
        }
        else if (Cmd == ACTIVE_CAROUSEL)
        {
          if (Code == BN_CLICKED)
          {
            SHORT nCarouselsActive = 0,
                  Carousel = pDevMode->pSetup->CurrentCarousel,
                  Index;
            BOOL bSet;


            for (Index = 0; Index < MAX_CAROUSELS; Index++)
              if (pDevMode->pSetup->bActiveCarousel[Index])
                nCarouselsActive++;

            if (!(bSet = pDevMode->pSetup->bActiveCarousel[Carousel]) ||
               (bSet && nCarouselsActive > 1))
            {
              check_menuitem(pDevMode->hMenu,
                             ACTIVE_CAROUSEL1+Carousel,
                             pDevMode->pSetup->bActiveCarousel[Carousel]
                                ^= 1?TRUE:FALSE);
              WinSendDlgItemMsg(hWnd,
                                ACTIVE_CAROUSEL,
                                BM_SETCHECK,
                                (MPARAM)
                                   pDevMode->pSetup->bActiveCarousel
                                   [Carousel],
                                (MPARAM)NULL);
            }
          }
        }
        else
        if (Cmd >= CAROUSEL_PEN1 && Cmd <= CAROUSEL_PEN8)
        {
          if (Code == BN_CLICKED)
          {
            BOOL bStatus = (BOOL)!WinSendDlgItemMsg(hWnd,Cmd,
                                                    BM_QUERYCHECK,
                                                    0L,0L);
            WinSendDlgItemMsg(hWnd,Cmd,
                              BM_SETCHECK,(MPARAM)bStatus,0L);
            pDevMode->bPenSelected[Cmd-CAROUSEL_PEN1] = bStatus;
            check_pens(pDevMode);
          }
        }
        else if (Cmd == FORMNAME)
        {
           if (Code == LN_SELECT)
           {
              // begin @MJH
              SHORT    sIndex;
              ULONG    ulHandle;

              sIndex = (SHORT)WinSendDlgItemMsg (hWnd, Cmd,
                                                 LM_QUERYSELECTION,
                                                 MPFROMSHORT (LIT_FIRST),
                                                 (MPARAM)0);
              ulHandle = (ULONG)WinSendDlgItemMsg (hWnd, Cmd,
                                                   LM_QUERYITEMHANDLE,
                                                   MPFROMSHORT (sIndex),
                                                   (MPARAM)0);

              if (ulHandle)
                 display_user_form_paper_size (pDevMode,
                                               hWnd,
                                               (PUSERFORMINFO)ulHandle);
              else
                 // end @MJH
                 display_paper_size(pDevMode,hWnd);
           }
        }
        break;
      }
    case  WM_VSCROLL :
      {
        PDEVMODE pDevMode = (PDEVMODE)WinQueryWindowULong(hWnd,QWL_USER);

        SHORT Code = HIUSHORT(mParam2),Cmd = LOUSHORT(mParam1);

        if (Code == SB_LINEUP || Code == SB_LINEDOWN)
        {
          if (Cmd == ROLL_SCROLL)
          {
            SHORT Length;

            WinQueryDlgItemShort(hWnd,ROLL_LENGTH,&Length,TRUE);

            if (Code == SB_LINEUP && Length < 500)
              Length++;
            else
              if (Code == SB_LINEDOWN && Length > 1)
                Length--;

            WinSetDlgItemShort(hWnd,ROLL_LENGTH,Length,TRUE);
          }
          else
            if (Cmd == CAROUSEL)
            {
              SHORT Carousel = pDevMode->pSetup->CurrentCarousel;
              SHORT sOldCar = Carousel;


              if ((Code == SB_LINEUP) && (Carousel < (MAX_CAROUSELS-1)))
                Carousel++;
              else
                if ((Code == SB_LINEDOWN) && (Carousel > 0))
                  Carousel--;


              if (sOldCar != Carousel)
              {
                /*
                ** Carousel has changed - deselect old, select new
                */
                check_menuitem(pDevMode->hMenu,
                               SEL_CAROUSEL1+sOldCar,
                               FALSE);
                pDevMode->pSetup->CurrentCarousel = Carousel;
                display_carousel(pDevMode,hWnd);
              }
            }
        }
        break;
      }
    default  :
      return ((ULONG)WinDefDlgProc(hWnd,Msg,mParam1,mParam2));
      break;
  }
  return 0;
}

/***************************************************************************
 *
 * FUNCTION NAME = options_dialog_proc
 *
 *
 * DESCRIPTION   = options_dialog_proc
 *
 *                 Handle the user interface for the pen
 *                 options display and modification dialog
 *                 box.  The options that apply are:  Speed
 *                 force, and acceleration.
 *
 *
 *
 * INPUT         = hWnd,Msg,mParam1,mParam2
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = Handled
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

ULONG options_dialog_proc(HWND hWnd,USHORT Msg,MPARAM mParam1,
                          MPARAM mParam2)

/*
**      Handle the user interface for the pen options display and
**  modification dialog box.  The options that apply are: Speed, force, and
**  acceleration.
*/

{
  ULONG Handled = FALSE;


  switch (Msg)
  {
    case  WM_INITDLG :
      {
        PDEVMODE pDevMode = (PDEVMODE)mParam2;

        SHORT PenOffset = 0,Plotter = pDevMode->Plotter,Carousel =
           pDevMode->pSetup->CurrentCarousel,Index;

        /*
        ** DCR 1476 - Set the help table for given OPTION.
        **            SPEED is assumed in the help table.
        */

        if ((SPEED+pDevMode->PenOption) == FORCE)
        {
          WinSetWindowUShort((HWND)hWnd,
                             (SHORT)QWS_ID,
                             (USHORT)IDD_OPTIONS_FORCE);
        }
        else
          if ((SPEED+pDevMode->PenOption) == ACCELERATION)
          {
            WinSetWindowUShort((HWND)hWnd,
                               (SHORT)QWS_ID,
                               (USHORT)IDD_OPTIONS_ACCEL);
          }
        WinSetWindowULong(hWnd,
                          QWL_USER,
                          (ULONG)mParam2);
        WinSetWindowText(hWnd,
                         get_string(pDevMode,
                                    SPEED+pDevMode->PenOption));
        WinSetDlgItemText(hWnd,
                          OPTION_UNITS,
                          get_string(pDevMode,
                                     CM_SECOND+pDevMode->PenOption));

        /*
        ** OPT_SCROLL Scroll Bar
        */
        WinSendDlgItemMsg(hWnd,
                          OPT_SCROLL,
                          SBM_SETSCROLLBAR,
                          MPFROMSHORT((USHORT)1),
                          MPFROM2SHORT((USHORT)0,
                                       (USHORT)2));

        for (Index = 0; Index < MAX_PENS; Index++)
        {
          WinSetDlgItemText(hWnd,CAROUSEL_PEN1+Index,"");
          WinSetDlgItemText(hWnd,CAROUSEL_COLOR1+Index,"");
          WinSetDlgItemText(hWnd,CAROUSEL_TYPE1+Index,"");
          WinSetDlgItemText(hWnd,CAROUSEL_VAR1+Index,"");
        }

        for (Index = 0; Index < pDevMode->DeviceInfo.PensInCarousel; Index++)

          if (pDevMode->bPenSelected[Index])
          {
            char PenDesc[10];

            SHORT Value,Group,Color = (SHORT)pDevMode->pSetup->Carousel
               [Carousel].Pen[Index].Color,Type = (SHORT)
                  pDevMode->pSetup->Carousel[Carousel].Pen[Index].Type;
            PBYTE pPenInfo = (PBYTE)&pDevMode->pSetup->Carousel[Carousel].Pen

               [Index].Speed,pDefPenInfo = (PBYTE)&pDevMode->PenOptions.Speed
                  [0],pDevInfo = (PBYTE)&pDevMode->DeviceInfo.Speed.Min;
            pDevInfo += pDevMode->PenOption *3;
            pDevMode->PenVarMin = *(pDevInfo+0);
            pDevMode->PenVarMax = *(pDevInfo+1);
            pDevMode->PenVarIncrement = *(pDevInfo+2);

            if ((pDevMode->PenValue[PenOffset] = *(pPenInfo+
               pDevMode->PenOption)) == 0)
            {
              Group = get_group(pDevMode->pSetup->Carousel[Carousel].Pen[Index
                 ].Type);
              pDevMode->PenValue[PenOffset] = *(pDefPenInfo+
                 (pDevMode->PenOption *MAX_PEN_GROUPS)+Group);
            }
            int_to_str((LONG)Index+1,PenDesc,1);
            WinSetDlgItemText(hWnd,CAROUSEL_PEN1+PenOffset,PenDesc);

            if (Color)
            {
              WinSetDlgItemText(hWnd,
                                CAROUSEL_COLOR1+PenOffset,
                                get_string(pDevMode,
                                           YELLOW+Color-1));
              WinSetDlgItemText(hWnd,
                                CAROUSEL_TYPE1+PenOffset,
                                get_string(pDevMode,
                                           P3+Type));
            }

            if (PenOffset++ == 0)
            {
              pDevMode->PenVariable = pDevMode->PenValue[PenOffset-1];

              if (pDevMode->PenOption == 1)
                Value = pDevMode->DeviceInfo.ForceValue[pDevMode->PenVariable-
                   1];
              else
                Value = pDevMode->PenVariable;

              WinSetDlgItemShort(hWnd,PEN_VARIABLE,Value,0);
            }
          }
        list_pen_options(pDevMode,
                         hWnd);
        break;
      }
    case  WM_COMMAND :
      {
        PDEVMODE pDevMode = (PDEVMODE)WinQueryWindowULong(hWnd,QWL_USER);


        switch (LOUSHORT(mParam1))
        {
          case  DID_OK :
            {
              SHORT Index,PenOffset = 0;

              for (Index = 0; Index < MAX_PENS; Index++)

                if (pDevMode->bPenSelected[Index])
                {
                  PUCHAR pPenInfo = (PUCHAR)&pDevMode->pSetup->Carousel
                     [pDevMode->pSetup->CurrentCarousel].Pen[Index].Speed;

                  *(pPenInfo+pDevMode->PenOption) = pDevMode->PenValue
                     [PenOffset++];
                }
              WinDismissDlg(hWnd,TRUE);
              break;
            }
          case  DID_CANCEL :
            WinDismissDlg(hWnd,TRUE);
            break;
          case  RESET :
            {
              SHORT Index;


              for (Index = 0; Index < MAX_PENS; Index++)
              {
                SHORT PenOffset = 0,Index,Group;

                PUCHAR pDefPenInfo = (PUCHAR)&pDevMode->PenOptions.Speed[0];

                for (Index = 0; Index < pDevMode->DeviceInfo.PensInCarousel;
                   Index++)

                  if (pDevMode->bPenSelected[Index])
                  {
                    Group = get_group(pDevMode->pSetup->Carousel
                       [pDevMode->pSetup->CurrentCarousel].Pen[Index].Type);
                    pDevMode->PenValue[PenOffset++] = *(pDefPenInfo+
                       (pDevMode->PenOption *MAX_PEN_GROUPS)+Group);
                  }
              }
              list_pen_options(pDevMode,hWnd);
              break;
            }
            break;
        }
      }
    case  WM_VSCROLL :
      {
        PDEVMODE pDevMode = (PDEVMODE)WinQueryWindowULong(hWnd,
                                                          QWL_USER);


        if ((ULONG)mParam1 == OPT_SCROLL)
        {

          if ((HIUSHORT(mParam2) == SB_LINEUP &&
              pDevMode->PenVariable <
              pDevMode->PenVarMax) ||
              (HIUSHORT(mParam2) == SB_LINEDOWN &&
              pDevMode->PenVariable > pDevMode->PenVarMin))
          {
            SHORT Value,PenOffset;


            if (HIUSHORT(mParam2) == SB_LINEUP)
              pDevMode->PenVariable += pDevMode->PenVarIncrement;

            else
              pDevMode->PenVariable -= pDevMode->PenVarIncrement;

            if (pDevMode->PenOption == 1)
              Value = pDevMode->DeviceInfo.ForceValue[pDevMode->PenVariable-1]
                 ;

            else
              Value = pDevMode->PenVariable;
            WinSetDlgItemShort(hWnd,PEN_VARIABLE,Value,FALSE);

            for (PenOffset = 0; PenOffset < pDevMode->nPensSelected; PenOffset
               ++)
              pDevMode->PenValue[PenOffset] = pDevMode->PenVariable;
            list_pen_options(pDevMode,hWnd);
          }
        }
        break;
      }
    default  :
      Handled = (ULONG)WinDefDlgProc(hWnd,Msg,mParam1,mParam2);
      break;
  }
  return (Handled);
}

/***************************************************************************
 *
 * FUNCTION NAME = priority_dialog_proc
 *
 *
 * DESCRIPTION   = priority_dialog_proc
 *
 *                 Handle the user interface for the display and
 *                 modification of the pen priority.  Each pen
 *                 selected in the carousel configuration list
 *                 box can be tagged with any of the following
 *                 priorities:  None, Lines/Text, and Fill.  A
 *                 pen that has priority on fill will be selected
 *                 over another pen of the same color that does
 *                 not have priority on fill on all fill output.
 *                 Likewise, a pen that has priority on
 *                 lines/text will be selected over another pen
 *                 of the same color that does not have priority
 *                 on lines/text on all lines/text output.
 *
 *
 *
 * INPUT         = hWnd,Msg,mParam1,mParam2
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = Handled
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 *************************************************************************/

ULONG priority_dialog_proc(HWND hWnd,USHORT Msg,MPARAM mParam1,
                           MPARAM mParam2)

/*
**      Handle the user interface for the display and modification
**  of the pen priority.  Each pen selected in the carousel configuration list
**  box can be tagged with any of the following priorities: None, Lines/Text,
**  and Fill. A pen that has priority on fill will be selected over another pen
**  of the same color that does not have priority on fill on all fill output.
**  Likewise, a pen that has priority on lines/text will be selected over
**  another pen of the same color that does not have priority on lines/text on
**  all lines/text output.
*/

{
  ULONG Handled = FALSE;


  switch (Msg)
  {
    case  WM_INITDLG :
      {
        PDEVMODE pDevMode = (PDEVMODE)mParam2;

        SHORT Index,PenOffset = 0;
        char PenDesc[10];

        WinSetWindowULong(hWnd,
                          QWL_USER,
                          (ULONG)mParam2);
        WinSendDlgItemMsg(hWnd,
                          USE_NONE,
                          BM_SETCHECK,
                          (MPARAM)TRUE,
                          0L);
        WinSendDlgItemMsg(hWnd,
                          USE_FILL,
                          BM_SETCHECK,
                          (MPARAM)FALSE,
                          0L);
        WinSendDlgItemMsg(hWnd,
                          USE_LINE,
                          BM_SETCHECK,
                          (MPARAM)FALSE,
                          0L);
        WinSendDlgItemMsg(hWnd,
                          USE_TEXT,
                          BM_SETCHECK,
                          (MPARAM)FALSE,
                          0L);

        for (Index = 0; Index < MAX_PENS; Index++)
        {
          WinSetDlgItemText(hWnd,CAROUSEL_PEN1+Index,"");
          WinSetDlgItemText(hWnd,CAROUSEL_COLOR1+Index,"");
          WinSetDlgItemText(hWnd,CAROUSEL_TYPE1+Index,"");
          WinSetDlgItemText(hWnd,CAROUSEL_VAR1+Index,"");
        }

        for (Index = 0; Index < MAX_PENS; Index++)
        {
          if (pDevMode->bPenSelected[Index])
          {
            SHORT Carousel = pDevMode->pSetup->CurrentCarousel;
            SHORT Color =
                 (SHORT)pDevMode->pSetup->Carousel[Carousel].Pen[Index].Color,
                  Type =
                  (SHORT)pDevMode->pSetup->Carousel[Carousel].Pen[Index].Type;

            pDevMode->PenPriority[PenOffset] = pDevMode->pSetup->Carousel
                                                [Carousel].Pen[Index].Usage;
            int_to_str((LONG)Index+1,PenDesc,1);
            WinSetDlgItemText(hWnd,CAROUSEL_PEN1+PenOffset,PenDesc);

            if (Color)
            {
              WinSetDlgItemText(hWnd,CAROUSEL_COLOR1+PenOffset,
                                get_string(pDevMode,YELLOW+Color-1));
              WinSetDlgItemText(hWnd,CAROUSEL_TYPE1+PenOffset,
                                get_string(pDevMode,P3+Type));
            }
            ++PenOffset;
          }
        }
        list_pen_priority(pDevMode,hWnd);
        break;
      }
    case  WM_COMMAND :
      {
        PDEVMODE pDevMode = (PDEVMODE)WinQueryWindowULong(hWnd,QWL_USER);
        USHORT cmd = LOUSHORT(mParam1);


        if (cmd == DID_OK || cmd == DID_CANCEL)
        {

          if (cmd == DID_OK)
          {

            SHORT Index,PenOffset = 0;

            for (Index = 0; Index < MAX_PENS; Index++)
            {

              if (pDevMode->bPenSelected[Index])
                pDevMode->pSetup->Carousel[pDevMode->pSetup->CurrentCarousel].
                   Pen[Index].Usage = (UCHAR)pDevMode->PenPriority[PenOffset++];
            }
          }
          WinDismissDlg(hWnd,TRUE);
        }
        else
          if (cmd == RESET)
          {
            SHORT PenOffset;

            WinSendDlgItemMsg(hWnd,USE_NONE,BM_SETCHECK,
                              (MPARAM)TRUE,0L);
            WinSendDlgItemMsg(hWnd,USE_FILL,
                              BM_SETCHECK,(MPARAM)FALSE,0L);
            WinSendDlgItemMsg(hWnd,USE_LINE,BM_SETCHECK,
                              (MPARAM)FALSE,0L);
            WinSendDlgItemMsg(hWnd,USE_TEXT,
                              BM_SETCHECK,(MPARAM)FALSE,0L);

            for (PenOffset = 0;
                 PenOffset < pDevMode->nPensSelected;
                 PenOffset++)
              pDevMode->PenPriority[PenOffset] = 0;

            list_pen_priority(pDevMode,hWnd);
          }
        break;
      }
    case  WM_CONTROL :
      {
        PDEVMODE pDevMode = (PDEVMODE)WinQueryWindowULong(hWnd,
                                                          QWL_USER);

        SHORT Code = HIUSHORT(mParam1),Cmd = LOUSHORT(mParam1);

        if (Code == BN_CLICKED)
        {
          if (Cmd >= USE_NONE && Cmd <= USE_TEXT)
          {
            SHORT PenOffset;

            WinSendDlgItemMsg(hWnd,
                              USE_NONE,
                              BM_SETCHECK,
                              (MPARAM)(Cmd == USE_NONE?TRUE:FALSE),
                              0L);
            WinSendDlgItemMsg(hWnd,
                              USE_FILL,
                              BM_SETCHECK,
                              (MPARAM)(Cmd == USE_FILL?TRUE:FALSE),
                              0L);
            WinSendDlgItemMsg(hWnd,
                              USE_LINE,
                              BM_SETCHECK,
                              (MPARAM)(Cmd == USE_LINE?TRUE:FALSE),
                              0L);
            WinSendDlgItemMsg(hWnd,
                              USE_TEXT,
                              BM_SETCHECK,
                              (MPARAM)(Cmd == USE_TEXT?TRUE:FALSE),
                              0L);

            for (PenOffset = 0;
                 PenOffset < pDevMode->nPensSelected;
                 PenOffset++)
              pDevMode->PenPriority[PenOffset] = (UCHAR)Cmd-USE_NONE;

            list_pen_priority(pDevMode,hWnd);
            Handled = TRUE;
          }
        }
        break;
      }
    default  :
      Handled = (ULONG)WinDefDlgProc(hWnd,Msg,mParam1,mParam2);
      break;
  }
  return (Handled);
}


/***************************************************************************
 *
 * FUNCTION NAME = GetMeasureItemInfo
 *
 *
 * DESCRIPTION   = GetMeasureItemInfo
 *
 *                 Calc the height and width of the text string
 *                 for WM_MEASUREITEM message.
 *
 *
 * INPUT         = hps or NULL  (presentation space or we will get one)
 *                 hwnd  (Window handle)
 *                 pch   (pointer to char string)
 *                 cch   (count of chars)
 *
 * OUTPUT        = NONE
 *
 *
 * RETURN-NORMAL = Handled
 *
 *
 * RETURN-ERROR  = NONE
 *
 *************************************************************************/

ULONG GetMeasureIteminfo(
    HPS hps,
    HWND hWnd,
    PCH pch,
    SHORT cch)
{
    TEXTBOX txtbox;
    HPS lhps;

    /*
    ** get a ps if none
    */
    if (!hps)
     lhps = WinGetPS(hWnd);
    else
     lhps = hps;

    /*
    ** get the text box from the presentation driver
    */
    GreQueryTextBox(lhps, (LONG)cch, pch, 5, (TEXTBOX *)&txtbox);

    /*
    ** return the ps if we got one
    */
    if (!hps)
      WinReleasePS(lhps);

    /*
    ** return the width in the low word and the height in the
    ** high word
    */
    return MAKEULONG( MAX(txtbox.ptlTopRight.x, txtbox.ptlBottomRight.x),
            (SHORT)txtbox.ptlTopLeft.y - (SHORT)txtbox.ptlBottomLeft.y );
}

/***************************************************************************
 *
 * FUNCTION NAME = pencolor_dialog_proc
 *
 *
 * DESCRIPTION   = pencolor_dialog_proc
 *
 *                 Handle the user interface for the Selecting
 *                 the pen color. Display a listbox of available
 *                 pen colors and update the main dialog with
 *                 the color selection.
 *
 *
 * INPUT         = hWnd,Msg,mParam1,mParam2
 *
 *
 * OUTPUT        = NONE
 *
 *
 * RETURN-NORMAL = Handled
 *
 *
 * RETURN-ERROR  = NONE
 *
 *************************************************************************/

ULONG pencolor_dialog_proc(HWND hWnd,USHORT Msg,MPARAM mParam1,
                           MPARAM mParam2)

{
  ULONG Handled = FALSE;


  switch (Msg)
  {
    case  WM_INITDLG :
      {
        PDEVMODE pDevMode = (PDEVMODE)mParam2;

        SHORT sIndex, sMax;
        HPS  hps;
        FONTMETRICS fm;
        char PenDesc[10];

        WinSetWindowULong(hWnd, QWL_USER, (ULONG)mParam2);

        /*
        ** get font info - store it in devmode struct
        ** for later use
        */
        hps = WinGetPS(hWnd);
        GpiQueryFontMetrics(hps, (ULONG)sizeof(FONTMETRICS), (PFONTMETRICS)&fm);
        pDevMode->lMaxDescender = fm.lMaxDescender;
        WinReleasePS(hps);

        sMax = NO_COLOR - YELLOW + 1;
        // @MARK
        /* Only use the first 16 (0..15) colors for the older plotters
        ** because they only understand a limited number of color values.
        */
        if (!(PlotterClass[pDevMode->Plotter].usHPGLCaps & HPGL2))
           sMax = (sMax > 15) ? 15 : sMax;

        /*
        ** fill list box with color entries
        */
        for (sIndex = 0; sIndex < sMax; sIndex++)
        {
          WinSendDlgItemMsg(hWnd,
                        IDC_LISTBOX,
                        LM_INSERTITEM,
                        (MPARAM)LIT_END,
                        (MPARAM)get_string(pDevMode,
                                           YELLOW+sIndex));
        }

        /*
        ** Select current color
        */
        WinSendDlgItemMsg(hWnd,
                    IDC_LISTBOX,
                    LM_SELECTITEM,
                    (MPARAM)(pDevMode->CurColor-1),
                    (MPARAM)TRUE);
        /*
        ** put selected item on top
        */
        WinSendDlgItemMsg(hWnd,
                    IDC_LISTBOX,
                    LM_SETTOPINDEX,
                    (MPARAM)(pDevMode->CurColor-1),
                    (MPARAM)NULL);

        break;
      }
    case  WM_COMMAND :
      {
        PDEVMODE pDevMode = (PDEVMODE)WinQueryWindowULong(hWnd,QWL_USER);
        USHORT cmd = LOUSHORT(mParam1);


        if (cmd == DID_OK || cmd == DID_CANCEL)
        {

          if (cmd == DID_OK)
          {
            PPENINFO pPenInfo;
            SHORT Index;
            SHORT iColor = (SHORT)WinSendDlgItemMsg(hWnd,IDC_LISTBOX,
                                          LM_QUERYSELECTION,0L,0L);
            if ((iColor == (NO_COLOR - YELLOW)) || iColor == LIT_NONE)
              iColor = 0;
            else
              iColor++;


            check_pen(pDevMode,FALSE);

            if (pDevMode->CurColor == 0)
                pDevMode->CurType = 0;
              pDevMode->CurColor = iColor;
              check_pen(pDevMode,TRUE);

            for (Index = 0; Index < pDevMode->DeviceInfo.PensInCarousel;
                 Index++)
              if (pDevMode->bPenSelected[Index])
              {
                pPenInfo = (PPENINFO)&pDevMode->pSetup->Carousel
                   [pDevMode->pSetup->CurrentCarousel].Pen[Index].Color;

                if (pPenInfo->Color == 0)
                  pPenInfo->Type = 0;
                pPenInfo->Color = (UCHAR)iColor;
                display_pen(pDevMode,
                            WinQueryWindow(hWnd,QW_OWNER),
                            Index);
              }
          }
          WinDismissDlg(hWnd,TRUE);
        }
        break;
      }
    case WM_MEASUREITEM:
      {
        FONTMETRICS fm;

        if ((ULONG)mParam1 == IDC_LISTBOX)
        {
          HPS hps;
          FONTMETRICS fm;
          USHORT iHeight;
          // return ((ULONG)GetMeasureIteminfo((HPS)NULL, hWnd,
          //                                     psz, strlen (psz)));
          hps = WinGetPS(HWND_DESKTOP);
          GpiQueryFontMetrics(hps, (ULONG)sizeof(FONTMETRICS), (PFONTMETRICS)&fm);
          iHeight = fm.lMaxBaselineExt;
          WinReleasePS(hps);
          return(iHeight);
        }
        else
        {
          return(FALSE);
        }
        break;
      }
    case WM_DRAWITEM:
      {
        POWNERITEM poi = ((POWNERITEM)mParam2);
        PPENINFO   pPenInfo;
        ULONG      ulSaveRGB;
        RECTL      rectl;
        HPS        hps = poi->hps;
        PSZ        psz;
        POINTL     ptl;
        COLOR      clrBackground, clrOldForeground;
        POINTL     pointl;
        ULONG      ulIndex, ulOldColor;
        //CHAR       achTemp[255];       // used for RGB values in list box

        PDEVMODE pDevMode = (PDEVMODE)WinQueryWindowULong(hWnd,QWL_USER);


        // pPenInfo should point to struc not to "first" element in struc
        pPenInfo = (PPENINFO)&pDevMode->pSetup->Carousel
                   [pDevMode->pSetup->CurrentCarousel].Pen[poi->idItem];

        /*
        ** define rectangle for color
        */
        rectl.xLeft  = poi->rclItem.xLeft;
        rectl.xRight = rectl.xLeft + ((poi->rclItem.xRight - rectl.xLeft) >> 3);
        rectl.yTop   = poi->rclItem.yTop;
        rectl.yBottom = poi->rclItem.yBottom;

        /*
        ** move text position over
        */
        poi->rclItem.xLeft = rectl.xRight;

        /*
        ** draw a box at the beginning of the text area
        ** in the rgb color for the color
        ** MarkH
        */
        /* Use RGB mode so that the colors will be dithered and will not
        ** map into the hardware colors.
        */
        GpiCreateLogColorTable (hps,
                                LCOL_RESET,
                                LCOLF_RGB,
                                0L,
                                0L,
                                (PLONG)NULL);

        pointl.x = rectl.xLeft;
        pointl.y = rectl.yTop;
        GpiMove (hps, &pointl);   // move to upper left-hand corner of box

        // Get the previous color (so we can restore it)...
        ulOldColor = GpiQueryColor (hps);

        if (0 <= poi->idItem && poi->idItem < MAX_COLORS)
        {
           /* Only index within the ColorList array!!! (ex. the color
           ** "none" is not in the array).
           */
           ulIndex = GpiQueryColorIndex (hps, 0L, ColorList[poi->idItem]);
           GpiSetColor (hps, ulIndex);
        }
        else
        {
           /* Either it is outside of the array or it is the last color in
           ** the array (which is COLOR_NONE).  Therefore, paint it White.
           */
           ulIndex = GpiQueryColorIndex (hps, 0L, 0xFFFFFF); // RGB_WHITE
           GpiSetColor (hps, ulIndex);
        }

        pointl.x = rectl.xRight;
        pointl.y = rectl.yBottom;
        /* Draw a box @ lower right-hand corner and fill it with the current
        ** color.
        */
        GpiBox (hps, DRO_FILL, &pointl, 0L, 0L);

        // Restore the color
        GpiSetColor (hps, ulOldColor);

        /*
         * setup background colour
         */
        if (poi->fsState == FALSE)                  /* normal  */
          clrBackground = SYSCLR_WINDOW ;
        else
          clrBackground = SYSCLR_HILITEBACKGROUND ;   /* hilite  */

        poi->fsState = poi->fsStateOld = FALSE ;

        /*
        ** get current foreground color
        */
        clrOldForeground = GpiQueryColor(hps);

        /*
        ** Draw the background for the text
        **
        */
        WinFillRect(hps, (PRECTL)&poi->rclItem, clrBackground);


        /*
        ** if high lite, then listbox item background != window background,
        ** so we set primitive colour = window colour (this makes us
        ** consiustent  with the rest of PM).
        */
        if (clrBackground != SYSCLR_WINDOW)
          GpiSetColor(hps,SYSCLR_HILITEFOREGROUND);

        /*
        ** draw the text
        */
        psz = (PSZ)get_string(pDevMode, (YELLOW+poi->idItem));
        ptl.x = poi->rclItem.xLeft;
        ptl.y = poi->rclItem.yBottom + pDevMode->lMaxDescender;
        GpiCharStringAt(hps, (PPOINTL)&ptl,
                        (LONG)strlen (psz),
                        (PSZ)psz );

        /*
        ** set forground back if necessary
        */
        if (clrBackground != SYSCLR_WINDOW)
          GpiSetColor(hps, clrOldForeground);

        return(TRUE);
      }

    default  :
      Handled = (ULONG)WinDefDlgProc(hWnd,Msg,mParam1,mParam2);
      break;
  }
  return (Handled);
}

/***************************************************************************
 *
 * FUNCTION NAME = OS2_DevPostDeviceModes
 *
 *
 * DESCRIPTION   = DevPostDeviceModes
 *
 *                 Called by applications wishing to change
 *                 the attributes of the driver, including
 *                 which device, pen configuration, etc.  It
 *                 gets the values based on the
 *                 pszDeviceName passed from the OS2.INI
 *                 file.  The flags passed in determine the
 *                 type of operation required by the caller,
 *                 where bits 0-1 mean the following:  %00
 *                 display dialog, no update to the INI file
 *                 %01 display dialog, update INI file %10
 *                 do not display dialog, just return INI
 *                 information %11 reserved
 *
 *
 *
 * INPUT         = (pDriverData,pszDriverName,pszDeviceName,
 *                 pszLogAddress,flOptions)
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = Result
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 *************************************************************************/

ULONG OS2_DevPostDeviceModes(PDRIVDATA pDriverData,
                             PSZ       pszDriverName,
                             PSZ       pszDeviceName,
                             PSZ       pszLogAddress,
                             ULONG     flOptions)

{
  ULONG  Result;
  ULONG  ulSize;
  USHORT Plotter  = 0;
  USHORT StringId = 0;
  ULONG  ulFlags  = PAG_COMMIT;
  BOOL   bFreeDrivData;

  flOptions &= 0x3L;                   /* get rid of extraneous bits        */
#ifdef DEBUG
//int3();
#endif

  /*
  ** If pDriverData == 0, then just return the size of the data area
  ** we'll need next time.
  */
  if (!pDriverData)
    return  DRIVDATASIZ;

  ulSize = DRIVDATASIZ;
  /*
  ** CSet/2 Conversion: Jim R
  ** We have to be carefull using DosQueryMem.  From my testing it only
  ** seems to work correctly if the memory was allocated using
  ** DosAllocMem.
  */
  if(DosQueryMem(pDriverData, &ulSize , &ulFlags) ||
           (!((ulFlags & PAG_FREE) || ((ulFlags & PAG_COMMIT)&&
           (ulSize >= DRIVDATASIZ)))))
//  if (!((!(DosQueryMem(pDriverData,(PULONG)&ulSize, (PULONG)&ulFlags))) &&
//      ((ulFlags & PAG_FREE) || ((ulFlags & PAG_COMMIT)&&
//      (ulSize >= DRIVDATASIZ)))))
  {
    GplErrSetError(PMERR_INV_DRIVER_DATA);
    return  DPDM_ERROR;
  }

  /*
  ** Validate Logical Printer Name
  */
  if (!pszLogAddress)
  {
    /*
    ** Change Properties requires a valid Logical Printer Name
    */
    if (flOptions == DPDM_CHANGEPROP)
    {
      GplErrSetError(PMERR_INV_LOGICAL_ADDRESS);
      return  DPDM_ERROR;
    }

    pszLogAddress = (PSZ)"";
  }

  /*
  ** Validate Driver Name
  */
  if (!pszDriverName)
    pszDriverName = (PSZ)"";

  /*
  ** Validate Device Name
  */
  if (!pszDeviceName)
    pszDeviceName = (PSZ)"";
  Result = DPDM_ERROR;

  if (flOptions != 0x3L)
  {
    HMCB hmcbHeap;
    PDEVMODE pDevMode;

    /*
    ** Create a heap and grow it by the same amount.
    ** Do not allocate anything greater than 16k from the heap-use dosallocmem.
    ** Make the heap non shareable
    */
    hmcbHeap = GplMemoryCreateInstance(HEAPSIZE,HEAPSIZE,0x4000,PROCESS_MEMORY);

    if (hmcbHeap)
    {
      pDevMode = (PDEVMODE)GplMemoryAlloc(hmcbHeap,sizeof(DEVMODE));

      if (pDevMode)
      {
        BOOL         fSaveProfile = FALSE;
        PPROFILEINFO pISetup, pOSetup;
        PDRIVDATA    pOurDrivData = NULL;

        build_app_name (pszDriverName,
                        pszDeviceName,
                        pszLogAddress,
                        (PSZ)pDevMode->achAppName);

        pDevMode->hmcbHeap = hmcbHeap;
        pDevMode->hAB      = (HAB)NULL;     // WinInitialize (0);

        if (!pDriverData->szDeviceName ||
            (!IsIta_Device_Name(pDriverData->szDeviceName)))
        {
            strcpy(pDriverData->szDeviceName, pszDeviceName);
        }

        pOurDrivData = return_driver_data (hmcbHeap,
                                           pDriverData,
                                           pszLogAddress,
                                           TRUE);

        if (pOurDrivData)
        {
           bFreeDrivData = TRUE;
           pISetup = (PPROFILEINFO)pOurDrivData->abGeneralData; // Our copy
           pOSetup = (PPROFILEINFO)pDriverData->abGeneralData;  // User's copy

        }
        else
        {
           // Error... try to recover...
           bFreeDrivData = FALSE;
           pISetup = (PPROFILEINFO)pDriverData->abGeneralData;  // User's copy
           pOSetup = pISetup;                                   // User's copy
           pOurDrivData = pDriverData;
        }
        if (!get_device_id(pOurDrivData->szDeviceName,&Plotter,&StringId))
        {
           // Error
           ASSERTSTRING("Bad szDevicename");
        }

        pDevMode->Plotter  = Plotter;
        pDevMode->StringId = StringId;

        copy_device_info(&pDevMode->DeviceInfo,Plotter);
        copy_pen_option_info(&pDevMode->PenOptions,Plotter);

        /*
        ** what about pDriverData->lVersion ????????????
        */
        /*
        ** Use the data passed by the user if:
        **    - bit 0 clear
        **    - pszLogAddress is null or null string
        **    - version number is correct
        ** Otherwise, read the info from .INI or as a
        ** last resort, set it to default values
        */

        if (flOptions != DPDM_POSTJOBPROP     ||
            pISetup->Version != JOBPROP_VERSION)                     // @MJH3
        /*
        ** if (flOptions & 0x01L || *pszLogAddress ||
        **   pSetup->Version != JOBPROP_VERSION)
        */
        {
          BOOL fReadProfile;
          /*
          ** read profile information from .INI file
          */
          fReadProfile = get_profile(pDevMode->hmcbHeap,
                                     pszDriverName,
                                     pszDeviceName,
                                     pszLogAddress,
                                     pISetup);

          /*
          ** Get default profile if .INI info invalid
          */
          if (!fReadProfile || pISetup->Version != JOBPROP_VERSION)  // @MJH3
          {
            /*
            ** Could fix up .INI here if we knew it was bad
            ** if ( fReadProfile &&
            **    pSetup->Version != JOBPROP_VERSION )
            **    fSaveProfile = TRUE;
            */
            get_defaults(Plotter, pISetup);
          }
        }
        pOurDrivData->cb = DRIVDATASIZ;
        pOurDrivData->lVersion = JOBPROP_VERSION;                    // @MJH3
        strcpy (pOurDrivData->szDeviceName,pszDeviceName);

        pDriverData->cb = DRIVDATASIZ;
        pDriverData->lVersion = JOBPROP_VERSION;                    // @MJH3
        strcpy (pDriverData->szDeviceName,pszDeviceName);

        /*
        ** Post dialog to allow the user to change properties
        */
        if (flOptions != DPDM_QUERYJOBPROP)
        {
          // @MJH   Differentiate between printer and job properties for
          //        user defined forms...
          pDevMode->bPrinterProperties = (flOptions == DPDM_CHANGEPROP) ? TRUE : FALSE;

          pDevMode->pSetup = (PPROFILEINFO)GplMemoryAlloc(hmcbHeap,
                                                      sizeof(PROFILEINFO) );

          if (pDevMode->pSetup)
          {

            /*
            ** Copy user profile for the dialog
            */
            *pDevMode->pSetup = *pISetup;
            pDevMode->bCancel = FALSE;
            hwndMain = (HWND)WinLoadDlg(HWND_DESKTOP,
                                        WinQueryActiveWindow(HWND_DESKTOP),
                                        (PFNWP)main_dialog_proc,
                                        get_mod_handle(),
                                        IDD_SETUPDLG,
                                        pDevMode);

            if (WinProcessDlg(hwndMain))
            {
              Result = DEV_OK;

              /*
              ** Copy changed profile back to user area
              */
              *pOSetup = *pDevMode->pSetup;

              if (!pDevMode->bCancel)
              {
                if (flOptions == DPDM_CHANGEPROP)
                  fSaveProfile = TRUE;
              }
            }

            /*
            ** We have to destroy the window,
            ** the WinDismissDlg will not destroy
            ** the modal window
            ** MarkV- fix hang in AutoCad  PTR# b734220
            */
            if (hwndMain)
              WinDestroyWindow(hwndMain);

            GplMemoryFree((PVOID)pDevMode->pSetup);
          }
        }
        else
        {
          Result = DEV_OK;
        }
        /*
        ** Write changes out to OS2SYS.INI file
        */
        if (fSaveProfile)
          save_profile(pOSetup, (PSZ)pDevMode->achAppName);

        /* WinTerminate( pDevMode->hAB );                           */

        // Clean up
        if (bFreeDrivData)
           GplMemoryFree((PVOID)pOurDrivData);

        GplMemoryFree((PVOID)pDevMode);
      }

      /*
      ** release heap space
      */

      if (GplMemoryDeleteInstance( hmcbHeap ))
         hmcbHeap = (HMCB)NULL;
    }

    /*
    ** If error, it's because we ran out of memory
    */
    if (Result != DEV_OK)
      GplErrSetError(PMERR_INSUFFICIENT_MEMORY);
  }
  return  Result;
}

/***************************************************************************
 *
 * FUNCTION NAME = EA_GetVersion
 *
 *
 * DESCRIPTION   = EA_GetVersion
 *
 *                 retreive the EA .VERSION from driver file
 *
 *
 * INPUT         =  PSZ pszStrVersion
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 *************************************************************************/

VOID EA_GetVersion(PSZ pszStrVersion)
{

  FEAL_VER feaVer;
  GEAL_VER geaVer;
  EAOP2 eaop2;                         /* change to EAOP2 for CSet/2 Conv */
  USHORT usVerNameCount;               // length of version data
  CHAR szFileName[MAX_PATH_SIZE];      // pscript driver file name
  USHORT rc;                           // return from DosQPathInfo

  szStrCopy(pszStrVersion,
            "???.???",
            MAX_VERNAME_SIZE);

  if (PrfQueryProfileString(HINI_USERPROFILE,
                            "PM_DEVICE_DRIVERS",
                            APP_NAME,
                            (PSZ)"",
                            (PSZ)szFileName,
                            (ULONG)sizeof(szFileName)))
  {

    /*
    ** Fill in GEALIST
    */
    szStrCopy(geaVer.szEAName,
              EA_NAME_VERSION,
              MAX_VERNAME_SIZE);       /* EA name                           */
    geaVer.cbName = SIZE_EA_NAME_VERSION;/* length of EA Name               */
    geaVer.cbList = sizeof(GEAL_VER);

    /*
    ** Initialize FEALIST
    */
    feaVer.cbList = sizeof(FEAL_VER);

    /*
    ** set EAOP2
    */
    geaVer.oNextEntryOffset = 0;           /* New field                    */

    eaop2.fpGEA2List = (PGEA2LIST)&geaVer;
    eaop2.fpFEA2List = (PFEA2LIST)&feaVer;
    eaop2.oError = 0L;
    rc = DosQueryPathInfo((PSZ)szFileName, /* File path                     */
                          3,               /* info level                    */
                          (PBYTE)&eaop2,   /* EAOP2 structure               */
                          sizeof(eaop2));  /* Size of EAOP2                 */

    if (!rc &&                         /* call sucseed                      */
       (feaVer.cbList > sizeof(feaVer.cbList)) && /* has return value       */
       (feaVer.cbValue) &&         /* value not zero                    */
       (feaVer.cbName == SIZE_EA_NAME_VERSION))/* name size must
                                          .VERSION                          */
    {

      switch (feaVer.usEAT_Type)       /* see what type we got              */
      {
        case  EAT_ASCII :              /* ASCII type                        */

          /*
          ** If we got EAT_ASCII out front, then follow the type will
          ** be USHORT of count and follow by the name
          */
          usVerNameCount = (USHORT)feaVer.usCodePage;

          if (usVerNameCount < (MAX_VERNAME_SIZE-1))
          {
            szStrCopy(pszStrVersion,(PSZ)((PUSHORT)&feaVer.usValueCount),
                      (usVerNameCount+1));
          }
          break;
        case  EAT_MVMT :
        case  EAT_MVST :

          if (!feaVer.usValueCount)
            break;
          usVerNameCount = (USHORT)feaVer.usSizeVerName;

          if (usVerNameCount < (MAX_VERNAME_SIZE-1))
          {
            szStrCopy(pszStrVersion,(PSZ)feaVer.szVersionName,
                      (usVerNameCount+1));
          }
          break;
        default  :
          break;
      }
    }                                  /* end of if DosQPathInfo sucesses   */
  }                                    /* end of if DosGetModName           */
}

/***************************************************************************
 *
 * FUNCTION NAME = szStrCopy
 *
 *
 * DESCRIPTION   = szStrCopy
 *
 *                 Copies a string from the source to the dest.
 *                 If the string is null terminated, the copy
 *                 stops when the terminator is hit.
 *                 Otherwise, the copy continues for the number
 *                 of bytes passed in.
 *
 *
 *
 * INPUT         = pszDst, pszSrc, nbDst
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 **************************************************************************/

VOID szStrCopy(register PSZ pszDst,register PSZ pszSrc,register SHORT nbDst)
{

  while (*pszDst++ = *pszSrc++)

    if (--nbDst <= 0)
    {
      *--pszDst = 0;
      break;
    }
}

/***************************************************************************
 *
 * FUNCTION NAME = SetHelpStubHook()
 *
 *
 * DESCRIPTION   = SetHelpStubHook()
 *
 *                 Add our stub HK_HELP hook to the hook chain.
 *                 This lets us get control the first time that
 *                 the user presses PF1 or clicks on a Help
 *                 button.
 *
 *
 *
 * INPUT         = NONE
 *
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL =  TRUE;
 *
 *
 *
 * RETURN-ERROR  = FALSE;
 *
 *
 *
 *************************************************************************/

BOOL SetHelpStubHook()
{
  if (!HelpStubHookIsSet)
  {
    if (WinSetHook(NULLHANDLE,
                   HMQ_CURRENT,
                   HK_HELP,
                   (PFN)HelpStubHook,
                   NULLHANDLE))
    {
      HelpStubHookIsSet = TRUE;
      DosExitList (EXLST_ADD, (PFNEXITLIST)CleanUpHelpStubHook);
      return  TRUE;
    }
  }
  return  FALSE;
}

/***************************************************************************
 *
 * FUNCTION NAME = InitializeHelp
 *
 *
 * DESCRIPTION   = InitializeHelp
 *
 *                 Initialize help. If we have already tried
 *                 to create a help instance, then return immediately.
 *
 *
 *
 * INPUT         = NONE
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 *************************************************************************/

VOID InitializeHelp()
{
  HAB hAB;
  CHAR szHelpFile[CCHMAXPATH];
  HMODULE hmod;
  CHAR achPath[CCHMAXPATH];
  BOOL fError = TRUE;


  if (HelpAlreadyInitialized)
    return ;

  /*
  ** Initialize Help
  ** ---------------
  **
  ** Create an instance of the Help Manager, and associate it
  ** with the Frame.  If the Association fails, we handle it
  ** the same way as if the creation fails, ie hwndHelp
  ** (the Help Manager Object Window handle) is set to NULL.
  ** If we can't load the Module containing the Help Panel
  ** definitions, we forget Help altogether.
  */
  hAB = WinQueryAnchorBlock(hwndMain);
  WinLoadString(hAB,get_mod_handle(),
                IDS_HELPTITLE,256,(PSZ)szHelpTitle);
  hmiHelpData.pszHelpWindowTitle = (PSZ)szHelpTitle;
  hmiHelpData.hmodHelpTableModule = get_mod_handle();
  strcpy ((PSZ)get_module_dir(szHelpFile),
         (PSZ)HELPFILENAME);
  hmiHelpData.pszHelpLibraryName = (PSZ)szHelpFile;

  if (DosLoadModule(achPath,sizeof(achPath),"HELPMGR",&hmod));//No Help Manager
  else
    if (DosQueryProcAddr(hmod, 51L,
                       "WINCREATEHELPINSTANCE",
                       (PFN *)&pfnWinCreateHelpInstance));  // No API

    else
      if (DosQueryProcAddr(hmod, 52L,
                         "WINDESTROYHELPINSTANCE",
                         (PFN *)&pfnWinDestroyHelpInstance));// No API
      else
        if (DosQueryProcAddr(hmod, 54L,
                           "WINASSOCIATEHELPINSTANCE",
                           (PFN *)&pfnWinAssociateHelpInstance));// No API
        else
          fError = FALSE;


  if (fError)
  {

    /*
    ** Should report error to user.
    */
    ReleaseHelpStubHook();
    SetHelpStubHook();
    return ;
  }

  do
  {
    hwndHelp = pfnWinCreateHelpInstance(hAB,
                                        &hmiHelpData);/* my hab             */
  }

  while (HelpErrorFilter(hmiHelpData.ulReturnCode,
                         (PSZ)szHelpFile));

  if (hwndHelp != NULLHANDLE)
  {
    if (!pfnWinAssociateHelpInstance(hwndHelp,
                                     hwndMain))/* my frame                  */
    {
      pfnWinDestroyHelpInstance(hwndHelp);
      hwndHelp = (HWND)NULL;
    }                                  /* END winassoc fail                 */
  }

  /*
  ** If help was initialized, get rid of our hook. Otherwise, we have
  ** to ensure that our stub hook is the FIRST hook in the HK_HELP
  ** hook chain, and show the "Out of Resource" dialog...
  */
  if (hwndHelp != NULLHANDLE)
  {
    HelpAlreadyInitialized = TRUE;
    ReleaseHelpStubHook();
  }

  else
  {
    /*
    ** ShowOutOfResourceDlg();
    */
    ReleaseHelpStubHook();
    SetHelpStubHook();
  }
}

/***************************************************************************
 *
 * FUNCTION NAME =  ReleaseHelpStubHook
 *
 *
 * DESCRIPTION   =  ReleaseHelpStubHook
 *
 *                  Remove our stub HK_HELP hook from the
 *                  hook chain, if it has been
 *                  successfully added via
 *                  SetHelpStubHook()...
 *
 * MarkH @MJH1 Removed the exit list that was installed in this function's
 *             counterpart function so that DosFreeModule would succeed.
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 *************************************************************************/

VOID ReleaseHelpStubHook()
{

  if (HelpStubHookIsSet)
  {
    WinReleaseHook(NULLHANDLE,
                   HMQ_CURRENT,
                   HK_HELP,
                   (PFN)HelpStubHook,
                   NULLHANDLE);
    DosExitList (EXLST_REMOVE, (PFNEXITLIST)CleanUpHelpStubHook);   // @MJH1
    HelpStubHookIsSet = FALSE;
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = CleanUpHelpStubHook
 *
 *
 * DESCRIPTION   = CleanUpHelpStubHook
 *
 *                 Exit list routine that will ensures we
 *                 always remove our stub HK_HELP hook
 *                 before exiting.
 *
 *
 *
 * INPUT         = ExitType
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = NONE
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 *************************************************************************/

VOID CleanUpHelpStubHook(USHORT ExitType)
{
  ReleaseHelpStubHook();
  DosExitList (EXLST_EXIT, (PFNEXITLIST)CleanUpHelpStubHook);
  ExitType;
}

/***************************************************************************
 *
 * FUNCTION NAME =  HelpStubHook
 *
 *
 * DESCRIPTION   =  HelpStubHook
 *
 *
 *                  This hook is placed in the HK_HELP hook chain
 *                  so that we can catch the first time that the
 *                  user presses PF1 or clicks on a "Help"
 *                  button.  We then initialize our help instance
 *                  and get the user's help request passed back
 *                  into the HK_HELP chain again by making a call
 *                  to the private function WinCallHelpHook()...
 *
 *
 *
 *
 *
 * INPUT         = AppHAB,Context,IdTopic,IdSubTopic,RectLPtr
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = TRUE
 *
 *
 *
 * RETURN-ERROR  = FALSE
 *
 *
 *
 *************************************************************************/

INT HelpStubHook(HAB AppHAB,USHORT Context,USHORT IdTopic,USHORT
                           IdSubTopic,PRECTL RectLPtr)
{
  AppHAB;                              /* avoid compile warning             */

  /*
  ** Initialize the help manager, so that it will be added to
  ** the HELP hook chain.
  */
  InitializeHelp();

  /*
  ** Now call the HK_HELP
  ** @MJH1 We need to call this otherwise, the keypress gets lost!
  */
//#ifdef   DCR1476
  if (hwndHelp != (HWND)NULL)
  {
     extern VOID _Far16 _Pascal Win16CallHelpHook (SHORT, SHORT, SHORT, PRECTL _Seg16);
     Win16CallHelpHook (Context, IdTopic, IdSubTopic, RectLPtr);
  }
//#endif
  return  FALSE;
}

/***************************************************************************
 *
 * FUNCTION NAME =  get_module_dir
 *
 *
 * DESCRIPTION   =  Return size of the directory path
 *
 *
 *
 *
 * INPUT         =  (pszStr)
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL =  PSZ
 *
 *
 *
 * RETURN-ERROR  = NONE
 *
 *
 *
 *************************************************************************/

PSZ get_module_dir(register PSZ pszStr)
{
  register USHORT usSize;
  register CHAR ch;

  DosQueryModuleName(get_mod_handle(),70,(PCH)pszStr);
  usSize = (USHORT)strlen (pszStr);

  while (usSize--)
  {

    if (((ch = pszStr[usSize]) == '\\') || (ch == ':'))
      break;
  }

  if (usSize < 0)
    usSize = 0;
  else
  {
    if (pszStr[usSize] == ':')
      ++usSize;
  }
  pszStr[usSize] = 0;
  return ((PSZ)&pszStr[usSize]);
}

/***************************************************************************
 *
 * FUNCTION NAME =  HelpErrorFilter
 *
 *
 * DESCRIPTION   =  HelpErrorFilter
 *
 *                  Checks for a recoverable help
 *                  manager initialization error.
 *                  If a a recoverable error is
 *                  detected we put up a message
 *                  box describing the error and
 *                  ask the user if we should
 *                  retry.
 *
 *
 * INPUT         =  (ULONG ulReturnCode,PSZ pszHelpFile)
 *
 *
 * OUTPUT        = NONE
 *
 *
 *
 *
 * RETURN-NORMAL = FALSE: No error or do not retry
 *
 *
 *
 * RETURN-ERROR  = TRUE: Retry
 *
 *
 *
 *************************************************************************/

#define  HLP_MSG_MAX   500
#define  CCH_MAXRCSTRING 256
BOOL HelpErrorFilter(ULONG ulReturnCode,PSZ pszHelpFile)
{
  SHORT sErrorID;
  CHAR szMessage[HLP_MSG_MAX];
  CHAR szSrc[CCH_MAXRCSTRING];
  PSZ apsz[1];
  ULONG ulRet;
  BOOL fRetry = FALSE;


  switch ((USHORT)ulReturnCode)
  {
    case  HMERR_NO_MEMORY :
    case  HMERR_ALLOCATE_SEGMENT :
      WinLoadString(NULLHANDLE,
                    get_mod_handle(),
                    IDS_NoHelpMemory,
                    CCH_MAXRCSTRING,
                    (PSZ)szSrc);
      fRetry = FALSE;
      break;
    case  HMERR_INVALID_LIB_FILE :
    case  HMERR_READ_LIB_FILE :
    case  HMERR_OPEN_LIB_FILE :

      /*
      ** get message
      */

      WinLoadString(NULLHANDLE,
                    get_mod_handle(),
                    IDS_NoHelpFile,
                    CCH_MAXRCSTRING,
                    (PSZ)szSrc);

      /*
      ** insert help file name
      */

      apsz[0] = pszHelpFile;
      DosInsertMessage(apsz,
                       1,
                       szSrc,
                       strlen ((PSZ)szSrc),
                       szMessage,
                       HLP_MSG_MAX,
                       &ulRet);
      szMessage[ulRet] = '\0';
      fRetry = TRUE;
      break;
    default  :                         /* no error or can recover-Do not
                                          retry                             */
      return (FALSE);
  }

  /*
  ** display error
  */

  return ((USHORT)WinMessageBox((HWND)HWND_DESKTOP,
                                (HWND)WinQueryActiveWindow(HWND_DESKTOP),
                                fRetry?(PSZ)szMessage:(PSZ)szSrc,
                                (PSZ)NULL,
                                (USHORT)NULL,
                                (USHORT)(MB_ICONHAND|MB_MOVEABLE|((fRetry)?
                                   MB_RETRYCANCEL:MB_CANCEL))) == MBID_RETRY);
}

