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