Annotation of mstools/samples/sdktools/spy/app/wprintf.c, revision 1.1.1.1

1.1       root        1: 
                      2: /******************************************************************************\
                      3: *       This is a part of the Microsoft Source Code Samples. 
                      4: *       Copyright (C) 1993 Microsoft Corporation.
                      5: *       All rights reserved. 
                      6: *       This source code is only intended as a supplement to 
                      7: *       Microsoft Development Tools and/or WinHelp documentation.
                      8: *       See these sources for detailed information regarding the 
                      9: *       Microsoft samples programs.
                     10: \******************************************************************************/
                     11: 
                     12: /*****************************************************************************\
                     13: *
                     14: * Module: wprintf.c
                     15: *
                     16: *   Contains the routines for using printf windows
                     17: *
                     18: * Functions:
                     19: *
                     20: *   MyCreatePrintfWin()
                     21: *   SetPrintFont()
                     22: *   SetPrintfTabs()
                     23: *   ClearPrintfWindow()
                     24: *   CopyToClipboard()
                     25: *   IsPrintfEmpty()
                     26: *   PrintfWndProc()
                     27: *   DebugPaint()
                     28: *   InsertString()
                     29: *   DebugHScroll()
                     30: *   DebugVScroll()
                     31: *   SetWindowClass()
                     32: *   LinesInDebugWindow()
                     33: *   CharsInDebugWindow()
                     34: *   wprintfSetScrollRange()
                     35: *   NewLine()
                     36: *
                     37: * Comments:
                     38: *
                     39: \*****************************************************************************/
                     40: 
                     41: #include "spy.h"
                     42: 
                     43: 
                     44: 
                     45: /*****************************************************************************\
                     46: *                                                                             
                     47: *  g e n e r a l   c o n s t a n t s                                          
                     48: *                                                                             
                     49: \*****************************************************************************/
                     50: 
                     51: #define MAXBUFLEN 200         /* Maximum string length for wprintf */
                     52: 
                     53: #define FIRST(pTxt) ((pTxt)->iFirst)
                     54: #define TOP(pTxt)   (((pTxt)->iFirst + (pTxt)->iTop) % (pTxt)->iMaxLines)
                     55: #define LAST(pTxt)  (((pTxt)->iFirst + (pTxt)->iCount-1) % (pTxt)->iMaxLines)
                     56: #define INC(pTxt,x) ((x) = ++(x) % (pTxt)->iMaxLines)
                     57: #define DEC(pTxt,x) ((x) = --(x) % (pTxt)->iMaxLines)
                     58: #define OFFSETX (pTxt->Tdx/2)
                     59: #define OFFSETY 1
                     60: #define VARSIZE 1
                     61: 
                     62: #define BOUND(x,mn,mx) ((x) < (mn) ? (mn) : ((x) > (mx) ? (mx) : (x)))
                     63: 
                     64: #define FTwixtI3(l,x,h) ((x)>=(l) && (x<=h))
                     65: 
                     66: #define EnterCrit(p)    EnterCriticalSection(&p->csSync)
                     67: #define LeaveCrit(p)    LeaveCriticalSection(&p->csSync)
                     68: 
                     69: /*****************************************************************************\
                     70: *                                                                              
                     71: *   g l o b a l   v a r i a b l e s                                            
                     72: *                                                                              
                     73: \*****************************************************************************/
                     74: 
                     75: typedef struct {
                     76:     INT     iLen;
                     77:     CHAR    * *hText;
                     78: }   LINE;
                     79: 
                     80: struct TEXT_STRUCT {
                     81:     CRITICAL_SECTION csSync;      // CritSect to sync the threads
                     82: 
                     83:     INT     iFirst;               /* First line in queue */
                     84:     INT     iCount;               /* Number of lines in queue */
                     85:     INT     iTop;                 /* Line at top of window */
                     86:     INT     iLeft;                /* X offset of the window */
                     87:     INT     MaxLen;               /* Max String Length */
                     88:     INT     iMaxLines;            /* max number of LINEs */
                     89:     HFONT   hFont;                /* Font to draw with */
                     90:     DWORD   Tdx, Tdy;             /* Font Size */
                     91:     LINE    arLines[VARSIZE];     /* array of iMaxLines LINEs */
                     92: };
                     93: 
                     94: typedef struct TEXT_STRUCT *PTXT; /* pointer to a text struct */
                     95: typedef PTXT               *HTXT; /* Handle to a text struct */
                     96: 
                     97: PRIVATE INT iSem = 0;
                     98: 
                     99: INT tabs[20];
                    100: INT nTabs = 0;
                    101: 
                    102: /*****************************************************************************\
                    103: *                                                                              
                    104: *   f u n c t i o n   d e f i n i t i o n s                                    
                    105: *                                                                              
                    106: \*****************************************************************************/
                    107: 
                    108: LONG APIENTRY PrintfWndProc(HWND, UINT, WPARAM, LONG);
                    109: 
                    110: PRIVATE VOID DebugPaint(HWND hwnd, LPPAINTSTRUCT pps);
                    111: PRIVATE INT  InsertString (PTXT, CHAR *);
                    112: PRIVATE VOID DebugHScroll(HWND, PTXT, INT);
                    113: PRIVATE VOID DebugVScroll(HWND, PTXT, INT);
                    114: PRIVATE BOOL SetWindowClass (HANDLE, LPSTR);
                    115: PRIVATE INT  LinesInDebugWindow (HWND);
                    116: PRIVATE INT  CharsInDebugWindow (HWND);
                    117: PRIVATE VOID wprintfSetScrollRange (HWND, BOOL);
                    118: PRIVATE VOID NewLine (PTXT pTxt);
                    119: 
                    120: 
                    121: 
                    122: /*****************************************************************************\
                    123: * MyCreatePrintfWin
                    124: *
                    125: * Creates a window to printf to.
                    126: *
                    127: * Arguments:
                    128: *    HWND hwnd - handle to the parent window
                    129: *
                    130: * Returns:
                    131: *    VOID
                    132: \*****************************************************************************/
                    133: 
                    134: VOID
                    135: MyCreatePrintfWin(
                    136:     HWND hwnd
                    137:     )
                    138: {
                    139:     RECT rc;
                    140: 
                    141:     if (ghwndPrintf)
                    142:         DestroyWindow(ghwndPrintf);
                    143: 
                    144:     GetClientRect(hwnd, &rc);
                    145: 
                    146:     ghwndPrintf = CreatePrintfWin(hwnd, ghInst, "", WS_CHILD | WS_VSCROLL |
                    147:         WS_HSCROLL, -gcxBorder, -gcyBorder, rc.right + (2 *gcxBorder),
                    148:         rc.bottom + (2 * gcyBorder), gnLines);
                    149: }
                    150: 
                    151: 
                    152: 
                    153: /*****************************************************************************\
                    154: * DebugPaint(hwnd, pps)                                                       
                    155: *                                                                             
                    156: * The paint function.                                                    
                    157: *                                                                        
                    158: * Arguments:                                                             
                    159: *    HWND hwnd - Window to paint to.                                    
                    160: *    LPPAINTSTRUCT - pps              
                    161: *                                                                              
                    162: *   Returns:                                                                   
                    163: *       nothing                                                                
                    164: *                                                                              
                    165: \*****************************************************************************/
                    166: 
                    167: PRIVATE VOID
                    168: DebugPaint(
                    169:     HWND hwnd,
                    170:     LPPAINTSTRUCT pps
                    171:     )
                    172: {
                    173:     PTXT pTxt;
                    174:     HTXT hTxt;
                    175:     INT iQueue;
                    176:     INT xco;
                    177:     INT yco;
                    178:     INT iLast;
                    179:     HBRUSH hb;
                    180:     COLORREF c;
                    181: 
                    182:     hTxt = (HTXT)GetWindowLong(hwnd, 0);
                    183:     pTxt = *hTxt;
                    184: 
                    185:     SetTextColor(pps->hdc, GetSysColor(COLOR_WINDOWTEXT));
                    186:     c = GetSysColor(COLOR_WINDOW);
                    187:     SetBkColor(pps->hdc, c);
                    188:     hb = CreateSolidBrush(c);
                    189:     if (pTxt->hFont)
                    190:         SelectObject(pps->hdc, pTxt->hFont);
                    191: 
                    192:     iLast  = LAST(pTxt);
                    193:     iQueue = TOP(pTxt);
                    194: 
                    195:     xco = OFFSETX - pTxt->iLeft * pTxt->Tdx;
                    196:     yco = OFFSETY;
                    197: 
                    198:     for (;;)
                    199:     {
                    200:         if (FTwixtI3((INT)pps->rcPaint.top, yco,(INT)pps->rcPaint.bottom)
                    201:             || FTwixtI3((INT)pps->rcPaint.top, yco + (INT)pTxt->Tdy, (INT)pps->rcPaint.bottom))
                    202:         {
                    203:             if (pTxt->arLines[iQueue].hText == NULL
                    204:                 || (LPSTR)*(pTxt->arLines[iQueue].hText) == NULL)
                    205:             {
                    206:                 RECT rcT;
                    207: 
                    208:                 rcT.top = yco;
                    209:                 rcT.bottom = yco+pTxt->Tdy;
                    210:                 rcT.left = pps->rcPaint.left;
                    211:                 rcT.right = pps->rcPaint.right;
                    212:                 FillRect(pps->hdc, &rcT, hb);
                    213:             }
                    214:             else
                    215:             {
                    216:                 TabbedTextOut(pps->hdc, xco, yco,
                    217:                     (LPSTR)*(pTxt->arLines[iQueue].hText),
                    218:                     pTxt->arLines[iQueue].iLen, nTabs, tabs, xco);
                    219:             }
                    220:         }
                    221: 
                    222:         if (iQueue == iLast)
                    223:             break;
                    224: 
                    225:         yco += pTxt->Tdy;
                    226:         INC(pTxt, iQueue);
                    227:     }
                    228: 
                    229:     DeleteObject((HANDLE)hb);
                    230: }
                    231: 
                    232: 
                    233: 
                    234: /*****************************************************************************\
                    235: * SetWindowClass (hInstance)                                                
                    236: *     
                    237: * Registers the window class of the printf window
                    238: *                                                                         
                    239: * Arguments:                                                                 
                    240: *   HANDLE hInstance - instance handle of current instance                    
                    241: *   LPSTR lpch - pointer to class name
                    242: *                                                                              
                    243: * Returns:                                                                   
                    244: *   TRUE if successful, FALSE if not                                       
                    245: \*****************************************************************************/
                    246: 
                    247: PRIVATE BOOL
                    248: SetWindowClass(
                    249:     HANDLE hInstance,
                    250:     LPSTR lpch
                    251:     )
                    252: {
                    253:     WNDCLASS wc;
                    254: 
                    255:     wc.style          = CS_HREDRAW | CS_VREDRAW;
                    256:     wc.lpfnWndProc    = PrintfWndProc;
                    257:     wc.cbClsExtra     = 0;
                    258:     wc.cbWndExtra     = sizeof(HANDLE);
                    259:     wc.hInstance      = hInstance;
                    260:     wc.hIcon          = NULL;
                    261:     wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
                    262:     wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
                    263:     wc.lpszMenuName   = NULL;
                    264:     wc.lpszClassName  = lpch;
                    265: 
                    266:     return RegisterClass(&wc);
                    267: }
                    268: 
                    269: 
                    270: /*****************************************************************************\
                    271: * CreatePrintfWin (hParent, lpchName, dwStyle, x, y, dx, dy, iMaxLines)       
                    272: *                                                                             
                    273: * Creates a window for the depositing of debuging messages.                
                    274: *                                                                              
                    275: * Arguments:                                                                 
                    276: *   HWND hParent - Window handle of the parent window.                          
                    277: *   HANDLE hInstance - Module instance handle.                                     
                    278: *   lPSTR lpchName - String to appear in the caption bar of the debuging window   
                    279: *   DWORD dwStyle - Window style                                                 
                    280: *   INT x,y - Location of window                                           
                    281: *   INT dx,dy - Size of the window                                           
                    282: *   INT iMaxLines - The maximum number of text lines to display in the window    
                    283: *                                                                              
                    284: * Returns:                                                                   
                    285: *   A window handle of the debuging window, or NULL if a error occured.      
                    286: \*****************************************************************************/
                    287: 
                    288: PUBLIC HWND APIENTRY
                    289: CreatePrintfWin (
                    290: HWND   hParent,
                    291: HANDLE hInstance,
                    292: LPSTR  lpchName,
                    293: DWORD  dwStyle,
                    294: INT   x,
                    295: INT   y,
                    296: INT   dx,
                    297: INT   dy,
                    298: INT    iMaxLines
                    299: )
                    300: {
                    301:     static BOOL bClass = FALSE;   /* Is the class registered */
                    302: 
                    303:     HWND   hwnd;
                    304:     HTXT   hTxt;      /* handle to a debuging window struct */
                    305:     PTXT   pTxt;
                    306:     static CHAR achClass[40];
                    307: 
                    308:     /*
                    309:         *  Make a Class name that is unique across instances
                    310:         */
                    311:     if (!bClass++) {
                    312:         wsprintf(achClass, "WPRINTF_%4.4X", hInstance);
                    313:         SetWindowClass(hInstance, achClass);
                    314:     }
                    315: 
                    316:     /* Allocate the window long before create the window, such that the
                    317:            window proc can find the window long during the create. */
                    318: 
                    319:     hTxt = (HTXT)LocalAlloc(LHND, sizeof(struct TEXT_STRUCT) + (iMaxLines
                    320:         - VARSIZE) * sizeof(LINE));
                    321: 
                    322:     if (!hTxt) {
                    323:         return FALSE;
                    324:     }
                    325: 
                    326:     pTxt = *hTxt;
                    327: 
                    328:     InitializeCriticalSection(&pTxt->csSync);
                    329: 
                    330:     pTxt->iFirst            = 0;    /* Set the queue up to have 1 NULL line */
                    331:     pTxt->iCount            = 1;
                    332:     pTxt->iTop              = 0;
                    333:     pTxt->iLeft             = 0;
                    334:     pTxt->MaxLen            = 0;
                    335:     pTxt->iMaxLines         = iMaxLines;
                    336:     pTxt->arLines[0].hText  = NULL;
                    337:     pTxt->arLines[0].iLen   = 0;
                    338: 
                    339:     hwnd = CreateWindow((LPSTR)achClass, (LPSTR)lpchName, dwStyle, x, y,
                    340:         dx, dy, (HWND)hParent,     /* parent window */
                    341:     (HMENU)NULL,       /* use class menu */
                    342:     (HANDLE)hInstance, /* handle to window instance */
                    343:     (LPSTR)hTxt        /* used by WM_CREATE to set the window long */
                    344:     );
                    345: 
                    346:     if (!hwnd) {
                    347:         return FALSE;
                    348:     }
                    349: 
                    350:     wprintfSetScrollRange(hwnd, FALSE);
                    351: 
                    352:     /* Make window visible */
                    353:     ShowWindow(hwnd, SHOW_OPENWINDOW);
                    354:     return hwnd;
                    355: }
                    356: 
                    357: 
                    358: /*****************************************************************************\
                    359: * SetPrintfFont (hwnd,hFont)                                                
                    360: *               
                    361: * Sets the font for the printf window.
                    362: *                                                               
                    363: * Arguments:                                                                 
                    364: *   HWND hwnd - Window handle of the printf window.                          
                    365: *   HFONT hFont - Font handle                                                  
                    366: *                                                                              
                    367: * Returns:                                                                   
                    368: *                                                                              
                    369: \*****************************************************************************/
                    370: 
                    371: VOID
                    372: SetPrintfFont(
                    373:     HWND hwnd,
                    374:     HFONT hfont
                    375:     )
                    376: {
                    377:     PTXT pTxt;
                    378:     HDC hDC;
                    379:     TEXTMETRIC tm;
                    380:     HFONT hfontOld;
                    381: 
                    382:     pTxt = *(HTXT)GetWindowLong(hwnd, 0);
                    383:     pTxt->hFont = hfont;
                    384: 
                    385:     /* Find out the size of a Char in the font */
                    386:     hDC = GetDC(hwnd);
                    387:     hfontOld = SelectObject(hDC, hfont);
                    388:     DeleteObject(hfontOld);
                    389:     GetTextMetrics(hDC, &tm);
                    390:     pTxt->Tdy = tm.tmHeight;
                    391:     pTxt->Tdx = tm.tmAveCharWidth;
                    392:     ReleaseDC(hwnd, hDC);
                    393: 
                    394:     CalculatePrintfTabs(hfont);
                    395: 
                    396:     InvalidateRect(hwnd, NULL, TRUE);
                    397:     UpdateWindow(hwnd);
                    398: }
                    399: 
                    400: 
                    401: 
                    402: /*****************************************************************************\
                    403: * SetPrintfTabs                                                             
                    404: *
                    405: * Sets the Tabstops in the printf window.
                    406: *        
                    407: * Arguments:
                    408: *    INT n - number of tabs to set.
                    409: *    LPINT pTabs - arrays of tabstops
                    410: *
                    411: * Returns:                                                                   
                    412: *    VOID                                                                              
                    413: \*****************************************************************************/
                    414: 
                    415: VOID
                    416: SetPrintfTabs(
                    417:     INT n,
                    418:     LPINT pTabs
                    419:     )
                    420: {
                    421:     INT i;
                    422: 
                    423:     nTabs = n;
                    424:     for (i = 0; i < nTabs; i++)
                    425:         tabs[i] = *pTabs++;
                    426: }
                    427: 
                    428: 
                    429: 
                    430: /*****************************************************************************\
                    431: * ClearPrintfWindow
                    432: *                                                                              
                    433: * Clears all text from the window                                             
                    434: *                                                                             
                    435: * Arguments:                                                                 
                    436: *    HWND hwnd - window handle for the Degubing window                  
                    437: *
                    438: * Returns:
                    439: *    VOID                                                                              
                    440: \*****************************************************************************/
                    441: 
                    442: VOID
                    443: ClearPrintfWindow(
                    444:     HWND hwnd
                    445:     )
                    446: {
                    447:     INT   i, iQueue;
                    448:     PTXT  pTxt;
                    449:     HTXT  hTxt;
                    450: 
                    451:     if (hwnd != NULL && IsWindow(hwnd)) {
                    452:         hTxt  = (HTXT)GetWindowLong(hwnd, 0);
                    453:         pTxt = *hTxt;
                    454: 
                    455:         EnterCrit(pTxt);
                    456: 
                    457:         iQueue = TOP(pTxt);
                    458:         for (i = 0; i < (pTxt)->iCount; i++, INC(pTxt, iQueue))
                    459:             if ((pTxt)->arLines[iQueue].hText != NULL) {
                    460:                 LocalFree ((HANDLE)pTxt->arLines[iQueue].hText);
                    461:                 pTxt->arLines[iQueue].hText = NULL;
                    462:             }
                    463: 
                    464:         pTxt->iFirst            = 0;  /* Set the queue up to have 1 NULL line */
                    465:         pTxt->iCount            = 1;
                    466:         pTxt->iTop              = 0;
                    467:         pTxt->iLeft             = 0;
                    468:         pTxt->MaxLen            = 0;
                    469:         pTxt->arLines[0].hText  = NULL;
                    470:         pTxt->arLines[0].iLen   = 0;
                    471: 
                    472:         wprintfSetScrollRange(hwnd, FALSE);
                    473:         InvalidateRect(hwnd, NULL, TRUE);
                    474: 
                    475:         LeaveCrit(pTxt);
                    476:     }
                    477: }
                    478: 
                    479: 
                    480: /*****************************************************************************\
                    481: * PrintfWndProc( hwnd, uiMessage, wParam, lParam )                          
                    482: *
                    483: * The window proc for the debugging window.  This processes all          
                    484: * of the window's messages.                                              
                    485: *                                                                              
                    486: * Arguments:                                                                 
                    487: *   HWND hwnd - window handle for the parent window                    
                    488: *   UINT uiMessage -message number                                         
                    489: *   WPARAM wParam - message-dependent                                      
                    490: *   LPARAM lParam - message-dependent                                      
                    491: *                                                                              
                    492: * Returns:                                                                   
                    493: *   0 if processed, nonzero if ignored                                     
                    494: \*****************************************************************************/
                    495: 
                    496: PUBLIC LONG APIENTRY
                    497: PrintfWndProc(
                    498: HWND   hwnd,
                    499: UINT   uiMessage,
                    500: WPARAM wParam,
                    501: LONG   lParam
                    502: )
                    503: {
                    504:     PAINTSTRUCT rPS;
                    505:     HTXT        hTxt;
                    506:     PTXT        pTxt;
                    507: 
                    508:     hTxt  = (HTXT)GetWindowLong(hwnd, 0);
                    509: 
                    510:     if ( hTxt ) {
                    511:         pTxt = *hTxt;
                    512:     }
                    513: 
                    514:     switch (uiMessage) {
                    515:     case WM_CREATE:
                    516:         {
                    517:             /* set the WindowLong before any other message tries to
                    518:                          * reference it during the create of a window
                    519:                          */
                    520:             LPCREATESTRUCT csWindowLong = (LPCREATESTRUCT) lParam;
                    521: 
                    522:             hTxt = (HTXT)csWindowLong->lpCreateParams;
                    523: 
                    524:             SetWindowLong(hwnd, 0, (LONG)hTxt);
                    525:             SetPrintfFont(hwnd, ghfontPrintf);
                    526:             wprintfSetScrollRange(hwnd, FALSE);
                    527:         }
                    528:         break;
                    529: 
                    530:     case WM_DESTROY:
                    531:         {
                    532:             INT i, iQueue;
                    533: 
                    534:             EnterCrit(pTxt);
                    535: 
                    536:             iQueue = TOP(pTxt);
                    537:             for (i = 0; i < (pTxt)->iCount; i++, INC(pTxt, iQueue))
                    538:                 if ((pTxt)->arLines[iQueue].hText != NULL) {
                    539:                     LocalFree ((HANDLE)(pTxt)->arLines[iQueue].hText);
                    540:                     pTxt->arLines[iQueue].hText = NULL;
                    541:                 }
                    542: 
                    543:             LeaveCrit(pTxt);
                    544:             DeleteCriticalSection(&pTxt->csSync);
                    545: 
                    546:             LocalFree((HANDLE)hTxt);
                    547:             break;
                    548:         }
                    549: 
                    550:     case WM_SIZE:
                    551:         EnterCrit(pTxt);
                    552:         if (!iSem) {
                    553:             wprintfSetScrollRange(hwnd, TRUE);
                    554:         }
                    555:         DebugVScroll(hwnd, pTxt, 0);
                    556:         LeaveCrit(pTxt);
                    557:         break;
                    558: 
                    559:     case WM_VSCROLL:
                    560:         EnterCrit(pTxt);
                    561: 
                    562:         switch (LOWORD(wParam)) {
                    563:         case SB_LINEDOWN:
                    564:             DebugVScroll(hwnd, pTxt, 1);
                    565:             break;
                    566:         case SB_LINEUP:
                    567:             DebugVScroll(hwnd, pTxt, -1);
                    568:             break;
                    569:         case SB_PAGEUP:
                    570:             DebugVScroll(hwnd, pTxt, -LinesInDebugWindow(hwnd));
                    571:             break;
                    572:         case SB_PAGEDOWN:
                    573:             DebugVScroll(hwnd, pTxt, LinesInDebugWindow(hwnd));
                    574:             break;
                    575:         case SB_THUMBTRACK:
                    576:         case SB_THUMBPOSITION:
                    577:             DebugVScroll(hwnd, pTxt, HIWORD(wParam) - pTxt->iTop);
                    578:             break;
                    579:         case SB_ENDSCROLL:
                    580:             break;
                    581:         }
                    582: 
                    583:         LeaveCrit(pTxt);
                    584:         break;
                    585: 
                    586:     case WM_HSCROLL:
                    587:         EnterCrit(pTxt);
                    588: 
                    589:         switch (LOWORD(wParam)) {
                    590:         case SB_LINEDOWN:
                    591:             DebugHScroll (hwnd, pTxt, 1);
                    592:             break;
                    593:         case SB_LINEUP:
                    594:             DebugHScroll (hwnd, pTxt, -1);
                    595:             break;
                    596:         case SB_PAGEUP:
                    597:             DebugHScroll (hwnd, pTxt, -CharsInDebugWindow(hwnd));
                    598:             break;
                    599:         case SB_PAGEDOWN:
                    600:             DebugHScroll (hwnd, pTxt, CharsInDebugWindow(hwnd));
                    601:             break;
                    602:         case SB_THUMBTRACK:
                    603:         case SB_THUMBPOSITION:
                    604:             DebugHScroll(hwnd, pTxt, HIWORD(wParam) - pTxt->iLeft);
                    605:             break;
                    606:         case SB_ENDSCROLL:
                    607:             break;
                    608:         }
                    609: 
                    610:         LeaveCrit(pTxt);
                    611:         break;
                    612: 
                    613:     case WM_PAINT:
                    614:         EnterCrit(pTxt);
                    615: 
                    616:         BeginPaint(hwnd, (LPPAINTSTRUCT) & rPS);
                    617:         DebugPaint(hwnd, &rPS);
                    618:         EndPaint(hwnd, (LPPAINTSTRUCT) & rPS);
                    619: 
                    620:         LeaveCrit(pTxt);
                    621:         break;
                    622: 
                    623:     case WM_KEYDOWN:
                    624:         EnterCrit(pTxt);
                    625: 
                    626:         switch (wParam) {
                    627:         case VK_UP:
                    628:             DebugVScroll(hwnd, pTxt, -1);
                    629:             break;
                    630:         case VK_DOWN:
                    631:             DebugVScroll(hwnd, pTxt, 1);
                    632:             break;
                    633:         case VK_PRIOR:
                    634:             DebugVScroll(hwnd, pTxt, -LinesInDebugWindow(hwnd));
                    635:             break;
                    636:         case VK_NEXT:
                    637:             DebugVScroll(hwnd, pTxt, LinesInDebugWindow(hwnd));
                    638:             break;
                    639:         case VK_LEFT:
                    640:             DebugHScroll(hwnd, pTxt, -1);
                    641:             break;
                    642:         case VK_RIGHT:
                    643:             DebugHScroll(hwnd, pTxt, 1);
                    644:             break;
                    645:         }
                    646: 
                    647:         LeaveCrit(pTxt);
                    648:         break;
                    649: 
                    650:     case WM_KEYUP:
                    651:         break;
                    652: 
                    653:     default:
                    654:         return DefWindowProc(hwnd, uiMessage, wParam, lParam);
                    655:     }
                    656:     return 0L;
                    657: }
                    658: 
                    659: 
                    660: /*****************************************************************************\
                    661: * DebugScroll
                    662: *   
                    663: * Scrolls the debug window vertically
                    664: *
                    665: * Arguments:
                    666: *    HWND hwnd - handle to the debug window
                    667: *    PTXT pTxt - pointer to the text to scroll
                    668: *    INT n - number of lines to scroll
                    669: *
                    670: * Returns:
                    671: *    VOID
                    672: \*****************************************************************************/
                    673: 
                    674: PRIVATE VOID
                    675: DebugVScroll(
                    676: HWND hwnd,
                    677: PTXT pTxt,
                    678: INT  n
                    679: )
                    680: {
                    681:     RECT rect;
                    682:     INT  iMinPos, iMaxPos;
                    683: 
                    684:     GetScrollRange(hwnd, SB_VERT, (LPINT) &iMinPos, (LPINT) &iMaxPos);
                    685:     GetClientRect(hwnd, (LPRECT) &rect);
                    686:     rect.left += OFFSETX;
                    687:     rect.top  += OFFSETY;
                    688: 
                    689:     n = BOUND(pTxt->iTop + n, iMinPos, iMaxPos) - pTxt->iTop;
                    690:     if (n == 0)
                    691:         return;
                    692: 
                    693:     pTxt->iTop += n;
                    694:     ScrollWindow(hwnd, 0, -n * pTxt->Tdy, (LPRECT) &rect, (LPRECT) &rect);
                    695:     SetScrollPos(hwnd, SB_VERT, pTxt->iTop, TRUE);
                    696: }
                    697: 
                    698: /*****************************************************************************\
                    699: * DebugHScroll
                    700: *
                    701: * Performs the horizontal scroll calculations
                    702: *
                    703: * Arguments:
                    704: *    HWND hwnd - handle to the debug window
                    705: *    PTXT pTxt - pointer to the text to scroll
                    706: *    INT n - number of characters to scroll
                    707: *
                    708: * Returns:
                    709: *    VOID
                    710: \*****************************************************************************/
                    711: 
                    712: PRIVATE VOID
                    713: DebugHScroll(
                    714: HWND hwnd,
                    715: PTXT pTxt,
                    716: INT  n
                    717: )
                    718: {
                    719:     RECT rect;
                    720:     INT  iMinPos, iMaxPos;
                    721: 
                    722:     GetScrollRange (hwnd, SB_HORZ, (LPINT) &iMinPos, (LPINT) &iMaxPos);
                    723:     GetClientRect (hwnd, (LPRECT) & rect);
                    724:     rect.left += OFFSETX;
                    725:     rect.top  += OFFSETY;
                    726: 
                    727:     n = BOUND(pTxt->iLeft + n, iMinPos, iMaxPos) - pTxt->iLeft;
                    728:     if (n == 0)
                    729:         return;
                    730: 
                    731:     pTxt->iLeft += n;
                    732:     ScrollWindow(hwnd, -n * pTxt->Tdx, 0, (LPRECT) & rect, (LPRECT) & rect);
                    733:     SetScrollPos(hwnd, SB_HORZ, pTxt->iLeft, TRUE);
                    734: }
                    735: 
                    736: /*****************************************************************************\
                    737: * LinesInDebugWindow
                    738: *
                    739: * Calculates the number of lines in the debug window
                    740: *
                    741: * Arguments:
                    742: *    HWND hwnd - handle to the debug window
                    743: *
                    744: * Returns:
                    745: *    INT - number of lines in the debug window
                    746: \*****************************************************************************/
                    747: 
                    748: PRIVATE INT
                    749: LinesInDebugWindow (
                    750: HWND hwnd
                    751: )
                    752: {
                    753:     RECT CRect;
                    754:     PTXT pTxt;
                    755: 
                    756:     pTxt = *(HTXT)GetWindowLong(hwnd, 0);
                    757:     GetClientRect(hwnd, &CRect);
                    758:     if ( pTxt->Tdy == 0 ) {
                    759:         return 0;
                    760:     }
                    761:     return pTxt ? (CRect.bottom - CRect.top - OFFSETY) / pTxt->Tdy : 0;
                    762: }
                    763: 
                    764: 
                    765: /*****************************************************************************\
                    766: * CharsInDebugWindow
                    767: *
                    768: * Calculates the number of characters horizontally in the debug window
                    769: *
                    770: * Arguments:
                    771: *    HWND hwnd - handle to the debug window
                    772: *
                    773: * Returns:
                    774: *    INT - number of horizontal characters in the debug window
                    775: \*****************************************************************************/
                    776: 
                    777: PRIVATE INT
                    778: CharsInDebugWindow (
                    779: HWND hwnd
                    780: )
                    781: {
                    782:     RECT CRect;
                    783:     PTXT pTxt;
                    784: 
                    785:     pTxt = *(HTXT)GetWindowLong (hwnd, 0);
                    786:     GetClientRect(hwnd, (LPRECT) & CRect);
                    787:     if ( pTxt->Tdx == 0 ) {
                    788:         return 0;
                    789:     }
                    790:     return pTxt ? (CRect.right - CRect.left - OFFSETX) / pTxt->Tdx : 0;
                    791: }
                    792: 
                    793: /*****************************************************************************\
                    794: * vwprintf
                    795: *
                    796: * variable printf - works like the C runtime printf
                    797: *
                    798: * Arguments:
                    799: *    HWND hwnd - handle to the debug window
                    800: *    LPSTR format - pointer to the format string
                    801: *    LPSTR marker - pointer to marker
                    802: *
                    803: * Returns:
                    804: *    INT - number of arguments printed
                    805: \*****************************************************************************/
                    806: 
                    807: PUBLIC INT FAR cdecl
                    808: vwprintf(
                    809: HWND  hwnd,
                    810: LPSTR format,
                    811: LPSTR marker
                    812: )
                    813: {
                    814:     static HWND hwndLast = NULL;
                    815:     static CHAR  pchBuf[MAXBUFLEN];
                    816:     RECT  rect;
                    817:     INT   iRet;
                    818:     INT   iLine;   // lines of output to show
                    819:     INT   cLine;   // lines in the current window
                    820:     INT   cScroll; // how much left to scroll
                    821:     PTXT  pTxt;
                    822:     HTXT  hTxt;
                    823: 
                    824:     if (hwnd == NULL)
                    825:         hwnd = hwndLast;
                    826: 
                    827:     if (hwnd == NULL || !IsWindow(hwnd))
                    828:         return 0;  /* exit if bad window handle */
                    829: 
                    830:     hwndLast = hwnd;
                    831: 
                    832:     //
                    833:     // First format the line and wait until we can play with the Txt structure
                    834:     //
                    835:     iRet = wvsprintf((LPSTR)pchBuf, format, marker);
                    836:     hTxt = (HTXT)GetWindowLong(hwnd, 0);
                    837:     pTxt = (PTXT)LocalLock((HANDLE)hTxt);
                    838: 
                    839:     EnterCrit(pTxt);
                    840: 
                    841:     //
                    842:     // Number of lines that we can display stuff in
                    843:     //
                    844:     cLine   = LinesInDebugWindow(hwnd);
                    845: 
                    846:     //
                    847:     // Number of lines actually displayed in the current window
                    848:     //
                    849:     iLine   = pTxt->iCount - pTxt->iTop;
                    850: 
                    851:     //
                    852:     // Return value is number of new lines to display
                    853:     //
                    854:     cScroll = InsertString(pTxt, pchBuf);
                    855: 
                    856:     //
                    857:     // Now make sure the new text is painted only if visable
                    858:     //
                    859:     GetClientRect(hwnd, (LPRECT) & rect);
                    860: 
                    861:     //
                    862:     // Calculate how much of the window to invalidate
                    863:     //
                    864:     rect.top += (iLine - 1) * pTxt->Tdy;
                    865: 
                    866:     InvalidateRect(hwnd, (LPRECT)&rect, TRUE);
                    867: 
                    868:     //
                    869:     // If we have more lines than we can display, scroll the window
                    870:     // such that the last line printed is now at the bottom
                    871:     //
                    872:     if (iLine + cScroll > cLine) {
                    873:         cScroll = iLine + cScroll - cLine;
                    874:         DebugVScroll(hwnd, pTxt, cScroll);
                    875:         LeaveCrit(pTxt);
                    876:         wprintfSetScrollRange(hwnd, FALSE);
                    877:     } else {
                    878:         LeaveCrit(pTxt);
                    879:     }
                    880: 
                    881:     LocalUnlock((HANDLE)hTxt);
                    882: 
                    883:     return(iRet);       /* return the count of arguments printed */
                    884: }
                    885: 
                    886: /*****************************************************************************\
                    887: * wprintfSetScrollRange
                    888: *
                    889: * Sets the scroll range of the debug window
                    890: *
                    891: * Arguments:
                    892: *    HWND hwnd - handle to the debug window
                    893: *    BOOL fRedraw - whether or not to redraw the window
                    894: *
                    895: * Returns:
                    896: *    VOID
                    897: \*****************************************************************************/
                    898: 
                    899: PRIVATE VOID
                    900: wprintfSetScrollRange (
                    901: HWND hwnd,
                    902: BOOL bRedraw
                    903: )
                    904: {
                    905:     PTXT pTxt;
                    906:     INT  iRange;
                    907:     INT  iLeftCritSect = 0;
                    908: 
                    909:     iSem++;
                    910:     pTxt = *(HTXT)GetWindowLong(hwnd, 0);
                    911: 
                    912:     /* Update the scroll bars */
                    913:     iRange = pTxt->iCount - 1 - LinesInDebugWindow(hwnd);
                    914: 
                    915:     if (iRange < 0) {
                    916:         iRange = 0;
                    917:         DebugVScroll(hwnd, pTxt, -pTxt->iTop);
                    918:     }
                    919: 
                    920:     while (GetCurrentThreadId() == (DWORD)pTxt->csSync.OwningThread){
                    921:         LeaveCrit(pTxt);
                    922:         iLeftCritSect++;
                    923:     }
                    924: 
                    925:     SetScrollRange(hwnd, SB_VERT, 0, iRange, FALSE);
                    926:     SetScrollPos(hwnd, SB_VERT, pTxt->iTop, bRedraw);
                    927: 
                    928:     if(iLeftCritSect) {
                    929:         EnterCrit(pTxt);
                    930:     }
                    931: 
                    932:     iRange = pTxt->MaxLen - CharsInDebugWindow(hwnd) + 1;
                    933:     if (iRange < 0) {
                    934:         iRange = 0;
                    935:         DebugHScroll(hwnd, pTxt, -pTxt->iLeft);
                    936:     }
                    937: 
                    938:     if(iLeftCritSect)
                    939:         LeaveCrit(pTxt);
                    940: 
                    941:     SetScrollRange(hwnd, SB_HORZ, 0, iRange, FALSE);
                    942:     SetScrollPos(hwnd, SB_HORZ, pTxt->iLeft, bRedraw);
                    943: 
                    944:     while (iLeftCritSect--) {
                    945:         EnterCrit(pTxt);
                    946:     }
                    947: 
                    948:     iSem--;
                    949: }
                    950: 
                    951: /*****************************************************************************\
                    952: * NewLine
                    953: *
                    954: * Calculates when a new line is needed in the debug window
                    955: *
                    956: * Arguments:
                    957: *    PTXT pTxt - pointer to the text
                    958: *
                    959: * Returns:
                    960: *    VOID
                    961: \*****************************************************************************/
                    962: 
                    963: PRIVATE VOID
                    964: NewLine (
                    965: PTXT pTxt
                    966: )
                    967: {
                    968:     INT iLast = LAST(pTxt);
                    969: 
                    970:     if (pTxt->iCount == pTxt->iMaxLines) {
                    971:         LocalFree ((HANDLE)pTxt->arLines[pTxt->iFirst].hText);
                    972:         pTxt->arLines[pTxt->iFirst].hText = NULL;
                    973:         INC (pTxt, pTxt->iFirst);
                    974:         if (pTxt->iTop > 0) {
                    975:             pTxt->iTop--;
                    976:         }
                    977:     } else {
                    978:         pTxt->iCount++;
                    979:     }
                    980:     iLast = LAST(pTxt);
                    981:     pTxt->arLines[iLast].hText = NULL;
                    982:     pTxt->arLines[iLast].iLen  = 0;
                    983: }
                    984: 
                    985: /*****************************************************************************\
                    986: * InsertString
                    987: *
                    988: * Inserts a string into the debug window
                    989: *
                    990: * Arguments:
                    991: *    PTXT pTxt - pointer to the text
                    992: *    CHAR *str - pointer to insertion string
                    993: *
                    994: * Returns:
                    995: *    INT - Line number at which string was inserted
                    996: \*****************************************************************************/
                    997: 
                    998: PRIVATE INT
                    999: InsertString (
                   1000: PTXT  pTxt,
                   1001: CHAR  *str
                   1002: )
                   1003: {
                   1004:     CHAR   pchBuf[MAXBUFLEN];        /* intermediate buffer */
                   1005:     INT    iBuf;
                   1006:     INT    iLast = LAST(pTxt);
                   1007:     INT    cLine = 0;
                   1008: 
                   1009:     for (iBuf = 0; iBuf < pTxt->arLines[iLast].iLen; iBuf++)
                   1010:         pchBuf[iBuf] = (*pTxt->arLines[iLast].hText)[iBuf];
                   1011: 
                   1012:     while (*str != '\0') {
                   1013:         while ((*str != '\n') && (*str != '\0'))
                   1014:             pchBuf[iBuf++] = *str++;
                   1015: 
                   1016:         if (pTxt->arLines[iLast].hText != NULL)
                   1017:             LocalFree((HANDLE)pTxt->arLines[iLast].hText);
                   1018: 
                   1019:         /* Test for the case of a zero length line, Only brian would do this */
                   1020: 
                   1021:         if (iBuf == 0)
                   1022:             pTxt->arLines[iLast].hText == NULL;
                   1023:         else {
                   1024:             if ((pTxt->arLines[iLast].hText = (CHAR **)LocalAlloc(LHND, iBuf))
                   1025:                 == NULL) {
                   1026:                 return 0;
                   1027:             }
                   1028:         }
                   1029: 
                   1030:         pTxt->arLines[iLast].iLen = iBuf;
                   1031:         while (--iBuf >= 0 )
                   1032:             (*pTxt->arLines[iLast].hText)[iBuf] = pchBuf[iBuf];
                   1033: 
                   1034:         if (*str == '\n') {   /* Now do the next string after the \n */
                   1035:             str++;
                   1036:             cLine++;
                   1037:             iBuf = 0;
                   1038:             NewLine(pTxt);
                   1039:             INC(pTxt, iLast);
                   1040:         }
                   1041:     }
                   1042: 
                   1043:     return cLine;
                   1044: }
                   1045: 
                   1046: /*****************************************************************************\
                   1047: * CopyToClipboard
                   1048: *
                   1049: * Copies all lines to the clipboard in text format.
                   1050: *
                   1051: * Arguments:
                   1052: *   none
                   1053: *
                   1054: * Returns:
                   1055: *   TRUE if successful, FALSE if not.
                   1056: *
                   1057: \*****************************************************************************/
                   1058: 
                   1059: BOOL
                   1060: CopyToClipboard(
                   1061:     VOID
                   1062:     )
                   1063: {
                   1064:     PTXT pTxt;
                   1065:     INT iQueue;
                   1066:     INT cch;
                   1067:     INT i;
                   1068:     BOOL fSuccess = FALSE;
                   1069:     LPSTR pBuf = NULL;
                   1070:     LPSTR pb;
                   1071: 
                   1072:     pTxt = *(HTXT)GetWindowLong(ghwndPrintf, 0);
                   1073: 
                   1074:     EnterCrit(pTxt);
                   1075: 
                   1076:     iQueue = FIRST(pTxt);
                   1077:     cch = 0;
                   1078:     for (i = 0; i < pTxt->iCount; i++, INC(pTxt, iQueue))
                   1079:     {
                   1080:         if (pTxt->arLines[iQueue].hText != NULL)
                   1081:         {
                   1082:             //
                   1083:             // Count the characters in the line, plus room for the
                   1084:             // carriage return and newline.
                   1085:             //
                   1086:             cch += pTxt->arLines[iQueue].iLen;
                   1087:             cch += 2;
                   1088:         }
                   1089:     }
                   1090: 
                   1091:     //
                   1092:     // Add one for the terminating null.
                   1093:     //
                   1094:     cch++;
                   1095: 
                   1096:     if (!(pBuf = (LPSTR)GlobalAlloc(GMEM_DDESHARE, cch * sizeof(TCHAR))))
                   1097:     {
                   1098:         LeaveCrit(pTxt);
                   1099:         return FALSE;
                   1100:     }
                   1101: 
                   1102:     pb = pBuf;
                   1103:     iQueue = FIRST(pTxt);
                   1104:     for (i = 0; i < pTxt->iCount; i++, INC(pTxt, iQueue))
                   1105:     {
                   1106:         if (pTxt->arLines[iQueue].hText != NULL)
                   1107:         {
                   1108:             lstrcpy(pb, *pTxt->arLines[iQueue].hText);
                   1109:             pb += pTxt->arLines[iQueue].iLen;
                   1110:             *pb++ = '\r';
                   1111:             *pb++ = '\n';
                   1112:         }
                   1113:     }
                   1114: 
                   1115:     LeaveCrit(pTxt);
                   1116: 
                   1117:     if (OpenClipboard(ghwndSpyApp))
                   1118:     {
                   1119:         EmptyClipboard();
                   1120:         fSuccess = SetClipboardData(CF_TEXT, pBuf) ? TRUE : FALSE;
                   1121:         CloseClipboard();
                   1122:     }
                   1123: 
                   1124:     return fSuccess;
                   1125: }
                   1126: 
                   1127: /*****************************************************************************\
                   1128: * IsPrintfEmpty
                   1129: *
                   1130: * Used to determine if the printf window is empty or not.
                   1131: *
                   1132: * Arguments:
                   1133: *   none
                   1134: *
                   1135: * Returns:
                   1136: *   TRUE if the printf window is empty, FALSE if there is at least
                   1137: *   one line in the window.
                   1138: *
                   1139: \*****************************************************************************/
                   1140: 
                   1141: BOOL
                   1142: IsPrintfEmpty(
                   1143:     VOID
                   1144:     )
                   1145: {
                   1146:     PTXT pTxt;
                   1147: 
                   1148:     pTxt = *(HTXT)GetWindowLong(ghwndPrintf, 0);
                   1149: 
                   1150:     //
                   1151:     // It is empty if the line count is zero (doesn't currently happen)
                   1152:     // or if there is only one line and it is NULL.
                   1153:     //
                   1154:     return (pTxt->iCount == 0 ||
                   1155:         (pTxt->iCount == 1 && pTxt->arLines[FIRST(pTxt)].hText == NULL))
                   1156:         ? TRUE : FALSE;
                   1157: }
                   1158: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.