home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / AVBROWSE.ZIP / AVIO.C next >
C/C++ Source or Header  |  1989-02-08  |  17KB  |  572 lines

  1. /*
  2.     avio.c -- AVIO action routines
  3.  
  4.     Implements scrollbars, sets up an AVIO Presentation Space
  5. */
  6. #define  INCL_AVIO
  7. #define     INCL_DEV
  8. #define  INCL_VIO
  9. #define  INCL_WINWINDOWMGR
  10. #define  INCL_WINSYS
  11. #define  INCL_WINMESSAGEMGR
  12. #define  INCL_WINTRACKRECT
  13. #define  INCL_WINFRAMEMGR
  14. #define  INCL_WINSCROLLBARS
  15. #include <os2.h>
  16. #include <string.h>    /* One strlen() call in the Blast() macro */
  17. #include "avio.h"    /* Get Avio-prefixed routine prototypes   */
  18. /*
  19.     Constants
  20. */
  21. char    Blank[2] = { 0x20, 0x07 };    /* <Space> + EGA white attribute */
  22. /*
  23.     Macros to make the code more readable
  24. */
  25. /* Upper and Lower Bound Calculations */
  26. #define    Abs(a)        (((a) > 0) ? (a) : (-(a)))
  27. #define    Min(a,b)    (((a) < (b)) ? (a) : (b))
  28. #define    Max(a,b)    (((a) > (b)) ? (a) : (b))
  29. #define LowerBound(pos, disp, lbound) Max(pos - disp, lbound)
  30. #define UpperBound(pos, disp, ubound) Min(pos + disp, ubound)
  31.  
  32. /* Scroll Bar Abbreviations */
  33. #define DisableSB(hSB)    WinSetParent(hSB, HWND_OBJECT, TRUE)
  34. #define EnableSB(hSB)     WinSetParent(hSB, hWndFrame,   TRUE)
  35. #define SetScroll(h, pos, max) \
  36.     WinSendMsg(h, SBM_SETSCROLLBAR, MPFROM2SHORT(pos, 0), MPFROM2SHORT(0, max))
  37.  
  38. /* Scrollbar redraw macros */
  39. #define UpdateOn(c, hsb)    if (!(++c)) WinEnableWindowUpdate(hsb, TRUE)
  40. #define UpdateOff(c, hsb)    if (!(c--)) WinEnableWindowUpdate(hsb, FALSE)
  41. #define    UpdateFrame(sb)    \
  42.     WinSendMsg(hWndFrame, WM_UPDATEFRAME, MPFROMLONG(sb), 0L)
  43.  
  44. /* Scrolling Macros */
  45. #define ClearScreen()    ScrollUp(-1)    /* Scroll up an "infinite" # lines */
  46. #define ScrollDown(n)    VioScrollDn(0, 0, -1, -1, n, Blank, hVPS)
  47. #define ScrollUp(n)    VioScrollUp(0, 0, -1, -1, n, Blank, hVPS)
  48.  
  49. /* RectL -> SWP conversion macros */
  50. #define    lcx(r)        ((r.xRight - r.xLeft) + 1)
  51. #define    lcy(r)        ((r.yTop - r.yBottom) + 1)
  52.  
  53. /* Miscellaneous macros */
  54. #define Blast(l, x, y)    VioWrtCharStr(l, Min(strlen(l), cxChScreen), x, y, hVPS)
  55. #define CalcChars(sPg, sCh) \
  56.     ((sCh) ? (Max(((sPg) / (sCh)), 0)) : 0)
  57. #define    SetCellSize(h,w) VioSetDeviceCellSize(h, w, hVPS)
  58. #define    Value(value)    WinQuerySysValue(HWND_DESKTOP, value)
  59. /*
  60.     File-Local Variables
  61. */
  62. HDC    hDC;        /* Device Context */
  63. HVPS    hVPS;        /* Virtual PS */
  64. int    iTopLine;    /* PS Line of window corner */
  65. int    iCurCol;     /* Current column of window corner */
  66. int    cxChPage;    /* Width and height of our window, in characters */
  67. int    cyChPage;
  68. int    iMaxHorz;    /* Scroll bar upper bounds */
  69. int    iMaxVert;    
  70. BOOL    fNeedHorz;    /* Do we need the scroll bars or not? */
  71. BOOL    fNeedVert;
  72. HWND    hWndHorzSB;    /* Window handles of ScrollBar windows */
  73. HWND    hWndVertSB;
  74. extern    HWND    hWndFrame;    /* Client, frame windows */
  75. extern    HWND    hWndClient;
  76. PFNWP    pfnOldClient;    /* Old Client Window Procedure pointer */
  77. PFNWP    pfnOldFrame;    /* Old Frame  Window Procedure pointer */
  78. SHORT    cyChPS;        /* Number of rows in AVIO PS */
  79. SHORT    cxChPS;        /* Number of cols in AVIO PS */
  80. SHORT    cyChScreen;        /* Number of rows in display space */
  81. SHORT    cxChScreen;        /* Number of cols in display space */
  82. PFNQL    pfnQueryLine;
  83. /*
  84.     Measurements used to help make the window look nice
  85. */
  86. LONG    cxConstant, cyConstant;            /* Miscellaneous frame lens */
  87. int    cxMaxFrame, cyMaxFrame;            /* Maximum frame widths */
  88. LONG    lChWidth,   lChHeight;
  89. SHORT    cxMaxClient, cyMaxClient;        /* Client area bounds  */
  90. BOOL    fCreatedPS;                /* AVIO PS created */
  91. int    cHUpdate = -1;                /* Keep track of updates */
  92. int    cVUpdate = -1;
  93. /*
  94.    Local prototypes
  95. */
  96. void FixScroll(BOOL, BOOL, HWND, ULONG, int *, int, int *);
  97. void UpdateScrollBars(RECTL);
  98. void Refresh(void);
  99. void Update(USHORT, USHORT, USHORT);
  100. /*
  101.     The actual routines
  102. */
  103. void AvioInit(PLBINFO plbi) {
  104. /*
  105.     Initialize Presentation Space, Device Context, Scroll Bars
  106. */
  107.     VIOCURSORINFO vci;
  108.     /*
  109.     Initialize the line buffer info 
  110.     */
  111.     cyChScreen    = plbi->sRows;
  112.     cxChScreen    = plbi->sCols;
  113.     cyChPS    = plbi->sPSrows;
  114.     cxChPS    = plbi->sPScols;
  115.     pfnQueryLine = plbi->pfnQL;
  116.     /*
  117.     One Time Initializations...
  118.     */
  119.     if (!fCreatedPS) {
  120.     /*
  121.        Create the AVIO Presentation Space, with one attribute byte
  122.     */
  123.     hDC = WinOpenWindowDC(hWndClient);    /* Open the device context */
  124.     VioCreatePS(&hVPS, cyChPS, cxChPS, 0, 1, 0);
  125.     VioAssociate(hDC, hVPS);        /* Link the PS with the DC */
  126.     /*
  127.         Turn off the cursor (set invisible attribute)
  128.     */
  129.     VioGetCurType(&vci, hVPS);
  130.     vci.attr = -1;
  131.     VioSetCurType(&vci, hVPS);
  132.     /*
  133.         Measure the frame components
  134.     */
  135.     cxConstant = 0;
  136.     cyConstant = Value(SV_CYTITLEBAR) + Value(SV_CYMENU);
  137.         /*
  138.         Snag scroll bar info
  139.     */
  140.     hWndHorzSB    = WinWindowFromID(hWndFrame,  FID_HORZSCROLL);
  141.     hWndVertSB    = WinWindowFromID(hWndFrame,  FID_VERTSCROLL);
  142.     fNeedHorz    = fNeedVert    = TRUE;
  143.     /*
  144.         Setup the Client and Frame routines
  145.     */
  146.     pfnOldFrame    = WinSubclassWindow(hWndFrame,  AvioFrameWndProc);
  147.     pfnOldClient    = WinSubclassWindow(hWndClient, AvioClientWndProc);
  148.     fCreatedPS    = TRUE;
  149.     }
  150.     /*
  151.     Repaint the screen
  152.     */
  153.     iTopLine = iCurCol = 0;
  154.     AvioStartup(plbi->fLargeFont);
  155. }
  156.  
  157. void AvioStartup(BOOL fLargeFont) {
  158. /*
  159.     Clear the screen, set the font, redraw the area
  160. */
  161.     RECTL rclFrame;
  162.  
  163.     ClearScreen();
  164.     AvioLargeFont(fLargeFont);
  165.     WinQueryWindowRect(hWndFrame, &rclFrame);
  166.     UpdateScrollBars(rclFrame);
  167.     Update(0, cyChPS, 0);
  168. }
  169.  
  170. void AvioScroll(USHORT SB_Command, USHORT Position, BOOL Horizontal) {
  171. /*
  172.     Process the scroll bar messages
  173.  
  174.     These routines are symmetric; in fact, SB_LINELEFT = SB_LINEUP, etc...
  175.     so one might note that this could be condensed.  It's left expanded for
  176.     speed and clarity.  The scrollbar values are bounded to stay inside
  177.     the Presentation Space.
  178. */
  179.     if (Horizontal) {  /* Horizontal Scroll Bar */
  180.     switch (SB_Command) {
  181.         case SB_LINELEFT:
  182.         iCurCol = LowerBound(iCurCol, 1, 0); break;
  183.         case SB_LINERIGHT:
  184.         iCurCol = UpperBound(iCurCol, 1, iMaxHorz); break;
  185.         case SB_PAGELEFT:
  186.         iCurCol = LowerBound(iCurCol, cxChPage, 0); break;
  187.         case SB_PAGERIGHT:
  188.         iCurCol = UpperBound(iCurCol, cxChPage, iMaxHorz); break;
  189.         case SB_SLIDERTRACK:
  190.         iCurCol = (SHORT) Position;
  191.         default: break;
  192.     }
  193.     if (SB_Command != SB_SLIDERTRACK)
  194.         SetScroll(hWndHorzSB, iCurCol, iMaxHorz);
  195.  
  196.     } else { /* Vertical Scroll Bar */
  197.     switch (SB_Command) {
  198.         case SB_LINEUP:
  199.         iTopLine = LowerBound(iTopLine, 1, 0); break;
  200.         case SB_LINEDOWN:
  201.         iTopLine = UpperBound(iTopLine, 1, iMaxVert); break;
  202.         case SB_PAGEUP:
  203.         iTopLine = LowerBound(iTopLine, cyChPage, 0); break;
  204.         case SB_PAGEDOWN:
  205.         iTopLine = UpperBound(iTopLine, cyChPage, iMaxVert);break;
  206.         case SB_SLIDERTRACK:
  207.         iTopLine = (SHORT) Position;
  208.         default: break;
  209.     }
  210.     if (SB_Command != SB_SLIDERTRACK)
  211.         SetScroll(hWndVertSB, iTopLine, iMaxVert);
  212.     }
  213.     Refresh();
  214. }
  215.  
  216. MRESULT AvioSize(HWND hWnd, USHORT msg, MPARAM mp1, MPARAM mp2) {
  217. /*
  218.     Do the default AVIO sizing, and kyfe a few values
  219. */
  220.     RECTL rclFrame;
  221.  
  222.     if (!fCreatedPS) return 0L;
  223.     /*
  224.     Update the scroll bars, and the screen
  225.     */
  226.     WinQueryWindowRect(hWndFrame, &rclFrame);
  227.     UpdateScrollBars(rclFrame);
  228.     /*
  229.     Now, do the normal AVIO processing
  230.     */
  231.     return WinDefAVioWindowProc(hWnd, msg, mp1, mp2);
  232. }
  233.  
  234. void Update(USHORT usLineNum, USHORT usHowMany, USHORT usStartLine) {
  235. /*
  236.     Updates N lines starting from START line on screen.
  237.     Starts at saved line LINENUM.
  238. */
  239.     USHORT    i;                /* Loop index variable */
  240.     USHORT    usWhichLine = usLineNum;    /* Line number to be queried */
  241.     char    *szLine;
  242.  
  243.     for (i = usStartLine; i < (usStartLine + usHowMany); i++) {
  244.     szLine = (*pfnQueryLine)(usWhichLine++);    /* Get the line */
  245.     if (szLine) Blast(szLine, i, 0);        /* Print it out */
  246.     }
  247. }
  248.  
  249. void Refresh(void) {
  250. /*
  251.     Do the origin shifting and screen updating
  252. */
  253.     SHORT  Delta;
  254.     int static iOldTopLine = 0;
  255.  
  256.     VioSetOrg(0, iCurCol, hVPS); /* Get the free AVIO horizontal shift */
  257.     Delta = iTopLine - iOldTopLine; /* Compute vertical shift */
  258.     if (Abs(Delta) < cyChPS) {
  259.     if (Delta < 0) {     /* Scroll Up -- make Delta positive*/
  260.         ScrollDown(-Delta);
  261.         Update(iTopLine, -Delta, 0);
  262.     } else {        /* Scroll Down by Delta */
  263.         ScrollUp(Delta);
  264.         Update(iTopLine + cyChPS - Delta, Delta, cyChPS - Delta);
  265.     }
  266.     } else AvioRedraw();    /* Redo the entire screen */
  267.     iOldTopLine = iTopLine;
  268. }
  269.  
  270. void AvioClose(void) {
  271. /*
  272.     Termination routines
  273. */
  274.     /*
  275.     Destroy the Presentation Space
  276.     */
  277.     VioAssociate(NULL, hVPS);
  278.     VioDestroyPS(hVPS);
  279.     fCreatedPS = FALSE;
  280. }
  281.  
  282. void AvioPaint(HWND hWnd) {
  283. /*
  284.     Paint the AVIO presentation space by telling it to show itself.
  285.     A possible optimization here is to repaint only the update region.
  286. */
  287.     static HPS     hPS;
  288.     static RECTL RectL;
  289.  
  290.     hPS = WinBeginPaint(hWnd, (HPS) NULL, &RectL);
  291.     VioShowPS(cyChPS, cxChPS, 0, hVPS);
  292.     WinEndPaint(hPS);
  293.  
  294. MRESULT AvioMinMax(PSWP pSWP) {
  295. /*
  296.     Handle WM_MINMAX messages, to make sure frame doesn't get too big
  297. */
  298.     if (pSWP->fs & (SWP_MAXIMIZE | SWP_RESTORE)) {
  299.     if (pSWP->fs & SWP_MAXIMIZE) {
  300.         /*
  301.         Save cx, cy values for later origin displacement
  302.         */
  303.         int Oldcx = pSWP->cx;
  304.         int Oldcy = pSWP->cy;
  305.         /*
  306.         Displace, and change to maximum size
  307.         */
  308.         pSWP->x += (Oldcx -
  309.         (pSWP->cx = cxMaxFrame + (int) (Value(SV_CXSIZEBORDER) << 1)));
  310.         pSWP->y += (Oldcy -
  311.         (pSWP->cy = cyMaxFrame + (int) (Value(SV_CYSIZEBORDER) << 1)));
  312.     }
  313.     /*
  314.         Now, fix the scroll bars
  315.     */
  316.     AvioAdjustFramePos(pSWP);
  317.     return TRUE;
  318.     }
  319.     return FALSE;
  320. }
  321.  
  322. void AvioClear(void) { ClearScreen(); }
  323.  
  324. void AvioAdjustFramePos(PSWP pSWP) {
  325. /*
  326.     Trap WM_ADJUSTWINDOWPOS messages to the frame with this routine.
  327.     Keep the window sized right, and control scrollbar visibility.
  328. */
  329.     RECTL rclFrame;
  330.  
  331.     if (!(pSWP->cx && pSWP->cy)) return;     /* Null area... */
  332.     if (pSWP->fs & SWP_MINIMIZE) return;    /* Iconic... */
  333.     /*
  334.     Make sure the dimensions are in range
  335.     */
  336.     pSWP->cx = Min(pSWP->cx, (cxMaxFrame + (SHORT)(Value(SV_CXSIZEBORDER)<<1)));
  337.     pSWP->cy = Min(pSWP->cy, (cyMaxFrame + (SHORT)(Value(SV_CYSIZEBORDER)<<1)));
  338.     /*
  339.     Update the scroll bars
  340.     */
  341.     rclFrame.xLeft    = (LONG) pSWP->x;
  342.     rclFrame.xRight    = (LONG) (pSWP->x + pSWP->cx - 1);
  343.     rclFrame.yBottom    = (LONG) pSWP->y;
  344.     rclFrame.yTop    = (LONG) (pSWP->y + pSWP->cy - 1);
  345.     UpdateScrollBars(rclFrame);
  346.  
  347.     return; 
  348. }
  349.  
  350. void AvioTrackFrame(HWND hWnd, MPARAM mpTrackFlags) {
  351. /*
  352.     Takes action on WM_TRACKFRAME message
  353. */
  354.     static TRACKINFO tiTrackInfo;
  355.     /*
  356.     Get the tracking information in the TrackInfo structure
  357.     */
  358.     WinSendMsg(hWnd, WM_QUERYTRACKINFO, mpTrackFlags, &tiTrackInfo);
  359.     WinTrackRect(hWnd, NULL, &tiTrackInfo);
  360. }
  361.  
  362. void AvioQueryTrackInfo(PTRACKINFO pTI) {
  363. /*
  364.     Routine which processes WM_QUERYTRACKINFO messages to the frame.
  365.     Call this routine after the default one to change various parameters.
  366.  
  367.     Note:  In reality, since we have a menu bar, we should make the
  368.     minimum width of the window something such that it does not "fold."
  369. */
  370.     BOOL fMove;
  371.     /*
  372.     Get the grid set up for byte alignment (unless moving)
  373.     */
  374.     fMove = ((pTI->fs & TF_MOVE) == TF_MOVE);
  375.     pTI->fs     |= TF_GRID;
  376.     pTI->cxGrid  = (SHORT) lChWidth;
  377.     pTI->cyGrid  = (fMove) ? 1 : ((SHORT) lChHeight);
  378.     /*
  379.     Bound the frame.
  380.     Maximum:    Sizing Border, Scrollbars, Title, Menus, client region
  381.     */
  382.     pTI->ptlMaxTrackSize.x = (LONG) (pTI->cxBorder << 1) + (LONG) cxMaxFrame;
  383.     pTI->ptlMaxTrackSize.y = (LONG) (pTI->cyBorder << 1) + (LONG) cyMaxFrame;
  384. }
  385.  
  386. void AvioRedraw(void) {
  387. /*
  388.     Clear, then redraw the entire Presentation Space
  389. */
  390.     ClearScreen();
  391.     Update(iTopLine, cyChPS, 0);
  392. }
  393.  
  394. MRESULT CALLBACK AvioClientWndProc
  395.     (HWND hWnd, USHORT msg, MPARAM mp1, MPARAM mp2) {
  396. /*
  397.      Window Procedure which traps messages to the Client area
  398. */
  399.      switch (msg) {
  400.       case WM_PAINT:        /* Paint the AVIO way! */
  401.         AvioPaint(hWnd);
  402.         break;
  403.  
  404.       case WM_SIZE:            /* Size the AVIO way!  */
  405.         return AvioSize(hWnd, msg, mp1, mp2);
  406.         break;
  407.  
  408.       case WM_HSCROLL:
  409.         AvioScroll(HIUSHORT(mp2), LOUSHORT(mp2), TRUE);
  410.         break;
  411.  
  412.       case WM_VSCROLL:
  413.         AvioScroll(HIUSHORT(mp2), LOUSHORT(mp2), FALSE);
  414.         break;
  415.  
  416.       case WM_ERASEBACKGROUND:
  417.         break;
  418.  
  419.       case WM_TRACKFRAME:
  420.         AvioTrackFrame(hWnd, mp1);
  421.         break;
  422.  
  423.       case WM_MINMAXFRAME:        /* Limit Maximized window size */
  424.         AvioMinMax((PSWP) mp1);
  425.  
  426.         /* fall through */
  427.  
  428.       default: return (*pfnOldClient)(hWnd, msg, mp1, mp2);
  429.      }
  430.      return 0;
  431. }
  432.  
  433. MRESULT CALLBACK AvioFrameWndProc(HWND hWnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  434. /*
  435.     Force the frame to stay small enough (no larger than the PS)
  436. */
  437. {
  438.     BOOL rc;        /* Return code from WM_QUERYTRACKINFO */
  439.  
  440.     switch(msg) {
  441.     case WM_ADJUSTWINDOWPOS:    /* Calculate scroll bar adjustments */
  442.         AvioAdjustFramePos(mp1);
  443.         break;
  444.  
  445.     case WM_QUERYTRACKINFO:        /* Get default, then process message */
  446.         rc = (BOOL) (*pfnOldFrame)(hWnd, msg, mp1, mp2);
  447.             AvioQueryTrackInfo((PTRACKINFO) mp2);
  448.         return rc;
  449.  
  450.     default: break;
  451.     }
  452.     return (*pfnOldFrame)(hWnd, msg, mp1, mp2);
  453. }
  454.  
  455. void UpdateScrollBars(RECTL rclClient) {
  456. /*
  457.     This routine fixes up the scroll bars when the window is resized, or
  458.     when the font size is changed.
  459.  
  460.     Parameters:    The dimensions of the frame window
  461.     Result:    Updates the scrollbars, enabling/disabling as needed
  462. */
  463.     BOOL    fNeededHorz = fNeedHorz;  /* Did we need the scrollbars then? */
  464.     BOOL    fNeededVert = fNeedVert;
  465.     /*
  466.     Compute the client rectangle, without the scrollbars
  467.     */
  468.     WinCalcFrameRect(hWndFrame, &rclClient, TRUE);
  469.     /*
  470.     Compute page width -- do we need the horizontal scroll bar?
  471.     */
  472.     cxChPage     = (int) CalcChars(lcx(rclClient), lChWidth);
  473.     fNeedHorz = ((iMaxHorz = Max(cxChScreen - cxChPage,  0)) > 0);
  474.     /*
  475.     Compute page height -- do we need the vertical scroll bar?
  476.     */
  477.     cyChPage     = (int) CalcChars(lcy(rclClient), lChHeight);
  478.     fNeedVert = ((iMaxVert = Max(cyChScreen - cyChPage, 0)) > 0);
  479.     /*
  480.     Maintain scrollbar integrity
  481.     */
  482.     iCurCol    = Min(iCurCol, iMaxHorz);
  483.     iTopLine    = Min(iTopLine, iMaxVert);
  484.     /*
  485.     Now, update the scrollbars as necessary
  486.     */
  487.     FixScroll(fNeededHorz, fNeedHorz, hWndHorzSB,
  488.           FCF_HORZSCROLL, &iCurCol, iMaxHorz, &cHUpdate);
  489.  
  490.     FixScroll(fNeededVert, fNeedVert, hWndVertSB,
  491.           FCF_VERTSCROLL, &iTopLine, iMaxVert, &cVUpdate);
  492.     /*
  493.     Now, update the screen to be visually consistent
  494.     */
  495.     Refresh();
  496. }
  497.  
  498. void FixScroll(fNeeded, fNeed, hWnd, flScroll, piPos, iMax, pc)
  499. /*
  500.     This routine makes the necessary scrollbar adjustments, and
  501.     also enables/disables them.
  502. */
  503. BOOL    fNeeded;        /* Whether we used to need the scrollbar */
  504. BOOL    fNeed;            /* Whether we need the scrollbar now */
  505. HWND    hWnd;            /* Handle to the scrollbar window */
  506. ULONG    flScroll;        /* FCF_xxxxSCROLL flag (for the scrollbar) */
  507. int    *piPos;         /* Current location of scrollbar thumb */
  508. int    iMax;            /* New maximum for the scrollbar */
  509. int    *pc;            /* Counter for WinEnableWindowUpdate recursion */
  510. {
  511.     if (fNeed) {    /* Enable the scroll bar -- we didn't need it before */
  512.     if (!fNeeded) {
  513.         EnableSB(hWnd);
  514.         UpdateOff((*pc), hWnd);
  515.         UpdateFrame(flScroll);
  516.         UpdateOn((*pc), hWnd);
  517.     }
  518.     SetScroll(hWnd, (*piPos) = Min((*piPos), iMax), iMax);
  519.     } else {        /* Disable the scroll bar, we no longer need it */
  520.     if (fNeeded) {
  521.         DisableSB(hWnd);
  522.         UpdateOff((*pc), hWnd);
  523.         UpdateFrame(flScroll);
  524.         UpdateOn((*pc), hWnd);
  525.     }
  526.     }
  527. }
  528.  
  529. void AvioLargeFont(BOOL fLargeFont) {
  530.     static BOOL fFirst = TRUE;                    // Need to init?
  531.     static LONG lSmallHt, lSmallWd, lLargeHt, lLargeWd;     // Font sizes
  532.     SWP swp;
  533.  
  534.     if (fFirst) {
  535.     /*
  536.         The first time through, get the small and large font sizes
  537.     */
  538.     DevQueryCaps(hDC, CAPS_CHAR_HEIGHT,        1L, &lLargeHt);
  539.     DevQueryCaps(hDC, CAPS_CHAR_WIDTH,        1L, &lLargeWd);
  540.     DevQueryCaps(hDC, CAPS_SMALL_CHAR_HEIGHT,    1L, &lSmallHt);
  541.     DevQueryCaps(hDC, CAPS_SMALL_CHAR_WIDTH,    1L, &lSmallWd);
  542.     fFirst = FALSE;
  543.     }
  544.     /*
  545.     Set the character size with VioSetDeviceCellSize
  546.     */
  547.     SetCellSize( (SHORT) (lChHeight = ((fLargeFont) ? lLargeHt : lSmallHt)),
  548.          (SHORT) (lChWidth  = ((fLargeFont) ? lLargeWd : lSmallWd)) );
  549.     /*
  550.     Compute maximum size of client area
  551.     */
  552.     cxMaxClient    = (cxChPS * (SHORT) lChWidth);
  553.     cxMaxFrame    = cxMaxClient + (SHORT) cxConstant;
  554.     cyMaxClient = (cyChPS * (SHORT) lChHeight);
  555.     cyMaxFrame  = cyMaxClient + (SHORT) cyConstant;
  556.     /*
  557.     Send a WM_ADJUSTFRAMEPOS message
  558.     */
  559.     WinQueryWindowPos(hWndFrame, &swp);
  560.     if (swp.fs & SWP_MAXIMIZE) {
  561.     AvioMinMax(&swp);
  562.     WinSetMultWindowPos(hWndFrame, &swp, 1);
  563.     } else {
  564.     swp.fs = SWP_ACTIVATE | SWP_MOVE | SWP_SHOW | SWP_SIZE;
  565.     WinSetWindowPos(hWndFrame, NULL, swp.x, swp.y,
  566.         Min(cxMaxFrame, swp.cx), Min(cyMaxFrame, swp.cy), swp.fs);
  567.     }
  568.     AvioAdjustFramePos(&swp);        /* Fix up the frame, scroll bars */
  569.     AvioPaint(hWndClient);        /* Repaint with new characters   */
  570. }
  571.