|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.