home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / prtsampl.zip / PRTPRINT.C < prev    next >
C/C++ Source or Header  |  1998-04-20  |  58KB  |  1,682 lines

  1. /**************************************************************************
  2.  *  File name  :  prtprint.c
  3.  *
  4.  *  Description:  This module contains all the functions needed to display
  5.  *                a listbox with the valid printer queues and to select a
  6.  *                printer and the print properties.
  7.  *
  8.  *                This source file contains the following functions:
  9.  *
  10.  *                Print( hwnd, pmp )
  11.  *                PrintingDlgProc( hwnd, msg, mp1, mp2 )
  12.  *                PrintDlgProc( hwnd, msg, mp1, mp2 )
  13.  *                QueryPrintQueue( hwnd, pmp, fShowDialog)
  14.  *                QueryPrintDlgProc( hwnd, msg, mp1, mp2 )
  15.  *                QueryJobProperties( hab, pQueueInfo )
  16.  *                ProcessUserPrint( hwnd, pmp )
  17.  *                PrinterBitblt( hwnd, pmp )
  18.  *                PrinterPaginate( hwnd, pmp )
  19.  *                PrinterPlayMetaFile( hwnd, pmp )
  20.  *                FindQueue( pszQueueName, pQueueInfo, sCount )
  21.  *                SortQueues( pQueue1, pQueue2 )
  22.  *
  23.  *  Concepts   :  Listbox, printer queue display and printer property dislpay
  24.  *                and modification.
  25.  *
  26.  *  API's      :  DevCloseDC
  27.  *                DevEscape
  28.  *                DevOpenDC
  29.  *                DevPostDeviceModes
  30.  *                DevQueryCaps
  31.  *
  32.  *                GpiAssociate
  33.  *                GpiBitblt
  34.  *                GpiConvert
  35.  *                GpiCreateLogFont
  36.  *                GpiCreatePS
  37.  *                GpiDeleteBitmap
  38.  *                GpiDeleteSetId
  39.  *                GpiDestroyPS
  40.  *                GpiPlayMetaFile
  41.  *                GpiQueryPS
  42.  *                GpiSetBitmap
  43.  *                GpiSetCharSet
  44.  *
  45.  *                PrfQueryProfileString
  46.  *
  47.  *                SplEnumQueue
  48.  *
  49.  *                WinDefDlgProc
  50.  *                WinDismissDlg
  51.  *                WinDlgBox
  52.  *                WinEnableControl
  53.  *                WinLoadDlg
  54.  *                WinLoadString
  55.  *                WinMessageBox
  56.  *                WinPostMsg
  57.  *                WinQueryDlgItemShort
  58.  *                WinQueryDlgItemText
  59.  *                WinQueryWindowULong
  60.  *                WinSendMsg
  61.  *                WinSetDlgItemShort
  62.  *                WinSetDlgItemText
  63.  *                WinSetWindowULong
  64.  *                WinSendDlgItemMsg
  65.  *                WinShowWindow
  66.  *
  67.  *    Files    :  OS2.H, PRTSAMP.H, PRTSDLG.H, PRTSHLP.H, PMASSERT.H
  68.  *
  69.  *  Copyright (C) 1991-1993 IBM Corporation
  70.  *
  71.  *      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is
  72.  *      sample code created by IBM Corporation. This sample code is not
  73.  *      part of any standard or IBM product and is provided to you solely
  74.  *      for  the purpose of assisting you in the development of your
  75.  *      applications.  The code is provided "AS IS", without
  76.  *      warranty of any kind.  IBM shall not be liable for any damages
  77.  *      arising out of your use of the sample code, even if they have been
  78.  *      advised of the possibility of such damages.                                                    *
  79.  *************************************************************************/
  80.  
  81. /* Include the required sections from the PM header file.  */
  82. #define INCL_DEV
  83. #define INCL_DOSMISC
  84. #define INCL_GPIBITMAPS
  85. #define INCL_GPICONTROL
  86. #define INCL_GPILCIDS
  87. #define INCL_GPIMETAFILES
  88. #define INCL_GPIPRIMITIVES
  89. #define INCL_GPITRANSFORMS
  90. #define INCL_SPL
  91. #define INCL_SPLDOSPRINT
  92. #define INCL_WINBUTTONS
  93. #define INCL_WINDIALOGS
  94. #define INCL_WINENTRYFIELDS
  95. #define INCL_WINERRORS
  96. #define INCL_WINHELP
  97. #define INCL_WININPUT
  98. #define INCL_WINLISTBOXES
  99. #define INCL_WINMENUS
  100. #define INCL_WINMESSAGEMGR
  101. #define INCL_WINSTDFILE
  102. #define INCL_WINSTDFONT
  103. #define INCL_WINWINDOWMGR
  104. #define INCL_WINSHELLDATA 
  105. #include <os2.h>
  106.  
  107. /* c language includes */
  108. #include <stdio.h>
  109. #include <stdlib.h>
  110. #include <string.h>
  111. #include <ctype.h>
  112. #include <stddef.h>
  113. #include <process.h>
  114. #include <memory.h>
  115. #include <sys\types.h>
  116. #include <sys\stat.h>
  117.  
  118. /* application includes */
  119. #include "prtsamp.h"
  120. #include "prtsdlg.h"
  121. #include "pmassert.h"
  122. #include "prtshlp.h"
  123.  
  124.  
  125. /* static function prototypes */
  126.  
  127. static int _Optlink SortQueues(const void *pQueue1, const void *pQueue2);
  128. MRESULT EXPENTRY PrintDlgProc(HWND, USHORT, MPARAM, MPARAM);
  129. MRESULT EXPENTRY PrintingDlgProc(HWND, USHORT, MPARAM, MPARAM);
  130. MRESULT EXPENTRY QueryPrintDlgProc(HWND, USHORT, MPARAM, MPARAM);
  131. BOOL QueryJobProperties(HAB hab, PPRQINFO3 pPrQ);
  132. LONG FindQueue(PSZ pszQueueName, PPRQINFO3 pQueueInfo, LONG lCount);
  133. VOID PrinterPaginate(HWND hwnd, PMAIN_PARM pmp);
  134. VOID PrinterBitblt(HWND hwnd, PMAIN_PARM pmp);
  135. VOID PrinterPlayMetaFile(HWND hwnd, PMAIN_PARM pmp);
  136. VOID ResetPrinterInfoDC( PMAIN_PARM pmp );
  137.  
  138. /*************************************************************************
  139.  *  Function   :  Print
  140.  *
  141.  *  Description:  This function displays the print dialog.
  142.  *
  143.  *  API's      :  WinDlgBox
  144.  *                WinSendMsg
  145.  *                WinLoadDlg
  146.  *
  147.  *  Parameters :  HWND         window handle of frame window
  148.  *                PMAIN_PARM   global application data
  149.  *
  150.  *  Return     :  TRUE if print successful, otherwise FALSE
  151.  *
  152.  *************************************************************************/
  153. BOOL Print(HWND hwnd, PMAIN_PARM pmp)
  154. {
  155.    SHORT      index;
  156.    PPRQINFO3  pQueueInfo;
  157.    ULONG      ul;
  158.    ULONG      cbNeeded;
  159.    BOOL       bOK;
  160.    CHAR       szWork[LEN_WORKSTRING],szTmp[LEN_WORKSTRING];
  161.  
  162.    /*
  163.     * Ensure that queue is correct, the user may have initiated a print
  164.     * without going thruogh any other of the dialogs
  165.     */
  166.    QueryPrintQueue( pmp, FALSE );
  167.  
  168.    /* Query to get latest forms data */
  169.    pmp->cForms = QueryPrinterForms( pmp, pmp->hcinfo, MAX_FORMS );
  170.    pmassert( pmp->hab, pmp->cForms );
  171.  
  172.    /*
  173.     * Check that the form selected by the user in page setup matches the
  174.     * form in job properties
  175.     */
  176.    index = FindForm( pmp->form.achFormName, pmp->hcinfo, pmp->cForms );
  177.    pmassert( pmp->hab, index != -1L);
  178.    if (! (pmp->hcinfo[index].flAttributes & HCAPS_CURRENT))
  179.    {
  180.       /* display warning message box */
  181.       bOK = WinLoadString( pmp->hab,
  182.                            (HMODULE)NULLHANDLE,
  183.                            ERRMSG_WRONG_FORM,
  184.                            LEN_WORKSTRING,
  185.                            szTmp );
  186.       pmassert( pmp->hab, bOK );
  187.       sprintf( szWork, szTmp, pmp->form.achFormName );
  188.       WinMessageBox( HWND_DESKTOP,
  189.                      pmp->hwndFrame,
  190.                      szWork,
  191.                      pmp->pszTitle,
  192.                      (USHORT)0,
  193.                      MB_OK | MB_MOVEABLE | MB_CUAWARNING | MB_APPLMODAL);
  194.  
  195.       /* query queue information */
  196.       ul = SplQueryQueue( NULL, pmp->achQueueName, 3, NULL, 0L, &cbNeeded );
  197.       pmassert( pmp->hab, ul );
  198.       pQueueInfo = malloc( cbNeeded );
  199.       ul = SplQueryQueue( NULL, pmp->achQueueName, 3, pQueueInfo, cbNeeded,
  200.                           &cbNeeded );
  201.       pmassert( pmp->hab, ul == 0 );
  202.  
  203.      /*
  204.       * store current driver data info into SplEnumQueue info
  205.       * so that when user wants to change a print property
  206.       * but not necessarily a printer, his previous settings
  207.       * will be shown in the print properties dialog
  208.       */
  209.      if( pQueueInfo->pDriverData->cb == pmp->cbDriverDataLen )
  210.      {
  211.        memcpy( pQueueInfo->pDriverData, pmp->pDriverData, pmp->cbDriverDataLen );
  212.      }
  213.  
  214.      /* display job properties dialog */
  215.      QueryJobProperties( pmp->hab, pQueueInfo);
  216.  
  217.      /* destroy allocations for printer driver data */
  218.      if( pmp->pDriverData )
  219.      {
  220.          free( pmp->pDriverData );
  221.          pmp->pDriverData      = NULL;
  222.          pmp->cbDriverDataLen  = 0;
  223.      }
  224.  
  225.      /* store new driver data length in pmp  */
  226.      pmp->cbDriverDataLen  = pQueueInfo->pDriverData->cb;
  227.  
  228.      /* store new driver data in pmp  */
  229.      pmp->pDriverData = (PDRIVDATA) malloc( pmp->cbDriverDataLen );
  230.      pmassert( pmp->hab, pmp->pDriverData );
  231.      memcpy( pmp->pDriverData, pQueueInfo->pDriverData, pmp->cbDriverDataLen );
  232.  
  233.      /* destroy allocation for Queue information */
  234.      free( pQueueInfo );
  235.  
  236.      /*
  237.       * reset the printer info device context so the changed form
  238.       * will be found next time
  239.       */
  240.      ResetPrinterInfoDC( pmp );
  241.    }
  242.  
  243.    /*
  244.     * Query user print options. See the PrintDlgProc for details.
  245.     */
  246.    if (WinDlgBox( HWND_DESKTOP,
  247.                   hwnd,
  248.                   (PFNWP)PrintDlgProc,
  249.                   (HMODULE)NULLHANDLE,
  250.                   IDD_PRINT,
  251.                   (PVOID)pmp) )
  252.    {
  253.       /*
  254.        * User wants to print, so start print job and display text
  255.        * showing job printing status.
  256.        */
  257.       WinSendMsg( hwnd, WM_USER_DISABLE_CLIENT, (MPARAM)0L, (MPARAM)0L );
  258.  
  259.       pmp->hwndPrinting = WinLoadDlg( HWND_DESKTOP,
  260.                                       hwnd,
  261.                                       (PFNWP)PrintingDlgProc,
  262.                                       (HMODULE)NULLHANDLE,
  263.                                       IDD_PRINTING,
  264.                                       (PVOID)pmp);
  265.    }
  266.    return FALSE;
  267. }
  268.  
  269. /*************************************************************************
  270.  *  Function   : PrintingDlgProc
  271.  *
  272.  *  Description:  This function displays the print dialog.
  273.  *
  274.  *  API's      :  WinPostMsg
  275.  *                WinDismissDlg
  276.  *                WinEnableControl
  277.  *                WinSetDlgItemText
  278.  *                WinDefDlgProc
  279.  *
  280.  *  Parameters :  HWND         window handle of printer selection dialog
  281.  *                USHORT       message
  282.  *                MPARAM       message parameter 1
  283.  *                MPARAM       message parameter 2
  284.  *
  285.  *  Return     :  message result
  286.  *
  287.  *************************************************************************/
  288. MRESULT EXPENTRY PrintingDlgProc(HWND hwnd,
  289.                                  USHORT msg,
  290.                                  MPARAM mp1,
  291.                                  MPARAM mp2)
  292. {
  293.    static PMAIN_PARM   pmp;
  294.    PSZ                 psz;
  295.    CHAR                szWork[LEN_WORKSTRING], szPrintString[LEN_WORKSTRING];
  296.    BOOL                bOK;
  297.  
  298.    switch (msg)
  299.    {
  300.    case WM_INITDLG:
  301.       /* Get pointer to application specific data */
  302.       pmp = (PMAIN_PARM) PVOIDFROMMP(mp2);
  303.  
  304.       WinSetDlgItemText(hwnd, IDD_PRINTPRINTER, (PSZ)pmp->achQueueDesc);
  305.  
  306.       /* Show the document name */
  307.       psz = strrchr( pmp->szFilename, '\\' );
  308.       if (psz && *psz)
  309.       {
  310.           ++psz;
  311.       }
  312.       else
  313.       {
  314.           psz = pmp->szFilename;
  315.       }
  316.       WinSetDlgItemText(hwnd, IDD_PRINTDOCUMENT, psz);
  317.  
  318.       /* set focus to cancel pushbutton */
  319.       WinSetFocus (HWND_DESKTOP, WinWindowFromID (hwnd, (USHORT)DID_CANCEL));
  320.  
  321.       /*
  322.        * send WM_USER_PRINT message
  323.        * disable client -- object window enables client
  324.        *   when complete
  325.        */
  326.       pmp->fCancel = FALSE;
  327.       WinPostMsg(pmp->hwndObject, WM_USER_PRINT, (MPARAM)hwnd, (MPARAM)0L);
  328.       return 0L;
  329.  
  330.    case WM_USER_ACK:
  331.       /*
  332.        *  The job has either completed or aborted, so tell the client
  333.        *  window and get out.
  334.        */
  335.  
  336.       WinPostMsg(pmp->hwndClient, WM_USER_ACK, 0L, 0L);
  337.  
  338.       WinDismissDlg(hwnd, FALSE);
  339.       return 0L;
  340.  
  341.    case WM_USER_NEW_PAGE:
  342.       /*
  343.        * Increment the page counter on the print confirmation dialog
  344.        */
  345.       bOK = WinLoadString( pmp->hab,
  346.                            (HMODULE)NULLHANDLE,
  347.                            PRINT_PAGE_MSG,
  348.                            LEN_WORKSTRING,
  349.                            szPrintString );
  350.       pmassert( pmp->hab, bOK );
  351.       sprintf(szWork, szPrintString, (ULONG)mp1);
  352.       WinSetDlgItemText( hwnd, IDD_PRINTINGTEXT, szWork);
  353.  
  354.       /* set focus to cancel pushbutton */
  355.       WinSetFocus (HWND_DESKTOP, WinWindowFromID (hwnd, (USHORT)DID_CANCEL));
  356.       break;
  357.  
  358.    case WM_USER_SKIP_PAGE:
  359.       /*
  360.        * Skip the page counter on the print confirmation dialog
  361.        */
  362.       bOK = WinLoadString( pmp->hab,
  363.                            (HMODULE)NULLHANDLE,
  364.                            PRINT_SCAN_MSG,
  365.                            LEN_WORKSTRING,
  366.                            szPrintString );
  367.       pmassert( pmp->hab, bOK );
  368.       sprintf(szWork, szPrintString, (ULONG)mp1);
  369.       WinSetDlgItemText( hwnd, IDD_PRINTINGTEXT, szWork);
  370.  
  371.       /* set focus to cancel pushbutton */
  372.       WinSetFocus (HWND_DESKTOP, WinWindowFromID (hwnd, (USHORT)DID_CANCEL));
  373.       break;
  374.  
  375.    case WM_COMMAND:
  376.       switch(SHORT1FROMMP(mp1))
  377.       {
  378.       case DID_CANCEL:
  379.          pmp->fCancel = TRUE;
  380.          WinEnableControl( hwnd, DID_CANCEL, FALSE );
  381.          bOK = WinLoadString( pmp->hab,
  382.                               (HMODULE)NULLHANDLE,
  383.                               PRINT_ABORT_MSG,
  384.                               LEN_WORKSTRING,
  385.                               szWork );
  386.          pmassert( pmp->hab, bOK );
  387.          WinSetDlgItemText( hwnd, IDD_PRINTINGTEXT, szWork);
  388.          return 0;
  389.       }
  390.       break;
  391.    }
  392.    return( WinDefDlgProc( hwnd, msg, mp1, mp2 ) );
  393. }  /* End of PrintingDlgProc */
  394.  
  395. /*************************************************************************
  396.  *  Function   :  PrintDlgProc
  397.  *
  398.  *  Description:
  399.  *
  400.  *  API's      :  WinSetDlgItemText
  401.  *                WinSetDlgItemShort
  402.  *                WinShowWindow
  403.  *                WinSendMsg
  404.  *                WinQueryDlgItemShort
  405.  *                WinQueryDlgItemText
  406.  *                WinDismissDlg
  407.  *                WinDefDlgProc
  408.  *
  409.  *  Parameters :  HWND         window handle of printer selection dialog
  410.  *                USHORT       message
  411.  *                MPARAM       message parameter 1
  412.  *                MPARAM       message parameter 2
  413.  *
  414.  *  Return     :  MRESULT         message result
  415.  *
  416.  *************************************************************************/
  417. MRESULT EXPENTRY PrintDlgProc(HWND hwnd,
  418.                               USHORT msg,
  419.                               MPARAM mp1,
  420.                               MPARAM mp2)
  421. {
  422.    static PMAIN_PARM pmp;
  423.    PSZ         psz;
  424.    ULONG       ulPanel;
  425.    USHORT      usCopies, usFirstPage, usLastPage;
  426.    CHAR        szEntryField[4];            /* text contents of entry field */
  427.  
  428.    switch (msg)
  429.    {
  430.    case WM_INITDLG:
  431.       /* Get pointer to application specific data */
  432.       pmp = (PMAIN_PARM) PVOIDFROMMP(mp2);
  433.  
  434.       /* Show the printer name */
  435.       WinSetDlgItemText(hwnd, IDD_PRTPRINTER, (PSZ)pmp->achQueueDesc);
  436.  
  437.       /* Show the document name */
  438.       psz = strrchr( pmp->szFilename, '\\' );
  439.       if (psz && *psz)
  440.       {
  441.           ++psz;
  442.       }
  443.       else
  444.       {
  445.           psz = pmp->szFilename;
  446.       }
  447.       WinSetDlgItemText(hwnd, IDD_PRTDOCUMENT, psz);
  448.  
  449.       /* Make entry fields read only */
  450.       WinSendMsg( WinWindowFromID( hwnd, IDD_PRTPRINTER ),
  451.                   EM_SETREADONLY, (MPARAM)TRUE, (MPARAM)0L );
  452.       WinSendMsg( WinWindowFromID( hwnd, IDD_PRTDOCUMENT ),
  453.                   EM_SETREADONLY, (MPARAM)TRUE, (MPARAM)0L );
  454.  
  455.       /* Initialize the number of copies */
  456.       WinSetDlgItemShort(hwnd, IDD_PRTCOPIES, pmp->usCopies, FALSE);
  457.  
  458.       /*
  459.        * If the file is TEXT then set the page fields. Otherwise reset the
  460.        * fields and disable the all fields and pushbuttons
  461.        */
  462.       if (pmp->ulMode == MODE_TEXT)
  463.       {
  464.          WinSetDlgItemShort(hwnd, IDD_PRTFIRSTPAGE, pmp->usFirstPage, FALSE);
  465.          WinSetDlgItemShort(hwnd, IDD_PRTLASTPAGE, pmp->usLastPage, FALSE);
  466.          WinEnableWindow(WinWindowFromID(hwnd, IDD_PRTFIRSTPAGE), TRUE);
  467.          WinEnableWindow(WinWindowFromID(hwnd, IDD_PRTLASTPAGE), TRUE);
  468.       }
  469.       else
  470.       {
  471.          WinSetDlgItemShort(hwnd, IDD_PRTFIRSTPAGE, 1, FALSE);
  472.          WinSetDlgItemShort(hwnd, IDD_PRTLASTPAGE, 1, FALSE);
  473.          WinEnableWindow(WinWindowFromID(hwnd, IDD_PRTALL), FALSE);
  474.          WinEnableWindow(WinWindowFromID(hwnd, IDD_PRTSELECT), FALSE);
  475.          WinEnableWindow(WinWindowFromID(hwnd, IDD_PRTFIRSTPAGE), FALSE);
  476.          WinEnableWindow(WinWindowFromID(hwnd, IDD_PRTLASTPAGE), FALSE);
  477.       }
  478.  
  479.       /* Set the state of the page select pushbuttons */
  480.       if (pmp->fPrintAllPages)
  481.       {
  482.          WinCheckButton( hwnd, IDD_PRTALL, 1);
  483.          WinCheckButton( hwnd, IDD_PRTSELECT, 0);
  484.          WinEnableWindow(WinWindowFromID(hwnd, IDD_PRTFIRSTPAGE), FALSE);
  485.          WinEnableWindow(WinWindowFromID(hwnd, IDD_PRTLASTPAGE), FALSE);
  486.       }
  487.       else
  488.       {
  489.          WinCheckButton( hwnd, IDD_PRTALL, 0);
  490.          WinCheckButton( hwnd, IDD_PRTSELECT, 1);
  491.       }
  492.  
  493.       /*
  494.        * Hide the preview control.  The reason it is included in the
  495.        * print sample DLG file is for the benefit of programmers who
  496.        * want their dialogs to look exactly like those presented in
  497.        * the Programming Guide for printing (Chapter 18).
  498.        */
  499.       WinShowWindow(WinWindowFromID(hwnd, IDD_PRTPREVIEW), FALSE);
  500.  
  501.       return 0;
  502.  
  503.    case WM_HELP:
  504.       if( pmp->hwndHelp )
  505.       {
  506.          ulPanel = PANEL_PRINTDLG;
  507.          WinSendMsg( pmp->hwndHelp, HM_DISPLAY_HELP,
  508.                    (MPARAM)&ulPanel, (MPARAM)HM_RESOURCEID );
  509.          return (MRESULT)NULL;
  510.       }
  511.       break;
  512.  
  513.    case WM_CONTROL:
  514.       switch(SHORT1FROMMP(mp1))
  515.       {
  516.       case IDD_PRTDOCUMENT:
  517.       case IDD_PRTPRINTER:
  518.          /* these fields are read-only */
  519.          return 0;
  520.  
  521.       case IDD_PRTCOPIES:
  522.          if (SHORT2FROMMP(mp1) == EN_CHANGE)
  523.          {
  524.             /* Verify that a non-zero number was typed in the entry field. */
  525.             if (!WinQueryDlgItemShort( hwnd, IDD_PRTCOPIES,
  526.                                        (PSHORT)&usCopies, FALSE) ||
  527.                                        !usCopies )
  528.             {
  529.                /* If the field has length, clear the value and beep */
  530.                if (WinQueryDlgItemText( hwnd, IDD_PRTCOPIES,
  531.                                         sizeof(szEntryField), szEntryField ) )
  532.                {
  533.                   WinSetDlgItemText( hwnd, IDD_PRTCOPIES, "" );
  534.                   DosBeep(600, 5);
  535.                }
  536.             }
  537.          }
  538.          return 0;
  539.  
  540.       case IDD_PRTALL:
  541.          /* check buttons appropriately */
  542.          WinCheckButton( hwnd, IDD_PRTALL, 1);
  543.          WinCheckButton( hwnd, IDD_PRTSELECT, 0);
  544.          /* disable first and last page entry fields */
  545.          WinEnableWindow(WinWindowFromID(hwnd, IDD_PRTFIRSTPAGE), FALSE);
  546.          WinEnableWindow(WinWindowFromID(hwnd, IDD_PRTLASTPAGE), FALSE);
  547.          return 0;
  548.  
  549.       case IDD_PRTSELECT:
  550.          /* check buttons appropriately */
  551.          WinCheckButton( hwnd, IDD_PRTALL, 0);
  552.          WinCheckButton( hwnd, IDD_PRTSELECT, 1);
  553.          /*
  554.           * if the mode is TEXT and the page selection is active, enable the
  555.           * the first and last page controls otherwise disable them
  556.           */
  557.          if (pmp->ulMode == MODE_TEXT)
  558.          {
  559.             WinEnableWindow(WinWindowFromID(hwnd, IDD_PRTFIRSTPAGE), TRUE);
  560.             WinEnableWindow(WinWindowFromID(hwnd, IDD_PRTLASTPAGE), TRUE);
  561.          }
  562.          return 0;
  563.  
  564.       case IDD_PRTFIRSTPAGE:
  565.          if (SHORT2FROMMP(mp1) == EN_CHANGE)
  566.          {
  567.             /* Verify that a non-zero number was typed in the entry field. */
  568.             if (!WinQueryDlgItemShort( hwnd, IDD_PRTFIRSTPAGE,
  569.                                        (PSHORT)&usFirstPage, FALSE) ||
  570.                                        !usFirstPage )
  571.                /* If the field has length, clear the value and beep */
  572.                if (WinQueryDlgItemText( hwnd, IDD_PRTFIRSTPAGE,
  573.                                         sizeof(szEntryField), szEntryField ) )
  574.                {
  575.                   WinSetDlgItemText( hwnd, IDD_PRTFIRSTPAGE, "" );
  576.                   DosBeep(600, 5);
  577.                }
  578.          }
  579.          return 0;
  580.  
  581.       case IDD_PRTLASTPAGE:
  582.          if (SHORT2FROMMP(mp1) == EN_CHANGE)
  583.          {
  584.             /* Verify that a non-zero number was typed in the entry field. */
  585.             if (!WinQueryDlgItemShort( hwnd, IDD_PRTLASTPAGE,
  586.                                        (PSHORT)&usLastPage, FALSE) ||
  587.                                        !usLastPage )
  588.             {
  589.                /* If the field has length, clear the value and beep */
  590.                if (WinQueryDlgItemText( hwnd, IDD_PRTLASTPAGE,
  591.                                         sizeof(szEntryField), szEntryField ) )
  592.                {
  593.                   WinSetDlgItemText( hwnd, IDD_PRTLASTPAGE, "" );
  594.                   DosBeep(600, 5);
  595.                }
  596.             }
  597.          }
  598.          return 0;
  599.  
  600.  
  601.       case IDD_PRTPREVIEW:
  602.          /* this field is not used in this sample program */
  603.          return 0;
  604.       }
  605.       break;
  606.  
  607.    case WM_COMMAND:
  608.       switch(SHORT1FROMMP(mp1))
  609.       {
  610.       case DID_OK:
  611.          /* get number of copies and store in global data structure */
  612.          WinQueryDlgItemShort( hwnd, IDD_PRTCOPIES,
  613.                                (PSHORT)&pmp->usCopies, FALSE);
  614.  
  615.          /* print all pages or selective pages */
  616.          pmp->fPrintAllPages =
  617.              (BOOL)WinSendDlgItemMsg( hwnd, IDD_PRTALL, BM_QUERYCHECK,
  618.                                       (MPARAM)TRUE, (MPARAM)0L );
  619.  
  620.          /*
  621.           * If mode is TEXT, get first and last page, even though
  622.           * page select may be greyed
  623.           */
  624.          if (pmp->ulMode == MODE_TEXT)
  625.          {
  626.             WinQueryDlgItemShort( hwnd, IDD_PRTFIRSTPAGE,
  627.                                   (PSHORT)&pmp->usFirstPage, FALSE);
  628.             WinQueryDlgItemShort( hwnd, IDD_PRTLASTPAGE,
  629.                                   (PSHORT)&pmp->usLastPage, FALSE);
  630.          }
  631.          if (pmp->usLastPage < pmp->usFirstPage)
  632.          {
  633.             pmp->fPrintAllPages = TRUE;
  634.             pmp->usFirstPage = 1;
  635.             pmp->usLastPage = 1;
  636.          }
  637.  
  638.          WinDismissDlg(hwnd, TRUE);
  639.          return 0;
  640.  
  641.       case DID_CANCEL:
  642.          WinDismissDlg(hwnd, FALSE);
  643.          return 0;
  644.  
  645.       case DID_HELP_BUTTON:
  646.          /* don't do anything yet */
  647.          return 0;
  648.       }
  649.       break;
  650.  
  651.    }
  652.    return(WinDefDlgProc(hwnd, msg, mp1, mp2));
  653.  
  654. } /* End of PrintDlgProc */
  655.  
  656. /*************************************************************************
  657.  *  Function   :  QueryPrintQueue
  658.  *
  659.  *  Description:  Query all printer queues, display them in a listbox
  660.  *                and do a selection.
  661.  *
  662.  *  Parameters:   PMAIN_PARM  pmp has global application data
  663.  *                fShowDialog     a flag:  should the dialog be displayed?
  664.  *
  665.  *  API's      :  SplEnumQueue
  666.  *                WinLoadString
  667.  *                WinMessageBox
  668.  *                DosQuerySysInfo
  669.  *                PrfQueryProfileString
  670.  *                WinDlgBox
  671.  *
  672.  *  Return     :  TRUE if printer changed, otherwise FALSE
  673.  *
  674.  *************************************************************************/
  675. BOOL QueryPrintQueue(PMAIN_PARM pmp, BOOL fShowDialog)
  676. {
  677.     ULONG           ul, cReturned, cTotal, cbNeeded;
  678.     PPRQINFO3       pQueueInfo, pqi;
  679.     LONG            i;
  680.     BOOL            fResult, bOK;
  681.     CHAR            szWork[LEN_WORKSTRING], *pch;
  682.     ULONG           aulVersion[2];
  683.  
  684.    /*
  685.     * Get count of total number of print queues and the size of the
  686.     * buffer needed (cbNeeded) to hold them.
  687.     */
  688.    ul = SplEnumQueue( NULL,          /* pszComputerName - local machine */
  689.                       3,             /* information level 3 requested   */
  690.                       NULL,          /* pBuf - NULL for first call      */
  691.                       0L,            /* cbBuf - 0 to get size needed    */
  692.                       &cReturned,    /* number of queues returned       */
  693.                       &cTotal,       /* total number of queues          */
  694.                       &cbNeeded,     /* number bytes needed to store    */
  695.                                      /* all requested information       */
  696.                       NULL );        /* reserved                        */
  697.  
  698.    /* If there are no print queues display Message Box */
  699.    if (cTotal == 0L)
  700.    {           /* this system has no printers defined */
  701.       bOK = WinLoadString( pmp->hab,
  702.                            (HMODULE)NULLHANDLE,
  703.                            ERRMSG_NO_QUEUES_DEFINED,
  704.                            LEN_WORKSTRING,
  705.                            szWork );
  706.       pmassert( pmp->hab, bOK );
  707.  
  708.       WinMessageBox( HWND_DESKTOP,
  709.                      pmp->hwndFrame,
  710.                      szWork,
  711.                      pmp->pszTitle,
  712.                      (USHORT)0,
  713.                      MB_OK | MB_MOVEABLE | MB_CUAWARNING | MB_APPLMODAL);
  714.  
  715.       /* Grey Print menu item */
  716.       WinEnableMenuItem( pmp->hwndMenubar, IDM_PRINT, FALSE );
  717.  
  718.       /*
  719.        * There are no printers now. A previously defined printer may have
  720.        * have been deleted, so reset all the fields in the global data
  721.        */
  722.       pmp->hdcPrinter = (HDC)NULL;
  723.       pmp->hpsPrinter = (HPS)NULL;
  724.       pmp->hdcPrinterInfo = (HDC)NULL;
  725.       pmp->achQueueName[0] = '\0';
  726.       pmp->achQueueDesc[0] = '\0';
  727.       pmp->pDriverData = (PDRIVDATA)NULL;
  728.  
  729.       /*
  730.        * Return TRUE if a printer was previously defined and then reset
  731.        * this field so that some default forms can be returned for
  732.        * the Page Setup dialog
  733.        */
  734.       fResult = pmp->hpsPrinterInfo;
  735.       pmp->hpsPrinterInfo = (HPS)NULL;
  736.       return fResult;
  737.    }
  738.  
  739.    /*
  740.     * allocate memory to store the enumerated queue information
  741.     */
  742.    pQueueInfo = malloc( cbNeeded ) ;
  743.     pmassert( pmp->hab, pQueueInfo );
  744.  
  745.     /* Call again to get print queue data. */
  746.    ul = SplEnumQueue( NULL,             /* pszComputerName - local machine */
  747.                       3,                /* information level 3 requested   */
  748.                       pQueueInfo,       /* pBuf - gets enumerated queues   */
  749.                       cbNeeded,         /* cbBuf - size of pBuf            */
  750.                       &cReturned,       /* number of queues returned       */
  751.                       &cTotal,          /* total number of queues          */
  752.                       &cbNeeded,        /* number bytes needed to store    */
  753.                                         /*   all requested information     */
  754.                       NULL );           /* reserved                        */
  755.  
  756.     pmassert( pmp->hab, ul == 0 );
  757.  
  758.     /*
  759.      * Validate that the user-preferred queue exists and if not then
  760.      * set preferred queue to none. User's preference of queues is
  761.      * named by the variable pmp->achQueueName.
  762.      */
  763.  
  764.     if( *pmp->achQueueName != 0 )
  765.     {
  766.       i = FindQueue( pmp->achQueueName, pQueueInfo, cReturned );
  767.       if (i == -1)
  768.       {
  769.         *pmp->achQueueName = 0;
  770.       }
  771.     }
  772.  
  773.     /*
  774.      * Validate that the user-preferred queue has been initialized OK.
  775.      * If not, initialize it now.
  776.      */
  777.  
  778.     if ( *pmp->achQueueName == 0 )
  779.     {
  780.        /*
  781.         * There is no preferred queue name because there was none
  782.         * in the INI file (perhaps this is the first time the
  783.         * program has run on this system?) or the profile reading
  784.         * failed somehow. Give the user the application default
  785.         * queue.
  786.         */
  787.  
  788.        /* check OS/2 version number */
  789.        ul = DosQuerySysInfo( QSV_VERSION_MAJOR, QSV_VERSION_MINOR,
  790.                         aulVersion, 8 );
  791.        pmassert( pmp->hab, ul == 0 );
  792.  
  793.        if (aulVersion[0] == 20 && aulVersion[1] == 0 )
  794.        {
  795.          ul = PrfQueryProfileString( HINI_PROFILE,
  796.                                      "PM_SPOOLER",
  797.                                      "QUEUE",
  798.                                      NULL,
  799.                                      szWork,
  800.                                      LEN_WORKSTRING );
  801.  
  802.          if ( ul )
  803.          {
  804.             /* truncate queuename at terminating semicolon */
  805.             pch = strchr( szWork, ';' );
  806.             pmassert( pmp->hab, pch );
  807.             *pch = 0;
  808.             strcpy( pmp->achQueueName, szWork );
  809.          }
  810.        }
  811.        else
  812.        {
  813.          for (i = 0L; i < cTotal; ++i)
  814.          {
  815.             if ( pQueueInfo[i].fsType & PRQ3_TYPE_APPDEFAULT)
  816.             {
  817.                strcpy( pmp->achQueueName, pQueueInfo[i].pszName );
  818.                break;
  819.             }
  820.          }
  821.        }
  822.  
  823.        /*
  824.         * Still no application default queue? odd. Give him the first queue
  825.         * from the SplEnumQueue calls
  826.         */
  827.        if ( *pmp->achQueueName == 0 )
  828.        {
  829.           pmassert( pmp->hab, NULL == "Error?? No application default queue" );
  830.           strcpy( pmp->achQueueName, pQueueInfo->pszName );
  831.        }
  832.     }
  833.     pmassert( pmp->hab, 0 < strlen( pmp->achQueueName ));
  834.  
  835.     /* find queue and queue settings including the driver data info */
  836.     i = FindQueue( pmp->achQueueName, pQueueInfo, cReturned );
  837.     pmassert( pmp->hab, i != -1 );
  838.     pqi = &pQueueInfo[i];
  839.  
  840.     /*
  841.      * Store current driver data info into SplEnumQueue info
  842.      * so that when user wants to change a job property
  843.      * but not necessarily a printer, his previous settings
  844.      * will be shown in the print properties dialog. Otherwise use
  845.      * the defaults from the SplEnumQueue info.
  846.      *
  847.      * Note if the device name, driver data length or version does not match,
  848.      * the driver may not be able to understand or correctly use the
  849.      * driver data info
  850.      */
  851.     if (pmp->cbDriverDataLen)
  852.     {
  853.       if ( ! strcmp( pqi->pDriverData->szDeviceName,
  854.                      pmp->pDriverData->szDeviceName ) )
  855.       {
  856.         if ( (pqi->pDriverData->cb == pmp->cbDriverDataLen ) &&
  857.              (pqi->pDriverData->lVersion == pmp->pDriverData->lVersion ) )
  858.         {
  859.           memcpy( pqi->pDriverData, pmp->pDriverData, pmp->cbDriverDataLen );
  860.         }
  861.         else
  862.         {
  863.           bOK = WinLoadString( pmp->hab,
  864.                                (HMODULE)NULLHANDLE,
  865.                                ERRMSG_NEW_DRIVER_VERSION,
  866.                                LEN_WORKSTRING,
  867.                                szWork );
  868.           pmassert( pmp->hab, bOK );
  869.  
  870.           WinMessageBox( HWND_DESKTOP,
  871.                          pmp->hwndFrame,
  872.                          szWork,
  873.                          pmp->pszTitle,
  874.                          (USHORT)0,
  875.                          MB_OK | MB_MOVEABLE | MB_CUAWARNING | MB_APPLMODAL);
  876.         }
  877.       }
  878.       else
  879.       {
  880.         bOK = WinLoadString( pmp->hab,
  881.                              (HMODULE)NULLHANDLE,
  882.                              ERRMSG_DEVICE_CHANGED,
  883.                              LEN_WORKSTRING,
  884.                              szWork );
  885.         pmassert( pmp->hab, bOK );
  886.  
  887.         WinMessageBox( HWND_DESKTOP,
  888.                        pmp->hwndFrame,
  889.                        szWork,
  890.                        pmp->pszTitle,
  891.                        (USHORT)0,
  892.                        MB_OK | MB_MOVEABLE | MB_CUAWARNING | MB_APPLMODAL);
  893.       }
  894.     }
  895.  
  896.     /*
  897.      * Display dialog box to select a printer
  898.      */
  899.  
  900.  
  901.     if (fShowDialog)
  902.     {
  903.         /* sort the data returned from SplEnumQueue by queue name  */
  904.         qsort((void *)pQueueInfo,
  905.           (size_t)cReturned,
  906.           (size_t)sizeof(PRQINFO3),
  907.           SortQueues);
  908.  
  909.         /*
  910.          * Dialog procedure requires the data from SplEnumQueue.
  911.          * Use the pmp to pass this data to the dialog.
  912.          */
  913.         pmp->pQueueInfo  = pQueueInfo;
  914.         pmp->lQueueCount = cReturned;
  915.  
  916.         /* present the dialog  */
  917.         ul = WinDlgBox( HWND_DESKTOP,
  918.                         pmp->hwndFrame,
  919.                         (PFNWP)QueryPrintDlgProc,
  920.                         (HMODULE)0,
  921.                         IDD_QUERYPRINT,
  922.                         (PVOID)pmp);
  923.  
  924.         pmassert( pmp->hab, ul != DID_ERROR );
  925.  
  926.         /* done with these vars for now  */
  927.         pmp->pQueueInfo  = NULL;
  928.         pmp->lQueueCount = 0;
  929.  
  930.  
  931.         if( ul == DID_CANCEL )
  932.         {
  933.              /* free queueinfo buffer for SplEnumQueue   */
  934.              free( pQueueInfo );
  935.              /* indicate to caller that no change occurred  */
  936.              return FALSE;
  937.         }
  938.     }
  939.  
  940.  
  941.  
  942.  
  943.     /*
  944.      * At this point, something changed about the printer destination:
  945.      * form, printer, queue, resolution, something.
  946.      *
  947.      * Prepare a printer info DC and associate a printer info PS with it
  948.      * for the print queue named by pmp->achQueueName.
  949.      */
  950.  
  951.  
  952.  
  953.     /* set pqi to point to the PRQINFO3 structure for pmp->achQueueName  */
  954.  
  955.     i = FindQueue( pmp->achQueueName, pQueueInfo, cReturned );
  956.     pmassert( pmp->hab, i  != -1 );
  957.     pqi = &pQueueInfo[i];
  958.  
  959.     /* destroy previous printer driver data */
  960.     if( pmp->pDriverData )
  961.     {
  962.         free( pmp->pDriverData );
  963.         pmp->pDriverData      = NULL;
  964.         pmp->cbDriverDataLen  = 0;
  965.     }
  966.  
  967.     /* store new driver name in pmp  */
  968.     strcpy( pmp->achDriverName, pqi->pszDriverName );
  969.  
  970.     /* store new driver data length in pmp  */
  971.     pmp->cbDriverDataLen  = pqi->pDriverData->cb;
  972.  
  973.     /* store new driver data in pmp  */
  974.     pmp->pDriverData = (PDRIVDATA) malloc( pmp->cbDriverDataLen );
  975.     pmassert( pmp->hab, pmp->pDriverData );
  976.     memcpy( pmp->pDriverData, pqi->pDriverData, pmp->cbDriverDataLen );
  977.  
  978.     /* store new queue description in pmp  */
  979.     strncpy(pmp->achQueueDesc, pqi->pszComment, QUEUEDESC_LENGTH);
  980.     pmp->achQueueDesc[QUEUEDESC_LENGTH-1] = 0;
  981.  
  982.     /*
  983.      * reset the printer info device context so that any changes
  984.      * will be found next time
  985.      */
  986.     ResetPrinterInfoDC( pmp );
  987.  
  988.  
  989.     /* free the buffer allocated for SplEnumQueue call  */
  990.     free( pQueueInfo );
  991.  
  992.     /* enable the Print menu item */
  993.     WinEnableMenuItem( pmp->hwndMenubar, IDM_PRINT, TRUE );
  994.  
  995.     /* return indication that something changed  */
  996.     return TRUE;
  997. }   /*  end of QueryPrintQueue */
  998.  
  999. /*************************************************************************
  1000.  *  Function   :  QueryPrintDlgProc
  1001.  *
  1002.  *  Description:  This function is the dialog window procedure for printer
  1003.  *                selection.
  1004.  *                This dialog presents to the user a list of printer
  1005.  *                destinations, or queues.  Typically, the user would
  1006.  *                hilight a queue, then press the Job Properties... button
  1007.  *                to set items like orientation, form, resolution, etc.
  1008.  *                The printer driver presents the job properties dialog
  1009.  *                when the application calls DevPostDeviceModes.
  1010.  *
  1011.  *                Today, there is no standard, uniform way to tell whether
  1012.  *                the user pressed OK or Cancel at the Job Properties dialog;
  1013.  *                therefore, the dialog processing assumes that
  1014.  *                job properties were changed no matter if the
  1015.  *                user pressed OK or cancel. See the use of the
  1016.  *                fVisitedJobProperties Boolean variable.
  1017.  *
  1018.  *                This function is associated with the dialog box that is
  1019.  *                included in the function name of the procedure. It
  1020.  *                provides the service routines for the events (messages)
  1021.  *                that occur because the end user operates one of the dialog
  1022.  *                box's buttons, entry fields, or controls.
  1023.  *
  1024.  *                The SWITCH statement in the function distributes the dialog
  1025.  *                box messages to the respective service routines, which are
  1026.  *                set apart by the CASE clauses. Like any other PM window,
  1027.  *                the Dialog Window procedures must provide an appropriate
  1028.  *                service routine for their end user initiated messages as
  1029.  *                well as for the general PM messages (like the WM_CLOSE
  1030.  *                message). If a message is sent to this procedure for which
  1031.  *                there is no programmed CASE condition (no service routine),
  1032.  *                the message is defaulted to the WinDefDlgProc function,
  1033.  *                where it is disposed of by PM.
  1034.  *
  1035.  *  Parameters :  HWND         window handle of printer selection dialog
  1036.  *                USHORT       message
  1037.  *                MPARAM       message parameter 1
  1038.  *                MPARAM       message parameter 2
  1039.  *
  1040.  *  API's      :  WinSetWindowULong
  1041.  *                WinSendDlgItemMsg
  1042.  *                WinEnableControl
  1043.  *                WinSendDlgItemMsg
  1044.  *                WinQueryWindowULong
  1045.  *                WinDismissDlg
  1046.  *                WinDefDlgProc
  1047.  *
  1048.  * Return      :  message result
  1049.  *
  1050.  *************************************************************************/
  1051. MRESULT EXPENTRY QueryPrintDlgProc( HWND hwnd,
  1052.                                     USHORT msg,
  1053.                                     MPARAM mp1,
  1054.                                     MPARAM mp2 )
  1055. {
  1056.    static BOOL         fVisitedJobProperties;
  1057.    PMAIN_PARM          pmp;
  1058.    INT                 i, index;
  1059.    PSZ                 psz;
  1060.    HWND                hwndListbox;
  1061.    ULONG               ulPanel;
  1062.  
  1063.    switch (msg)
  1064.    {
  1065.    case WM_BUTTON1DBLCLK:
  1066.       WinSendMsg( hwnd, WM_COMMAND, (MPARAM)DID_OK, (MPARAM)0L );
  1067.       break;
  1068.  
  1069.  
  1070.    case WM_INITDLG:
  1071.       /* Get pointer to application specific data */
  1072.       pmp = (PMAIN_PARM) mp2;
  1073.       WinSetWindowULong( hwnd, QWL_USER, (ULONG) mp2 );
  1074.  
  1075.  
  1076.       /*
  1077.        *  Assume user will not select job properties.
  1078.        *  This affects how to dismiss this dialog.
  1079.        */
  1080.       fVisitedJobProperties = FALSE;
  1081.  
  1082.       /* Fill listbox with print objects */
  1083.  
  1084.         hwndListbox = WinWindowFromID( hwnd, IDD_QPLISTBOX );
  1085.         pmassert( pmp->hab, hwndListbox );
  1086.  
  1087.       for (i = 0; i < pmp->lQueueCount; ++i)
  1088.       {
  1089.        /* use printer comment if possible, else use queue name for display */
  1090.          psz = *pmp->pQueueInfo[i].pszComment ?
  1091.                 pmp->pQueueInfo[i].pszComment :
  1092.                 pmp->pQueueInfo[i].pszName;
  1093.             /* pmwin.h macro for inserting list box items   */
  1094.             index = WinInsertLboxItem( hwndListbox, LIT_END, psz );
  1095.  
  1096.             /* pre-select this one?  */
  1097.             if( 0 == strcmp( pmp->pQueueInfo[i].pszName, pmp->achQueueName ))
  1098.             {
  1099.                WinSendMsg( hwndListbox, LM_SELECTITEM,
  1100.                                             (MPARAM)index, (MPARAM)TRUE );
  1101.             }
  1102.       }
  1103.  
  1104.         /* one must be selected */
  1105.         index = WinQueryLboxSelectedItem( hwndListbox );
  1106.         pmassert( pmp->hab, index != LIT_NONE );
  1107.  
  1108.       return FALSE;
  1109.  
  1110.    case WM_HELP:
  1111.       /* get pointer to structure from window words of this dialog */
  1112.       pmp = (PMAIN_PARM)WinQueryWindowULong( hwnd, QWL_USER );
  1113.  
  1114.       if( pmp->hwndHelp )
  1115.       {
  1116.          ulPanel = PANEL_QUERYPRINT;
  1117.          WinSendMsg( pmp->hwndHelp, HM_DISPLAY_HELP,
  1118.                    (MPARAM)&ulPanel, (MPARAM)HM_RESOURCEID );
  1119.          return (MRESULT)NULL;
  1120.       }
  1121.       break;
  1122.  
  1123.  
  1124.    case WM_COMMAND:
  1125.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  1126.       switch(SHORT1FROMMP(mp1))
  1127.       {
  1128.       case IDD_QPJOBPROP:
  1129.           /*
  1130.            * Flag that we visited the job properties dialog. Since
  1131.            * DevPostDeviceModes (OS2_PM_DRV_DEVMODES) option
  1132.            * DPDM_POSTJOBPROP has no return code or standard way to
  1133.            * indicate user cancel, we have to assume something might
  1134.            * have changed.
  1135.            */
  1136.           fVisitedJobProperties = TRUE;
  1137.           hwndListbox = WinWindowFromID( hwnd, IDD_QPLISTBOX );
  1138.           pmassert( pmp->hab, hwndListbox );
  1139.           index = WinQueryLboxSelectedItem( hwndListbox );
  1140.           pmassert( pmp->hab, index != LIT_NONE );
  1141.           QueryJobProperties( pmp->hab, &pmp->pQueueInfo[ index ] );
  1142.           return 0;
  1143.  
  1144.       case DID_OK:
  1145.             hwndListbox = WinWindowFromID( hwnd, IDD_QPLISTBOX );
  1146.             pmassert( pmp->hab, hwndListbox );
  1147.             index = WinQueryLboxSelectedItem( hwndListbox );
  1148.             pmassert( pmp->hab, index != LIT_NONE );
  1149.  
  1150.          /* modify pmp->achQueueName; it is now the user's preferred queue */
  1151.             strcpy( pmp->achQueueName,  pmp->pQueueInfo[ index ].pszName );
  1152.             WinDismissDlg( hwnd, DID_OK );
  1153.             return 0;
  1154.  
  1155.  
  1156.       case DID_CANCEL:
  1157.          WinDismissDlg(hwnd, fVisitedJobProperties ? DID_OK : DID_CANCEL );
  1158.          return (MRESULT)NULL;
  1159.       }
  1160.       break;
  1161.  
  1162.    }
  1163.    return( WinDefDlgProc(hwnd, msg, mp1, mp2) );
  1164. } /* End of QueryPrintDlgProc */
  1165.  
  1166.  
  1167. /*************************************************************************
  1168.  *  Function   :  QueryJobProperties
  1169.  *
  1170.  *  Description:  Query job properties (print properties) of the printer
  1171.  *                driver.
  1172.  *
  1173.  *  Parameters :  HAB             anchor block handle of the process
  1174.  *                PPRQINFO3       pointer to queue information structure
  1175.  *
  1176.  *  API's      :  DevPostDeviceModes
  1177.  *
  1178.  *  Return     :  TRUE if ok, otherwise FALSE
  1179.  *
  1180.  *************************************************************************/
  1181. BOOL QueryJobProperties(HAB hab, PPRQINFO3 pQueueInfo)
  1182. {
  1183.    CHAR        achDriverName[DRIVERNAME_LENGTH];
  1184.    CHAR        achDeviceName[DEVICENAME_LENGTH];
  1185.    INT         i;
  1186.    LONG        l;
  1187.    PSZ         pszTemp;
  1188.  
  1189.    /*
  1190.     * The pszDriverName is of the form DRIVER.DEVICE (e.g.,
  1191.     * LASERJET.HP LaserJet IID) so we need to separate it
  1192.     * at the dot
  1193.     */
  1194.    i = strcspn(pQueueInfo->pszDriverName, ".");
  1195.    if (i)
  1196.    {
  1197.       strncpy(achDriverName, pQueueInfo->pszDriverName, i);
  1198.       achDriverName[i] = '\0';
  1199.       strcpy(achDeviceName, &pQueueInfo->pszDriverName[i + 1]);
  1200.    }
  1201.    else
  1202.    {
  1203.       strcpy(achDriverName, pQueueInfo->pszDriverName);
  1204.       *achDeviceName = '\0';
  1205.    }
  1206.  
  1207.    /*
  1208.     * There may be more than one printer assigned to this print queue
  1209.     * We will use the first in the comma separated list.  We would
  1210.     * need an expanded dialog for the user to be more specific.
  1211.     */
  1212.    pszTemp = strchr(pQueueInfo->pszPrinters, ',');
  1213.    if ( pszTemp )
  1214.    {
  1215.       /* Strip off comma and trailing printer names */
  1216.       *pszTemp = '\0' ;
  1217.    }
  1218.  
  1219.    /*
  1220.     * Post the job properties dialog for the printer to allow the
  1221.     * user to modify the options
  1222.     */
  1223.    l = DevPostDeviceModes( hab,
  1224.                            pQueueInfo->pDriverData,
  1225.                            achDriverName,
  1226.                            achDeviceName,
  1227.                            pQueueInfo->pszPrinters,
  1228.                            DPDM_POSTJOBPROP );
  1229.  
  1230.    return (l == DEV_OK);
  1231. }  /* End of QueryJobProperties */
  1232.  
  1233. /*************************************************************************
  1234.  *
  1235.  *  Name:         ProcessUserPrint
  1236.  *
  1237.  *  Description:  This routine handles the user print (WM_USER_PRINT)
  1238.  *                message. We're running thread 2 here because it can be
  1239.  *                a long operation. The device context and presentation
  1240.  *                space are created here, then one of three functions
  1241.  *                is called to print depending on whether we have a
  1242.  *                bitmap, metafile or text document.
  1243.  *
  1244.  *  Parameters :  HWND           window handle
  1245.  *                PMAIN_PARM     global application data
  1246.  *
  1247.  *  API's      :  DevOpenDC
  1248.  *                GpiCreatePS
  1249.  *                DevEscape
  1250.  *                GpiAssociate
  1251.  *                GpiDestroyPS
  1252.  *                DevCloseDC
  1253.  *
  1254.  *  Return     :  VOID
  1255.  *
  1256.  *
  1257.  *************************************************************************/
  1258.  
  1259. VOID ProcessUserPrint( HWND hwnd, PMAIN_PARM pmp)
  1260. {
  1261.    DEVOPENSTRUC    dos;
  1262.    VOID            (*pfnPrintDocument)(HWND, PMAIN_PARM);
  1263.    CHAR            achDriverName[DRIVERNAME_LENGTH];
  1264.    CHAR            achQueueProcParams[8];
  1265.    CHAR            achSpoolerParams[40];
  1266.    SIZEL           sizel;
  1267.    PSZ             psz;
  1268.  
  1269.    /* Build the device context data for DevOpenDC */
  1270.    memset((PVOID)&dos, 0, sizeof(dos));
  1271.  
  1272.    strcpy(achDriverName, pmp->achDriverName);
  1273.    achDriverName[strcspn(achDriverName, ".")] = '\0';
  1274.    sprintf(achQueueProcParams, "COP=%d", pmp->usCopies);
  1275.    sprintf(achSpoolerParams, "FORM=%s", pmp->form.achFormName);
  1276.  
  1277.    dos.pszLogAddress = pmp->achQueueName;
  1278.    dos.pszDriverName = (PSZ)achDriverName;
  1279.    dos.pdriv = pmp->pDriverData;
  1280.    dos.pszDataType = (PSZ)"PM_Q_STD";
  1281.    dos.pszComment = pmp->pszTitle;
  1282.    dos.pszQueueProcParams = (PSZ)achQueueProcParams;
  1283.    dos.pszSpoolerParams = (PSZ)achSpoolerParams;
  1284.  
  1285.    /*
  1286.     * Switch on whether we are writing text, a bitmap
  1287.     * or a metafile into the PS, and process
  1288.     */
  1289.    switch (pmp->ulMode)
  1290.    {
  1291.    case MODE_TEXT:
  1292.         /* Seek to beginning of user-specified file */
  1293.       fseek(pmp->f, 0, SEEK_SET);
  1294.       pfnPrintDocument = PrinterPaginate;
  1295.       break;
  1296.  
  1297.    case MODE_BITMAP:
  1298.       pfnPrintDocument = PrinterBitblt;
  1299.       break;
  1300.  
  1301.    case MODE_METAFILE:
  1302.       pfnPrintDocument = PrinterPlayMetaFile;
  1303.       break;
  1304.  
  1305.    default:
  1306.       pmassert(pmp->hab, FALSE);
  1307.       return;
  1308.    }
  1309.  
  1310.    /* Create DC for the printer */
  1311.    pmp->hdcPrinter = DevOpenDC( pmp->hab,
  1312.                                 OD_QUEUED,
  1313.                                 "*",
  1314.                                 9L,
  1315.                                 (PVOID)&dos,
  1316.                                 (HDC)NULLHANDLE );
  1317.  
  1318.    /* Create PS for the printer */
  1319.    pmp->hpsPrinter = GPI_ERROR;
  1320.    if (pmp->hdcPrinter != DEV_ERROR)
  1321.    {
  1322.       /*
  1323.        * Set page size to 0,0. A page size should not be defined for printing
  1324.        * because when the job is printed, the output will be scaled to fit
  1325.        * the page size specified on GpiCreatePS
  1326.        */
  1327.       sizel.cx = 0;
  1328.       sizel.cy = 0;
  1329.       pmp->hpsPrinter = GpiCreatePS( pmp->hab,
  1330.                                      pmp->hdcPrinter,
  1331.                                      &sizel,
  1332.                                      PU_TWIPS | GPIA_ASSOC );
  1333.       pmassert( pmp->hab, pmp->hpsPrinter != GPI_ERROR );
  1334.  
  1335.       if (pmp->hpsPrinter != GPI_ERROR)
  1336.       {
  1337.          /* parse full-qualified filename to just get filename and extension */
  1338.          psz = strrchr( pmp->szFilename, '\\' );
  1339.          if (psz && *psz)
  1340.          {
  1341.              ++psz;
  1342.          }
  1343.          else
  1344.          {
  1345.              psz = pmp->szFilename;
  1346.          }
  1347.  
  1348.          /* Issue STARTDOC to begin printing */
  1349.          DevEscape( pmp->hdcPrinter,
  1350.                     DEVESC_STARTDOC,
  1351.                     (LONG)strlen(psz),
  1352.                     (PBYTE)psz,
  1353.                     (PLONG)NULL, (PBYTE)NULL );
  1354.  
  1355.          /* Print the document */
  1356.          (*pfnPrintDocument)(hwnd, pmp);
  1357.  
  1358.          /*
  1359.           * Issue ABORTDOC if user cancelled print job, or ENDDOC
  1360.           * to for normal job termination.
  1361.           */
  1362.          DevEscape( pmp->hdcPrinter,
  1363.                     pmp->fCancel ? DEVESC_ABORTDOC : DEVESC_ENDDOC,
  1364.                     0L, (PBYTE)NULL, (PLONG)NULL, (PBYTE)NULL );
  1365.  
  1366.          /* Release and destroy the PS */
  1367.          GpiAssociate( pmp->hpsPrinter, (HDC)NULLHANDLE );
  1368.          GpiDestroyPS( pmp->hpsPrinter );
  1369.       }
  1370.    }
  1371.  
  1372.    /* Clean up the DC */
  1373.    if (pmp->hdcPrinter != DEV_ERROR)
  1374.    {
  1375.       DevCloseDC(pmp->hdcPrinter);
  1376.       pmp->hdcPrinter = DEV_ERROR;
  1377.    }
  1378.  
  1379.    return;
  1380. }
  1381.  
  1382. /*************************************************************************
  1383.  *
  1384.  *  Name       :  PrinterBitblt
  1385.  *
  1386.  *  Description:  Load a bitmap into a memory DC using the WM_USER_LOAD_BITMAP
  1387.  *                processing. Calculate what size to print the bitmap in order
  1388.  *                to preserve the bitmap aspect ratio and still have it fit on
  1389.  *                the page. Then bit blit into the printer PS, allowing the
  1390.  *                device presentation driver to do the stretch blit.
  1391.  *
  1392.  *  Parameters :  HWND           window handle
  1393.  *                PMAIN_PARM     global application data
  1394.  *
  1395.  *  API's      :  WinSendMsg
  1396.  *                GpiQueryPS
  1397.  *                GpiConvert
  1398.  *                GpiBitblt
  1399.  *                GpiSetBitmap
  1400.  *                GpiDeleteBitmap
  1401.  *                GpiAssociate
  1402.  *                GpiDestroyPS
  1403.  *                DevCloseDC
  1404.  *
  1405.  *  Return     :  VOID
  1406.  *
  1407.  *************************************************************************/
  1408.  
  1409. VOID PrinterBitblt(HWND hwnd, PMAIN_PARM pmp)
  1410. {
  1411.  
  1412.     /* Clear our variables to ensure USER_LOAD_BITMAP starts fresh */
  1413.     pmp->hdcMem4Printer = (HDC)NULLHANDLE;
  1414.     pmp->hpsMem4Printer = (HPS)NULLHANDLE;
  1415.     pmp->hbm4Printer = (HBITMAP)NULLHANDLE;
  1416.  
  1417.     /* update print confirmation dialog */
  1418.     WinSendMsg( pmp->hwndPrinting, WM_USER_NEW_PAGE, MPFROMLONG(1L), NULL);
  1419.  
  1420.     /* Send message to create a printer PS with our bitmap set into it */
  1421.     WinSendMsg(hwnd, WM_USER_LOAD_BITMAP, (MPARAM)hwnd,
  1422.                (MPARAM)FLAGS_PRINTER);
  1423.  
  1424.     /* draw bitmap into presentation space */
  1425.     PaintBitmap( pmp, FLAGS_PRINTER );
  1426.  
  1427.     /* Clean up bitmap, memory PS and memory DC */
  1428.     GpiDeleteBitmap( pmp->hbm4Printer );
  1429.     GpiAssociate( pmp->hpsMem4Printer, (HDC)NULLHANDLE );
  1430.     GpiDestroyPS( pmp->hpsMem4Printer );
  1431.     DevCloseDC( pmp->hdcMem4Printer );
  1432.  
  1433.     return;
  1434. }  /* End of PrinterBitblt */
  1435.  
  1436. /*************************************************************************
  1437.  *
  1438.  *  Name:      :  PrinterPaginate
  1439.  *
  1440.  *  Description:  This function uses WM_USER_PAGINATE processing to
  1441.  *                print text to printer There is a check of the fCancel
  1442.  *                Boolean in the main parameters after paginating each
  1443.  *                page. If this Boolean becomes true, then printing the
  1444.  *                text is aborted.
  1445.  *
  1446.  *  API's      :  GpiCreateLogFont
  1447.  *                GpiSetCharSet
  1448.  *                WinSendMsg
  1449.  *                DevEscape
  1450.  *                GpiSetCharSet
  1451.  *                GpiDeleteSetId
  1452.  *
  1453.  *  Return     :  VOID
  1454.  *
  1455.  *************************************************************************/
  1456. VOID PrinterPaginate(HWND hwnd, PMAIN_PARM pmp)
  1457. {
  1458.    ULONG   ul;
  1459.    BOOL    bOK;
  1460.    ULONG   cPage = 0;
  1461.    ULONG   cPagesPrinted = 0;
  1462.    CHAR    szWork[LEN_WORKSTRING];
  1463.  
  1464.    /*
  1465.     * Create a logical font for the printer and set it
  1466.     * into the PS
  1467.     */
  1468.    ul = (ULONG)GpiCreateLogFont( pmp->hpsPrinter,
  1469.                                  (PSTR8)NULL,
  1470.                                  1L,
  1471.                                  (PFATTRS)&pmp->fontdlg.fAttrs );
  1472.    pmassert(pmp->hab, ul != GPI_ERROR);
  1473.  
  1474.    bOK = GpiSetCharSet( pmp->hpsPrinter, 1L );
  1475.    pmassert( pmp->hab, bOK );
  1476.  
  1477.    if (!pmp->fPrintAllPages && pmp->usFirstPage != 1)
  1478.    {
  1479.       WinSendMsg( pmp->hwndPrinting, WM_USER_SKIP_PAGE,
  1480.                   MPFROMLONG(pmp->usFirstPage), NULL);
  1481.    }
  1482.  
  1483.    do
  1484.    {
  1485.       cPage++;
  1486.       /*
  1487.        * Print to info PS until correct page is reached
  1488.        */
  1489.       if (!pmp->fPrintAllPages && cPage < pmp->usFirstPage)
  1490.       {
  1491.          ul = (ULONG)WinSendMsg( hwnd, WM_USER_PAGINATE, (MPARAM)hwnd,
  1492.                                  (MPARAM)FLAGS_INFO );
  1493.       }
  1494.       else
  1495.       {
  1496.          WinSendMsg( pmp->hwndPrinting, WM_USER_NEW_PAGE,
  1497.                      MPFROMLONG(cPage), NULL);
  1498.          ul = (ULONG)WinSendMsg( hwnd, WM_USER_PAGINATE, (MPARAM)hwnd,
  1499.                                  (MPARAM)FLAGS_PRINTER );
  1500.          cPagesPrinted++;
  1501.       }
  1502.  
  1503.       /* break out of loop if no more pages to print */
  1504.       if (!pmp->fPrintAllPages && cPage + 1 > pmp->usLastPage)
  1505.       {
  1506.          break;
  1507.       }
  1508.  
  1509.       if ( ul == PAGINATE_NOT_EOF )
  1510.       {
  1511.          DevEscape( pmp->hdcPrinter,
  1512.                     DEVESC_NEWFRAME,
  1513.                     0L,
  1514.                     (PBYTE)NULL,
  1515.                     (PLONG)NULL,
  1516.                     (PBYTE)NULL );
  1517.       }
  1518.       else
  1519.       {
  1520.            /* End of file; Break out of this loop and return to do enddoc */
  1521.           break;
  1522.       }
  1523.     } while ( !pmp->fCancel );
  1524.  
  1525.     /* Report error if no pages actually printed */
  1526.     if (! cPagesPrinted)
  1527.     {
  1528.       bOK = WinLoadString( pmp->hab,
  1529.                            (HMODULE)NULLHANDLE,
  1530.                            ERRMSG_NOTHING_PRINTED,
  1531.                            LEN_WORKSTRING,
  1532.                            szWork );
  1533.       pmassert( pmp->hab, bOK );
  1534.       WinMessageBox( HWND_DESKTOP,
  1535.                      pmp->hwndFrame,
  1536.                      szWork,
  1537.                      pmp->pszTitle,
  1538.                      (USHORT)0,
  1539.                      MB_OK | MB_MOVEABLE | MB_CUAWARNING | MB_APPLMODAL);
  1540.     }
  1541.  
  1542.     /* Clean up logical font id */
  1543.     GpiSetCharSet(pmp->hpsPrinter, 0L);
  1544.     GpiDeleteSetId(pmp->hpsPrinter, 1L);
  1545.  
  1546.    return;
  1547. }  /* End of PrinterPaginate */
  1548.  
  1549. /*************************************************************************
  1550.  *
  1551.  *  Name       :  PrinterPlayMetafile
  1552.  *
  1553.  *  Description:  Play metafile into printer PS without the reset and
  1554.  *                suppress options.
  1555.  *
  1556.  *  Parameters :  HWND           window handle
  1557.  *                PMAIN_PARM     global application data
  1558.  *
  1559.  *  Return     :  VOID
  1560.  *
  1561.  *************************************************************************/
  1562. VOID PrinterPlayMetaFile(HWND hwnd, PMAIN_PARM pmp)
  1563. {
  1564.     /* update print confirmation dialog */
  1565.     WinSendMsg( pmp->hwndPrinting, WM_USER_NEW_PAGE, MPFROMLONG(1L), NULL);
  1566.     /* print metafile */
  1567.     PaintMetaFile( pmp, FLAGS_PRINTER );
  1568.     return;
  1569. }  /* End of PrinterPlayMetafile */
  1570.  
  1571. /*************************************************************************
  1572.  *
  1573.  *   Function   :  FindQueue
  1574.  *
  1575.  *   Description:  Finds the queue name in the PRQINFO3 structure.
  1576.  *
  1577.  *   Parameters :  PSZ          pointer to the name of the queue
  1578.  *                 PPRQINFO3    pointer to queue selection structure 1
  1579.  *                 SHORT        number of queue names to compare
  1580.  *
  1581.  *   API's      :  [none]
  1582.  *
  1583.  *************************************************************************/
  1584. LONG FindQueue(PSZ pszQueueName, PPRQINFO3 pQueueInfo, LONG lCount)
  1585. {
  1586.    LONG i;
  1587.  
  1588.    for (i = 0L; i < lCount; ++i)
  1589.    {
  1590.       if ( !strcmp( pszQueueName, pQueueInfo[i].pszName ) )
  1591.          return i;
  1592.    }
  1593.  
  1594.    return -1L;                 /*  if not found  */
  1595. }  /* End of FindQueue */
  1596.  
  1597. /*************************************************************************
  1598.  *  Function   :  SortQueues
  1599.  *
  1600.  *  Description:  Compare routine for sorting the queue names table.
  1601.  *
  1602.  *  Parameters :  PPRQINFO3    pointer to queue selection structure 1
  1603.  *                PPRQINFO3    pointer to queue selection structure 2
  1604.  *
  1605.  *  API's      :  [none]
  1606.  *
  1607.  *  Return     :  result of comparison
  1608.  *
  1609.  *************************************************************************/
  1610. static int _Optlink SortQueues(const void *pQueue1, const void *pQueue2)
  1611. {
  1612. return(strcmp(((PPRQINFO3)pQueue1)->pszComment,
  1613.               ((PPRQINFO3)pQueue2)->pszComment));
  1614. } /* end of SortQueues() */
  1615.  
  1616.  
  1617. /*************************************************************************
  1618.  *  Function   :  ResetPrinterInfoDC
  1619.  *
  1620.  *  Description:  Close the info DC, PS and re-open another one
  1621.  *
  1622.  *  Parameters :  PMP          pointer to global data structure
  1623.  *
  1624.  *  API's      :  [none]
  1625.  *
  1626.  *  Return     :  [none]
  1627.  *
  1628.  *************************************************************************/
  1629. VOID ResetPrinterInfoDC( PMAIN_PARM pmp )
  1630. {
  1631.     CHAR            achDriverName[DRIVERNAME_LENGTH];
  1632.     SIZEL           sizel;
  1633.     DEVOPENSTRUC    dos;
  1634.  
  1635.     /* initialize local variables to zeros */
  1636.     memset( &dos,   0, sizeof(dos));
  1637.     memset( &sizel, 0, sizeof(sizel));
  1638.  
  1639.  
  1640.     /* destroy previous printer info PS's and DC's */
  1641.     if( pmp->hpsPrinterInfo )
  1642.     {
  1643.         GpiAssociate(pmp->hpsPrinterInfo, (HDC)NULL);
  1644.         GpiDestroyPS(pmp->hpsPrinterInfo);
  1645.         pmp->hpsPrinterInfo = (HPS)0;
  1646.     }
  1647.     if( pmp->hdcPrinterInfo )
  1648.     {
  1649.         DevCloseDC(pmp->hdcPrinterInfo);
  1650.         pmp->hdcPrinterInfo = (HDC)0;
  1651.     }
  1652.  
  1653.     /* build a devopenstruct for the call to DevOpenDC */
  1654.     dos.pszLogAddress = pmp->achQueueName;
  1655.     strcpy( achDriverName, pmp->achDriverName );
  1656.     achDriverName[strcspn(achDriverName, ".")] = '\0';
  1657.     dos.pszDriverName = (PSZ)achDriverName;
  1658.     dos.pdriv = pmp->pDriverData;
  1659.  
  1660.     /* Create an OD_INFO device context */
  1661.     pmp->hdcPrinterInfo = DevOpenDC(
  1662.                             pmp->hab,
  1663.                             OD_INFO,
  1664.                             "*",
  1665.                             3L,
  1666.                             (PVOID)&dos,
  1667.                             (HDC)NULL);
  1668.     pmassert(pmp->hab, pmp->hdcPrinterInfo != DEV_ERROR);
  1669.  
  1670.  
  1671.     /* create PS for printer info -- not a full-blown PS */
  1672.     pmp->hpsPrinterInfo = GpiCreatePS(
  1673.                         pmp->hab,
  1674.                         pmp->hdcPrinterInfo,
  1675.                         (PSIZEL)&sizel,
  1676.                         PU_TWIPS | GPIA_ASSOC);
  1677.     pmassert(pmp->hab, pmp->hpsPrinterInfo != GPI_ERROR);
  1678.  
  1679. } /* end of ResetPrinterInfoDC */
  1680.  
  1681. /***************************  End of prtprint.c ****************************/
  1682.