home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / d / d020_1_4 / 6.ddi / TTY / WSTDIO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-01  |  15.9 KB  |  585 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 "wstdio.h"
  27.  
  28. //========================================================================\\
  29.  
  30. // Declarations
  31.  
  32. //========================================================================\\
  33.  
  34. #define MaxLines   25
  35. #define MaxLine    MaxLines - 1
  36. char sScrBuff[MaxLines][81];    // Array of characters on TTY
  37.                                  // could make this heap object so can realloc
  38. short nFirstLine;        // Index of first line on TTY in the array
  39. short nLastLine;        // Index of last line on TTY in the array
  40.  
  41. short nCurrPos;         // Current TTY line output position
  42. short nStdioCharWidth,
  43.       nStdioCharHeight;     // width and height of Stdio font chars
  44.  
  45.  
  46. DWORD StdiobkRGB;                      // background color
  47. DWORD StdiotextRGB;                    // text color
  48. #define Stdio_FONT SYSTEM_FIXED_FONT   // font used for display
  49. HFONT hOldFont;
  50. HWND hWndStdio = NULL;                 // Handle to standard I/O window 
  51. HANDLE hStdioInst;
  52. BOOL bStdioQuit;
  53. BOOL bInited = FALSE;
  54.  
  55.  
  56. //========================================================================\\
  57.  
  58. // FUNCTION: SetupStdioDC(HWND, HDC)
  59.  
  60. // PURPOSE:  Sets up the I/O window DC. Called at GetDC/BeginPaint time.
  61.  
  62. //========================================================================\\
  63.  
  64. void SetupStdioDC(HWND hWnd, HDC hDC)
  65. {
  66.     RECT rClRect;
  67.  
  68.     GetClientRect(hWnd,&rClRect);
  69.  
  70.     // set origin to 25(+1 extra) lines from the bottom of the window
  71.     SetViewportOrg(hDC,0,rClRect.bottom - ((MaxLines+1) * nStdioCharHeight));
  72.  
  73.     SetMapMode(hDC, MM_ANISOTROPIC);
  74.  
  75.     // Set the extents such that one unit horizontally or 
  76.     // vertically is one character width or height.
  77.     SetWindowExt(hDC,1,1);
  78.  
  79.     // Set the viewport such that the last line in the buffer is 
  80.     // displayed at the bottom of the window. 
  81.     SetViewportExt(hDC,nStdioCharWidth,nStdioCharHeight);
  82.  
  83.     // Set the background mode to opaque, and select the font.
  84.     SetBkMode(hDC,OPAQUE);
  85.     hOldFont = SelectObject(hDC,GetStockObject(Stdio_FONT));
  86.  
  87. }
  88.  
  89.  
  90. //========================================================================\\
  91.  
  92. // FUNCTION: ResetStdioDC(HDC)
  93.  
  94. // PURPOSE:  Prepare to release the DC by selecting the system font.
  95.  
  96. //========================================================================\\
  97.  
  98. void ResetStdioDC(HDC hDC)
  99. {
  100.     SelectObject(hDC,hOldFont);
  101. }
  102.  
  103.  
  104.  
  105. //========================================================================\\
  106.  
  107. // FUNCTION: GetStdioLine(short)
  108.  
  109. // PURPOSE:  Return a pointer to the specified line of the display.
  110.  
  111. //========================================================================\\
  112.  
  113. char *GetStdioLine(short ndx)
  114. {
  115.     short pos;
  116.  
  117.     // find the first line (one past the last line since we have a 
  118.     // circular buffer). index to the desired line from there.
  119.     pos = nLastLine + 1;
  120.     if(pos == MaxLines) pos = 0;
  121.  
  122.     pos = pos + ndx;
  123.     if(pos > MaxLine) pos = pos - MaxLines;
  124.  
  125.     return(sScrBuff[pos]);
  126. }
  127.  
  128.  
  129.  
  130. //========================================================================\\
  131.  
  132. // FUNCTION: StdioUpdate(HWND, HDC, int)
  133.  
  134. // PURPOSE:  Scroll the window by the number of lines we have received,
  135. //           and display the text in the invalidated areas.
  136.  
  137. //========================================================================\\
  138.  
  139. void StdioUpdate(HWND hWnd, HDC hDC, int iLinesOut)
  140. {
  141.     RECT rcRect;
  142.  
  143.     if(iLinesOut > 0){
  144.  
  145.          // scroll screen by number of lines received
  146.      GetClientRect(hWnd,&rcRect);
  147.      rcRect.bottom -= nStdioCharHeight;
  148.     
  149.      ScrollWindow(hWnd,0,-(nStdioCharHeight * iLinesOut),&rcRect,NULL);
  150.     }
  151.  
  152.     UpdateWindow(hWnd);
  153. }
  154.  
  155.  
  156. //========================================================================\\
  157.  
  158. // FUNCTION: putStdio(HWND, HDC, WORD, LPSTR)
  159.  
  160. // PURPOSE:  Process incoming text to Stdio window.
  161.  
  162. //========================================================================\\
  163.  
  164. void putStdio(HWND hWnd, HDC hDC, WORD wParam, LPSTR lParam)
  165. {
  166.     short i, j;
  167.     char *sBuffer;
  168.     RECT rClRect, rcInvalid;
  169.     char *psLine;
  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, rcClient;
  271.     int nVPaintBeg, nVPaintEnd, nHPaintBeg, nHPaintEnd;
  272.  
  273.     hDC = BeginPaint( hWnd, (LPPAINTSTRUCT)&ps );
  274.     SetupStdioDC(hWnd,hDC);
  275.  
  276.     rcUpdate = ps.rcPaint;
  277.     DPtoLP(hDC,(POINT *) &rcUpdate, 2);
  278.  
  279.     // calculate first and last lines to update
  280.     nVPaintBeg = max (0, rcUpdate.top);
  281.     nVPaintEnd = min (MaxLines, rcUpdate.bottom);
  282.  
  283.     // calculate the first and last columns to update
  284.     nHPaintBeg = max (0, rcUpdate.left);
  285.     nHPaintEnd = min (80, rcUpdate.right);
  286.  
  287.     // display the lines that need to be drawn
  288.     for(i=nVPaintBeg; i<nVPaintEnd; i++){
  289.     psLine = GetStdioLine(i) + nHPaintBeg;
  290.         TextOut(hDC,
  291.         nHPaintBeg,
  292.                 i,
  293.         psLine,
  294.         strlen(psLine));
  295.     }
  296.     ResetStdioDC(hDC);
  297.     EndPaint( hWnd, (LPPAINTSTRUCT)&ps );
  298.  
  299. }
  300.  
  301.  
  302. //========================================================================\\
  303.  
  304. // FUNCTION: InitStdio(HWND)
  305.  
  306. // PURPOSE:  Initialize variables used by I/O window.
  307.  
  308. //========================================================================\\
  309.  
  310. void InitStdio(HWND hWnd)
  311. {
  312.     int i,j;
  313.     HDC hDC;
  314.     TEXTMETRIC Metrics;
  315.  
  316.     // initialize screen buffer to nulls 
  317.     for(i=0; i<MaxLines; i++)
  318.     for(j=0; j<81; j++)
  319.         sScrBuff[i][j] = '\0';
  320.  
  321.     nFirstLine = 0;
  322.     nLastLine = MaxLine;
  323.     nCurrPos = 0;
  324.  
  325.     // get the text metrics for the font we are using
  326.     hDC = GetDC(hWnd);
  327.     hOldFont = SelectObject(hDC,GetStockObject(Stdio_FONT));
  328.     GetTextMetrics(hDC,&Metrics);
  329.     SelectObject(hDC,hOldFont);
  330.     ReleaseDC(hWnd,hDC);
  331.  
  332.     // calculate the height and width of the font 
  333.     nStdioCharWidth = Metrics.tmMaxCharWidth;
  334.     nStdioCharHeight = Metrics.tmHeight + Metrics.tmExternalLeading;
  335.  
  336.     // get the background and forground colors we are going to use
  337.     StdiobkRGB = GetSysColor(COLOR_WINDOW); // background color
  338.     StdiotextRGB = GetSysColor(COLOR_WINDOWTEXT); // text color
  339.  
  340.     bInited = TRUE;
  341.  
  342. }
  343.  
  344.  
  345. //========================================================================\\
  346.  
  347. // FUNCTION: stdioInit(HANDLE)
  348.  
  349. // PURPOSE:  Initialize the stdio module. Registers the window class.
  350.  
  351. // RETURNS:  Status of RegisterClass().
  352.  
  353. //========================================================================\\
  354.  
  355. BOOL stdioInit(HANDLE hInstance)
  356. {
  357.  
  358.     PWNDCLASS pStdioClass;
  359.     HWND hDummyWnd;
  360.  
  361.     if(hInstance == NULL) return FALSE;
  362.  
  363.     // create the stdio window
  364.     pStdioClass = (PWNDCLASS)LocalAlloc( LPTR, sizeof(WNDCLASS) );
  365.  
  366.     pStdioClass->hCursor        = LoadCursor( NULL, IDC_ARROW );
  367.     pStdioClass->lpszClassName  = (LPSTR)"Stdio";
  368.     pStdioClass->hbrBackground  = COLOR_WINDOW + 1;
  369.     pStdioClass->hInstance      = hInstance;
  370.     pStdioClass->style        = CS_HREDRAW | CS_VREDRAW;
  371.     pStdioClass->lpfnWndProc    = StdioWndProc;
  372.  
  373.     if (!RegisterClass( (LPWNDCLASS)pStdioClass ) )
  374.         // Initialization failed.
  375.         // Windows will automatically deallocate all allocated memory.
  376.         return FALSE;
  377.  
  378.     LocalFree( (HANDLE)pStdioClass );
  379.  
  380.     hStdioInst = hInstance;
  381.     return TRUE;
  382. }
  383.  
  384.  
  385. //========================================================================\\
  386.  
  387. // FUNCTION: wopen(HWND, BOOL)
  388.  
  389. // PURPOSE:  Create a default style stdio window. If bQuit is TRUE, 
  390. //           PostQuitMessage will be called when the window is closed. 
  391. //           Therefore, the stdio window can be used for the main 
  392. //           application window.
  393.  
  394. // RETURNS:  Handle to window created. 
  395.  
  396. //========================================================================\\
  397.  
  398. HWND wopen(HWND hWndParent, BOOL bQuit)
  399. {
  400.  
  401.     // if window already created, return handle
  402.     if(hWndStdio != NULL) return hWndStdio;
  403.  
  404.     hWndStdio = CreateWindow((LPSTR)"Stdio",
  405.                     (LPSTR)"STDIO",
  406.             WS_OVERLAPPEDWINDOW,
  407.                     CW_USEDEFAULT,
  408.                     CW_USEDEFAULT,
  409.                     CW_USEDEFAULT,
  410.                     CW_USEDEFAULT,
  411.                     (HWND)hWndParent,
  412.                     (HMENU)NULL,       
  413.                     (HANDLE)hStdioInst, 
  414.                     (LPSTR)NULL        
  415.                 );
  416.     if(hWndStdio == NULL) return FALSE;
  417.     ShowWindow(hWndStdio, SW_SHOW);
  418.     UpdateWindow(hWndStdio);
  419.  
  420.     bStdioQuit = bQuit;
  421.     return hWndStdio;
  422.  
  423. }
  424.  
  425.  
  426. //========================================================================\\
  427.  
  428. // FUNCTION: CreateStdioWindow(LPSTR, DWORD, int, int, int, int, HWND, 
  429. //                            HANDLE, BOOL)
  430.  
  431. // PURPOSE:  Create an I/O window with definable name, style, size, etc.
  432.  
  433. // RETURNS:  Handle to window created. 
  434.  
  435. //========================================================================\\
  436.  
  437. HWND CreateStdioWindow(LPSTR lpWindowName, DWORD dwStyle,
  438.                        int X, int Y, int nWidth, int nHeight,
  439.                        HWND hWndParent, HANDLE hInstance, BOOL bQuit)
  440. {
  441.  
  442.     // if window already created, return handle
  443.     if(hWndStdio != NULL) return hWndStdio;
  444.  
  445.     hWndStdio = CreateWindow((LPSTR)"Stdio",
  446.                     (LPSTR)lpWindowName,
  447.                     dwStyle,
  448.                     X,
  449.                     Y,
  450.                     nWidth,
  451.                     nHeight,
  452.                     (HWND)hWndParent,
  453.                     (HMENU)NULL,       
  454.                     (HANDLE)hInstance, 
  455.                     (LPSTR)NULL);
  456.  
  457.     if(hWndStdio == NULL) return FALSE;
  458.  
  459.     bStdioQuit = bQuit;
  460.     return hWndStdio;
  461. }
  462.  
  463.  
  464. //========================================================================\\
  465.  
  466. // FUNCTION: wputs(LPSTR)
  467.  
  468. // PURPOSE:  Equivalent to puts() stdio function. Currently, '\n' is
  469. //           not recognized as in '\r\n', as with normal puts(). Must 
  470. //           send '\r\n' explicitly.
  471.  
  472. // RETURNS:  Status of wopen(), if called, otherwise TRUE.
  473.  
  474. //========================================================================\\
  475.  
  476.  
  477. BOOL wputs(LPSTR lpStr)
  478. {
  479.     HDC hDC;
  480.     int nStrLen;
  481.  
  482.     // if being used for quick and dirty text output, a stdio window
  483.     // will be opened if it hasn't been already.
  484.     if(hWndStdio == NULL) if(wopen(NULL, FALSE) == NULL) return FALSE;
  485.  
  486.     hDC = GetDC(hWndStdio);
  487.     SetupStdioDC(hWndStdio,hDC);
  488.     nStrLen = lstrlen(lpStr);
  489.  
  490.     putStdio(hWndStdio,hDC,nStrLen,(LPSTR)lpStr);
  491.  
  492.     ResetStdioDC(hDC);
  493.     ReleaseDC(hWndStdio,hDC);
  494.  
  495.     return TRUE;
  496. }
  497.  
  498.  
  499. //========================================================================\\
  500.  
  501. // FUNCTION: StdioWndProc(HWND, unsigned, WORD, LONG)
  502.  
  503. // PURPOSE:  Process messages for the I/O window. This function should 
  504. //           be exported in the application's .DEF file. 
  505.  
  506. //========================================================================\\
  507.  
  508. long FAR PASCAL StdioWndProc( hWnd, message, wParam, lParam )
  509. HWND hWnd;
  510. unsigned message;
  511. WORD wParam;
  512. LONG lParam;
  513. {
  514.     PAINTSTRUCT ps;
  515.     HDC hDC;
  516.     LPPOINT ptMinMaxInfo;
  517.  
  518.  
  519.     switch (message)
  520.     {
  521.  
  522.     case WM_CREATE:
  523.  
  524.     // initialize stdio variables
  525.     InitStdio(hWnd);
  526.     break;
  527.  
  528.  
  529.     case WM_SYSCOLORCHANGE:
  530.  
  531.     // if the colors have been changed in the control panel,
  532.     // we need to change also.
  533.  
  534.     StdiobkRGB = GetSysColor(COLOR_WINDOW); // background color
  535.     StdiotextRGB = GetSysColor(COLOR_WINDOWTEXT); // text color
  536.         return DefWindowProc( hWnd, message, wParam, lParam );
  537.     break;
  538.  
  539.     case WM_GETMINMAXINFO:
  540.     if(!bInited) InitStdio(hWnd);
  541.  
  542.     // constrain the sizing of the window to 80 by 25 characters.
  543.  
  544.     ptMinMaxInfo = (LPPOINT) lParam;
  545.  
  546.     ptMinMaxInfo[1].x = nStdioCharWidth * 80
  547.                  + 2 * GetSystemMetrics(SM_CXFRAME);
  548.     ptMinMaxInfo[1].y = nStdioCharHeight * 26
  549.                  + 2 * GetSystemMetrics(SM_CYFRAME);
  550.  
  551.     ptMinMaxInfo[4].x = nStdioCharWidth * 80
  552.                  + 2 * GetSystemMetrics(SM_CXFRAME);
  553.     ptMinMaxInfo[4].y = nStdioCharHeight * 26
  554.                  + 2 * GetSystemMetrics(SM_CYFRAME);
  555.     break;
  556.  
  557.     case WM_PAINT:
  558.  
  559.     // repaint the Stdio window
  560.     StdioPaint(hWnd);
  561.     break;
  562.  
  563.     case WM_DESTROY:
  564.  
  565.     // if specified when created, PostQuitMessage should be called
  566.     // when the window is destroyed.
  567.  
  568.         if(bStdioQuit)
  569.             PostQuitMessage(0);
  570.         break;
  571.  
  572.     case WM_CLOSE:
  573.         // destroy stdio data
  574.         hWndStdio = NULL;
  575.  
  576.         // go ahead and close down
  577.         // -- fall through to default --
  578.     default:
  579.         return DefWindowProc( hWnd, message, wParam, lParam );
  580.         break;
  581.     }
  582.     return(0L);
  583. }
  584. 
  585.