home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional Developers Kit 1992 November / Disc01 / Disc01.mdf / os2tk20 / c / samples / print / prtsamp.c__ / PRTSAMP.C
Encoding:
C/C++ Source or Header  |  1992-07-15  |  37.1 KB  |  1,007 lines

  1. /***************************************************************************
  2.  *
  3.  * File name   :  prtsamp.c
  4.  *
  5.  * Description :  This program demonstrates how to display and print ascii
  6.  *                text, meta files and bitmaps.  It also shows how to use
  7.  *                the standard file dialog and the standard font dialog,
  8.  *                how to display and change printer properties and how to
  9.  *                display and select printer queues.
  10.  *
  11.  *                This source file contains the following functions:
  12.  *
  13.  *                main()
  14.  *                WinProc(hwnd, msg, mp1, mp2)
  15.  *                CalibrateScrollBar(pmp)
  16.  *
  17.  * Required
  18.  *    files    :
  19.  *                PRTSAMP.C        - Source code
  20.  *                PRTCREAT.C       - Source code
  21.  *                PRTMENU.C        - Source code
  22.  *                PRTOBJ.C         - Source code
  23.  *                PRTPRINT.C       - Source code
  24.  *                PRTPROF.C        - Source code
  25.  *                PRTSAMP.H        - Application header file
  26.  *                PMASSERT.H       - Application header file
  27.  *                PRTSDLG.H        - Application header file
  28.  *                PRTSHLP.H        - Application header file
  29.  *                PRTSAMP.RC       - Resource file
  30.  *                PRTSAMP.DLG      - Dialog file
  31.  *                PRTSAMP.IPF      - Help file
  32.  *                PRTSAMP.MAK      - Make file for this program
  33.  *                PRTSAMP.BMP      - Bitmap file
  34.  *                PRTSAMP.TXT      - Text file
  35.  *                PRTSAMP.MET      - Meta file
  36.  *                PRTSAMP.ICO      - Print sample icon
  37.  *
  38.  *                OS2.H            - Presentation Manager include file
  39.  *                STDIO.H          - Standard input/output c include file
  40.  *                STDLIB.H         - Standard c include file
  41.  *                STRING.H         - String handling function declarations
  42.  *                CTYPE.H
  43.  *                STDDEF.H
  44.  *                PROCESS.H
  45.  *                MEMORY.H
  46.  *                SYS\TYPES.H
  47.  *                SYS\STAT.H
  48.  *
  49.  *  Concepts   :  listboxes, directory search
  50.  *
  51.  *  API's      :  GpiAssociate
  52.  *                GpiConvert
  53.  *                GpiDeleteBitmap
  54.  *                GpiDeleteMetafile
  55.  *                GpiDestroyPS
  56.  *                GpiDrawChain
  57.  *                GpiSetDefaultViewMatrix
  58.  *
  59.  *                WinAddSwitchEntry
  60.  *                WinAssociateHelpInstance
  61.  *                WinBeginPaint
  62.  *                WinCreateHelpInstance
  63.  *                WinCreateMsgQueue
  64.  *                WinCreateStdWindow
  65.  *                WinDestroyHelpInstance
  66.  *                WinDestroyMsgQueue
  67.  *                WinDestroyWindow
  68.  *                WinDispatchMsg
  69.  *                WinEndPaint
  70.  *                WinFillRect
  71.  *                WinGetMsg
  72.  *                WinInitialize
  73.  *                WinInvalidateRect
  74.  *                WinIsWindowEnabled
  75.  *                WinLoadString
  76.  *                WinMessageBox
  77.  *                WinPostMsg
  78.  *                WinQuerySysPointer
  79.  *                WinQueryWindowRect
  80.  *                WinQueryWindowULong
  81.  *                WinRegisterClass
  82.  *                WinRemoveSwitchEntry
  83.  *                WinSendMsg
  84.  *                WinSetPointer
  85.  *                WinSetWindowText
  86.  *                WinTerminate
  87.  *
  88.  * Required
  89.  *   libraries :  OS2386.LIB     - Presentation Manager/OS2 library
  90.  *                C library
  91.  *
  92.  * Required
  93.  *   programs  :  C Compiler
  94.  *                Linker
  95.  *                Resource Compiler
  96.  *
  97.  *  Copyright (C) 1991 IBM Corporation
  98.  *
  99.  *      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is
  100.  *      sample code created by IBM Corporation. This sample code is not
  101.  *      part of any standard or IBM product and is provided to you solely
  102.  *      for  the purpose of assisting you in the development of your
  103.  *      applications.  The code is provided "AS IS", without
  104.  *      warranty of any kind.  IBM shall not be liable for any damages
  105.  *      arising out of your use of the sample code, even if they have been
  106.  *      advised of the possibility of such damages.                                                    *
  107.  *
  108.  ******************************************************************************/
  109.  
  110. /* Include the required sections from the PM header files.  */
  111. #define INCL_DOSFILEMGR
  112. #define INCL_WINSTDFILE
  113. #define INCL_WINSTDFONT
  114. #define INCL_WINWINDOWMGR
  115. #define INCL_WINSCROLLBARS
  116. #define INCL_WINDIALOGS
  117. #define INCL_WINPOINTERS
  118. #define INCL_WININPUT
  119. #define INCL_WINMENUS
  120. #define INCL_WINHELP
  121. #define INCL_WINSYS
  122. #define INCL_WINFRAMEMGR
  123. #define INCL_GPITRANSFORMS
  124. #define INCL_SPL
  125. #define INCL_SPLDOSPRINT
  126. #include <os2.h>
  127.  
  128. /* c language includes */
  129. #include <stdio.h>
  130. #include <stdlib.h>
  131. #include <string.h>
  132. #include <ctype.h>
  133. #include <stddef.h>
  134. #include <process.h>
  135. #include <memory.h>
  136. #include <sys\types.h>
  137. #include <sys\stat.h>
  138.  
  139. /* application includes */
  140. #include "prtsamp.h"
  141. #include "prtsdlg.h"
  142. #include "prtshlp.h"
  143. #include "pmassert.h"
  144.  
  145. /**************************************************************************
  146.  *
  147.  *  Name       : main()
  148.  *
  149.  *  Description: Initializes the application, gets and dispatches messages
  150.  *               for the client window on thread 1 and terminates the
  151.  *               application when a WM_QUIT message is received.  It then
  152.  *               saves the configuration in os2.ini, destroys all OS/2
  153.  *               PM resources, and terminates.
  154.  *
  155.  *               The following routine is the Presentation Manager program
  156.  *               main body. The main body of a PM program is concerned with
  157.  *               associating the application with the Presentation Manager
  158.  *               system, creating its message queue, registering and displaying
  159.  *               its main window, servicing its message queue during the time
  160.  *               that the application is active, and disassociating the
  161.  *               application from PM when the user is finished with the
  162.  *               it. The remaining parts of this source module that are
  163.  *               concerned with the Presentation Manager are the application's
  164.  *               window procedures (main window procedure, child window
  165.  *               procedures, and dialog window procedures) that process the
  166.  *               messages associated with the application's various windows.
  167.  *
  168.  *  Concepts   : - obtains anchor block handle and creates message
  169.  *                   queue
  170.  *               - creates the main frame window which creates the
  171.  *                   main client window
  172.  *               - polls the message queue via Get/Dispatch Msg loop
  173.  *               - upon exiting the loop, exits
  174.  *
  175.  *  API's      :  WinInitialize
  176.  *                WinCreateMsgQueue
  177.  *                WinRegisterClass
  178.  *                WinLoadString
  179.  *                WinCreateHelpInstance
  180.  *                WinMessageBox
  181.  *                WinCreateStdWindow
  182.  *                WinQueryWindowULong
  183.  *                WinAssociateHelpInstance
  184.  *                WinAddSwitchEntry
  185.  *                WinGetMsg
  186.  *                WinDispatchMsg
  187.  *                WinRemoveSwitchEntry
  188.  *                WinDestroyHelpInstance
  189.  *                WinDestroyWindow
  190.  *                WinDestroyMsgQueue
  191.  *                WinTerminate
  192.  *
  193.  *  Parameters :  [none]
  194.  *
  195.  *  Return     :  Always returns zero.  The ANSI standard requires that
  196.  *                main be declared as an INT.
  197.  *
  198.  *************************************************************************/
  199. INT main(VOID)
  200. {
  201.                                         /* Define variables by type     */
  202.    BOOL       bOK;                      /* Boolean used for return code */
  203.    HAB        hab;                      /* PM anchor block handle       */
  204.    HMQ        hmq;                      /* Message queue handle         */
  205.    QMSG       qmsg;                     /* Message from message queue   */
  206.    ULONG      ulCtlData;                /* Standard window create flags */
  207.    HWND       hwndFrame;                /* Frame window handle          */
  208.    HWND       hwndClient;               /* Client area window handle    */
  209.    HWND       hwndHelp;                 /* Help window handle           */
  210.    PMAIN_PARM pmp;                      /* Main parameters structure    */
  211.    SWCNTRL    swctl;                    /* Struct to add to window list */
  212.    HSWITCH    hsw;                      /* Window list handle ret'd     */
  213.    HELPINIT   hmi;                      /* Struct for help creation     */
  214.    CHAR       szWork[ LEN_WORKSTRING ]; /* General use string work area */
  215.    PSZ        pszTitle;                 /* Pointer to program title     */
  216.  
  217.  
  218.    /* normal PM application startup */
  219.    hab = WinInitialize( 0 );
  220.    hmq = WinCreateMsgQueue( hab, 0 );
  221.  
  222.    /*
  223.     * Register a class for my client window's behavior.
  224.     * This class has enough extra window words to hold a pointer.
  225.     */
  226.    bOK = WinRegisterClass(
  227.                      hab,
  228.                      CLASSNAME,
  229.                      WinProc,
  230.                      CS_SIZEREDRAW,
  231.                      sizeof( PMAIN_PARM ));
  232.    /*
  233.     * Ensure WinRegisterClass worked ok; if not, present a message box.
  234.     * ( See pmassert.h. )
  235.     */
  236.    pmassert( hab, bOK );
  237.  
  238.  
  239.    /* Load program title and allocate a local copy. Use it in help creation. */
  240.    WinLoadString( hab, (HMODULE)NULLHANDLE,
  241.                   PROGRAM_TITLE, LEN_WORKSTRING, szWork );
  242.    pszTitle = strdup( szWork );
  243.  
  244.    /* Create help. */
  245.    memset( &hmi, 0, sizeof( hmi ));
  246.    hmi.cb                 = sizeof( HELPINIT );
  247.    hmi.phtHelpTable       = (PVOID)(0xffff0000 | ID_PRTSAMP);
  248.    hmi.pszHelpWindowTitle = pszTitle;
  249.    hmi.pszHelpLibraryName = HELP_FILE;
  250.    hwndHelp = WinCreateHelpInstance( hab, &hmi );
  251.    if( ! hwndHelp )
  252.    {
  253.       WinLoadString(hab, (HMODULE)NULLHANDLE,
  254.                     ERRMSG_NO_HELP, LEN_WORKSTRING, szWork);
  255.       WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, szWork, pszTitle, 0, MB_CANCEL);
  256.    }
  257.  
  258.    /* done with local copy of title text */
  259.    free( pszTitle );
  260.  
  261.  
  262.    /* flags to control creation of window; use on call to WinCreateStdWindow */
  263.    ulCtlData = FCF_SYSMENU | FCF_TITLEBAR | FCF_SIZEBORDER
  264.                            | FCF_MINMAX | FCF_MENU | FCF_ACCELTABLE
  265.                            | FCF_VERTSCROLL;
  266.  
  267.    hwndFrame = WinCreateStdWindow( HWND_DESKTOP,
  268.                                    WS_VISIBLE | FS_ICON | FS_SHELLPOSITION,
  269.                                    &ulCtlData,
  270.                                    CLASSNAME,
  271.                                    NULL,    /* title text set in prtcreat.c */
  272.                                    0,       /* client style                 */
  273.                                    (HMODULE)NULLHANDLE,  /* resources in exe */
  274.                                    ID_PRTSAMP,
  275.                                    &hwndClient  );
  276.  
  277.    pmassert( hab, hwndFrame );
  278.    pmassert( hab, hwndClient );
  279.  
  280.    /* create.c placed pointer to main params in client's window words; get it */
  281.    pmp = (PMAIN_PARM) WinQueryWindowULong( hwndClient, QWL_USER );
  282.    /* store help instance handle in main parameter block */
  283.    pmp->hwndHelp  = hwndHelp;
  284.  
  285.    bOK = WinAssociateHelpInstance( hwndHelp, hwndFrame );
  286.    pmassert( hab, bOK );
  287.  
  288.    /* Add program to task list. */
  289.    memset( &swctl, 0, sizeof( SWCNTRL ));
  290.    strcpy( swctl.szSwtitle, pmp->pszTitle );
  291.    swctl.hwnd          = hwndFrame;
  292.    swctl.uchVisibility = SWL_VISIBLE;
  293.    swctl.fbJump        = SWL_JUMPABLE;
  294.    hsw = WinAddSwitchEntry( &swctl );
  295.  
  296.    /* message loop */
  297.    while( WinGetMsg( hab, &qmsg, (HWND)NULLHANDLE, 0, 0 ))
  298.    {
  299.      WinDispatchMsg( hab, &qmsg );
  300.    }
  301.  
  302.    /* clean up */
  303.    WinRemoveSwitchEntry( hsw );
  304.    WinDestroyHelpInstance( hwndHelp );
  305.    WinDestroyWindow( hwndFrame );
  306.    WinDestroyMsgQueue( hmq );
  307.    WinTerminate( hab );
  308.  
  309.    DosExit( EXIT_PROCESS, 0 );
  310. }  /* End of main() */
  311.  
  312. /*************************************************************************
  313.  *
  314.  * Name       : WinProc(hwnd, msg, mp1, mp2)
  315.  *
  316.  * Description: Processes the messages sent to the main client
  317.  *              window.  This routine processes the basic
  318.  *              messages all client windows should process.
  319.  *
  320.  * Concepts   : This procedure provides service routines for the general
  321.  *              PM events (messages) that PM sends to the window, as well
  322.  *              as the user initiated events (messages) that are generated
  323.  *              when the user selects the action bar and pulldown menu
  324.  *              controls or the corresponding keyboard accelerators.
  325.  *
  326.  *              The switch statement shown below distributes the window
  327.  *              messages to the respective message service routines, which
  328.  *              are set apart by the case statements.  The window
  329.  *              procedures must provide an appropriate service routine for
  330.  *              its end user initiated messages, as well as the general PM
  331.  *              messages (like the WM_CLOSE message). If a message is sent
  332.  *              to this procedure for which there is no programmed case
  333.  *              clause (i.e., no service routine), the message is defaulted
  334.  *              function WinDefWindowProc, where it is disposed of by PM.
  335.  *
  336.  *              Time-consuming tasks are posted to the object window where
  337.  *              they can be performed without the 1/10 second turnaround
  338.  *              time imposed on the client window. When the object window
  339.  *              is busy, the client window is usually disabled. The object
  340.  *              window then posts an acknowledgement
  341.  *              back to the client when the lengthy task is completed.
  342.  *
  343.  *              Cases under the big switch appear in alphabetical order.
  344.  *
  345.  *  API's     :   WinLoadString
  346.  *                WinMessageBox
  347.  *                WinQueryWindowULong
  348.  *                WinSendMsg
  349.  *                WinPostMsg
  350.  *                WinIsWindowEnabled
  351.  *                WinSetPointer
  352.  *                WinQuerySysPointer
  353.  *                WinBeginPaint
  354.  *                WinQueryWindowRect
  355.  *                WinFillRect
  356.  *                WinEndPaint
  357.  *                WinInvalidateRect
  358.  *                WinSetWindowText
  359.  *                GpiDrawChain
  360.  *                GpiConvert
  361.  *                GpiSetDefaultViewMatrix
  362.  *                GpiAssociate
  363.  *                GpiDestroyPS
  364.  *                GpiDeleteBitmap
  365.  *                GpiDeleteMetafile
  366.  *
  367.  * Parameters : HWND         window handle
  368.  *              ULONG        message
  369.  *              MPARAM       message parameter 1
  370.  *              MPARAM       message parameter 2
  371.  *
  372.  * Result     : MRESULT      message result
  373.  *
  374.  *************************************************************************/
  375. MRESULT EXPENTRY WinProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  376. {
  377.    BOOL                bOK;
  378.    PMAIN_PARM          pmp;
  379.    HPS                 hps;
  380.    RECTL               rectl;
  381.    PCHAR               pch;
  382.    CHAR                szWork[ LEN_WORKSTRING ];
  383.    SHORT               cx, cy;
  384.    POINTL              pointl;
  385.    SHORT               sStep;
  386.    float               floatWork;
  387.    ULONG               ulWork;
  388.  
  389.    switch(msg)
  390.    {
  391.    case WM_CLOSE:
  392.       /* obtain the main parameter pointer from window words */
  393.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  394.  
  395.       if( pmp->fBusy )
  396.       {
  397.          /* OK to close when object window is busy?  */
  398.          WinLoadString( pmp->hab, (HMODULE)NULLHANDLE,
  399.                    ERRMSG_CLOSE_QUESTION, LEN_WORKSTRING, szWork );
  400.          ulWork = WinMessageBox( HWND_DESKTOP, pmp->hwndFrame,
  401.                       szWork, pmp->pszTitle, 0, MB_YESNOCANCEL );
  402.  
  403.          if( ulWork == MBID_YES )
  404.          {
  405.             /* close down the application in spite of being busy */
  406.             pmp->fCancel = TRUE;
  407.             /* disable client during exit */
  408.             WinSendMsg( hwnd, WM_USER_DISABLE_CLIENT, (MPARAM)0 , (MPARAM)0  );
  409.             /* start a watchdog timer to ensure a timely death */
  410.             WinStartTimer( pmp->hab, hwnd, ID_DEATH_TIMER, LEN_DEATH_TIMER );
  411.             /* Tell object window to close, quit, and post me a WM_QUIT */
  412.             WinPostMsg( pmp->hwndObject, WM_USER_CLOSE, (MPARAM)hwnd, (MPARAM)0 );
  413.          }
  414.       }
  415.       else
  416.       {
  417.          /* not busy, so initiate closure by telling object window to close */
  418.          WinPostMsg( pmp->hwndObject, WM_USER_CLOSE, (MPARAM)hwnd, (MPARAM)0 );
  419.       }
  420.       return (MRESULT)NULL;
  421.  
  422.  
  423.    case WM_COMMAND:
  424.       /* do menu activities; see menu.c */
  425.       return Menu( hwnd, msg, mp1, mp2 );
  426.  
  427.  
  428.    case WM_CREATE:
  429.       /*
  430.        * Do one-time, startup processing in PRTCREAT.C.
  431.        * This function allocates the pmp, a pointer to the program's
  432.        * main parameters. See the declaration of this block of
  433.        * parameters in PRTSAMP.H, the MAIN_PARM structure.
  434.        *
  435.        * The Create() function allocates this structure and
  436.        * begins to initialize it. Throughout all the code, the pmp->
  437.        * pointer is usually obtainable with a call to WinQueryWindowULong.
  438.        * Window word space for this pointer was reserved on the call
  439.        * to WinRegisterClass.
  440.        *
  441.        * Create() allocates, initializes, and stores the pmp pointer
  442.        * in the client window words. It then starts thread 2 of the
  443.        * application on which the object window operates. The pmp
  444.        * pointer is passed to thread 2 with _beginthread in PRTCREAT.C.
  445.        * The pmp is passed to the object window on the call to
  446.        * WinCreateWindow in PRTOBJ.C. Finally, the object window stores
  447.        * the pmp in its window words under the WM_CREATE case of the
  448.        * ObjectWinProc in PRTOBJ.C.
  449.        *
  450.        */
  451.       Create( hwnd );
  452.       return (MRESULT)NULL;
  453.  
  454.  
  455.    case WM_MOUSEMOVE:
  456.       /* display which pointer? -- could query pmp->fBusy or... */
  457.       if( WinIsWindowEnabled( hwnd ))
  458.       {
  459.          /* not disabled; display regular pointer */
  460.          WinSetPointer( HWND_DESKTOP,
  461.                         WinQuerySysPointer( HWND_DESKTOP, SPTR_ARROW, FALSE ));
  462.       }
  463.       else
  464.       {
  465.          /* disabled; display hourglass because I'm busy */
  466.          WinSetPointer( HWND_DESKTOP,
  467.                         WinQuerySysPointer( HWND_DESKTOP, SPTR_WAIT, FALSE ));
  468.       }
  469.      return (MRESULT) 1;
  470.  
  471.  
  472.  
  473.    case WM_NACK_BITMAP_NOT_SUPPORTED:
  474.       /*
  475.        * Object window does not support this format of bitmap -
  476.        * show a message box.
  477.        */
  478.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  479.       WinSendMsg( hwnd, WM_USER_ENABLE_CLIENT, (MPARAM)0, (MPARAM)0 );
  480.       bOK = WinLoadString( pmp->hab, (HMODULE)0,
  481.                    ERRMSG_BITMAP_NOT_SUPPORTED, LEN_WORKSTRING, szWork );
  482.       pmassert( pmp->hab, bOK );
  483.       WinMessageBox( HWND_DESKTOP, pmp->hwndFrame,
  484.                      szWork, pmp->pszTitle, 0, MB_CANCEL );
  485.  
  486.       pmp->ulNextMode        = MODE_UNKNOWN;
  487.       pmp->szNextFilename[0] = 0;
  488.       WinPostMsg( hwnd, WM_USER_NEW_MODE, (MPARAM)0, (MPARAM)0 );
  489.       return (MRESULT) 0;
  490.  
  491.  
  492.    case WM_NACK_DEFAULT_FONT:
  493.       /*
  494.        * On the call to GpiCreateLogFont in PRTOBJ.C, the GPI returned
  495.        * some font other than a perfect match. Warn user that a default
  496.        * face is in use. This can happen for Postscript and PCL 5 printer
  497.        * users.
  498.        *
  499.        * Only warn the user once after each visit to the font dialog.
  500.        *
  501.        * Don't re-enable the client yet. That message is still to come.
  502.        */
  503.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  504.       if( pmp->fVisitedFontDialog )
  505.       {
  506.          /* only one warning per font dialog visit */
  507.          pmp->fVisitedFontDialog  = FALSE;
  508.  
  509.          bOK = WinLoadString( pmp->hab, (HMODULE)0,
  510.                       ERRMSG_DEFAULT_FONT, LEN_WORKSTRING, szWork );
  511.          pmassert( pmp->hab, bOK );
  512.          WinMessageBox( HWND_DESKTOP, pmp->hwndFrame,
  513.                         szWork, pmp->pszTitle, 0, MB_CANCEL );
  514.       }
  515.       return (MRESULT) 0;
  516.  
  517.  
  518.  
  519.    case WM_NACK_FILE_READING_ERROR:
  520.       /*
  521.        * Object window had a problem with reading the disk -
  522.        * show a message box.
  523.        */
  524.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  525.       WinSendMsg( hwnd, WM_USER_ENABLE_CLIENT, (MPARAM)0, (MPARAM)0 );
  526.       bOK = WinLoadString( pmp->hab, (HMODULE)NULLHANDLE,
  527.                            ERRMSG_READ_ERROR, LEN_WORKSTRING, szWork );
  528.       pmassert( pmp->hab, bOK );
  529.       WinMessageBox( HWND_DESKTOP, pmp->hwndFrame,
  530.                      szWork, pmp->pszTitle, 0, MB_CANCEL );
  531.       pmp->ulNextMode        = MODE_UNKNOWN;
  532.       pmp->szNextFilename[0] = 0;
  533.       WinPostMsg( hwnd, WM_USER_NEW_MODE, (MPARAM)0, (MPARAM)0 );
  534.       return (MRESULT) 0;
  535.  
  536.  
  537.    case WM_PAINT:
  538.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  539.  
  540.       /* current mode of the program affects window painting */
  541.       switch( pmp->ulMode )
  542.       {
  543.       case MODE_UNKNOWN:
  544.          /* blank the client window with background color; use a cache ps */
  545.          hps = WinBeginPaint( hwnd, (HPS) 0, &rectl );
  546.          pmassert( pmp->hab, hps );
  547.          bOK = WinFillRect( pmp->hpsClient, &rectl, SYSCLR_WINDOW );
  548.          pmassert( pmp->hab, bOK );
  549.          WinEndPaint( hps );
  550.          return (MRESULT) 0;
  551.  
  552.       case MODE_TEXT:
  553.          if( pmp->fBusy )
  554.          {
  555.             /*
  556.              * Object window is busy with the client PS drawing into
  557.              * retained segments. Use a cached micro PS to merely
  558.              * fill the client window with a background wash.
  559.              *
  560.              * Proper painting of the text will occur in due time
  561.              * because the WM_USER_ACK case below will
  562.              * invalidate the client window and force a paint.
  563.              * The object window won't be busy then.
  564.              */
  565.             hps = WinBeginPaint( hwnd, (HPS) 0, &rectl );
  566.             pmassert( pmp->hab, hps );
  567.             bOK = WinFillRect( hps, &rectl, SYSCLR_WINDOW );
  568.             pmassert( pmp->hab, bOK );
  569.             WinEndPaint( hps );
  570.          }
  571.          else
  572.          {
  573.             /* PS not busy. Use GpiDrawChain to repaint the text */
  574.             hps = WinBeginPaint( hwnd, (HPS)pmp->hpsClient, &rectl );
  575.             pmassert( pmp->hab, hps );
  576.             bOK = WinFillRect( pmp->hpsClient, &rectl, SYSCLR_WINDOW );
  577.             pmassert( pmp->hab, bOK );
  578.             /*
  579.              * GpiDrawChain re-plays the GpiCharString orders that were
  580.              * retain in the WM_USER_PAGINATE case in prtobj.c
  581.              */
  582.             bOK = GpiDrawChain( pmp->hpsClient );
  583.             pmassert( pmp->hab, bOK );
  584.             bOK = WinEndPaint( pmp->hpsClient );
  585.             pmassert( pmp->hab, bOK );
  586.          }
  587.          return (MRESULT) 0;
  588.  
  589.       case MODE_BITMAP:
  590.          if( pmp->hbm )
  591.          {
  592.             WinSendMsg( hwnd, WM_USER_DISABLE_CLIENT, (MPARAM)0, (MPARAM)0 );
  593.             WinPostMsg( pmp->hwndObject, WM_USER_PAINT_BITMAP,
  594.                         (MPARAM)hwnd, (MPARAM)0 );
  595.          }
  596.          /* must call default window proc for window validation */
  597.          break;
  598.  
  599.       case MODE_METAFILE:
  600.          hps = WinBeginPaint( hwnd, (HPS) 0, &rectl );
  601.          pmassert( pmp->hab, hps );
  602.          WinFillRect( hps, &rectl, SYSCLR_WINDOW );
  603.          if( pmp->hmf )
  604.          {
  605.             WinSendMsg( hwnd, WM_USER_DISABLE_CLIENT, (MPARAM)0, (MPARAM)0 );
  606.             WinPostMsg( pmp->hwndObject, WM_USER_PAINT_METAFILE,
  607.                         (MPARAM)hwnd, (MPARAM)0 );
  608.          }
  609.          WinEndPaint( hps );
  610.          return (MRESULT) 0;
  611.  
  612.       default:
  613.          pmassert( pmp->hab, NULL == "bad case in WM_PAINT" );
  614.       }
  615.       break;
  616.  
  617.  
  618.    case WM_SIZE:
  619.       /* Do size process if frame is not minimized and mode is text. */
  620.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  621.  
  622.       /*
  623.        * If the object window is busy drawing, the GPI calls here can fail
  624.        * because the PS is busy. Check for this situation and delay
  625.        * the sizing operation by a few milliseconds.
  626.        */
  627.       if( pmp->fBusy )
  628.       {
  629.           WinStartTimer( pmp->hab, hwnd, ID_SIZE_TIMER, LEN_SIZE_TIMER );
  630.           return (MRESULT) 0;
  631.       }
  632.  
  633.       switch( pmp->ulMode )
  634.       {
  635.       case MODE_TEXT:
  636.          ulWork = WinQueryWindowULong( pmp->hwndFrame, QWL_STYLE );
  637.  
  638.          if( !( ulWork & WS_MINIMIZED ))
  639.          {
  640.             /* Frame is not minimized. Get window size in pels. */
  641.             WinQueryWindowRect( hwnd, &rectl );
  642.  
  643.             /* how many twips will fit into the client window now? */
  644.             bOK = GpiConvert( pmp->hpsClient, CVTC_DEVICE,
  645.                               CVTC_WORLD, 2L, (PPOINTL)&rectl );
  646.             pmassert( pmp->hab, bOK );
  647.  
  648.             /* compute client size in twips, store in pmp */
  649.             pmp->sizelClient.cx = rectl.xRight - rectl.xLeft;
  650.             pmp->sizelClient.cy = rectl.yTop   - rectl.yBottom;
  651.  
  652.             /* reset scroll bar values; set thumbbutton position at zero */
  653.             pmp->sVScrollPos = 0;
  654.             CalibrateScrollBar( pmp );
  655.  
  656.             /*
  657.              * Modify def-view matrix Y translation to home the displayed page.
  658.              * This depends on the current scaling value.
  659.              */
  660.             pmp->matlfDefView.lM32 = (LONG)(pmp->floatScale *
  661.                 (float) ( OFFSET_XY_TWIPS - pmp->sVScrollRange ));
  662.             bOK = GpiSetDefaultViewMatrix( pmp->hpsClient, 9,
  663.                              &pmp->matlfDefView, TRANSFORM_REPLACE );
  664.             pmassert( pmp->hab, bOK );
  665.  
  666.             /* force a paint */
  667.             WinInvalidateRect( hwnd, NULL, FALSE );
  668.          }
  669.          break;
  670.       }
  671.       return (MRESULT) 0;
  672.  
  673.  
  674.  
  675.  
  676.    case WM_TIMER:
  677.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  678.       switch( (ULONG) mp1 )
  679.       {
  680.       case ID_DEATH_TIMER:
  681.          /* object window never posted a quit in allotted time.
  682.          WinPostMsg( hwnd, WM_QUIT, 0, 0 );
  683.          break;
  684.       case ID_SIZE_TIMER:
  685.          /* object window was busy with the PS before; try sizing now */
  686.          bOK = WinStopTimer( pmp->hab, hwnd, ID_SIZE_TIMER );
  687.          pmassert( pmp->hab, bOK );
  688.          WinSendMsg( hwnd, WM_SIZE, 0, 0 );
  689.          break;
  690.       }
  691.       return (MRESULT) 0;
  692.  
  693.  
  694.  
  695.  
  696.  
  697.    case WM_USER_ACK:
  698.       /*
  699.        * Object window is done processing lengthy task.
  700.        * mp1 contains the WM_USER msg originally posted to the object window
  701.        * mp2 may contain a result code, depending on mp1
  702.        */
  703.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  704.  
  705.       /* reenable the client window */
  706.       WinSendMsg( hwnd, WM_USER_ENABLE_CLIENT, (MPARAM)0, (MPARAM)0 );
  707.  
  708.       switch( (ULONG)mp1 )
  709.       {
  710.       case WM_USER_LOAD_TEXT:
  711.          /*
  712.           * Do size processing so that document will
  713.           * "home" in the client window.
  714.           */
  715.          WinSendMsg( hwnd, WM_SIZE, (MPARAM)0, (MPARAM)0 );
  716.          break;
  717.       case WM_USER_PAGINATE:
  718.          switch( (ULONG)mp2  )
  719.          {
  720.          case PAGINATE_EOF:
  721.          case PAGINATE_EOF_PART_PAGE:
  722.             /* seek top of file */
  723.             fseek( pmp->f, 0, SEEK_SET );
  724.          }
  725.          WinInvalidateRect( hwnd, NULL, FALSE );
  726.          break;
  727.       }
  728.  
  729.       return (MRESULT) 0;
  730.  
  731.  
  732.    case WM_USER_DISABLE_CLIENT:
  733.       /*
  734.        * usually disable before posting a task to the object window
  735.        * this message may be sent; disable menu action bar as well
  736.        */
  737.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  738.       pmp->fBusy = TRUE;
  739.       WinEnableWindow( pmp->hwndClient,  FALSE );
  740.       WinEnableWindow( pmp->hwndMenubar, FALSE );
  741.       WinEnableControl( pmp->hwndFrame, FID_VERTSCROLL,  FALSE );
  742.       WinEnableMenuItem( pmp->hwndMenubar, IDM_PAGEDOWN, FALSE );
  743.       WinEnableMenuItem( pmp->hwndMenubar, IDM_VIEWFULL, FALSE );
  744.       WinEnableMenuItem( pmp->hwndMenubar, IDM_VIEWHALF, FALSE );
  745.       return (MRESULT)0;
  746.  
  747.  
  748.    case WM_USER_ENABLE_CLIENT:
  749.       /*
  750.        * usually enable upon receipt of object window ack/nack
  751.        * this message may be sent; enable menu actions if text mode
  752.        */
  753.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  754.       pmp->fBusy = FALSE;
  755.       WinEnableWindow( pmp->hwndClient,  TRUE );
  756.       WinEnableWindow( pmp->hwndMenubar, TRUE );
  757.       if( pmp->ulMode == MODE_TEXT )
  758.       {
  759.          WinEnableControl( pmp->hwndFrame, FID_VERTSCROLL,  TRUE );
  760.          WinEnableMenuItem( pmp->hwndMenubar, IDM_PAGEDOWN, TRUE );
  761.          WinEnableMenuItem( pmp->hwndMenubar, IDM_VIEWFULL, TRUE );
  762.          WinEnableMenuItem( pmp->hwndMenubar, IDM_VIEWHALF, TRUE );
  763.       }
  764.       return (MRESULT) 0;
  765.  
  766.  
  767.  
  768.    case WM_USER_NEW_MODE:
  769.       /*
  770.        * The program now has a new file, file type, or printer, or
  771.        * printer form, orientation, resolution, etc. The receipt
  772.        * and processing of this message works to reset the program:
  773.        * Old file, bitmap, or metafile handles are closed, and
  774.        * new ones get opened. The titlebar shows the new filename.
  775.        * This case works very much like a program reset.
  776.        */
  777.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  778.  
  779.       /* close processing on current file */
  780.  
  781.       switch( pmp->ulMode )
  782.       {
  783.       case MODE_BITMAP:
  784.         /* destroy previous memory dc, ps, and hbm */
  785.         if( pmp->hpsMemory )
  786.         {
  787.           GpiAssociate( pmp->hpsMemory, (HDC)0 );
  788.           GpiDestroyPS( pmp->hpsMemory );
  789.           pmp->hpsMemory = (HPS) 0;
  790.         }
  791.         if( pmp->hdcMemory )
  792.         {
  793.           DevCloseDC( pmp->hdcMemory );
  794.           pmp->hdcMemory = (HDC) 0;
  795.         }
  796.         if( pmp->hbm )
  797.         {
  798.           GpiDeleteBitmap( pmp->hbm );
  799.           pmp->hbm = (HBITMAP) 0;
  800.         }
  801.         break;
  802.  
  803.       case MODE_METAFILE:
  804.         /* destroy old metafile handle */
  805.         if( pmp->hmf )
  806.         {
  807.           GpiDeleteMetafile( pmp->hmf );
  808.           pmp->hmf = (HMF) 0;
  809.         }
  810.         break;
  811.  
  812.       case MODE_TEXT:
  813.         fclose( pmp->f );
  814.         pmp->f = (FILE *) 0;
  815.         /* turn off options for text mode */
  816.         WinEnableMenuItem( pmp->hwndMenubar, IDM_VIEWHALF, FALSE );
  817.         WinEnableMenuItem( pmp->hwndMenubar, IDM_VIEWFULL, FALSE );
  818.         WinEnableMenuItem( pmp->hwndMenubar, IDM_PAGEDOWN, FALSE );
  819.         WinEnableMenuItem( pmp->hwndMenubar, IDM_SETFONT,  FALSE );
  820.         WinEnableControl( pmp->hwndFrame, FID_VERTSCROLL,  FALSE );
  821.         break;
  822.       }
  823.  
  824.  
  825.       /* copy over current values with the next values */
  826.       pmp->ulMode = pmp->ulNextMode;
  827.       strcpy( pmp->szFilename, pmp->szNextFilename );
  828.  
  829.       /* enable the print menu option if mode is known and there
  830.          is a printer set up. */
  831.       WinEnableMenuItem( pmp->hwndMenubar, IDM_PRINT,
  832.        (pmp->ulMode != MODE_UNKNOWN && pmp->hpsPrinterInfo ) );
  833.  
  834.  
  835.       /* update title bar text and show filename in use */
  836.       if( *pmp->szFilename )
  837.       {
  838.         pch = strrchr( pmp->szFilename, '\\' );
  839.         pmassert( pmp->hab, pch );
  840.         pch++;
  841.         pmassert( pmp->hab, *pch );
  842.         sprintf( szWork, "%s - %s", pmp->pszTitle, pch );
  843.       }
  844.       else
  845.       {
  846.         strcpy( szWork, pmp->pszTitle );
  847.       }
  848.       WinSetWindowText( pmp->hwndTitlebar, szWork );
  849.  
  850.       /* process this new mode */
  851.       switch( pmp->ulMode )
  852.       {
  853.       case MODE_BITMAP:
  854.         /* load the bitmap into memory so it is compatible with the screen */
  855.         WinSendMsg( hwnd, WM_USER_DISABLE_CLIENT, 0, 0 );
  856.         WinPostMsg( pmp->hwndObject, WM_USER_LOAD_BITMAP,
  857.                     (MPARAM)hwnd, (MPARAM)HDCMEM_COMPATIBILITY_SCREEN );
  858.         break;
  859.  
  860.       case MODE_METAFILE:
  861.         /* make object window read metafile */
  862.         WinSendMsg( hwnd, WM_USER_DISABLE_CLIENT, 0, 0 );
  863.         WinPostMsg( pmp->hwndObject, WM_USER_LOAD_METAFILE, (MPARAM)hwnd, 0 );
  864.         break;
  865.  
  866.       case MODE_TEXT:
  867.         /* turn on options for text mode */
  868.         WinEnableMenuItem( pmp->hwndMenubar, IDM_VIEWHALF, TRUE  );
  869.         WinEnableMenuItem( pmp->hwndMenubar, IDM_VIEWFULL, TRUE  );
  870.         WinEnableMenuItem( pmp->hwndMenubar, IDM_PAGEDOWN, TRUE  );
  871.         WinEnableMenuItem( pmp->hwndMenubar, IDM_SETFONT,  TRUE  );
  872.         WinEnableControl( pmp->hwndFrame, FID_VERTSCROLL,  TRUE  );
  873.         /* reset view matrix that was last in effect for viewing text pages; */
  874.         /* this gets lost after viewing a metafile */
  875.         bOK = GpiSetDefaultViewMatrix( pmp->hpsClient, 9,
  876.                                        &pmp->matlfDefView, TRANSFORM_REPLACE );
  877.         pmassert( pmp->hab, bOK );
  878.         /* disable until text loaded */
  879.         WinSendMsg( hwnd, WM_USER_DISABLE_CLIENT, 0, 0 );
  880.         /* tell object window to load the text file */
  881.         bOK = WinPostMsg( pmp->hwndObject, WM_USER_LOAD_TEXT, (MPARAM)hwnd, 0 );
  882.         pmassert( pmp->hab, bOK );
  883.         break;
  884.  
  885.  
  886.       case MODE_UNKNOWN:
  887.         /* clear the client window */
  888.         WinInvalidateRect( hwnd, NULL, FALSE );
  889.         break;
  890.  
  891.       }
  892.       return (MRESULT) 0;
  893.  
  894.    case WM_VSCROLL:
  895.       pmp = (PMAIN_PARM) WinQueryWindowULong( hwnd, QWL_USER );
  896.       pmassert( pmp->hab, pmp->ulMode == MODE_TEXT );
  897.  
  898.       /* Compute some fraction of scroll bar range for a unit of scrolling. */
  899.       sStep  = pmp->sVScrollRange / 50;
  900.  
  901.       switch( SHORT2FROMMP( mp2 ))
  902.       {
  903.       case SB_LINEUP:
  904.          pmp->sVScrollPos       -= sStep;
  905.          break;
  906.       case SB_PAGEUP:
  907.          pmp->sVScrollPos       -= pmp->sizelClient.cy;
  908.          break;
  909.       case SB_LINEDOWN:
  910.          pmp->sVScrollPos       += sStep;
  911.          break;
  912.       case SB_PAGEDOWN:
  913.          pmp->sVScrollPos += pmp->sizelClient.cy;
  914.          break;
  915.       case SB_SLIDERPOSITION:
  916.       case SB_SLIDERTRACK:
  917.          pmp->sVScrollPos = SHORT1FROMMP( mp2 );
  918.          break;
  919.       }
  920.  
  921.       /* Don't allow step assignments to exceed limits of zero to range. */
  922.       pmp->sVScrollPos = max( (SHORT)0,
  923.                               min( pmp->sVScrollPos, pmp->sVScrollRange ));
  924.  
  925.       if( pmp->sVScrollPos != SHORT1FROMMR(WinSendMsg( pmp->hwndVScroll,
  926.           SBM_QUERYPOS, (MPARAM)0, (MPARAM)0 )))
  927.       {
  928.          /*
  929.           * New scroll bar thumbbutton position is different than current.
  930.           * Set a new Y translation value to effect the scroll.
  931.           * Current scale setting affects the Y element of the matrix.
  932.           */
  933.          pmp->matlfDefView.lM32 =  (LONG)(pmp->floatScale *
  934.              (float)( OFFSET_XY_TWIPS +
  935.                       pmp->sVScrollPos -
  936.                       pmp->sVScrollRange ));
  937.          bOK = GpiSetDefaultViewMatrix( pmp->hpsClient,
  938.                                         9,
  939.                                         &pmp->matlfDefView,
  940.                                         TRANSFORM_REPLACE );
  941.          pmassert( pmp->hab, bOK );
  942.          CalibrateScrollBar( pmp );
  943.          WinInvalidateRect( hwnd, NULL, FALSE );
  944.       }
  945.       return (MRESULT) 0;
  946.  
  947.  
  948.    }
  949.  
  950.    return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  951. }  /* End of WinProc() */
  952.  
  953.  
  954.  /************************************************************************
  955.  *
  956.  * Name        : CalibrateScrollBar( pmp )
  957.  *
  958.  * Description : This function computes the scroll bar range to be that
  959.  *               portion of the text document that is clipped from the
  960.  *               client window, then sends this range to the scroll bar.
  961.  *               The thumb position used is that which is already in the pmp.
  962.  *
  963.  *               Thumbsize is then computed by the scroll bar to be a ratio
  964.  *               of the visible part of the document / the entire document.
  965.  *
  966.  * Concepts    : Manipulation of thum position and scroll bar.
  967.  *
  968.  * API's       : WinSendMsg
  969.  *
  970.  * Parameters  : PMAIN_PARM      structure containing important data such
  971.  *                                as window handles, device context handles,
  972.  *                                and other bitmap, printing and program
  973.  *                                information
  974.  *
  975.  * Returns     : [nothing]
  976.  *
  977.  **************************************************************************/
  978. VOID CalibrateScrollBar( PMAIN_PARM pmp )
  979. {
  980.    BOOL bOK;
  981.  
  982.    /*
  983.     * The range of the scroll bar is the length of the
  984.     * printed page that is clipped by the client window.
  985.     */
  986.    pmp->sVScrollRange = ( pmp->sizelPage.cy + 2*OFFSET_XY_TWIPS ) -
  987.                                    pmp->sizelClient.cy;
  988.  
  989.    /* Position the thumbbutton according to pmp->sVScrollPos. */
  990.    bOK = (BOOL)WinSendMsg( pmp->hwndVScroll,
  991.                      SBM_SETSCROLLBAR,
  992.                      (MPARAM) pmp->sVScrollPos,
  993.                      MPFROM2SHORT( (USHORT)0,  pmp->sVScrollRange ));
  994.    pmassert( pmp->hab, bOK );
  995.  
  996.    /* Set thumbsize of the scroll bar. */
  997.  
  998.    bOK = (BOOL)WinSendMsg( pmp->hwndVScroll,
  999.                      SBM_SETTHUMBSIZE,
  1000.                      MPFROM2SHORT( pmp->sizelClient.cy, pmp->sizelPage.cy ),
  1001.                      (MPARAM)0 );
  1002.  
  1003.    pmassert( pmp->hab, bOK );
  1004.  
  1005. }  /* End of CalibrateScrollBar(). */
  1006. /***************************  End of prtsamp.c ****************************/
  1007.