home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional Developers Kit 1992 November / Disc01 / Disc01.mdf / os2tk20 / c / samples / print / prtprint.c__ / PRTPRINT.C
Encoding:
C/C++ Source or Header  |  1992-07-15  |  45.7 KB  |  1,364 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.  *                PrinterResetMetaFile( hwnd, pmp )
  21.  *                FindQueue( pszQueueName, pQueueInfo, sCount )
  22.  *                SortQueues( pQueue1, pQueue2 )
  23.  *
  24.  *  Concepts   :  Listbox, printer queue display and printer property dislpay
  25.  *                and modification.
  26.  *
  27.  *  API's      :  DevCloseDC
  28.  *                DevEscape
  29.  *                DevOpenDC
  30.  *                DevPostDeviceModes
  31.  *                DevQueryCaps
  32.  *
  33.  *                GpiAssociate
  34.  *                GpiBitblt
  35.  *                GpiConvert
  36.  *                GpiCreateLogFont
  37.  *                GpiCreatePS
  38.  *                GpiDeleteBitmap
  39.  *                GpiDeleteSetID
  40.  *                GpiDestroyPS
  41.  *                GpiPlayMetaFile
  42.  *                GpiQueryPS
  43.  *                GpiSetBitmap
  44.  *                GpiSetCharSet
  45.  *
  46.  *                PrfQueryProfileString
  47.  *
  48.  *                SplEnumQueue
  49.  *
  50.  *                WinDefDlgProc
  51.  *                WinDismissDlg
  52.  *                WinDlgBox
  53.  *                WinEnableControl
  54.  *                WinLoadDlg
  55.  *                WinLoadString
  56.  *                WinMessageBox
  57.  *                WinPostMsg
  58.  *                WinQueryDlgItemShort
  59.  *                WinQueryDlgItemText
  60.  *                WinQueryWindowULong
  61.  *                WinSendMsg
  62.  *                WinSetDlgItemShort
  63.  *                WinSetDlgItemText
  64.  *                WinSetWindowULong
  65.  *                WinSendDlgItemMsg
  66.  *                WinShowWindow
  67.  *
  68.  *  Files      :  OS2.H, MAIN.H, HELP.H, XTRN.H
  69.  *
  70.  *  Copyright (C) 1991 IBM Corporation
  71.  *
  72.  *      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is
  73.  *      sample code created by IBM Corporation. This sample code is not
  74.  *      part of any standard or IBM product and is provided to you solely
  75.  *      for  the purpose of assisting you in the development of your
  76.  *      applications.  The code is provided "AS IS", without
  77.  *      warranty of any kind.  IBM shall not be liable for any damages
  78.  *      arising out of your use of the sample code, even if they have been
  79.  *      advised of the possibility of such damages.                                                    *
  80.  *************************************************************************/
  81.  
  82. /* Include the required sections from the PM header file.  */
  83. #define INCL_WINSTDFILE
  84. #define INCL_WINSTDFONT
  85. #define INCL_WINHELP
  86. #define INCL_WINENTRYFIELDS
  87. #define INCL_WINLISTBOXES
  88. #define INCL_WINDIALOGS
  89. #define INCL_WINWINDOWMGR
  90. #define INCL_GPITRANSFORMS
  91. #define INCL_GPIBITMAPS
  92. #define INCL_GPICONTROL
  93. #define INCL_GPIMETAFILES
  94. #define INCL_GPILCIDS
  95. #define INCL_DEV
  96. #define INCL_SPL
  97. #define INCL_SPLDOSPRINT
  98. #include <os2.h>
  99.  
  100. /* c language includes */
  101. #include <stdio.h>
  102. #include <stdlib.h>
  103. #include <string.h>
  104. #include <ctype.h>
  105. #include <stddef.h>
  106. #include <process.h>
  107. #include <memory.h>
  108. #include <sys\types.h>
  109. #include <sys\stat.h>
  110.  
  111. /* application includes */
  112. #include "prtsamp.h"
  113. #include "prtsdlg.h"
  114. #include "pmassert.h"
  115. #include "prtshlp.h"
  116.  
  117.  
  118. /* static function prototypes */
  119.  
  120. static int _Optlink SortQueues(const void *pQueue1, const void *pQueue2);
  121. MRESULT EXPENTRY PrintDlgProc(HWND, USHORT, MPARAM, MPARAM);
  122. MRESULT EXPENTRY PrintingDlgProc(HWND, USHORT, MPARAM, MPARAM);
  123. MRESULT EXPENTRY QueryPrintDlgProc(HWND, USHORT, MPARAM, MPARAM);
  124. BOOL QueryJobProperties(HAB hab, PPRQINFO3 pPrQ);
  125. LONG FindQueue(PSZ pszQueueName, PPRQINFO3 pQueueInfo, LONG lCount);
  126. VOID PrinterPaginate(HWND hwnd, PMAIN_PARM pmp);
  127. VOID PrinterBitblt(HWND hwnd, PMAIN_PARM pmp);
  128. VOID PrinterPlayMetaFile(HWND hwnd, PMAIN_PARM pmp);
  129. VOID PrinterResetMetaFile(HWND hwnd, PMAIN_PARM pmp);
  130.  
  131. /*************************************************************************
  132.  *  Function   :  Print
  133.  *
  134.  *  Description:  This function displays the print dialog.
  135.  *
  136.  *  API's      :  WinDlgBox
  137.  *                WinSendMsg
  138.  *                WinLoadDlg
  139.  *
  140.  *  Parameters :  HWND         window handle of frame window
  141.  *                PMAIN_PARM   global application data
  142.  *
  143.  *  Return     :  TRUE if print successful, otherwise FALSE
  144.  *
  145.  *************************************************************************/
  146. BOOL Print(HWND hwnd, PMAIN_PARM pmp)
  147. {
  148.    /*
  149.     * Query user print options.  Of the standard print dialog, we've only
  150.     * made use of the number of copies the user wants. See the PrintDlgProc
  151.     * for details.
  152.     */
  153.    if (WinDlgBox( HWND_DESKTOP,
  154.                   hwnd,
  155.                   (PFNWP)PrintDlgProc,
  156.                   (HMODULE)NULLHANDLE,
  157.                   IDD_PRINT,
  158.                   (PVOID)pmp) )
  159.    {
  160.       /*
  161.        * User wants to print, so start print job and display text
  162.        * showing job printing status.
  163.        */
  164.       WinSendMsg( hwnd, WM_USER_DISABLE_CLIENT, (MPARAM)0L, (MPARAM)0L );
  165.  
  166.       WinLoadDlg( HWND_DESKTOP,
  167.                   hwnd,
  168.                   (PFNWP)PrintingDlgProc,
  169.                   (HMODULE)NULLHANDLE,
  170.                   IDD_PRINTING,
  171.                   (PVOID)pmp);
  172.    }
  173.    return FALSE;
  174. }
  175.  
  176. /*************************************************************************
  177.  *  Function   : PrintingDlgProc
  178.  *
  179.  *  Description:  This function displays the print dialog.
  180.  *
  181.  *  API's      :  WinPostMsg
  182.  *                WinDismissDlg
  183.  *                WinEnableControl
  184.  *                WinSetDlgItemText
  185.  *                WinDefDlgProc
  186.  *
  187.  *  Parameters :  HWND         window handle of printer selection dialog
  188.  *                USHORT       message
  189.  *                MPARAM       message parameter 1
  190.  *                MPARAM       message parameter 2
  191.  *
  192.  *  Return     :  message result
  193.  *
  194.  *************************************************************************/
  195. MRESULT EXPENTRY PrintingDlgProc(HWND hwnd,
  196.                                  USHORT msg,
  197.                                  MPARAM mp1,
  198.                                  MPARAM mp2)
  199. {
  200.    static PMAIN_PARM   pmp;
  201.  
  202.    switch (msg)
  203.    {
  204.    case WM_INITDLG:
  205.       /* Get pointer to application specific data */
  206.       pmp = (PMAIN_PARM) PVOIDFROMMP(mp2);
  207.  
  208.       /*
  209.        * send WM_USER_PRINT message
  210.        * disable client -- object window enables client
  211.        *   when complete
  212.        */
  213.       pmp->fCancel = FALSE;
  214.       WinPostMsg(pmp->hwndObject, WM_USER_PRINT, (MPARAM)hwnd, (MPARAM)0L);
  215.       return 0L;
  216.  
  217.    case WM_USER_ACK:
  218.       /*
  219.        *  The job has either completed or aborted, so tell the client
  220.        *  window and get out.
  221.        */
  222.  
  223.       WinPostMsg(pmp->hwndClient, WM_USER_ACK, 0L, 0L);
  224.  
  225.       WinDismissDlg(hwnd, FALSE);
  226.       return 0L;
  227.  
  228.    case WM_COMMAND:
  229.       switch(SHORT1FROMMP(mp1))
  230.       {
  231.       case DID_CANCEL:
  232.          pmp->fCancel = TRUE;
  233.          WinEnableControl( hwnd, DID_CANCEL, FALSE );
  234.          WinSetDlgItemText( hwnd, IDD_PRINTINGTEXT, (PSZ)"Aborting..." );
  235.          return 0;
  236.       }
  237.       break;
  238.    }
  239.    return( WinDefDlgProc( hwnd, msg, mp1, mp2 ) );
  240. }  /* End of PrintingDlgProc */
  241.  
  242. /*************************************************************************
  243.  *  Function   :  PrintDlgProc
  244.  *
  245.  *  Description:
  246.  *
  247.  *  API's      :  WinSetDlgItemText
  248.  *                WinSetDlgItemShort
  249.  *                WinShowWindow
  250.  *                WinSendMsg
  251.  *                WinQueryDlgItemShort
  252.  *                WinQueryDlgItemText
  253.  *                WinDismissDlg
  254.  *                WinDefDlgProc
  255.  *
  256.  *  Parameters :  HWND         window handle of printer selection dialog
  257.  *                USHORT       message
  258.  *                MPARAM       message parameter 1
  259.  *                MPARAM       message parameter 2
  260.  *
  261.  *  Return     :  MRESULT         message result
  262.  *
  263.  *************************************************************************/
  264. MRESULT EXPENTRY PrintDlgProc(HWND hwnd,
  265.                               USHORT msg,
  266.                               MPARAM mp1,
  267.                               MPARAM mp2)
  268. {
  269.    static PMAIN_PARM pmp;
  270.    PSZ         psz;
  271.    USHORT      us;
  272.    ULONG       ulPanel;
  273.  
  274.    switch (msg)
  275.    {
  276.    case WM_INITDLG:
  277.       /* Get pointer to application specific data */
  278.       pmp = (PMAIN_PARM) PVOIDFROMMP(mp2);
  279.  
  280.       /* Show the printer name */
  281.       WinSetDlgItemText(hwnd, IDD_PRTPRINTER, (PSZ)pmp->achQueueDesc);
  282.  
  283.       /* Show the document name */
  284.       psz = strrchr( pmp->szFilename, '\\' );
  285.       if (psz && *psz)
  286.       {
  287.           ++psz;
  288.           WinSetDlgItemText(hwnd, IDD_PRTDOCUMENT, psz);
  289.       }
  290.  
  291.       /* Initialize the number of copies */
  292.       WinSetDlgItemShort(hwnd, IDD_PRTCOPIES,
  293.                          pmp->usCopies, FALSE);
  294.  
  295.         /*
  296.          * Hide the page and preview controls.  The reason they are
  297.          * included in the print sample DLG file is for the benefit
  298.          * of programmers who want their dialogs to look exactly like
  299.          * those presented in the Programming Guide for printing.
  300.          */
  301.         for (us = IDD_PRTALL; us <= IDD_PRTPREVIEW; ++us)
  302.             WinShowWindow(WinWindowFromID(hwnd, us), FALSE);
  303.  
  304.       /* Make entry fields read only */
  305.       WinSendMsg(WinWindowFromID(hwnd, IDD_PRTPRINTER),
  306.                  EM_SETREADONLY, (MPARAM)TRUE, (MPARAM)0L);
  307.       WinSendMsg(WinWindowFromID(hwnd, IDD_PRTDOCUMENT),
  308.                  EM_SETREADONLY, (MPARAM)TRUE, (MPARAM)0L);
  309.  
  310.       return 0;
  311.  
  312.    case WM_HELP:
  313.       if( pmp->hwndHelp )
  314.       {
  315.          ulPanel = PANEL_PRINTDLG;
  316.          WinSendMsg( pmp->hwndHelp, HM_DISPLAY_HELP,
  317.                    (MPARAM)&ulPanel, (MPARAM)HM_RESOURCEID );
  318.          return (MRESULT)NULL;
  319.       }
  320.       break;
  321.  
  322.    case WM_CONTROL:
  323.       switch(SHORT1FROMMP(mp1))
  324.       {
  325.       case IDD_PRTCOPIES:
  326.          if (SHORT2FROMMP(mp1) == EN_CHANGE)
  327.          {
  328.             /*
  329.              * Verify that a non-zero number was typed in the entry field.
  330.              * If not, beep and set it back to 1.
  331.              */
  332.             if (!WinQueryDlgItemShort( hwnd, IDD_PRTCOPIES,
  333.                                        (PSHORT)&pmp->usCopies, FALSE) ||
  334.                                        !pmp->usCopies )
  335.             {
  336.                CHAR    szCopies[4];        /* text contents of entry field */
  337.  
  338.                /*
  339.                 * If the field has length (no length means user backspaced
  340.                 * over the current value), the clear the invalid value and
  341.                 * beep to warn the user.
  342.                 */
  343.                if (WinQueryDlgItemText( hwnd, IDD_PRTCOPIES,
  344.                                         sizeof(szCopies), (PSZ)szCopies ))
  345.                {
  346.                   WinSetDlgItemText(hwnd, IDD_PRTCOPIES, "");
  347.                   DosBeep(600, 5);
  348.                }
  349.                pmp->usCopies = 1;
  350.             }
  351.          }
  352.          return 0;
  353.  
  354.         /* Not using these controls; see comment under WM_INITDLG */
  355.       case IDD_PRTALL:
  356.       case IDD_PRTSELECT:
  357.       case IDD_PRTFIRSTPAGE:
  358.       case IDD_PRTLASTPAGE:
  359.       case IDD_PRTPREVIEW:
  360.       case IDD_PRTDOCUMENT:
  361.       case IDD_PRTPRINTER:
  362.          return 0;
  363.       }
  364.       break;
  365.  
  366.    case WM_COMMAND:
  367.       switch(SHORT1FROMMP(mp1))
  368.       {
  369.       case DID_OK:
  370.          WinDismissDlg(hwnd, TRUE);
  371.          return 0;
  372.  
  373.       case DID_CANCEL:
  374.          WinDismissDlg(hwnd, FALSE);
  375.          return 0;
  376.  
  377.       case DID_HELP_BUTTON:
  378.          /* don't do anything yet */
  379.          return 0;
  380.       }
  381.       break;
  382.  
  383.    }
  384.    return(WinDefDlgProc(hwnd, msg, mp1, mp2));
  385.  
  386. } /* End of PrintDlgProc */
  387.  
  388. /*************************************************************************
  389.  *  Function   :  QueryPrintQueue
  390.  *
  391.  *  Description:  Query all printer queues, display them in a listbox
  392.  *                and do a selection.
  393.  *
  394.  *  Parameters:   PMAIN_PARM  pmp has global application data
  395.  *                fShowDialog     a flag:  should the dialog be displayed?
  396.  *
  397.  *  API's      :  WinLoadString
  398.  *                WinMessageBox
  399.  *                WinDlgBox
  400.  *                SplEnumQueue
  401.  *
  402.  *  Return     :  TRUE if printer changed, otherwise FALSE
  403.  *
  404.  *************************************************************************/
  405. BOOL QueryPrintQueue(PMAIN_PARM pmp, BOOL fShowDialog)
  406. {
  407.     ULONG           ul, cReturned, cTotal, cbNeeded;
  408.     PPRQINFO3       pQueueInfo, pqi;
  409.     LONG            i;
  410.     BOOL            fResult, fSameQueue, bOK;
  411.     CHAR            szWork[LEN_WORKSTRING];
  412.     PSZ             pszWork;
  413.     SIZEL           sizel;
  414.     DEVOPENSTRUC    dos;
  415.     CHAR            achDriverName[DRIVERNAME_LENGTH];
  416.     PCHAR           pch;
  417.  
  418.    /*
  419.     * Get count of total number of print queues and the size of the
  420.     * buffer needed (cbNeeded) to hold them.
  421.     */
  422.    ul = SplEnumQueue( NULL,          /* pszComputerName - local machine */
  423.                       3,             /* information level 3 requested   */
  424.                       NULL,          /* pBuf - NULL for first call      */
  425.                       0L,            /* cbBuf - 0 to get size needed    */
  426.                       &cReturned,    /* number of queues returned       */
  427.                       &cTotal,       /* total number of queues          */
  428.                       &cbNeeded,     /* number bytes needed to store    */
  429.                                      /* all requested information       */
  430.                       NULL );        /* reserved                        */
  431.  
  432.    /* If there are no print queues display Message Box */
  433.    if (cTotal == 0L)
  434.    {           /* this system has no printers defined */
  435.       bOK = WinLoadString( pmp->hab,
  436.                            (HMODULE)NULLHANDLE,
  437.                            ERRMSG_NO_QUEUES_DEFINED,
  438.                            LEN_WORKSTRING,
  439.                            szWork );
  440.       pmassert( pmp->hab, bOK );
  441.  
  442.       WinMessageBox( HWND_DESKTOP,
  443.                      pmp->hwndFrame,
  444.                      szWork,
  445.                      pmp->pszTitle,
  446.                      (USHORT)0,
  447.                      MB_OK | MB_MOVEABLE | MB_CUAWARNING | MB_APPLMODAL);
  448.         /* nothing changed */
  449.       return FALSE;
  450.    }
  451.  
  452.    /*
  453.     * allocate memory to store the enumerated queue information
  454.     */
  455.    pQueueInfo = malloc( cbNeeded ) ;
  456.     pmassert( pmp->hab, pQueueInfo );
  457.  
  458.     /* Call again to get print queue data. */
  459.    ul = SplEnumQueue( NULL,             /* pszComputerName - local machine */
  460.                       3,                /* information level 3 requested   */
  461.                       pQueueInfo,       /* pBuf - gets enumerated queues   */
  462.                       cbNeeded,         /* cbBuf - size of pBuf            */
  463.                       &cReturned,       /* number of queues returned       */
  464.                       &cTotal,          /* total number of queues          */
  465.                       &cbNeeded,        /* number bytes needed to store    */
  466.                                         /*   all requested information     */
  467.                       NULL );           /* reserved                        */
  468.  
  469.     pmassert( pmp->hab, ul == 0 );
  470.  
  471.     /*
  472.      * Validate that the user-preferred queue has been initialized OK.
  473.      * If not, initialize it now. User's preference of queues is
  474.      * named by the variable pmp->achQueueName.
  475.      */
  476.  
  477.     if( *pmp->achQueueName == 0 )
  478.     {
  479.        /*
  480.         * There is no preferred queue name because there was none
  481.         * in the INI file (perhaps this is the first time the
  482.         * program has run on this system?) or the profile reading
  483.         * failed somehow. Give the user the application default
  484.         * queue.
  485.         *
  486.         * get default queue's name
  487.         */
  488.        ul = PrfQueryProfileString( HINI_PROFILE,
  489.                                    "PM_SPOOLER",
  490.                                    "QUEUE",
  491.                                    NULL,
  492.                                    szWork,
  493.                                    LEN_WORKSTRING );
  494.  
  495.        if( ul )
  496.        {
  497.           /* truncate queuename at terminating semicolon */
  498.           pch = strchr( szWork, ';' );
  499.           pmassert( pmp->hab, pch );
  500.           *pch = 0;
  501.           strcpy( pmp->achQueueName, szWork );
  502.        }
  503.        else
  504.        {  /*
  505.            * no application default queue? odd. Give him the first queue
  506.            * from the SplEnumQueue calls
  507.            */
  508.           pmassert( pmp->hab, *pQueueInfo->pszName );
  509.           strcpy( pmp->achQueueName, pQueueInfo->pszName );
  510.        }
  511.     }
  512.  
  513.     pmassert( pmp->hab, 0 < strlen( pmp->achQueueName ));
  514.  
  515.     /*
  516.      * store current driver data info into SplEnumQueue info
  517.      * so that when user wants to change a print property
  518.      * but not necessarily a printer, his previous settings
  519.      * will be shown in the print properties dialog
  520.      */
  521.     i = FindQueue( pmp->achQueueName, pQueueInfo, cReturned );
  522.     pmassert( pmp->hab, i != -1 );
  523.     pqi = &pQueueInfo[i];
  524.     if( pqi->pDriverData->cb == pmp->cbDriverDataLen )
  525.     {
  526.       memcpy( pqi->pDriverData, pmp->pDriverData, pmp->cbDriverDataLen );
  527.     }
  528.  
  529.  
  530.     /*
  531.      * Display dialog box to select a printer
  532.      */
  533.  
  534.  
  535.     if (fShowDialog)
  536.     {
  537.         /* sort the data returned from SplEnumQueue by queue name  */
  538.         qsort((void *)pQueueInfo,
  539.           (size_t)cReturned,
  540.           (size_t)sizeof(PRQINFO3),
  541.           SortQueues);
  542.  
  543.         /*
  544.          * Dialog procedure requires the data from SplEnumQueue.
  545.          * Use the pmp to pass this data to the dialog.
  546.          */
  547.         pmp->pQueueInfo  = pQueueInfo;
  548.         pmp->lQueueCount = cReturned;
  549.  
  550.         /* present the dialog  */
  551.         ul = WinDlgBox( HWND_DESKTOP,
  552.                         pmp->hwndFrame,
  553.                         (PFNWP)QueryPrintDlgProc,
  554.                         (HMODULE)0,
  555.                         IDD_QUERYPRINT,
  556.                         (PVOID)pmp);
  557.  
  558.         pmassert( pmp->hab, ul != DID_ERROR );
  559.  
  560.         /* done with these vars for now  */
  561.         pmp->pQueueInfo  = NULL;
  562.         pmp->lQueueCount = 0;
  563.  
  564.  
  565.         if( ul == DID_CANCEL )
  566.         {
  567.              /* free queueinfo buffer for SplEnumQueue   */
  568.              free( pQueueInfo );
  569.              /* indicate to caller that no change occurred  */
  570.              return FALSE;
  571.         }
  572.     }
  573.  
  574.  
  575.  
  576.  
  577.     /*
  578.      * At this point, something changed about the printer destination:
  579.      * form, printer, queue, resolution, something.
  580.      *
  581.      * Prepare a printer info DC and associate a printer info PS with it
  582.      * for the print queue named by pmp->achQueueName.
  583.      */
  584.  
  585.  
  586.  
  587.     /* set pqi to point to the PRQINFO3 structure for pmp->achQueueName  */
  588.  
  589.     i = FindQueue( pmp->achQueueName, pQueueInfo, cReturned );
  590.     pmassert( pmp->hab, i  != -1 );
  591.     pqi = &pQueueInfo[i];
  592.  
  593.     /*
  594.      * destroy previous printer info PS's and DC's and
  595.      * allocations for their driver data
  596.      */
  597.     if( pmp->pDriverData )
  598.     {
  599.         free( pmp->pDriverData );
  600.         pmp->pDriverData      = NULL;
  601.         pmp->cbDriverDataLen  = 0;
  602.     }
  603.  
  604.     if( pmp->hpsPrinterInfo )
  605.     {
  606.         GpiAssociate(pmp->hpsPrinterInfo, (HDC)NULL);
  607.         GpiDestroyPS(pmp->hpsPrinterInfo);
  608.         pmp->hpsPrinterInfo = (HPS)0;
  609.     }
  610.  
  611.     if( pmp->hdcPrinterInfo )
  612.     {
  613.         DevCloseDC(pmp->hdcPrinterInfo);
  614.         pmp->hdcPrinterInfo = (HDC)0;
  615.     }
  616.  
  617.     /* store new driver name in pmp  */
  618.     strcpy( pmp->achDriverName, pqi->pszDriverName );
  619.  
  620.     /* store new driver data length in pmp  */
  621.     pmp->cbDriverDataLen  = pqi->pDriverData->cb;
  622.  
  623.     /* store new driver data in pmp  */
  624.     pmp->pDriverData = (PDRIVDATA) malloc( pmp->cbDriverDataLen );
  625.     pmassert( pmp->hab, pmp->pDriverData );
  626.     memcpy( pmp->pDriverData, pqi->pDriverData, pmp->cbDriverDataLen );
  627.  
  628.     /* store new queue description in pmp  */
  629.     strncpy(pmp->achQueueDesc, pqi->pszComment, QUEUEDESC_LENGTH);
  630.     pmp->achQueueDesc[QUEUEDESC_LENGTH-1] = 0;
  631.  
  632.     /* initialize local variables to zeros */
  633.     memset( &dos,   0, sizeof(dos));
  634.     memset( &sizel, 0, sizeof(sizel));
  635.  
  636.     /* build a devopenstruct for the call to DevOpenDC */
  637.     strcpy( achDriverName, pqi->pszDriverName );
  638.     achDriverName[strcspn(achDriverName, ".")] = '\0';
  639.     dos.pszLogAddress = pmp->achQueueName;
  640.     dos.pszDriverName = (PSZ)achDriverName;
  641.     dos.pdriv = pmp->pDriverData;
  642.  
  643.     /* Create an OD_INFO device context */
  644.     pmp->hdcPrinterInfo = DevOpenDC(
  645.                             pmp->hab,
  646.                             OD_INFO,
  647.                             "*",
  648.                             3L,
  649.                             (PVOID)&dos,
  650.                             (HDC)NULL);
  651.     pmassert(pmp->hab, pmp->hdcPrinterInfo != DEV_ERROR);
  652.  
  653.  
  654.     /* create PS for printer info -- not a full-blown PS */
  655.     pmp->hpsPrinterInfo = GpiCreatePS(
  656.                         pmp->hab,
  657.                         pmp->hdcPrinterInfo,
  658.                         (PSIZEL)&sizel,
  659.                         PU_TWIPS | GPIA_ASSOC);
  660.     pmassert(pmp->hab, pmp->hpsPrinterInfo != GPI_ERROR);
  661.  
  662.     /* Store the page size of the device (PU_TWIPS) */
  663.     ul = GpiQueryPS(pmp->hpsPrinterInfo, (PSIZEL)&pmp->sizelPage);
  664.     pmassert(pmp->hab, ul != GPI_ERROR);
  665.  
  666.  
  667.     /* free the buffer allocated for SplEnumQueue call  */
  668.     free( pQueueInfo );
  669.  
  670.     /* return indication that something changed  */
  671.     return TRUE;
  672. }   /*  end of QueryPrintQueue */
  673.  
  674. /*************************************************************************
  675.  *  Function   :  QueryPrintDlgProc
  676.  *
  677.  *  Description:  This function is the dialog window procedure for printer
  678.  *                selection.
  679.  *                This dialog presents to the user a list of printer
  680.  *                destinations, or queues.  Typically, the user would
  681.  *                hilight a queue, then press the Job Properties... button
  682.  *                to set items like orientation, form, resolution, etc.
  683.  *                The printer driver presents the job properties dialog
  684.  *                when the application calls DevPostDeviceModes.
  685.  *
  686.  *                Today, there is no standard, uniform way to tell whether
  687.  *                the user pressed OK or Cancel at the Job Properties dialog;
  688.  *                therefore, the dialog processing assumes that
  689.  *                job properties were changed no matter if the
  690.  *                user pressed OK or cancel. See the use of the
  691.  *                fVisitedJobProperties Boolean variable.
  692.  *
  693.  *                This function is associated with the dialog box that is
  694.  *                included in the function name of the procedure. It
  695.  *                provides the service routines for the events (messages)
  696.  *                that occur because the end user operates one of the dialog
  697.  *                box's buttons, entry fields, or controls.
  698.  *
  699.  *                The SWITCH statement in the function distributes the dialog
  700.  *                box messages to the respective service routines, which are
  701.  *                set apart by the CASE clauses. Like any other PM window,
  702.  *                the Dialog Window procedures must provide an appropriate
  703.  *                service routine for their end user initiated messages as
  704.  *                well as for the general PM messages (like the WM_CLOSE
  705.  *                message). If a message is sent to this procedure for which
  706.  *                there is no programmed CASE condition (no service routine),
  707.  *                the message is defaulted to the WinDefDlgProc function,
  708.  *                where it is disposed of by PM.
  709.  *
  710.  *  Parameters :  HWND         window handle of printer selection dialog
  711.  *                USHORT       message
  712.  *                MPARAM       message parameter 1
  713.  *                MPARAM       message parameter 2
  714.  *
  715.  *  API's      :  WinSetWindowULong
  716.  *                WinSendDlgItemMsg
  717.  *                WinEnableControl
  718.  *                WinSendDlgItemMsg
  719.  *                WinQueryWindowULong
  720.  *                WinDismissDlg
  721.  *                WinDefDlgProc
  722.  *
  723.  * Return      :  message result
  724.  *
  725.  *************************************************************************/
  726. MRESULT EXPENTRY QueryPrintDlgProc( HWND hwnd,
  727.                                     USHORT msg,
  728.                                     MPARAM mp1,
  729.                                     MPARAM mp2 )
  730. {
  731.    static BOOL         fVisitedJobProperties;
  732.    PMAIN_PARM          pmp;
  733.    INT                 i, index;
  734.    PSZ                 psz;
  735.    HWND                hwndListbox;
  736.    ULONG               ulPanel;
  737.  
  738.    switch (msg)
  739.    {
  740.    case WM_INITDLG:
  741.       /* Get pointer to application specific data */
  742.       pmp = (PMAIN_PARM) mp2;
  743.       WinSetWindowULong( hwnd, QWL_USER, (ULONG) mp2 );
  744.  
  745.  
  746.       /*
  747.        *  Assume user will not select job properties.
  748.        *  This affects how to dismiss this dialog.
  749.        */
  750.       fVisitedJobProperties = FALSE;
  751.  
  752.       /* Fill listbox with print objects */
  753.  
  754.         hwndListbox = WinWindowFromID( hwnd, IDD_QPLISTBOX );
  755.         pmassert( pmp->hab, hwndListbox );
  756.  
  757.       for (i = 0; i < pmp->lQueueCount; ++i)
  758.       {
  759.        /* use printer comment if possible, else use queue name for display */
  760.          psz = *pmp->pQueueInfo[i].pszComment ?
  761.                 pmp->pQueueInfo[i].pszComment :
  762.                 pmp->pQueueInfo[i].pszName;
  763.             /* pmwin.h macro for inserting list box items   */
  764.             index = WinInsertLboxItem( hwndListbox, LIT_END, psz );
  765.  
  766.             /* pre-select this one?  */
  767.             if( 0 == strcmp( pmp->pQueueInfo[i].pszName, pmp->achQueueName ))
  768.             {
  769.                WinSendMsg( hwndListbox, LM_SELECTITEM,
  770.                                             (MPARAM)index, (MPARAM)TRUE );
  771.             }
  772.       }
  773.  
  774.         /* one must be selected */
  775.         index = WinQueryLboxSelectedItem( hwndListbox );
  776.         pmassert( pmp->hab, index != LIT_NONE );
  777.  
  778.       return FALSE;
  779.  
  780.    case WM_HELP:
  781.       /* get pointer to structure from window words of this dialog */
  782.       pmp = (PMAIN_PARM)WinQueryWindowULong( hwnd, QWL_USER );
  783.  
  784.       if( pmp->hwndHelp )
  785.       {
  786.          ulPanel = PANEL_QUERYPRINT;
  787.          WinSendMsg( pmp->hwndHelp, HM_DISPLAY_HELP,
  788.                    (MPARAM)&ulPanel, (MPARAM)HM_RESOURCEID );
  789.          return (MRESULT)NULL;
  790.       }
  791.       break;
  792.  
  793.  
  794.    case WM_COMMAND:
  795.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  796.       switch(SHORT1FROMMP(mp1))
  797.       {
  798.       case IDD_QPJOBPROP:
  799.           /*
  800.            * Flag that we visited the job properties dialog. Since
  801.            * DevPostDeviceModes (OS2_PM_DRV_DEVMODES) option
  802.            * DPDM_POSTJOBPROP has no return code or standard way to
  803.            * indicate user cancel, we have to assume something might
  804.            * have changed.
  805.            */
  806.           fVisitedJobProperties = TRUE;
  807.           hwndListbox = WinWindowFromID( hwnd, IDD_QPLISTBOX );
  808.           pmassert( pmp->hab, hwndListbox );
  809.           index = WinQueryLboxSelectedItem( hwndListbox );
  810.           pmassert( pmp->hab, index != LIT_NONE );
  811.           QueryJobProperties( pmp->hab, &pmp->pQueueInfo[ index ] );
  812.           return 0;
  813.  
  814.       case DID_OK:
  815.             hwndListbox = WinWindowFromID( hwnd, IDD_QPLISTBOX );
  816.             pmassert( pmp->hab, hwndListbox );
  817.             index = WinQueryLboxSelectedItem( hwndListbox );
  818.             pmassert( pmp->hab, index != LIT_NONE );
  819.  
  820.          /* modify pmp->achQueueName; it is now the user's preferred queue */
  821.             strcpy( pmp->achQueueName,  pmp->pQueueInfo[ index ].pszName );
  822.             WinDismissDlg( hwnd, DID_OK );
  823.             return 0;
  824.  
  825.  
  826.       case DID_CANCEL:
  827.          WinDismissDlg(hwnd, fVisitedJobProperties ? DID_OK : DID_CANCEL );
  828.          return (MRESULT)NULL;
  829.       }
  830.       break;
  831.  
  832.    }
  833.    return( WinDefDlgProc(hwnd, msg, mp1, mp2) );
  834. } /* End of QueryPrintDlgProc */
  835.  
  836.  
  837. /*************************************************************************
  838.  *  Function   :  QueryJobProperties
  839.  *
  840.  *  Description:  Query job properties (print properties) of the printer
  841.  *                driver.
  842.  *
  843.  *  Parameters :  HAB             anchor block handle of the process
  844.  *                PPRQINFO3       pointer to queue information structure
  845.  *
  846.  *  API's      :  DevPostDeviceModes
  847.  *
  848.  *  Return     :  TRUE if ok, otherwise FALSE
  849.  *
  850.  *************************************************************************/
  851. BOOL QueryJobProperties(HAB hab, PPRQINFO3 pQueueInfo)
  852. {
  853.    CHAR        achDriverName[DRIVERNAME_LENGTH];
  854.    CHAR        achDeviceName[DEVICENAME_LENGTH];
  855.    INT         i;
  856.    LONG        l;
  857.    PSZ         pszTemp;
  858.  
  859.    /*
  860.     * The pszDriverName is of the form DRIVER.DEVICE (e.g.,
  861.     * LASERJET.HP LaserJet IID) so we need to separate it
  862.     * at the dot
  863.     */
  864.    i = strcspn(pQueueInfo->pszDriverName, ".");
  865.    if (i)
  866.    {
  867.       strncpy(achDriverName, pQueueInfo->pszDriverName, i);
  868.       achDriverName[i] = '\0';
  869.       strcpy(achDeviceName, &pQueueInfo->pszDriverName[i + 1]);
  870.    }
  871.    else
  872.    {
  873.       strcpy(achDriverName, pQueueInfo->pszDriverName);
  874.       *achDeviceName = '\0';
  875.    }
  876.  
  877.    /*
  878.     * There may be more than one printer assigned to this print queue
  879.     * We will use the first in the comma separated list.  We would
  880.     * need an expanded dialog for the user to be more specific.
  881.     */
  882.    pszTemp = strchr(pQueueInfo->pszPrinters, ',');
  883.    if ( pszTemp )
  884.    {
  885.       /* Strip off comma and trailing printer names */
  886.       *pszTemp = '\0' ;
  887.    }
  888.  
  889.    /*
  890.     * Post the job properties dialog for the printer to allow the
  891.     * user to modify the options
  892.     */
  893.    l = DevPostDeviceModes( hab,
  894.                            pQueueInfo->pDriverData,
  895.                            achDriverName,
  896.                            achDeviceName,
  897.                            pQueueInfo->pszPrinters,
  898.                            DPDM_POSTJOBPROP );
  899.  
  900.    return l == DEV_OK;
  901. }  /* End of QueryJobProperties */
  902.  
  903. /*************************************************************************
  904.  *
  905.  *  Name:         ProcessUserPrint
  906.  *
  907.  *  Description:  This routine handles the user print (WM_USER_PRINT)
  908.  *                message. We're running thread 2 here because it can be
  909.  *                a long operation. The device context and presentation
  910.  *                space are created here, then one of three functions
  911.  *                is called to print depending on whether we have a
  912.  *                bitmap, metafile or text document.
  913.  *
  914.  *  Parameters :  HWND           window handle
  915.  *                PMAIN_PARM     global application data
  916.  *
  917.  *  API's      :  DevOpenDC
  918.  *                GpiCreatePS
  919.  *                DevEscape
  920.  *                GpiAssociate
  921.  *                GpiDestroyPS
  922.  *                DevCloseDC
  923.  *
  924.  *  Return     :  VOID
  925.  *
  926.  *
  927.  *************************************************************************/
  928.  
  929. VOID ProcessUserPrint( HWND hwnd, PMAIN_PARM pmp)
  930. {
  931.    DEVOPENSTRUC    dos;
  932.    USHORT          us;
  933.    VOID            (*pfnPrintDocument)(HWND, PMAIN_PARM);
  934.    CHAR            achDriverName[DRIVERNAME_LENGTH];
  935.    CHAR            achQueueProcParams[8];
  936.    BOOL            fResult;
  937.  
  938.    /* Build the device context data for DevOpenDC */
  939.    memset((PVOID)&dos, 0, sizeof(dos));
  940.  
  941.    strcpy(achDriverName, pmp->achDriverName);
  942.    achDriverName[strcspn(achDriverName, ".")] = '\0';
  943.    sprintf(achQueueProcParams, "COP=%d", pmp->usCopies);
  944.  
  945.    dos.pszLogAddress = pmp->achQueueName;
  946.    dos.pszDriverName = (PSZ)achDriverName;
  947.    dos.pdriv = pmp->pDriverData;
  948.    dos.pszDataType = (PSZ)"PM_Q_STD";
  949.    dos.pszComment = pmp->pszTitle;
  950.    dos.pszQueueProcParams = (PSZ)achQueueProcParams;
  951.  
  952.    /*
  953.     * Switch on whether we are writing text, a bitmap
  954.     * or a metafile into the PS, and process
  955.     */
  956.    switch (pmp->ulMode)
  957.    {
  958.    case MODE_TEXT:
  959.         /* Seek to beginning of user-specified file */
  960.       fseek(pmp->f, 0, SEEK_SET);
  961.       pfnPrintDocument = PrinterPaginate;
  962.       break;
  963.  
  964.    case MODE_BITMAP:
  965.       pfnPrintDocument = PrinterBitblt;
  966.  
  967.       /*
  968.        * Don't create PM_Q_STD bitmaps because of color conversion
  969.        * problems if printing color bitmaps on a monochrome device.
  970.        */
  971.       dos.pszDataType = (PSZ)"PM_Q_RAW";
  972.       break;
  973.  
  974.    case MODE_METAFILE:
  975.       pfnPrintDocument = PrinterPlayMetaFile;
  976.       break;
  977.  
  978.    default:
  979.       pmassert(pmp->hab, FALSE);
  980.       return;
  981.    }
  982.  
  983.    /* Create DC for the printer */
  984.    pmp->hdcPrinter = DevOpenDC( pmp->hab,
  985.                                 OD_QUEUED,
  986.                                 "*",
  987.                                 9L,
  988.                                 (PVOID)&dos,
  989.                                 (HDC)NULLHANDLE );
  990.  
  991.    /* Create PS for the printer */
  992.    pmp->hpsPrinter = GPI_ERROR;
  993.    if (pmp->hdcPrinter != DEV_ERROR)
  994.    {
  995.       pmp->hpsPrinter = GpiCreatePS( pmp->hab,
  996.                                      pmp->hdcPrinter,
  997.                                      (PSIZEL)&pmp->sizelPage,
  998.                                      PU_TWIPS | GPIA_NOASSOC );
  999.       pmassert( pmp->hab, pmp->hpsPrinter != GPI_ERROR );
  1000.  
  1001.       if (pmp->hpsPrinter != GPI_ERROR)
  1002.       {
  1003.          /*
  1004.           * Didn't use GPI_ASSOC to create the PS so that in the case
  1005.           * of a metafile, we can first play the metafile to reset the
  1006.           * PS before it is associated to the DC.
  1007.           */
  1008.          if (pmp->ulMode == MODE_METAFILE)
  1009.          {
  1010.             PrinterResetMetaFile(hwnd, pmp);
  1011.          }
  1012.  
  1013.          /* Now associate the presentation space */
  1014.          fResult = GpiAssociate(pmp->hpsPrinter, pmp->hdcPrinter);
  1015.          pmassert(pmp->hab, fResult);
  1016.  
  1017.          /* Issue STARTDOC to begin printing */
  1018.          DevEscape( pmp->hdcPrinter,
  1019.                     DEVESC_STARTDOC,
  1020.                     (LONG)strlen(pmp->szFilename),
  1021.                     (PBYTE)pmp->szFilename,
  1022.                     (PLONG)NULL, (PBYTE)NULL );
  1023.  
  1024.          /* Print the document */
  1025.          (*pfnPrintDocument)(hwnd, pmp);
  1026.  
  1027.          /*
  1028.           * Issue ABORTDOC if user cancelled print job, or ENDDOC
  1029.           * to for normal job termination.
  1030.           */
  1031.          DevEscape( pmp->hdcPrinter,
  1032.                     pmp->fCancel ? DEVESC_ABORTDOC : DEVESC_ENDDOC,
  1033.                     0L, (PBYTE)NULL, (PLONG)NULL, (PBYTE)NULL );
  1034.  
  1035.          /* Release and destroy the PS */
  1036.          GpiAssociate( pmp->hpsPrinter, (HDC)NULLHANDLE );
  1037.          GpiDestroyPS( pmp->hpsPrinter );
  1038.       }
  1039.    }
  1040.  
  1041.    /* Clean up the DC */
  1042.    if (pmp->hdcPrinter != DEV_ERROR)
  1043.    {
  1044.       DevCloseDC(pmp->hdcPrinter);
  1045.       pmp->hdcPrinter = DEV_ERROR;
  1046.    }
  1047.  
  1048.    return;
  1049. }
  1050.  
  1051. /*************************************************************************
  1052.  *
  1053.  *  Name       :  PrinterBitblt
  1054.  *
  1055.  *  Description:  Load a bitmap into a memory DC using the WM_USER_LOAD_BITMAP
  1056.  *                processing. Calculate what size to print the bitmap in order
  1057.  *                to preserve the bitmap aspect ratio and still have it fit on
  1058.  *                the page. Then bit blit into the printer PS, allowing the
  1059.  *                device presentation driver to do the stretch blit.
  1060.  *
  1061.  *  Parameters :  HWND           window handle
  1062.  *                PMAIN_PARM     global application data
  1063.  *
  1064.  *  API's      :  WinSendMsg
  1065.  *                GpiQueryPS
  1066.  *                GpiConvert
  1067.  *                GpiBitblt
  1068.  *                GpiSetBitmap
  1069.  *                GpiDeleteBitmap
  1070.  *                GpiAssociate
  1071.  *                GpiDestroyPS
  1072.  *                DevCloseDC
  1073.  *
  1074.  *  Return     :  VOID
  1075.  *
  1076.  *************************************************************************/
  1077.  
  1078. VOID PrinterBitblt(HWND hwnd, PMAIN_PARM pmp)
  1079. {
  1080.     BITMAPINFOHEADER bmi;
  1081.     POINTL  aptl[4];
  1082.     LONG    lResult;
  1083.     double  xRatio, yRatio;
  1084.  
  1085.     /* Clear our variables to ensure USER_LOAD_BITMAP starts fresh */
  1086.     pmp->hdcMem4Printer = (HDC)NULLHANDLE;
  1087.     pmp->hpsMem4Printer = (HPS)NULLHANDLE;
  1088.     pmp->hbm4Printer = (HBITMAP)NULLHANDLE;
  1089.  
  1090.     /* Send message to create a printer PS with our bitmap set into it */
  1091.     WinSendMsg(hwnd, WM_USER_LOAD_BITMAP, (MPARAM)hwnd,
  1092.                (MPARAM)HDCMEM_COMPATIBILITY_PRINTER);
  1093.  
  1094.     /* Set up source and target blt rectangles */
  1095.     aptl[0].x = aptl[0].y = 0L;
  1096.     aptl[2].x = aptl[2].y = 0L;
  1097.  
  1098.     aptl[3].x = pmp->cxBitmap;
  1099.     aptl[3].y = pmp->cyBitmap;
  1100.  
  1101.     if (pmp->cxBitmapRes && pmp->cyBitmapRes)
  1102.     {
  1103.         /*
  1104.          * Since the intended resolution for the bitmap is known,
  1105.          * the actual size of the bitmap can be calculated, in
  1106.          * twips (1440 twips/inch).
  1107.          */
  1108.         aptl[1].x = ((double)pmp->cxBitmap)/((double)pmp->cxBitmapRes)
  1109.                     * 1440.0;
  1110.         aptl[1].y = ((double)pmp->cyBitmap)/((double)pmp->cyBitmapRes)
  1111.                     * 1440.0;
  1112.     }
  1113.     else
  1114.     {
  1115.        /*
  1116.         * Assume the bitmap aspect ratio is 1.0 and fit this to
  1117.         * the size of the presentation space
  1118.         */
  1119.        GpiQueryPS(pmp->hpsPrinter, (PSIZEL)&aptl[1]);
  1120.        xRatio = ((double)aptl[1].x) / ((double)aptl[3].x);
  1121.        yRatio = ((double)aptl[1].y) / ((double)aptl[3].y);
  1122.        if (yRatio > xRatio)
  1123.           aptl[1].y = xRatio * (double)aptl[3].y;
  1124.        else
  1125.           aptl[1].x = yRatio * (double)aptl[3].x;
  1126.     }
  1127.  
  1128.     /* Convert twips to device pels */
  1129.     GpiConvert( pmp->hpsPrinter, CVTC_WORLD, CVTC_DEVICE, 1L,
  1130.                 (PPOINTL)&aptl[1] );
  1131.  
  1132.     /* Translate the position of the bitmap on the page here */
  1133.  
  1134.     /* Bitblt the source bitmap onto the printer presentation space */
  1135.     lResult = GpiBitblt( pmp->hpsPrinter,
  1136.                          pmp->hpsMem4Printer,
  1137.                          4L,
  1138.                          (PPOINTL)aptl,
  1139.                          ROP_SRCCOPY,
  1140.                          BBO_IGNORE );
  1141.     pmassert( pmp->hab, lResult == GPI_OK );
  1142.  
  1143.     /* Clean up bitmap, memory PS and memory DC */
  1144.     GpiSetBitmap( pmp->hpsMem4Printer, (HBITMAP)NULLHANDLE );
  1145.     GpiDeleteBitmap( pmp->hbm4Printer );
  1146.     GpiAssociate( pmp->hpsMem4Printer, (HDC)NULLHANDLE );
  1147.     GpiDestroyPS( pmp->hpsMem4Printer );
  1148.     DevCloseDC( pmp->hdcMem4Printer );
  1149.  
  1150.     return;
  1151. }  /* End of PrinterBitblt */
  1152.  
  1153. /*************************************************************************
  1154.  *
  1155.  *  Name:      :  PrinterPaginate
  1156.  *
  1157.  *  Description:  This function uses WM_USER_PAGINATE processing to
  1158.  *                print text to printer There is a check of the fCancel
  1159.  *                Boolean in the main parameters after paginating each
  1160.  *                page. If this Boolean becomes true, then printing the
  1161.  *                text is aborted.
  1162.  *
  1163.  *  API's      :  GpiCreateLogFont
  1164.  *                GpiSetCharSet
  1165.  *                WinSendMsg
  1166.  *                DevEscape
  1167.  *                GpiSetCharSet
  1168.  *                GpiDeleteSetID
  1169.  *
  1170.  *  Return     :  VOID
  1171.  *
  1172.  *************************************************************************/
  1173. VOID PrinterPaginate(HWND hwnd, PMAIN_PARM pmp)
  1174. {
  1175.    ULONG   ul;
  1176.    BOOL    fResult;
  1177.  
  1178.    /*
  1179.     * Create a logical font for the printer and set it
  1180.     * into the PS
  1181.     */
  1182.    ul = (ULONG)GpiCreateLogFont( pmp->hpsPrinter,
  1183.                                  (PSTR8)NULL,
  1184.                                  1L,
  1185.                                  (PFATTRS)&pmp->fontdlg.fAttrs );
  1186.    pmassert(pmp->hab, ul == FONT_MATCH);
  1187.  
  1188.    fResult = GpiSetCharSet( pmp->hpsPrinter, 1L );
  1189.    pmassert( pmp->hab, fResult );
  1190.  
  1191.    do
  1192.    {
  1193.       ul = (ULONG)WinSendMsg( hwnd,
  1194.                               WM_USER_PAGINATE,
  1195.                               (MPARAM)hwnd,
  1196.                               (MPARAM)FLAGS_PAGINATE_PRINTER );
  1197.       if ( ul == PAGINATE_NOT_EOF )
  1198.       {
  1199.          DevEscape( pmp->hdcPrinter,
  1200.                     DEVESC_NEWFRAME,
  1201.                     0L,
  1202.                     (PBYTE)NULL,
  1203.                     (PLONG)NULL,
  1204.                     (PBYTE)NULL );
  1205.       }
  1206.       else
  1207.       {
  1208.            /* End of file; Break out of this loop and return to do enddoc */
  1209.           break;
  1210.       }
  1211.     } while (  !pmp->fCancel );
  1212.  
  1213.    /* Clean up logical font id */
  1214.    GpiSetCharSet(pmp->hpsPrinter, 0L);
  1215.    GpiDeleteSetID(pmp->hpsPrinter, 1L);
  1216.  
  1217.    return;
  1218. }  /* End of PrinterPaginate */
  1219.  
  1220. /*************************************************************************
  1221.  *
  1222.  *  Name       :  PrinterPlayMetafile
  1223.  *
  1224.  *  Description:  Play metafile into printer PS without the reset and
  1225.  *                suppress options.
  1226.  *
  1227.  *  Parameters :  HWND           window handle
  1228.  *                PMAIN_PARM     global application data
  1229.  *
  1230.  *  API's      :  GpiPlayMetaFile
  1231.  *
  1232.  *  Return     :  VOID
  1233.  *
  1234.  *  reference  :  Graham C.E. Winn, "OS/2 PM GPI", VNR Computer Library
  1235.  *
  1236.  *************************************************************************/
  1237. VOID PrinterPlayMetaFile(HWND hwnd, PMAIN_PARM pmp)
  1238. {
  1239.    LONG    alOptions[ LEN_PLAYMETAFILEOPTS ];
  1240.    BYTE    abDesc[ LEN_PLAYMETAFILEDESCS ];
  1241.    LONG    lSegments;
  1242.    BOOL    fResult;
  1243.  
  1244.    lSegments = 0;
  1245.  
  1246.    memset(alOptions, 0, sizeof(alOptions));
  1247.    alOptions[ PMF_SEGBASE         ] = 0L;
  1248.    alOptions[ PMF_LOADTYPE        ] = LT_NOMODIFY;
  1249.    alOptions[ PMF_RESOLVE         ] = RS_DEFAULT;
  1250.    alOptions[ PMF_LCIDS           ] = LC_LOADDISC;
  1251.    alOptions[ PMF_RESET           ] = RES_NORESET;
  1252.    alOptions[ PMF_SUPPRESS        ] = SUP_NOSUPPRESS;
  1253.    alOptions[ PMF_COLORTABLES     ] = CTAB_REPLACE;
  1254.    alOptions[ PMF_COLORREALIZABLE ] = CREA_NOREALIZE;
  1255.    alOptions[ PMF_DEFAULTS        ] = DDEF_LOADDISC;
  1256.  
  1257.    fResult = (BOOL)GpiPlayMetaFile( pmp->hpsPrinter,
  1258.                                     pmp->hmf,
  1259.                                     LEN_PLAYMETAFILEOPTS,
  1260.                                     alOptions,
  1261.                                     (PLONG)&lSegments,
  1262.                                     LEN_PLAYMETAFILEDESCS,
  1263.                                     (PSZ)abDesc );
  1264.    pmassert( pmp->hab, fResult );
  1265.  
  1266.    return;
  1267. }  /* End of PrinterPlayMetafile */
  1268.  
  1269. /*************************************************************************
  1270.  *
  1271.  *  Function   :  PrinterResetMetafile
  1272.  *
  1273.  *  Description:  Reset the printer PS with page units, size and default viewing
  1274.  *                transform specified in the metafile.  Note that the PS must
  1275.  *                not be associated with the DC if this is an PM_Q_STD print job.
  1276.  *
  1277.  *  Parameters :  HWND           window handle
  1278.  *                PMAIN_PARM     global application data
  1279.  *
  1280.  *  API's      :  GpiPlayMetaFile
  1281.  *
  1282.  *  Return     :  VOID
  1283.  *
  1284.  *  reference  :  Graham C.E. Winn, "OS/2 PM GPI", VNR Computer Library
  1285.  *
  1286.  *************************************************************************/
  1287. VOID PrinterResetMetaFile(HWND hwnd, PMAIN_PARM pmp)
  1288. {
  1289.    LONG        alOptions[ LEN_PLAYMETAFILEOPTS ];
  1290.    BYTE        abDesc[ LEN_PLAYMETAFILEDESCS ];
  1291.    LONG        lSegments;
  1292.    BOOL        fResult;
  1293.  
  1294.    lSegments = 0L;
  1295.  
  1296.    memset(alOptions, 0, sizeof(alOptions));
  1297.    alOptions[ PMF_SEGBASE         ] = 0L;
  1298.    alOptions[ PMF_LOADTYPE        ] = LT_NOMODIFY;
  1299.    alOptions[ PMF_RESOLVE         ] = RS_DEFAULT;
  1300.    alOptions[ PMF_LCIDS           ] = LC_LOADDISC;
  1301.    alOptions[ PMF_RESET           ] = RES_RESET;
  1302.    alOptions[ PMF_SUPPRESS        ] = SUP_SUPPRESS;
  1303.    alOptions[ PMF_COLORTABLES     ] = CTAB_DEFAULT;
  1304.    alOptions[ PMF_COLORREALIZABLE ] = CREA_DEFAULT;
  1305.    alOptions[ PMF_DEFAULTS        ] = DDEF_DEFAULT;
  1306.  
  1307.    fResult = (BOOL)GpiPlayMetaFile( pmp->hpsPrinter,
  1308.                                     pmp->hmf,
  1309.                                     LEN_PLAYMETAFILEOPTS,
  1310.                                     alOptions,
  1311.                                     (PLONG)&lSegments,
  1312.                                     LEN_PLAYMETAFILEDESCS,
  1313.                                     (PSZ)abDesc );
  1314.    pmassert( pmp->hab, fResult );
  1315.  
  1316.    return;
  1317. }  /* End of PrinterResetMetaFile */
  1318.  
  1319. /*************************************************************************
  1320.  *
  1321.  *   Function   :  FindQueue
  1322.  *
  1323.  *   Description:  Finds the queue name in the PRQINFO3 structure.
  1324.  *
  1325.  *   Parameters :  PSZ          pointer to the name of the queue
  1326.  *                 PPRQINFO3    pointer to queue selection structure 1
  1327.  *                 SHORT        number of queue names to compare
  1328.  *
  1329.  *   API's      :  [none]
  1330.  *
  1331.  *************************************************************************/
  1332. LONG FindQueue(PSZ pszQueueName, PPRQINFO3 pQueueInfo, LONG lCount)
  1333. {
  1334.    LONG i;
  1335.  
  1336.    for (i = 0L; i < lCount; ++i)
  1337.    {
  1338.       if ( !strcmp( pszQueueName, pQueueInfo[i].pszName ) )
  1339.          return i;
  1340.    }
  1341.  
  1342.    return -1L;                 /*  if not found  */
  1343. }  /* End of FindQueue */
  1344.  
  1345. /*************************************************************************
  1346.  *  Function   :  SortQueues
  1347.  *
  1348.  *  Description:  Compare routine for sorting the queue names table.
  1349.  *
  1350.  *  Parameters :  PPRQINFO3    pointer to queue selection structure 1
  1351.  *                PPRQINFO3    pointer to queue selection structure 2
  1352.  *
  1353.  *  API's      :  [none]
  1354.  *
  1355.  *  Return     :  result of comparison
  1356.  *
  1357.  *************************************************************************/
  1358. static int _Optlink SortQueues(const void *pQueue1, const void *pQueue2)
  1359. {
  1360. return(strcmp(((PPRQINFO3)pQueue1)->pszComment,
  1361.               ((PPRQINFO3)pQueue2)->pszComment));
  1362. } /* end of SortQueues() */
  1363. /***************************  End of prtprint.c ****************************/
  1364.