home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c221 / 7.ddi / MWHC.007 / VB < prev    next >
Encoding:
Text File  |  1991-08-28  |  15.7 KB  |  570 lines

  1. //
  2.  
  3. //    FILE:    WSTDIO.c
  4.  
  5. //    PURPOSE: Contains functions for managing a standard I/O window.
  6. //          Provides a means for easily sending text to a window 
  7. //          for debugging, etc.
  8.  
  9. //    FUNCTIONS:
  10. //          SetupStdioDC() - Initializes DC.
  11. //          ResetStdioDC() - Selects former font into DC.
  12. //          GetStdioLine() - Returns pointer to specified line in buffer.
  13. //          StdioUpdate() - Scroll and update displayed text.
  14. //          putStdio() - Process I/O window messages.
  15. //          StdioPaint() - Paint procedure for I/O window.
  16. //          InitStdio() - Initialize values used by I/O window.
  17. //          stdioInit() - Define/register I/O window class.
  18. //          wopen() - Create a default I/O window.
  19. //          CreateStdioWindow() - Create a customized I/O window.
  20. //          wputs() - Puts a string in the I/O window.
  21. //          StdioWndProc() - Processes messages for the I/O window.
  22. //                          
  23.  
  24.  
  25. #include <windows.h>
  26. #include <string.h>
  27. #include "wstdio.h"
  28.  
  29. //========================================================================
  30.  
  31. // Declarations
  32.  
  33. //========================================================================
  34.  
  35. #define MaxLines   25
  36. #define MaxLine    MaxLines - 1
  37. char sScrBuff[MaxLines][81];    // Array of characters on TTY
  38.                                  // could make this heap object so can realloc
  39. short nFirstLine;        // Index of first line on TTY in the array
  40. short nLastLine;        // Index of last line on TTY in the array
  41.  
  42. short nCurrPos;         // Current TTY line output position
  43. short nStdioCharWidth,
  44.       nStdioCharHeight;     // width and height of Stdio font chars
  45.  
  46.  
  47. DWORD StdiobkRGB;                      // background color
  48. DWORD StdiotextRGB;                    // text color
  49. #define Stdio_FONT SYSTEM_FIXED_FONT   // font used for display
  50. HFONT hOldFont;
  51. HWND hWndStdio = NULL;                 // Handle to standard I/O window 
  52. HANDLE hStdioInst;
  53. BOOL bStdioQuit;
  54. BOOL bInited = FALSE;
  55.  
  56.  
  57. //========================================================================
  58.  
  59. // FUNCTION: SetupStdioDC(HWND, HDC)
  60.  
  61. // PURPOSE:  Sets up the I/O window DC. Called at GetDC/BeginPaint time.
  62.  
  63. //========================================================================
  64.  
  65. void SetupStdioDC(HWND hWnd, HDC hDC)
  66. {
  67.     RECT rClRect;
  68.  
  69.     GetClientRect(hWnd,&rClRect);
  70.  
  71.     // set origin to 25(+1 extra) lines from the bottom of the window
  72.     SetViewportOrg(hDC,0,rClRect.bottom - ((MaxLines+1) * nStdioCharHeight));
  73.  
  74.     SetMapMode(hDC, MM_ANISOTROPIC);
  75.  
  76.     // Set the extents such that one unit horizontally or 
  77.     // vertically is one character width or height.
  78.     SetWindowExt(hDC,1,1);
  79.  
  80.     // Set the viewport such that the last line in the buffer is 
  81.     // displayed at the bottom of the window. 
  82.     SetViewportExt(hDC,nStdioCharWidth,nStdioCharHeight);
  83.  
  84.     // Set the background mode to opaque, and select the font.
  85.     SetBkMode(hDC,OPAQUE);
  86.     hOldFont = SelectObject(hDC,GetStockObject(Stdio_FONT));
  87.  
  88. }
  89.  
  90.  
  91. //========================================================================
  92.  
  93. // FUNCTION: ResetStdioDC(HDC)
  94.  
  95. // PURPOSE:  Prepare to release the DC by selecting the system font.
  96.  
  97. //========================================================================
  98.  
  99. void ResetStdioDC(HDC hDC)
  100. {
  101.     SelectObject(hDC,hOldFont);
  102. }
  103.  
  104.  
  105.  
  106. //========================================================================
  107.  
  108. // FUNCTION: GetStdioLine(short)
  109.  
  110. // PURPOSE:  Return a pointer to the specified line of the display.
  111.  
  112. //========================================================================
  113.  
  114. char *GetStdioLine(short ndx)
  115. {
  116.     short pos;
  117.  
  118.     // find the first line (one past the last line since we have a 
  119.     // circular buffer). index to the desired line from there.
  120.     pos = nLastLine + 1;
  121.     if(pos == MaxLines) pos = 0;
  122.  
  123.     pos = pos + ndx;
  124.     if(pos > MaxLine) pos = pos - MaxLines;
  125.  
  126.     return(sScrBuff[pos]);
  127. }
  128.  
  129.  
  130.  
  131. //========================================================================
  132.  
  133. // FUNCTION: StdioUpdate(HWND, HDC, int)
  134.  
  135. // PURPOSE:  Scroll the window by the number of lines we have received,
  136. //           and display the text in the invalidated areas.
  137.  
  138. //========================================================================
  139.  
  140. void StdioUpdate(HWND hWnd, HDC hDC, int iLinesOut)
  141. {
  142.     RECT rcRect;
  143.  
  144.     if(iLinesOut > 0){
  145.  
  146.          // scroll screen by number of lines received
  147.      GetClientRect(hWnd,&rcRect);
  148.      rcRect.bottom -= nStdioCharHeight;
  149.     
  150.      ScrollWindow(hWnd,0,-(nStdioCharHeight * iLinesOut),&rcRect,NULL);
  151.     }
  152.  
  153.     UpdateWindow(hWnd);
  154. }
  155.  
  156.  
  157. //========================================================================
  158.  
  159. // FUNCTION: putStdio(HWND, HDC, WORD, LPSTR)
  160.  
  161. // PURPOSE:  Process incoming text to Stdio window.
  162.  
  163. //========================================================================
  164.  
  165. void putStdio(HWND hWnd, HDC hDC, WORD wParam, LPSTR lParam)
  166. {
  167.     short i, j;
  168.     char *sBuffer;
  169.     RECT rcInvalid;
  170.     short iLinesOut = 0;    // # of lines to scroll
  171.  
  172.     sBuffer = sScrBuff[nLastLine]; // pointer to current line
  173.  
  174.     // scan the text, handle any special characters, and display the rest.
  175.  
  176.     for(i=0; i<wParam; i++){
  177.     switch(lParam[i]) {
  178.  
  179.         case '\r': // return
  180.             // move to the start of the line
  181.         nCurrPos = 0;   // reset the current position in the line
  182.             break;
  183.  
  184.         case '\n': // new line
  185.  
  186.         // "scroll" the window
  187.         ++iLinesOut;    // increment lines to scroll
  188.         nCurrPos = 0;   // reset the current position in the line
  189.  
  190.         ++nLastLine;
  191.         if(nLastLine > MaxLine) nLastLine = 0;
  192.  
  193.             // clear the new line
  194.         sBuffer = sScrBuff[nLastLine];
  195.         for(j=0; j<80; j++) sBuffer[j] = '\0';
  196.             break;
  197.  
  198.         case '\b': // backspace
  199.  
  200.             // move back one space
  201.         if(nCurrPos > 0) {
  202.  
  203.         --nCurrPos;
  204.         sBuffer[nCurrPos] = '\0';
  205.         rcInvalid.top = MaxLine; rcInvalid.bottom = MaxLine + 1;
  206.         rcInvalid.left = nCurrPos;
  207.         rcInvalid.right = nCurrPos + 1;
  208.         LPtoDP(hDC,(POINT *) &rcInvalid, 2);
  209.  
  210.         // invalidate the area so that it gets redrawn
  211.         InvalidateRect(hWnd,&rcInvalid, TRUE);
  212.  
  213.         }
  214.         break;
  215.  
  216.     case '\t':
  217.         // ignore tabs for now
  218.         break;
  219.  
  220.         default:
  221.             //add char to buffer
  222.         if(nCurrPos < 80){
  223.  
  224.         // put the character in the screen buffer
  225.         sBuffer[nCurrPos] = lParam[i]; // add char to screen line
  226.  
  227.         // calculate area to invalidate
  228.         rcInvalid.top = MaxLine; rcInvalid.bottom = MaxLine + 1;
  229.         rcInvalid.left = nCurrPos;
  230.         ++nCurrPos;
  231.         rcInvalid.right = nCurrPos;
  232.  
  233.         // only need to invalidate the area if it is on the last line
  234.         if(iLinesOut == 0) {
  235.             LPtoDP(hDC,(POINT *) &rcInvalid, 2);
  236.             // invalidate the area so that it gets redrawn
  237.             InvalidateRect(hWnd,&rcInvalid, FALSE);
  238.         }
  239.             }
  240.             break;
  241.     }
  242.     // force scroll after 2 lines. you will scroll faster if you increase
  243.     // this, but it may not look good.
  244.  
  245.     if(iLinesOut > 2) {
  246.         StdioUpdate(hWnd, hDC, iLinesOut);
  247.         iLinesOut = 0;
  248.     }
  249.     }
  250.  
  251.     // force scroll and update at the end of each bunch of characters.
  252.     StdioUpdate(hWnd, hDC, iLinesOut);
  253. }
  254.  
  255. //========================================================================
  256.  
  257. // FUNCTION: StdioPaint(HWND)
  258.  
  259. // PURPOSE:  The I/O window paint procedure.  Draws necessary text in 
  260. //           the window.
  261.  
  262. //========================================================================
  263.  
  264. void StdioPaint(HWND hWnd )   
  265. {
  266.     char *psLine;
  267.     register int i;
  268.     PAINTSTRUCT ps;
  269.     HDC hDC;
  270.     RECT rcUpdate;
  271.     LP48POINT lpPoint = (LP48POINT) &rcUpdate.left;
  272.     int nVPaintBeg, nVPaintEnd, nHPaintBeg, nHPaintEnd;
  273.  
  274.     hDC = BeginPaint( hWnd, (LPPAINTSTRUCT)&ps );
  275.     SetupStdioDC(hWnd,hDC);
  276.  
  277.     rcUpdate = ps.rcPaint;
  278.     //DPtoLP(hDC, (POINT *)&rcUpdate, 2);
  279.     DPtoLP(hDC, (LP48POINT)&rcUpdate, 2);
  280.  
  281.     // calculate first and last lines to update
  282.     nVPaintBeg = max (0, rcUpdate.top);
  283.     nVPaintEnd = min (MaxLines, rcUpdate.bottom);
  284.  
  285.     // calculate the first and last columns to update
  286.     nHPaintBeg = max (0, rcUpdate.left);
  287.     nHPaintEnd = min (80, rcUpdate.right);
  288.  
  289.     // display the lines that need to be drawn
  290.     for(i=nVPaintBeg; i<nVPaintEnd; i++){
  291.     psLine = GetStdioLine(i) + nHPaintBeg;
  292.         TextOut(hDC,
  293.         nHPaintBeg,
  294.                 i,
  295.         psLine,
  296.         strlen(psLine));
  297.     }
  298.     ResetStdioDC(hDC);
  299.     EndPaint( hWnd, (LPPAINTSTRUCT)&ps );
  300. }
  301.  
  302.  
  303. //========================================================================
  304.  
  305. // FUNCTION: InitStdio(HWND)
  306.  
  307. // PURPOSE:  Initialize variables used by I/O window.
  308.  
  309. //========================================================================
  310.  
  311. void InitStdio(HWND hWnd)
  312. {
  313.     int i,j;
  314.     HDC hDC;
  315.     TEXTMETRIC Metrics;
  316.  
  317.     // initialize screen buffer to nulls 
  318.     for(i=0; i<MaxLines; i++)
  319.     for(j=0; j<81; j++)
  320.         sScrBuff[i][j] = '\0';
  321.  
  322.     nFirstLine = 0;
  323.     nLastLine = MaxLine;
  324.     nCurrPos = 0;
  325.  
  326.     // get the text metrics for the font we are using
  327.     hDC = GetDC(hWnd);
  328.     hOldFont = SelectObject(hDC,GetStockObject(Stdio_FONT));
  329.     GetTextMetrics(hDC,&Metrics);
  330.     SelectObject(hDC,hOldFont);
  331.     ReleaseDC(hWnd,hDC);
  332.  
  333.     // calculate the height and width of the font 
  334.     nStdioCharWidth = Metrics.tmMaxCharWidth;
  335.     nStdioCharHeight = Metrics.tmHeight + Metrics.tmExternalLeading;
  336.  
  337.     // get the background and forground colors we are going to use
  338.     StdiobkRGB = GetSysColor(COLOR_WINDOW); // background color
  339.     StdiotextRGB = GetSysColor(COLOR_WINDOWTEXT); // text color
  340.  
  341.     bInited = TRUE;
  342.  
  343. }
  344.  
  345.  
  346. //========================================================================
  347.  
  348. // FUNCTION: stdioInit(HANDLE)
  349.  
  350. // PURPOSE:  Initialize the stdio module. Registers the window class.
  351.  
  352. // RETURNS:  Status of RegisterClass().
  353.  
  354. //========================================================================
  355.  
  356. BOOL stdioInit(HANDLE hInstance)
  357. {
  358.  
  359.     PWNDCLASS pStdioClass;
  360.     WNDCLASS  ww;
  361.  
  362.     pStdioClass = &ww;
  363.     memset(pStdioClass, 0, sizeof ww);
  364.  
  365.     if (hInstance == NULL) return FALSE;
  366.  
  367.     pStdioClass->hCursor        = LoadCursor( NULL, IDC_ARROW );
  368.     pStdioClass->lpszClassName  = "Stdio";
  369.     pStdioClass->hbrBackground  = COLOR_WINDOW + 1;
  370.     pStdioClass->hInstance      = hInstance;
  371.     pStdioClass->style        = CS_HREDRAW | CS_VREDRAW;
  372.     pStdioClass->lpfnWndProc    = StdioWndProc;
  373.  
  374.     if (!RegisterClass(pStdioClass))
  375.         // Initialization failed.
  376.         // Windows will automatically deallocate all allocated memory.
  377.         return FALSE;
  378.  
  379.     hStdioInst = hInstance;
  380.     return TRUE;
  381. }
  382.  
  383.  
  384. //========================================================================
  385. // FUNCTION: wopen(HWND, BOOL)
  386. // PURPOSE:  Create a default style stdio window. If bQuit is TRUE, 
  387. //           PostQuitMessage will be called when the window is closed. 
  388. //           Therefore, the stdio window can be used for the main 
  389. //           application window.
  390. // RETURNS:  Handle to window created. 
  391. //========================================================================
  392.  
  393. HWND wopen(HWND hWndParent, BOOL bQuit)
  394. {
  395.     // if window already created, return handle
  396.     if(hWndStdio != NULL) return hWndStdio;
  397.  
  398.     hWndStdio = CreateWindow(
  399.                 "Stdio",
  400.                     "STDIO",
  401.             WS_OVERLAPPEDWINDOW,
  402.                     CW_USEDEFAULT,
  403.                     CW_USEDEFAULT,
  404.                     CW_USEDEFAULT,
  405.                     CW_USEDEFAULT,
  406.                     hWndParent,
  407.                     (HMENU)NULL,       
  408.                     hStdioInst, 
  409.                     (LPSTR)NULL        
  410.                 );
  411.  
  412.     if(hWndStdio == NULL) return FALSE;
  413.     ShowWindow(hWndStdio, SW_SHOW);
  414.     UpdateWindow(hWndStdio);
  415.  
  416.     bStdioQuit = bQuit;
  417.     return hWndStdio;
  418.  
  419. }
  420.  
  421.  
  422. //========================================================================
  423. // FUNCTION: CreateStdioWindow(LPSTR, DWORD, int, int, int, int, HWND, 
  424. //                            HANDLE, BOOL)
  425. // PURPOSE:  Create an I/O window with definable name, style, size, etc.
  426. // RETURNS:  Handle to window created. 
  427. //========================================================================
  428.  
  429. HWND CreateStdioWindow(LPSTR lpWindowName, DWORD dwStyle,
  430.                        int X, int Y, int nWidth, int nHeight,
  431.                        HWND hWndParent, HANDLE hInstance, BOOL bQuit)
  432. {
  433.     // if window already created, return handle
  434.     if (hWndStdio != NULL) {
  435.         return hWndStdio;
  436.     }
  437.  
  438.     hWndStdio = CreateWindow(
  439.                 "Stdio",
  440.             lpWindowName,
  441.                     dwStyle,
  442.                     X,
  443.                     Y,
  444.                     nWidth,
  445.                     nHeight,
  446.                     hWndParent, 
  447.                     (HMENU) NULL,       
  448.                     hInstance, 
  449.             (LPSTR) NULL
  450.             );
  451.     if(hWndStdio == NULL) return FALSE;
  452.  
  453.     bStdioQuit = bQuit;
  454.     return hWndStdio;
  455. }
  456.  
  457.  
  458. //========================================================================
  459.  
  460. // FUNCTION: wputs(LPSTR)
  461.  
  462. // PURPOSE:  Equivalent to puts() stdio function. Currently, '\n' is
  463. //           not recognized as in '\r\n', as with normal puts(). Must 
  464. //           send '\r\n' explicitly.
  465.  
  466. // RETURNS:  Status of wopen(), if called, otherwise TRUE.
  467.  
  468. //========================================================================
  469.  
  470.  
  471. BOOL wputs(LPSTR lpStr)
  472. {
  473.     HDC hDC;
  474.     int nStrLen;
  475.  
  476.     // if being used for quick and dirty text output, a stdio window
  477.     // will be opened if it hasn't been already.
  478.     if(hWndStdio == NULL) if(wopen(NULL, FALSE) == NULL) return FALSE;
  479.  
  480.     hDC = GetDC(hWndStdio);
  481.     SetupStdioDC(hWndStdio,hDC);
  482.     nStrLen = lstrlen(lpStr);
  483.  
  484.     putStdio(hWndStdio,hDC,nStrLen,(LPSTR)lpStr);
  485.  
  486.     ResetStdioDC(hDC);
  487.     ReleaseDC(hWndStdio,hDC);
  488.  
  489.     return TRUE;
  490. }
  491.  
  492.  
  493. //========================================================================
  494.  
  495. // FUNCTION: StdioWndProc(HWND, WORD, WORD, LONG)
  496.  
  497. // PURPOSE:  Process messages for the I/O window. This function should 
  498. //           be exported in the application's .DEF file. 
  499.  
  500. //========================================================================
  501.  
  502. long FAR PASCAL StdioWndProc( hWnd, message, wParam, lParam )
  503. HWND hWnd;
  504. WORD message;
  505. WORD wParam;
  506. LONG lParam;
  507. {
  508.     LPPOINT ptMinMaxInfo;
  509.  
  510.     switch (message)
  511.     {
  512.  
  513.     case WM_CREATE:
  514.     // initialize stdio variables
  515.     InitStdio(hWnd);
  516.     break;
  517.  
  518.  
  519.     case WM_SYSCOLORCHANGE:
  520.     // if the colors have been changed in the control panel,
  521.     // we need to change also.
  522.  
  523.     StdiobkRGB = GetSysColor(COLOR_WINDOW); // background color
  524.     StdiotextRGB = GetSysColor(COLOR_WINDOWTEXT); // text color
  525.         return DefWindowProc( hWnd, message, wParam, lParam );
  526.  
  527.     case WM_GETMINMAXINFO:
  528.     if (!bInited) {
  529.         InitStdio(hWnd);
  530.         }
  531.  
  532.     // constrain the sizing of the window to 80 by 25 characters.
  533.     ptMinMaxInfo = (LPPOINT) BRK_FP(lParam);
  534.  
  535.     ptMinMaxInfo[1].x = nStdioCharWidth * 80
  536.                  + 2 * GetSystemMetrics(SM_CXFRAME);
  537.     ptMinMaxInfo[1].y = nStdioCharHeight * 26
  538.                  + 2 * GetSystemMetrics(SM_CYFRAME);
  539.  
  540.     ptMinMaxInfo[4].x = nStdioCharWidth * 80
  541.                  + 2 * GetSystemMetrics(SM_CXFRAME);
  542.     ptMinMaxInfo[4].y = nStdioCharHeight * 26
  543.                  + 2 * GetSystemMetrics(SM_CYFRAME);
  544.     break;
  545.  
  546.     case WM_PAINT:
  547.     // repaint the Stdio window
  548.     StdioPaint(hWnd);
  549.     break;
  550.  
  551.     case WM_DESTROY:
  552.     // if specified when created, PostQuitMessage should be called
  553.     // when the window is destroyed.
  554.  
  555.         if(bStdioQuit)
  556.             PostQuitMessage(0);
  557.         break;
  558.  
  559.     case WM_CLOSE:
  560.         // destroy stdio data
  561.         hWndStdio = NULL;
  562.  
  563.         // go ahead and close down
  564.         // -- fall through to default --
  565.     default:
  566.         return DefWindowProc( hWnd, message, wParam, lParam );
  567.     }
  568.     return(0L);
  569. }
  570.