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

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

unix.superglobalmegacorp.com

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