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

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