home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / MDI-15.ZIP / BROWSER.C < prev    next >
Text File  |  1990-08-27  |  27KB  |  752 lines

  1. // Includes
  2. // --------
  3.    #define INCL_WIN
  4.    #define INCL_GPICONTROL
  5.    #define INCL_GPILCIDS
  6.    #define INCL_GPIPRIMITIVES
  7.    #define INCL_DOSFILEMGR
  8.  
  9.    #include <string.h>
  10.    #include <stdlib.h>
  11.    #include <os2.h>
  12.  
  13.    #include "Browser.H"
  14.    #include "Browser.RH"
  15.  
  16.    #include "OpenDlg.H"
  17.    #include "TellUser.H"
  18.    #include "AllocMem.H"
  19.    #include "MDI.H"
  20.  
  21.  
  22. // Document Descriptor
  23. // -------------------
  24.    typedef struct _DOCUMENTDESC
  25.      {USHORT offLine;                  // Line offset
  26.       USHORT cchLine;                  // Line size
  27.      } DOCUMENTDESC;
  28.  
  29.    typedef DOCUMENTDESC *PDOCUMENTDESC;
  30.  
  31.  
  32. // Document Data
  33. // -------------
  34.    typedef struct _DOCUMENTDATA
  35.      {BOOL fValid;                     // Is data valid?
  36.       ULONG cLines;                    // Number of lines in document
  37.       USHORT cchMax;                   // Largest line in document
  38.       PDOCUMENTDESC pdesc;             // -->document descriptor
  39.       CHAR chText[1];                  // Actual text
  40.      } DOCUMENTDATA;
  41.  
  42.    typedef DOCUMENTDATA *PDOCUMENTDATA;
  43.  
  44.  
  45. // Instance Data
  46. // -------------
  47.    typedef struct _INSTANCEDATA
  48.      {ULONG idesc;                     // Current index into doc descriptor
  49.       USHORT ich;                      // Current index into each line
  50.       HPS hps;                         // Presentation space
  51.       FONTMETRICS fm;                  // Font metrics
  52.       SWP swp;                         // Document position and size
  53.       HWND hwndHScroll;                // Horizontal scroll bar
  54.       HWND hwndVScroll;                // Vertical scroll bar
  55.       SHORT sVLines;                   // Vertical size in lines
  56.       SHORT sHChars;                   // Horizontal size in characters
  57.      } INSTANCEDATA;
  58.  
  59.    typedef INSTANCEDATA *PINSTANCEDATA;
  60.  
  61.  
  62. // Constants
  63. // ---------
  64.    #define MAX_STRING     128          // Maximum string size
  65.    #define LCID_FIXED     128L         // Local fixed pitch font id
  66.  
  67.    const ULONG cbMaxFile =             // Maximum file size
  68.      (65535 - (sizeof (DOCUMENTDATA) - 1));
  69.  
  70.    const ULONG cMaxLines =             // Maximum number of lines in file
  71.      (65534 / sizeof (USHORT));
  72.  
  73.  
  74. // Function Declarations
  75. // ---------------------
  76.    VOID    EXPENTRY MDIInitialize          (HAB);
  77.  
  78.    MRESULT EXPENTRY BrowserDesktopWndProc  (HWND, USHORT, MPARAM, MPARAM);
  79.    MRESULT FAR      BrowserDocumentCreate  (HWND, PINSTANCEDATA);
  80.    MRESULT FAR      BrowserDocumentDestroy (HWND, PDOCUMENTDATA);
  81.    MRESULT FAR      BrowserDocumentHScroll (HWND, USHORT, SHORT);
  82.    MRESULT FAR      BrowserDocumentOpen    (HWND);
  83.    MRESULT FAR      BrowserDocumentPaint   (HWND);
  84.    MRESULT FAR      BrowserDocumentSize    (HWND);
  85.    MRESULT FAR      BrowserDocumentVScroll (HWND, USHORT, SHORT);
  86.    MRESULT EXPENTRY BrowserDocumentWndProc (HWND, USHORT, MPARAM, MPARAM) ;
  87.    MRESULT FAR      BrowserInstanceDestroy (HWND, PINSTANCEDATA);
  88.  
  89.  
  90. // Function: main - Create Browser desktop
  91. // ---------------------------------------
  92.    VOID main (VOID)
  93.  
  94.    // Define function data
  95.  
  96.      {HAB hab;                         // Application anchor block
  97.       HMQ hmq;                         // Message queue handle
  98.       QMSG qmsg ;                      // Message queue entry
  99.       HWND hwndFrame, hwndDesktop;     // MDI desktop frame, client
  100.  
  101.       ULONG flCreateFlags =            // Creation flags
  102.         FCF_STANDARD | FCF_NOBYTEALIGN;
  103.  
  104.    // Initialize PM procesing
  105.  
  106.       hab = WinInitialize (0);
  107.       hmq = WinCreateMsgQueue (hab, 0);
  108.  
  109.    // Initialize MDI processing
  110.  
  111.       MDIInitialize (hab);
  112.  
  113.    // Create the MDI desktop
  114.  
  115.       hwndFrame = MDICreateDesktop (BrowserDesktopWndProc,
  116.         flCreateFlags, "", (HMODULE) NULL, BROWSER_RESOURCES,
  117.         &hwndDesktop, 0, 1, "E~xit", "E~xit", "~Window", 0L);
  118.       if ((hwndFrame == (HWND) NULL) || (hwndDesktop == (HWND) NULL)) return;
  119.  
  120.    // Process PM messages
  121.  
  122.       while (WinGetMsg (hab, &qmsg, (HWND) NULL, 0, 0))
  123.          WinDispatchMsg (hab, &qmsg) ;
  124.  
  125.    // Terminate PM processing
  126.  
  127.       WinDestroyMsgQueue (hmq) ;
  128.       WinTerminate (hab) ;
  129.  
  130.      }
  131.  
  132.  
  133. // Function: BrowserDesktopWndProc - Desktop window procedure
  134. // ----------------------------------------------------------
  135.    MRESULT EXPENTRY BrowserDesktopWndProc (hwndDesktop, msg, mp1, mp2)
  136.  
  137.       HWND hwndDesktop;                // Browser desktop window
  138.       USHORT msg;                      // PM message
  139.       MPARAM mp1;                      // Message parameter 1
  140.       MPARAM mp2;                      // Message parameter 2
  141.  
  142.    // Process PM messages
  143.  
  144.      {switch (msg)
  145.  
  146.       // Process menu command
  147.  
  148.         {case WM_COMMAND:
  149.             switch (LOUSHORT (mp1))
  150.  
  151.             // Open a file
  152.  
  153.               {case CMD_OPEN:
  154.                   return BrowserDocumentOpen (hwndDesktop);
  155.  
  156.             // Display "about" box
  157.  
  158.                case CMD_ABOUT:
  159.                   WinDlgBox (HWND_DESKTOP, hwndDesktop, WinDefDlgProc,
  160.                     (HMODULE) NULL, DIALOG_ABOUT, (PVOID) NULL);
  161.                   return (MRESULT) NULL;
  162.  
  163.             // End processing menu commands
  164.  
  165.               }
  166.  
  167.             break;
  168.  
  169.       // End processing PM messages
  170.  
  171.         }
  172.  
  173.    // Return to MDI
  174.  
  175.       return MDIDesktopWndProc (hwndDesktop, msg, mp1, mp2) ;
  176.  
  177.      }
  178.  
  179.  
  180. // Function: BrowserDocumentCreate - Create document Window
  181. // --------------------------------------------------------
  182.    MRESULT FAR BrowserDocumentCreate (hwndDocument, pinst)
  183.  
  184.       HWND hwndDocument;               // Browser document window
  185.       PINSTANCEDATA pinst;             // -->instance data
  186.  
  187.    // Define function data
  188.  
  189.      {HDC hdc;                         // Device context
  190.       SIZEL sizl;                      // Presentation space size
  191.       FONTMETRICS afm[14];             // List of available fonts
  192.       FATTRS fat;                      // Font attributes
  193.       ULONG cfm;                       // Number of fonts actualy available
  194.       ULONG ifm;                       // Index into available fonts
  195.       PDOCUMENTDATA pdoc;              // -->document data
  196.  
  197.    // Get a presentation space
  198.  
  199.       hdc = WinOpenWindowDC (hwndDocument);
  200.       sizl.cx = 0;
  201.       sizl.cy = 0;
  202.       pinst->hps = GpiCreatePS ((HAB) NULL, hdc, &sizl, PU_PELS | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC);
  203.  
  204.    // Create a fixed-pitch font for document painting. Note that the
  205.    // Browser painting logic is optimized on the basis of the fixed
  206.    // pitch font.
  207.  
  208.       cfm = sizeof (afm) / sizeof (FONTMETRICS);
  209.       GpiQueryFonts (pinst->hps, QF_PUBLIC, "Courier", &cfm, (LONG)sizeof (FONTMETRICS), afm);
  210.       for (ifm = 0; ifm < cfm; ifm++)
  211.          if (!(afm[ifm].fsDefn & 0x0001)) break;
  212.       fat.usRecordLength = sizeof(fat);
  213.       fat.fsSelection = afm[ifm].fsSelection;
  214.       fat.lMatch = afm[ifm].lMatch;
  215.       strcpy (fat.szFacename, afm[ifm].szFacename);
  216.       fat.idRegistry = afm[ifm].idRegistry;
  217.       fat.usCodePage = 850;
  218.       fat.lMaxBaselineExt = afm[ifm].lMaxBaselineExt;
  219.       fat.lAveCharWidth = afm[ifm].lAveCharWidth;
  220.       fat.fsType = 0;
  221.       fat.fsFontUse = 0;
  222.       GpiCreateLogFont (pinst->hps, (PSTR8) NULL, LCID_FIXED, &fat);
  223.       GpiSetCharSet (pinst->hps, LCID_FIXED);
  224.  
  225.    // Store the font metrics for later use
  226.  
  227.       GpiQueryFontMetrics (pinst->hps, (LONG) sizeof (pinst->fm), &(pinst->fm));
  228.  
  229.    // Determine initial window position and size
  230.  
  231.       WinQueryWindowPos (hwndDocument, &(pinst->swp));
  232.  
  233.    // Locate document data
  234.  
  235.       pdoc = (PDOCUMENTDATA) WinSendMsg (hwndDocument, MDI_MSG_LOCATE_DOCUMENT_DATA, (MPARAM) NULL, (MPARAM) NULL);
  236.  
  237.    // Locate scroll bars
  238.  
  239.       pinst->hwndHScroll = WinWindowFromID (WinQueryWindow (hwndDocument,
  240.         QW_PARENT, FALSE), FID_HORZSCROLL);
  241.       pinst->hwndVScroll = WinWindowFromID (WinQueryWindow (hwndDocument,
  242.         QW_PARENT, FALSE), FID_VERTSCROLL);
  243.  
  244.    // Indicate create handled
  245.  
  246.       return (MRESULT) NULL;
  247.  
  248.      }
  249.  
  250.  
  251. // Function: BrowserDocumentDestroy - Destroy Document
  252. // ---------------------------------------------------
  253.    MRESULT FAR BrowserDocumentDestroy (hwndDocument, pdoc)
  254.  
  255.       HWND hwndDocument;               // Browser document window
  256.       PDOCUMENTDATA pdoc;              // -->document data
  257.  
  258.    // Fool the compiler
  259.  
  260.      {hwndDocument = hwndDocument;
  261.  
  262.    // Free document descriptor
  263.  
  264.       AllocMemFree (pdoc->pdesc);
  265.  
  266.    // Indicate destroy handled
  267.  
  268.       return (MRESULT) NULL;
  269.  
  270.      }
  271.  
  272.  
  273. // Function: BrowserDocumentHScroll - Horizontally Scroll Document
  274. // ---------------------------------------------------------------
  275.    MRESULT FAR BrowserDocumentHScroll (hwndDocument, usCmd, sPos)
  276.  
  277.       HWND hwndDocument;               // Browser document window
  278.       USHORT usCmd;                    // Scrolling comand
  279.       SHORT sPos;                      // Scrolling position
  280.  
  281.    // Define function data
  282.  
  283.      {SHORT sInc;                      // Scrolling increment
  284.       PINSTANCEDATA pinst;             // -->instance data
  285.       PDOCUMENTDATA pdoc;              // -->document data
  286.  
  287.    // Locate document and instance data
  288.  
  289.       pinst = (PINSTANCEDATA) WinSendMsg (hwndDocument, MDI_MSG_LOCATE_INSTANCE_DATA, (MPARAM) NULL, (MPARAM) NULL);
  290.       pdoc = (PDOCUMENTDATA) WinSendMsg (hwndDocument, MDI_MSG_LOCATE_DOCUMENT_DATA, (MPARAM) NULL, (MPARAM) NULL);
  291.  
  292.    // Analyze scrolling command and determine scrolling increment
  293.  
  294.       switch (usCmd)
  295.         {case SB_LINELEFT:    sInc = -1;
  296.             break;
  297.          case SB_LINERIGHT:   sInc = 1;
  298.             break;
  299.          case SB_PAGEUP:      sInc = min (-1, -pinst->sHChars);
  300.             break;
  301.          case SB_PAGEDOWN:    sInc = max (1, pinst->sHChars);
  302.             break;
  303.          case SB_SLIDERTRACK: sInc = sPos - (SHORT) pinst->ich;
  304.             break;
  305.          default:             sInc = 0;
  306.             break;
  307.         }
  308.       sInc = max ((SHORT) pinst->ich * -1,
  309.         min (sInc, (SHORT) (pdoc->cchMax - pinst->ich - pinst->sHChars)));
  310.  
  311.    // If necessary, perform actual scroll
  312.  
  313.       if (sInc != 0)
  314.         {pinst->ich += sInc;
  315.          WinScrollWindow (hwndDocument, -sInc * (SHORT) pinst->fm.lAveCharWidth, 0,
  316.            (PRECTL) NULL, (PRECTL) NULL, (HRGN) NULL, (PRECTL) NULL, SW_INVALIDATERGN);
  317.          WinSendMsg (pinst->hwndHScroll, SBM_SETPOS, MPFROMSHORT ((USHORT) pinst->ich), (MPARAM) NULL);
  318.          WinUpdateWindow (hwndDocument);
  319.         }
  320.  
  321.    // Indicate scroll handled
  322.  
  323.       return (MRESULT) NULL;
  324.  
  325.      }
  326.  
  327.  
  328. // Function: BrowserDocumentOpen - Open a new document
  329. // ---------------------------------------------------
  330.    MRESULT FAR BrowserDocumentOpen (hwndDesktop)
  331.  
  332.       HWND hwndDesktop;                // Browser desktop window
  333.  
  334.    // Define function data
  335.  
  336.      {HWND hwndFrame, hwndDocument;    // MDI document frame, client
  337.       DLF dlf;                         // Open dialog interchange data
  338.       HFILE hfile;                     // File handle
  339.       FILESTATUS fsts;                 // File status
  340.       CHAR szOpenTitle[MAX_STRING];    // Open dialog box title
  341.       CHAR szOpenHelp[MAX_STRING];     // Open dialog box help
  342.       PINSTANCEDATA pinst;             // -->instance data
  343.       PDOCUMENTDATA pdoc;              // -->file document data
  344.       USHORT cbBytes;                  // Number of bytes read
  345.       USHORT ichText;                  // Index into document text
  346.       USHORT offLine;                  // Line offset
  347.       ULONG idesc;                     // Index into document descriptor
  348.  
  349.       ULONG flCreateFlags =            // Creation flags
  350.         FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER | FCF_MINMAX |
  351.         FCF_ICON | FCF_SHELLPOSITION | FCF_NOBYTEALIGN |
  352.         FCF_VERTSCROLL | FCF_HORZSCROLL;
  353.  
  354.    // Obtain document name and open document, verifying document is not
  355.    // too large to browse
  356.  
  357.       WinLoadString ((HAB) NULL, (HMODULE) NULL, STRING_OPENTITLE, sizeof (szOpenTitle), szOpenTitle);
  358.       WinLoadString ((HAB) NULL, (HMODULE) NULL, STRING_OPENHELP, sizeof (szOpenHelp), szOpenHelp);
  359.       while (TRUE)
  360.         {SetupDLF (&dlf, DLG_OPENDLG, &hfile, "\\*.*", NULL, szOpenTitle, szOpenHelp);
  361.          if (DlgFile (hwndDesktop, &dlf) != TDF_OLDOPEN) return;
  362.          DosQFileInfo (hfile, 0x0001, (PBYTE) &fsts, sizeof (fsts));
  363.          if (fsts.cbFile > cbMaxFile)
  364.             TellUser (STRING_TOOLARGE, BROWSER_MODNAME, MB_OK, dlf.szFileName, fsts.cbFile, cbMaxFile);
  365.          else break;
  366.         }
  367.  
  368.    // Create document window
  369.  
  370.       hwndFrame = MDICreateDocument (BrowserDocumentWndProc, hwndDesktop,
  371.         flCreateFlags, dlf.szFileName, (HMODULE) NULL, DOCUMENT_RESOURCES,
  372.         &hwndDocument, (USHORT) (fsts.cbFile + (sizeof (DOCUMENTDATA) - 1)),
  373.         sizeof (INSTANCEDATA), 1);
  374.       if ((hwndFrame == (HWND) NULL) || (hwndDocument == (HWND) NULL)) return;
  375.  
  376.    // Locate document and instance data
  377.  
  378.       pinst = (PINSTANCEDATA) WinSendMsg (hwndDocument, MDI_MSG_LOCATE_INSTANCE_DATA, (MPARAM) NULL, (MPARAM) NULL);
  379.       pdoc = (PDOCUMENTDATA) WinSendMsg (hwndDocument, MDI_MSG_LOCATE_DOCUMENT_DATA, (MPARAM) NULL, (MPARAM) NULL);
  380.  
  381.    // If document data is not yet valid...
  382.  
  383.       if (! pdoc->fValid)
  384.  
  385.       // Read entire file into document data and check that read was
  386.       // successful
  387.  
  388.         {if (DosRead (hfile, pdoc->chText, (USHORT) fsts.cbFile, &cbBytes)
  389.           || (fsts.cbFile != cbBytes))
  390.            {TellUser (STRING_BADREAD, BROWSER_MODNAME, MB_OK, dlf.szFileName);
  391.             return;
  392.            }
  393.  
  394.       // Count the number of lines in the document and verify that
  395.       // it is less than the maximum allowed
  396.  
  397.          for (ichText = 0; ichText < cbBytes; ichText++)
  398.             if (pdoc->chText[ichText] == '\n') pdoc->cLines++;
  399.          if (pdoc->cLines > cMaxLines)
  400.            {TellUser (STRING_TOOMANY, BROWSER_MODNAME, MB_OK, dlf.szFileName, pdoc->cLines, cMaxLines);
  401.             return;
  402.            }
  403.  
  404.       // Allocate and fill the document descriptor array
  405.  
  406.          pdoc->pdesc = (PDOCUMENTDESC) AllocMemAlloc (pdoc->cLines * sizeof (DOCUMENTDESC));
  407.          pdoc->cchMax = 0;
  408.          offLine = 0;
  409.          idesc = 0;
  410.          for (ichText = 0; ichText < cbBytes; ichText++)
  411.            {if (pdoc->chText[ichText] == '\r')
  412.                pdoc->chText[ichText] = ' ';
  413.             else if (pdoc->chText[ichText] == '\n')
  414.               {pdoc->pdesc[idesc].offLine = offLine;
  415.                pdoc->pdesc[idesc].cchLine = ichText - offLine;
  416.                if (pdoc->pdesc[idesc].cchLine > pdoc->cchMax)
  417.                   pdoc->cchMax = pdoc->pdesc[idesc].cchLine;
  418.                offLine = ichText + 1;
  419.                idesc++;
  420.               }
  421.            }
  422.  
  423.       // Validate document data
  424.  
  425.          pdoc->fValid = TRUE;
  426.         }
  427.  
  428.    // Force document to be resized
  429.  
  430.       BrowserDocumentSize (hwndDocument);
  431.  
  432.    // Force document window to be re-painted
  433.  
  434.       WinInvalidateRect (hwndDocument, (PRECTL) NULL, FALSE);
  435.  
  436.    // Indicate open handled
  437.  
  438.       return (MRESULT) NULL;
  439.  
  440.      }
  441.  
  442.  
  443. // Function: BrowserDocumentPaint - Paint document
  444. // -----------------------------------------------
  445.    MRESULT FAR BrowserDocumentPaint (hwndDocument)
  446.  
  447.       HWND hwndDocument;               // Browser document window
  448.  
  449.    // Define function data
  450.  
  451.      {HPS hps;                         // Presentation space
  452.       PINSTANCEDATA pinst;             // -->instance data
  453.       PDOCUMENTDATA pdoc;              // -->document data
  454.       RECTL rclInvalid;                // Invalid rectangle
  455.       RECTL rclWnd;                    // Window rectangle
  456.       RECTL rclLine;                   // Line rectangle
  457.       ULONG cLines;                    // Count of lines in window
  458.       ULONG idesc;                     // Index into document descriptor
  459.       SHORT sTop;                      // Top line displacement
  460.       SHORT sLeft;                     // Left character displacement
  461.       POINTL ptl;                      // Temporary point
  462.  
  463.       static CHAR chDummy = ' ';       // Dummy line
  464.  
  465.    // Locate document and instance data
  466.  
  467.       pinst = (PINSTANCEDATA) WinSendMsg (hwndDocument, MDI_MSG_LOCATE_INSTANCE_DATA, (MPARAM) NULL, (MPARAM) NULL);
  468.       pdoc = (PDOCUMENTDATA) WinSendMsg (hwndDocument, MDI_MSG_LOCATE_DOCUMENT_DATA, (MPARAM) NULL, (MPARAM) NULL);
  469.  
  470.    // Initialize painting
  471.  
  472.       WinQueryWindowRect (hwndDocument, &rclWnd);
  473.       hps = WinBeginPaint (hwndDocument, pinst->hps, &rclInvalid);
  474.  
  475.    // Optimize by initially calculating the top line and left character
  476.    // displacement using the invalid rectangle. Adjust the invalid rectangle
  477.    // such that it starts at an integral line/character position. This
  478.    // logic only works because we use a fixed pitch font.
  479.  
  480.       sTop = (SHORT) ((rclWnd.yTop - rclInvalid.yTop) / pinst->fm.lMaxBaselineExt);
  481.       sLeft = (SHORT) ((rclInvalid.xLeft - rclWnd.xLeft) / pinst->fm.lAveCharWidth);
  482.       rclInvalid.yTop = rclWnd.yTop - ((LONG) sTop * pinst->fm.lMaxBaselineExt);
  483.       rclInvalid.xLeft = rclWnd.xLeft + ((LONG) sLeft * pinst->fm.lAveCharWidth);
  484.       cLines = ((rclInvalid.yTop - rclInvalid.yBottom) / pinst->fm.lMaxBaselineExt) + 1L;
  485.  
  486.    // Initialize the rectangle that bounds each line to be painted
  487.  
  488.       rclLine.xLeft = rclInvalid.xLeft;
  489.       rclLine.xRight = rclInvalid.xRight;
  490.       rclLine.yTop = rclInvalid.yTop - 1L;
  491.  
  492.    // Draw each line
  493.  
  494.       for (idesc = pinst->idesc + sTop; idesc < pdoc->cLines; idesc++)
  495.         {if (cLines-- == 0) break;
  496.          rclLine.yBottom = rclLine.yTop - pinst->fm.lMaxBaselineExt + 1L;
  497.          ptl.x = rclLine.xLeft;
  498.          ptl.y = rclLine.yBottom + pinst->fm.lMaxDescender;
  499.          if (pdoc->pdesc[idesc].cchLine > (USHORT) (sLeft + pinst->ich))
  500.            {GpiCharStringPosAt (hps, &ptl, &rclLine, CHS_OPAQUE,
  501.               (LONG) (pdoc->pdesc[idesc].cchLine - sLeft - pinst->ich),
  502.               pdoc->chText + pdoc->pdesc[idesc].offLine + sLeft + pinst->ich, (PLONG) NULL);
  503.            }
  504.          else GpiCharStringPosAt (hps, &ptl, &rclLine, CHS_OPAQUE, 1L, &chDummy, (PLONG) NULL);
  505.          rclLine.yTop = rclLine.yBottom - 1L;
  506.         }
  507.  
  508.    // Fill the remainder (if any) of the window
  509.  
  510.       rclLine.yTop++;
  511.       rclLine.yBottom = rclInvalid.yBottom;
  512.       WinFillRect (hps, &rclLine, CLR_WHITE);
  513.  
  514.    // Terminate painting
  515.  
  516.       WinEndPaint (hps);
  517.  
  518.    // Indicate paint handled
  519.  
  520.       return (MRESULT) NULL;
  521.  
  522.      }
  523.  
  524.  
  525. // Function: BrowserDocumentSize - Resize document
  526. // -----------------------------------------------
  527.    MRESULT FAR BrowserDocumentSize (hwndDocument)
  528.  
  529.       HWND hwndDocument;               // Browser document window
  530.  
  531.    // Define function data
  532.  
  533.      {PINSTANCEDATA pinst;             // -->instance data
  534.       PDOCUMENTDATA pdoc;              // -->document data
  535.  
  536.    // Locate document and instance data
  537.  
  538.       pinst = (PINSTANCEDATA) WinSendMsg (hwndDocument, MDI_MSG_LOCATE_INSTANCE_DATA, (MPARAM) NULL, (MPARAM) NULL);
  539.       pdoc = (PDOCUMENTDATA) WinSendMsg (hwndDocument, MDI_MSG_LOCATE_DOCUMENT_DATA, (MPARAM) NULL, (MPARAM) NULL);
  540.  
  541.    // Determine new window position and size
  542.  
  543.       WinQueryWindowPos (hwndDocument, &(pinst->swp));
  544.  
  545.    // Determine new dimensions in lines and characters
  546.  
  547.       pinst->sVLines = pinst->swp.cy / (SHORT) pinst->fm.lMaxBaselineExt;
  548.       pinst->sHChars = pinst->swp.cx / (SHORT) pinst->fm.lAveCharWidth;
  549.  
  550.    // Set scroll bar thumb sizes
  551.  
  552.       WinSendMsg (pinst->hwndHScroll, SBM_SETTHUMBSIZE,
  553.         MPFROM2SHORT (pinst->sHChars, pdoc->cchMax), (MPARAM) NULL);
  554.       WinSendMsg (pinst->hwndVScroll, SBM_SETTHUMBSIZE,
  555.         MPFROM2SHORT (pinst->sVLines, pdoc->cLines), (MPARAM) NULL);
  556.  
  557.    // Set scroll bar limits
  558.  
  559.       WinSendMsg (pinst->hwndHScroll, SBM_SETSCROLLBAR,
  560.         MPFROMSHORT (pinst->ich), MPFROM2SHORT (0, (USHORT) pdoc->cchMax - pinst->sHChars-1));
  561.       WinSendMsg (pinst->hwndVScroll, SBM_SETSCROLLBAR,
  562.         MPFROMSHORT (pinst->idesc), MPFROM2SHORT (0, (USHORT) pdoc->cLines- pinst->sVLines-1));
  563.  
  564.    // Indicate resize handled
  565.  
  566.       return (MRESULT) NULL;
  567.  
  568.      }
  569.  
  570.  
  571. // Function: BrowserDocumentVScroll - Vertically Scroll Document
  572. // -------------------------------------------------------------
  573.    MRESULT FAR BrowserDocumentVScroll (hwndDocument, usCmd, sPos)
  574.  
  575.       HWND hwndDocument;               // Browser document window
  576.       USHORT usCmd;                    // Scrolling comand
  577.       SHORT sPos;                      // Scrolling position
  578.  
  579.    // Define function data
  580.  
  581.      {SHORT sInc;                      // Scrolling increment
  582.       PINSTANCEDATA pinst;             // -->instance data
  583.       PDOCUMENTDATA pdoc;              // -->document data
  584.  
  585.    // Locate document and instance data
  586.  
  587.       pinst = (PINSTANCEDATA) WinSendMsg (hwndDocument, MDI_MSG_LOCATE_INSTANCE_DATA, (MPARAM) NULL, (MPARAM) NULL);
  588.       pdoc = (PDOCUMENTDATA) WinSendMsg (hwndDocument, MDI_MSG_LOCATE_DOCUMENT_DATA, (MPARAM) NULL, (MPARAM) NULL);
  589.  
  590.    // Analyze scrolling command and determine scrolling increment
  591.  
  592.       switch (usCmd)
  593.         {case SB_LINEUP:      sInc = -1;
  594.             break;
  595.          case SB_LINEDOWN:    sInc = 1;
  596.             break;
  597.          case SB_PAGEUP:      sInc = min (-1, -pinst->sVLines);
  598.             break;
  599.          case SB_PAGEDOWN:    sInc = max (1, pinst->sVLines);
  600.             break;
  601.          case SB_SLIDERTRACK: sInc = sPos - (SHORT) pinst->idesc;
  602.             break;
  603.          default:             sInc = 0;
  604.             break;
  605.         }
  606.       sInc = max ((SHORT) pinst->idesc * -1,
  607.         min (sInc, (SHORT) (pdoc->cLines - pinst->idesc - pinst->sVLines)));
  608.  
  609.    // If necessary, perform actual scroll
  610.  
  611.       if (sInc != 0)
  612.         {pinst->idesc += sInc;
  613.          WinScrollWindow (hwndDocument, 0, sInc * (SHORT) pinst->fm.lMaxBaselineExt,
  614.            (PRECTL) NULL, (PRECTL) NULL, (HRGN) NULL, (PRECTL) NULL, SW_INVALIDATERGN);
  615.          WinSendMsg (pinst->hwndVScroll, SBM_SETPOS, MPFROMSHORT ((USHORT) pinst->idesc), (MPARAM) NULL);
  616.          WinUpdateWindow (hwndDocument);
  617.         }
  618.  
  619.    // Indicate scroll handled
  620.  
  621.       return (MRESULT) NULL;
  622.  
  623.      }
  624.  
  625.  
  626. // Function: BrowserDocumentWndProc - Document window procedure
  627. // ------------------------------------------------------------
  628.    MRESULT EXPENTRY BrowserDocumentWndProc (hwndDocument, msg, mp1, mp2)
  629.  
  630.       HWND hwndDocument;               // Browser document window
  631.       USHORT msg;                      // PM message
  632.       MPARAM mp1;                      // Message parameter 1
  633.       MPARAM mp2;                      // Message parameter 2
  634.  
  635.    // Define function data
  636.  
  637.      {USHORT fsKeyFlags;               // From WM_CHAR
  638.       UCHAR uchRepeat;                 // From WM_CHAR
  639.       USHORT usVKey;                   // From WM_CHAR
  640.  
  641.    // Process PM messages
  642.  
  643.       switch (msg)
  644.  
  645.       // MDI control messages
  646.  
  647.         {case WM_CONTROL:
  648.             switch (SHORT2FROMMP (mp1))
  649.  
  650.             // Process destruction of document
  651.  
  652.               {case MDI_NOTIFY_CREATE_INSTANCE:
  653.                   return BrowserDocumentCreate (hwndDocument, (PINSTANCEDATA) mp2);
  654.  
  655.             // Process destruction of document
  656.  
  657.                case MDI_NOTIFY_DESTROY_DOCUMENT:
  658.                   return BrowserDocumentDestroy (hwndDocument, (PDOCUMENTDATA) mp2);
  659.  
  660.             // Process destruction of instance
  661.  
  662.                case MDI_NOTIFY_DESTROY_INSTANCE:
  663.                   return BrowserInstanceDestroy (hwndDocument, (PINSTANCEDATA) mp2);
  664.               }
  665.             return (MRESULT) NULL;
  666.  
  667.       // Simulate scrolling from character keys
  668.  
  669.          case WM_CHAR:
  670.             fsKeyFlags = SHORT1FROMMP (mp1);
  671.             uchRepeat = CHAR3FROMMP (mp1);
  672.             usVKey = SHORT2FROMMP (mp2);
  673.             if (! (fsKeyFlags & KC_KEYUP) && (fsKeyFlags & KC_VIRTUALKEY))
  674.               {while (uchRepeat--)
  675.                  {switch (usVKey)
  676.                     {case VK_LEFT:
  677.                        BrowserDocumentHScroll (hwndDocument, SB_LINELEFT, 0);
  678.                        break;
  679.                      case VK_RIGHT:
  680.                        BrowserDocumentHScroll (hwndDocument, SB_LINERIGHT, 0);
  681.                        break;
  682.                      case VK_UP:
  683.                        BrowserDocumentVScroll (hwndDocument, SB_LINEUP, 0);
  684.                        break;
  685.                      case VK_DOWN:
  686.                        BrowserDocumentVScroll (hwndDocument, SB_LINEDOWN, 0);
  687.                        break;
  688.                      case VK_PAGEUP:
  689.                        BrowserDocumentVScroll (hwndDocument, SB_PAGEUP, 0);
  690.                        break;
  691.                      case VK_PAGEDOWN:
  692.                        BrowserDocumentVScroll (hwndDocument, SB_PAGEDOWN, 0);
  693.                        break;
  694.                     }
  695.                  }
  696.               }
  697.             return (MRESULT) NULL;
  698.  
  699.       // Horizontally scroll document
  700.  
  701.          case WM_HSCROLL:
  702.             return BrowserDocumentHScroll (hwndDocument, SHORT2FROMMP (mp2), SHORT1FROMMP (mp2));
  703.  
  704.       // Process paint request for document
  705.  
  706.          case WM_PAINT:
  707.             return BrowserDocumentPaint (hwndDocument);
  708.  
  709.       // Process resize request for document
  710.  
  711.          case WM_SIZE:
  712.             return BrowserDocumentSize (hwndDocument);
  713.  
  714.       // Vertically scroll document
  715.  
  716.          case WM_VSCROLL:
  717.             return BrowserDocumentVScroll (hwndDocument, SHORT2FROMMP (mp2), SHORT1FROMMP (mp2));
  718.  
  719.       // End processing PM messages
  720.  
  721.         }
  722.  
  723.    // Allow MDI to process all messages
  724.  
  725.       return MDIDocumentWndProc (hwndDocument, msg, mp1, mp2);
  726.  
  727.      }
  728.  
  729.  
  730. // Function: BrowserInstanceDestroy - Destroy Document Window
  731. // ----------------------------------------------------------
  732.    MRESULT FAR BrowserInstanceDestroy (hwndDocument, pinst)
  733.  
  734.       HWND hwndDocument;               // Browser document window
  735.       PINSTANCEDATA pinst;             // -->instance data
  736.  
  737.    // Fool the compiler
  738.  
  739.      {hwndDocument = hwndDocument;
  740.  
  741.    // Destroy font and presentation space
  742.  
  743.       GpiSetCharSet (pinst->hps, (LONG) NULL);
  744.       GpiDeleteSetId (pinst->hps, LCID_FIXED);
  745.       GpiDestroyPS (pinst->hps);
  746.  
  747.    // Indicate destroy handled
  748.  
  749.       return (MRESULT) NULL;
  750.  
  751.      }
  752.