|
|
1.1 ! root 1: /**************************************************************************\ ! 2: * display.c -- module for the window with the test font. ! 3: * Includes the window procedure and an initialization routine. ! 4: * ! 5: * Steve Firebaugh ! 6: * Microsoft Developer Support ! 7: * Copyright (c) 1992 Microsoft Corporation ! 8: * ! 9: * store the handle to the test font in the extra bytes of this window. ! 10: * ! 11: * ! 12: * HORZ_SCROLL used to step through UC ranges when in "all glyphs" mode. ! 13: * VERT_SCROLL: ! 14: * scroll bar range is the total number of lines needed for all glyphs ! 15: * minus the number which may be shown in the window. ! 16: * scroll bar position is then the first line which is to be drawn. ! 17: * ! 18: * ! 19: * ! 20: \**************************************************************************/ ! 21: #define UNICODE ! 22: ! 23: #include <windows.h> ! 24: #include <string.h> ! 25: #include "ntfonts.h" ! 26: ! 27: /* defines for the gridding pattern in background of window */ ! 28: #define GRIDCOLOR PALETTEINDEX (3) ! 29: #define TICKSPACE 10 ! 30: ! 31: ! 32: /* global variables store the start and end codepoints for UC ranges. */ ! 33: #define MAXSEGMENTS 100 ! 34: USHORT endCount[MAXSEGMENTS]; ! 35: USHORT startCount[MAXSEGMENTS]; ! 36: ! 37: ! 38: ! 39: ! 40: VOID BlamGlyphs (HDC, PTEXTMETRIC, USHORT, USHORT, PRECT, BOOL); ! 41: ! 42: int CountUCSegments (HDC); ! 43: /* error return value from CountUCSegments */ ! 44: #define SEGMENTERROR -1 ! 45: ! 46: ! 47: ! 48: ! 49: ! 50: ! 51: ! 52: ! 53: int initDisplay(HWND hwndParent) ! 54: { ! 55: WNDCLASS wc; ! 56: ! 57: wc.style = CS_VREDRAW | CS_HREDRAW; ! 58: wc.lpfnWndProc = (WNDPROC)DisplayWndProc; ! 59: wc.cbClsExtra = 0; ! 60: wc.cbWndExtra = 0; ! 61: wc.hInstance = hInst; ! 62: wc.hIcon = LoadIcon(hInst, TEXT("ntfontsIcon")); ! 63: wc.hCursor = LoadCursor(NULL, IDC_ARROW); ! 64: wc.hbrBackground = NULL; ! 65: wc.lpszMenuName = NULL; ! 66: wc.lpszClassName = TEXT("display"); ! 67: ! 68: if (!RegisterClass(&wc)) return (FALSE); ! 69: ! 70: hwndDisplay = CreateMDIWindow( ! 71: TEXT("display"), ! 72: TEXT("Display"), ! 73: WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE | ! 74: WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_VSCROLL | WS_HSCROLL, ! 75: CHILDLEFT(2), ! 76: CHILDTOP, ! 77: GetSystemMetrics (SM_CXFULLSCREEN)/3 - 10, ! 78: GetSystemMetrics (SM_CYFULLSCREEN)/3, ! 79: hwndParent, hInst, 0); ! 80: ! 81: if (!hwndDisplay) return (FALSE); ! 82: ! 83: ! 84: return TRUE; ! 85: } ! 86: ! 87: ! 88: ! 89: ! 90: /**************************************************************************\ ! 91: * ! 92: * function: DisplayWndProc() ! 93: * ! 94: * input parameters: normal window procedure parameters. ! 95: * ! 96: * global variables: ! 97: * gDisplaymode - menu state ! 98: \**************************************************************************/ ! 99: LRESULT CALLBACK DisplayWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ! 100: { ! 101: static HANDLE hPenGrid; ! 102: static LPLOGFONT lplf; ! 103: static LPTEXTMETRIC lptm; ! 104: static HFONT hfont; ! 105: static HDC hdcStatic; /* Sent to other window procedures. */ ! 106: ! 107: static HDC hdc; ! 108: static RECT rect; ! 109: static int min, max; ! 110: static TEXTMETRIC tm; ! 111: static int iSeg; ! 112: static TCHAR buffer[100]; ! 113: ! 114: static int nCharPerLine, nTotalGlyphs, lineHeight; ! 115: static int nLinesTotal, nLinesWindow, nLinesDifference; ! 116: static int scrollRangeHigh, topLineShowing; ! 117: int i; ! 118: ! 119: ! 120: switch (message) { ! 121: ! 122: ! 123: ! 124: ! 125: ! 126: ! 127: /**********************************************************************\ ! 128: * WMU_DEMOTOLF ! 129: * ! 130: * lParam - pointer to LOGFONT structure. ! 131: * ! 132: * User message. Fill up the display LOGFONT from the HFONT ! 133: * in the extra bytes. ! 134: \**********************************************************************/ ! 135: case WMU_DEMOTOLF: { ! 136: lplf = (LPLOGFONT) lParam; ! 137: ! 138: hfont = (HFONT) GetWindowLong (hwnd, GWL_USERDATA); ! 139: GetObject (hfont, sizeof(LOGFONT), lplf); ! 140: } return 0; ! 141: ! 142: ! 143: ! 144: ! 145: /**********************************************************************\ ! 146: * WMU_DEMOTOTM ! 147: * ! 148: * lParam - pointer to TEXTMETRIC structure. ! 149: * ! 150: * User message. Fill up the TEXTMETRIC from the HFONT ! 151: * in the extra bytes. ! 152: \**********************************************************************/ ! 153: case WMU_DEMOTOTM: { ! 154: lptm = (LPTEXTMETRIC) lParam; ! 155: ! 156: hfont = (HFONT) GetWindowLong (hwnd, GWL_USERDATA); ! 157: ! 158: hdc = GetDC (hwnd); ! 159: SelectObject (hdc,hfont); ! 160: GetTextMetrics (hdc, lptm); ! 161: ReleaseDC (hwnd, hdc); ! 162: } return 0; ! 163: ! 164: ! 165: /**********************************************************************\ ! 166: * WMU_DEMOGETDC ! 167: * ! 168: * User message. Return an HDC. ! 169: \**********************************************************************/ ! 170: case WMU_DEMOGETDC: { ! 171: hfont = (HFONT) GetWindowLong (hwnd, GWL_USERDATA); ! 172: ! 173: hdcStatic = GetDC (hwnd); ! 174: SelectObject (hdcStatic,hfont); ! 175: return (LRESULT)hdcStatic; ! 176: } break; ! 177: ! 178: ! 179: /**********************************************************************\ ! 180: * WMU_DEMORELEASEDC ! 181: * ! 182: * lParam - the same HDC returned by WMU_DEMOGETDC ! 183: * ! 184: * User message. Release the HDC. ! 185: \**********************************************************************/ ! 186: case WMU_DEMORELEASEDC: { ! 187: hdcStatic = (HDC) lParam; ! 188: ReleaseDC (hwnd, hdcStatic); ! 189: } return 0; ! 190: ! 191: ! 192: ! 193: ! 194: /**********************************************************************\ ! 195: * WMU_NEWFONT ! 196: * ! 197: * lParam - pointer to LOGFONT structure. ! 198: * ! 199: * User message. Use the input LOGFONT structure to create a new ! 200: * font for this window. Store the new font in the HFONT extra bytes. ! 201: \**********************************************************************/ ! 202: case WMU_NEWFONT: { ! 203: lplf = (LPLOGFONT) lParam; ! 204: ! 205: /* Get and delete the last font placed in this window. */ ! 206: hfont = (HFONT) GetWindowLong (hwnd, GWL_USERDATA); ! 207: DeleteObject (hfont); ! 208: ! 209: /* Create a new logical font and set it into the windows extra bytes. */ ! 210: hfont = CreateFontIndirect (lplf); ! 211: SetWindowLong (hwnd, GWL_USERDATA, (LONG) hfont); ! 212: ! 213: /* make sure that scroll metrics are ok */ ! 214: switch (gDisplaymode) { ! 215: case IDM_MODEHELLO: SendMessage (hwnd, WMU_NEWMODEHELLO, 0,0); ! 216: break; ! 217: case IDM_MODETMRANGE: SendMessage (hwnd, WMU_NEWMODETMRANGE, 0,0); ! 218: break; ! 219: case IDM_MODEALL: ! 220: if (!SendMessage (hwndDisplay, WMU_NEWMODEALL, 0,0)) { ! 221: MessageBox (NULL, TEXT("Resetting display"), MBERROR, MBERRORFLAGS); ! 222: SendMessage (hwndMain, WM_COMMAND, IDM_MODEHELLO, 0); ! 223: return 0; ! 224: } ! 225: break; ! 226: } /* end switch */ ! 227: ! 228: ! 229: InvalidateRect (hwnd, NULL, TRUE); ! 230: } return 0; ! 231: ! 232: ! 233: ! 234: ! 235: ! 236: ! 237: /**********************************************************************\ ! 238: * WM_CREATE ! 239: * ! 240: * Create pens for drawing with later. ! 241: \**********************************************************************/ ! 242: case WM_CREATE: ! 243: hPenGrid = CreatePen (PS_SOLID, 1, GRIDCOLOR); ! 244: SetWindowLong (hwnd, GWL_USERDATA, (LONG) GetStockObject (SYSTEM_FONT)); ! 245: break; ! 246: ! 247: ! 248: /**********************************************************************\ ! 249: * WM_DESTROY ! 250: * ! 251: * Complement of the WM_CREATE message. Delete the pens that were ! 252: * created and then call postquitmessage. ! 253: \**********************************************************************/ ! 254: case WM_DESTROY: ! 255: DeleteObject (hPenGrid); ! 256: break; ! 257: ! 258: ! 259: ! 260: ! 261: /**********************************************************************\ ! 262: * WM_ERASEBKGND ! 263: * ! 264: * Offset the origin conditional on gDisplaymode. Grid the window. ! 265: \**********************************************************************/ ! 266: case WM_ERASEBKGND: { ! 267: HDC hdc; ! 268: RECT rect; ! 269: int i; ! 270: ! 271: hdc = (HDC)wParam; ! 272: ! 273: GetClientRect (hwnd, &rect); ! 274: FillRect (hdc, &rect, GetStockObject (LTGRAY_BRUSH)); ! 275: ! 276: if (gDisplaymode == IDM_MODEHELLO) { ! 277: SetViewportOrgEx (hdc, rect.right /2, rect.bottom/2, NULL); ! 278: OffsetRect (&rect, -rect.right/2, -rect.bottom/2); ! 279: ! 280: SelectObject(hdc, hPenGrid); ! 281: /* Draw vertical lines. */ ! 282: for (i = 0; i<= rect.right; i+=TICKSPACE){ ! 283: MoveToEx (hdc, i, rect.top, NULL); ! 284: LineTo (hdc, i, rect.bottom); ! 285: MoveToEx (hdc, -i, rect.top, NULL); ! 286: LineTo (hdc, -i, rect.bottom); ! 287: } ! 288: MoveToEx (hdc, 1, rect.top, NULL); ! 289: LineTo (hdc, 1, rect.bottom); ! 290: ! 291: /* Draw horizontal lines. */ ! 292: for (i = 0; i<= rect.bottom; i+=TICKSPACE){ ! 293: MoveToEx (hdc, rect.left,i, NULL); ! 294: LineTo (hdc, rect.right,i); ! 295: MoveToEx (hdc, rect.left,-i, NULL); ! 296: LineTo (hdc, rect.right,-i); ! 297: } ! 298: MoveToEx (hdc, rect.left, 1, NULL); ! 299: LineTo (hdc, rect.right,1); ! 300: ! 301: } ! 302: ! 303: ! 304: } return TRUE; ! 305: ! 306: ! 307: ! 308: ! 309: /**********************************************************************\ ! 310: * WM_VSCROLL ! 311: * ! 312: * Slide the contents of the window up and down. Notice that the ! 313: * scroll bar thumb position is important for painting. ! 314: \**********************************************************************/ ! 315: case WM_VSCROLL: ! 316: ! 317: switch (LOWORD(wParam)){ ! 318: int OldPos, NewPos; ! 319: ! 320: case SB_PAGEDOWN: ! 321: case SB_LINEDOWN: ! 322: OldPos = GetScrollPos (hwnd, SB_VERT); ! 323: SetScrollPos (hwnd, SB_VERT, (OldPos+1), TRUE); ! 324: NewPos = GetScrollPos (hwnd, SB_VERT); ! 325: ScrollWindow (hwnd, 0,(OldPos-NewPos)*lineHeight, NULL, NULL); ! 326: break; ! 327: ! 328: case SB_PAGEUP: ! 329: case SB_LINEUP: ! 330: OldPos = GetScrollPos (hwnd, SB_VERT); ! 331: SetScrollPos (hwnd, SB_VERT, (OldPos-1), TRUE); ! 332: NewPos = GetScrollPos (hwnd, SB_VERT); ! 333: ScrollWindow (hwnd, 0,(OldPos-NewPos)*lineHeight, NULL, NULL); ! 334: break; ! 335: ! 336: case SB_THUMBPOSITION: ! 337: OldPos = GetScrollPos (hwnd, SB_VERT); ! 338: NewPos = HIWORD (wParam); ! 339: SetScrollPos (hwnd, SB_VERT, NewPos, TRUE); ! 340: ScrollWindow (hwnd, 0, (OldPos-NewPos)*lineHeight, NULL, NULL); ! 341: break; ! 342: ! 343: } ! 344: break; ! 345: ! 346: ! 347: ! 348: ! 349: /**********************************************************************\ ! 350: * WM_HSCROLL ! 351: * ! 352: * The horz scroll should only be present when in MODEALL. ! 353: * Step through the allglyphs ranges. ! 354: * In every case, inform the window the range has changed, ! 355: * and invalidate it to force a repaint. ! 356: \**********************************************************************/ ! 357: case WM_HSCROLL: ! 358: ! 359: switch (LOWORD(wParam)){ ! 360: int OldPos, NewPos; ! 361: ! 362: case SB_PAGEDOWN: ! 363: case SB_LINEDOWN: ! 364: OldPos = GetScrollPos (hwnd, SB_HORZ); ! 365: SetScrollPos (hwnd, SB_HORZ, (OldPos+1), TRUE); ! 366: SendMessage (hwnd,WMU_NEWMODE_NEWSEG, 0,0); ! 367: InvalidateRect (hwnd, NULL, TRUE); ! 368: break; ! 369: ! 370: case SB_PAGEUP: ! 371: case SB_LINEUP: ! 372: OldPos = GetScrollPos (hwnd, SB_HORZ); ! 373: SetScrollPos (hwnd, SB_HORZ, (OldPos-1), TRUE); ! 374: SendMessage (hwnd,WMU_NEWMODE_NEWSEG, 0,0); ! 375: InvalidateRect (hwnd, NULL, TRUE); ! 376: break; ! 377: ! 378: case SB_THUMBPOSITION: ! 379: OldPos = GetScrollPos (hwnd, SB_HORZ); ! 380: NewPos = HIWORD (wParam); ! 381: SetScrollPos (hwnd, SB_HORZ, NewPos, TRUE); ! 382: SendMessage (hwnd,WMU_NEWMODE_NEWSEG, 0,0); ! 383: InvalidateRect (hwnd, NULL, TRUE); ! 384: break; ! 385: ! 386: } ! 387: ! 388: break; ! 389: ! 390: ! 391: ! 392: /**********************************************************************\ ! 393: * WMU_NEWMODEALL ! 394: * ! 395: * returns - TRUE if a scalable font file. ! 396: * FALSE if GetFontData fails. ! 397: * ! 398: * This message is sent one time when the user checks "Show all glyphs." ! 399: * Here we set up the horizontal scroll bar, and the start/endCount arrays. ! 400: \**********************************************************************/ ! 401: case WMU_NEWMODEALL: { ! 402: HDC hdc; ! 403: int nSegments; ! 404: ! 405: SetCursor (LoadCursor (NULL, IDC_WAIT)); ! 406: hdc = GetDC(hwnd); ! 407: hfont = (HFONT) GetWindowLong (hwnd, GWL_USERDATA); ! 408: SelectObject (hdc,hfont); ! 409: nSegments = CountUCSegments (hdc); /* slow computation */ ! 410: ReleaseDC (hwnd, hdc); ! 411: SetCursor (LoadCursor (NULL, IDC_ARROW)); ! 412: ! 413: if (nSegments == SEGMENTERROR) return FALSE; ! 414: ! 415: gDisplaymode =IDM_MODEALL; ! 416: SetScrollRange (hwnd, SB_HORZ, 0, (nSegments-1), TRUE); ! 417: SetScrollPos (hwnd, SB_HORZ, 0, TRUE); ! 418: ! 419: SendMessage (hwndDisplay, WMU_NEWMODE_NEWSEG, 0,0); ! 420: return TRUE; ! 421: ! 422: } break; ! 423: ! 424: ! 425: ! 426: /**********************************************************************\ ! 427: * WMU_NEWMODEHELLO ! 428: * WMU_NEWMODETMRANGE ! 429: * WMU_NEWMODE_NEWSEG ! 430: * ! 431: * ! 432: * Sent every time an event occurs which will change the layout of ! 433: * the display glyphs. I.e. ! 434: * window resized. ! 435: * display mode switch ! 436: * allglyph display mode, next range ! 437: * ! 438: \**********************************************************************/ ! 439: case WMU_NEWMODEHELLO: ! 440: /* Set the window title text. */ ! 441: SetWindowText (hwnd, TEXT("Display - Hello")); ! 442: ! 443: SetScrollRange (hwnd, SB_HORZ, 0, 0, TRUE); ! 444: SetScrollRange (hwnd, SB_VERT, 0, 0, TRUE); ! 445: gDisplaymode =IDM_MODEHELLO; ! 446: break; ! 447: ! 448: ! 449: case WMU_NEWMODETMRANGE: { ! 450: /* Set the window title text. */ ! 451: SetWindowText (hwnd, TEXT("Display [tmFirstChar, tmLastChar]")); ! 452: ! 453: SetScrollRange (hwnd, SB_HORZ, 0, 0, TRUE); ! 454: gDisplaymode =IDM_MODETMRANGE; ! 455: ! 456: hdc = GetDC(hwnd); ! 457: GetClientRect (hwnd, &rect); ! 458: ! 459: /* subtract off the scroll width if it is NOT there. ! 460: * (if it is, it will be automatically excluded by GetClientRect) ! 461: * if it is not there, it may be added, and we want space for it. ! 462: */ ! 463: GetScrollRange (hwnd, SB_VERT, &min, &max); ! 464: if (min == max) rect.right -= GetSystemMetrics (SM_CXVSCROLL); ! 465: ! 466: /* select the font into the window to get text metrics for. */ ! 467: hfont = (HFONT) GetWindowLong (hwnd, GWL_USERDATA); ! 468: SelectObject (hdc,hfont); ! 469: GetTextMetrics (hdc, &tm); ! 470: ! 471: nCharPerLine = rect.right / tm.tmAveCharWidth; ! 472: nTotalGlyphs = tm.tmLastChar-tm.tmFirstChar; ! 473: lineHeight = tm.tmHeight + tm.tmExternalLeading; ! 474: nLinesTotal = nTotalGlyphs / nCharPerLine; ! 475: nLinesWindow = rect.bottom / lineHeight; ! 476: nLinesDifference = nLinesTotal - nLinesWindow; ! 477: scrollRangeHigh = nLinesTotal - nLinesWindow; ! 478: ! 479: /* reset the scroll bar range. If there is no need for one, ! 480: * then set the position to 0, and the range to 0,0 and it ! 481: * will not be visisble. ! 482: */ ! 483: if (nLinesDifference >0) { ! 484: SetScrollRange (hwnd, SB_VERT, 0, (nLinesDifference +1), TRUE); ! 485: } else { ! 486: SetScrollPos (hwnd, SB_VERT, 0, TRUE); ! 487: SetScrollRange (hwnd, SB_VERT, 0, 0, TRUE); ! 488: } ! 489: ! 490: ReleaseDC (hwnd, hdc); ! 491: } return FALSE; ! 492: ! 493: ! 494: ! 495: case WMU_NEWMODE_NEWSEG: { ! 496: gDisplaymode =IDM_MODEALL; ! 497: SetScrollPos (hwnd, SB_VERT, 0, TRUE); ! 498: ! 499: hdc = GetDC(hwnd); ! 500: GetClientRect (hwnd, &rect); ! 501: ! 502: /* subtract off the scroll width if it is NOT there. ! 503: * (if it is, it will be automatically excluded by GetClientRect) ! 504: * if it is not there, it may be added, and we want space for it. ! 505: */ ! 506: GetScrollRange (hwnd, SB_VERT, &min, &max); ! 507: if (min == max) rect.right -= GetSystemMetrics (SM_CXVSCROLL); ! 508: ! 509: ! 510: /* select the font into the window to get text metrics for. */ ! 511: hfont = (HFONT) GetWindowLong (hwnd, GWL_USERDATA); ! 512: SelectObject (hdc,hfont); ! 513: GetTextMetrics (hdc, &tm); ! 514: ! 515: ! 516: iSeg = GetScrollPos (hwnd, SB_HORZ); ! 517: ! 518: /* Set the window title text to show display range. */ ! 519: wsprintf (buffer, TEXT("Display [%04x, %04x]"), ! 520: (int)startCount[iSeg], ! 521: (int)endCount[iSeg]); ! 522: SetWindowText (hwnd, buffer); ! 523: ! 524: ! 525: ! 526: ! 527: nTotalGlyphs = endCount[iSeg] - startCount[iSeg]; ! 528: ! 529: nCharPerLine = rect.right / tm.tmAveCharWidth; ! 530: nLinesTotal = nTotalGlyphs / nCharPerLine; ! 531: ! 532: lineHeight = tm.tmHeight + tm.tmExternalLeading; ! 533: nLinesWindow = rect.bottom / lineHeight; ! 534: nLinesDifference = nLinesTotal - nLinesWindow; ! 535: scrollRangeHigh = nLinesTotal - nLinesWindow; ! 536: ! 537: /* reset the scroll bar range. If there is no need for one, ! 538: * then set the position to 0, and the range to 0,0 and it ! 539: * will not be visisble. ! 540: */ ! 541: if (nLinesDifference >0) { ! 542: SetScrollRange (hwnd, SB_VERT, 0, (nLinesDifference +1), FALSE); ! 543: } else { ! 544: SetScrollPos (hwnd, SB_VERT, 0, TRUE); ! 545: SetScrollRange (hwnd, SB_VERT, 0, 0, TRUE); ! 546: } ! 547: ! 548: ReleaseDC (hwnd, hdc); ! 549: } return FALSE; ! 550: ! 551: ! 552: ! 553: ! 554: /**********************************************************************\ ! 555: * WM_SIZE ! 556: * ! 557: \**********************************************************************/ ! 558: case WM_SIZE: ! 559: /* make sure that scroll metrics are ok */ ! 560: switch (gDisplaymode) { ! 561: case IDM_MODEHELLO: SendMessage (hwnd, WMU_NEWMODEHELLO, 0,0); ! 562: break; ! 563: case IDM_MODETMRANGE: SendMessage (hwnd, WMU_NEWMODETMRANGE, 0,0); ! 564: break; ! 565: case IDM_MODEALL: SendMessage (hwnd, WMU_NEWMODE_NEWSEG, 0,0); ! 566: break; ! 567: } /* end switch */ ! 568: ! 569: break; /* fall through to MDIChildProc */ ! 570: ! 571: ! 572: /**********************************************************************\ ! 573: * WM_PAINT ! 574: * ! 575: * Offset the origin conditional on gDisplaymode. Write the "Hello" ! 576: * string, or step though all of the glyphs (from TEXTMETRIC.tmFirstChar ! 577: * to TEXTMETRIC.tmLastChar), or paint all of the glyphs in the UC segment. ! 578: \**********************************************************************/ ! 579: case WM_PAINT: { ! 580: HDC hdc; ! 581: PAINTSTRUCT ps; ! 582: RECT rect; ! 583: ! 584: hdc = BeginPaint(hwnd, &ps); ! 585: ! 586: ! 587: GetClientRect (hwnd, &rect); ! 588: hfont = (HFONT) GetWindowLong (hwnd, GWL_USERDATA); ! 589: SelectObject (hdc,hfont); ! 590: SetBkMode (hdc, TRANSPARENT); ! 591: SetTextAlign (hdc, TA_LEFT | TA_TOP | TA_UPDATECP); ! 592: GetTextMetrics (hdc, &tm); ! 593: MoveToEx (hdc, 0,0, NULL); ! 594: ! 595: ! 596: switch (gDisplaymode) { ! 597: case IDM_MODEHELLO: ! 598: SetViewportOrgEx (hdc, rect.right /2, rect.bottom/2, NULL); ! 599: TextOut (hdc, 0, 0, TEXT("Hello"), 5); ! 600: break; ! 601: ! 602: case IDM_MODETMRANGE: { ! 603: USHORT start, end; ! 604: ! 605: topLineShowing= GetScrollPos (hwnd, SB_VERT); ! 606: start = tm.tmFirstChar; ! 607: start += (topLineShowing * nCharPerLine); ! 608: end = tm.tmLastChar; ! 609: BlamGlyphs (hdc, &tm, start, end, &rect, FALSE); ! 610: ! 611: } break; ! 612: ! 613: case IDM_MODEALL: { ! 614: USHORT start, end; ! 615: ! 616: iSeg= GetScrollPos (hwnd, SB_HORZ); ! 617: topLineShowing = GetScrollPos (hwnd, SB_VERT); ! 618: start = startCount[iSeg]; ! 619: start += (topLineShowing * nCharPerLine); ! 620: end = endCount[iSeg]; ! 621: ! 622: BlamGlyphs (hdc, &tm, start, end, &rect, FALSE); ! 623: } break; ! 624: ! 625: } /* end switch */ ! 626: ! 627: ! 628: ! 629: ! 630: EndPaint (hwnd, &ps); ! 631: ! 632: } return FALSE; /* end WM_PAINT */ ! 633: ! 634: ! 635: ! 636: /**********************************************************************\ ! 637: * WMU_PRINT ! 638: * ! 639: * user message. Get an HDC for the printer, send it formatted ! 640: * output based on the mode of the display window. ! 641: \**********************************************************************/ ! 642: case WMU_PRINT: { ! 643: HDC hdc; ! 644: RECT rect; ! 645: POINT point; ! 646: int nchar; ! 647: int ScrollMin, ScrollMax; ! 648: UINT cbData; ! 649: LPOUTLINETEXTMETRIC lpoltm; ! 650: DOCINFO di; ! 651: di.cbSize = sizeof(DOCINFO); ! 652: di.lpszDocName = TEXT("NTFonts"); ! 653: di.lpszOutput = NULL; ! 654: ! 655: ! 656: SetCursor (LoadCursor (NULL, IDC_WAIT)); ! 657: ! 658: hdc = GetPrinterDC(); ! 659: if (hdc == NULL) return NULL; ! 660: StartDoc (hdc, &di); ! 661: StartPage (hdc); ! 662: ! 663: ! 664: hfont = (HFONT) GetWindowLong (hwnd, GWL_USERDATA); ! 665: SelectObject (hdc,hfont); ! 666: rect.top = rect.left = 0; ! 667: rect.right = GetDeviceCaps (hdc, HORZRES); ! 668: rect.bottom = GetDeviceCaps (hdc, VERTRES); ! 669: SetBkMode (hdc, TRANSPARENT); ! 670: SetTextAlign (hdc, TA_LEFT | TA_TOP | TA_UPDATECP); ! 671: GetTextMetrics (hdc, &tm); ! 672: ! 673: /* write a little banner at the top */ ! 674: MoveToEx (hdc, 0,0, NULL); ! 675: TextOut (hdc, 0,0,TEXT ("NTFONTS -- "), 11); ! 676: ! 677: cbData = GetOutlineTextMetrics (hdc, 0, NULL); ! 678: if (cbData == 0) { ! 679: TextOut (hdc, 0,0, MBGETFONTDATAERR, ! 680: CharStrLen(MBGETFONTDATAERR)); ! 681: } else { ! 682: lpoltm = (LPOUTLINETEXTMETRIC)LocalAlloc (LPTR, cbData); ! 683: GetOutlineTextMetrics (hdc, cbData, lpoltm); ! 684: ! 685: /***** Removed because it is TRAPPING as of 10/1/92. Should work... ! 686: TextOut (hdc, 0,0, (LPCTSTR)(lpoltm + (size_t)lpoltm->otmpFullName), ! 687: CharStrLen((LPCTSTR)(lpoltm + (size_t)lpoltm->otmpFullName))); ! 688: *****/ ! 689: LocalFree (LocalHandle (lpoltm)); ! 690: } ! 691: ! 692: /* Draw a thick line, and leave the cursor in the right place. */ ! 693: GetCurrentPositionEx (hdc, &point); /* fill point */ ! 694: point.x = rect.right; ! 695: point.y += tm.tmHeight; ! 696: for (i = 0; i<5; i++) { ! 697: MoveToEx (hdc, point.x, point.y, NULL); ! 698: LineTo (hdc, 0, point.y); ! 699: point.y++; ! 700: } ! 701: ! 702: ! 703: switch (gDisplaymode) { ! 704: case IDM_MODEHELLO: ! 705: SetViewportOrgEx (hdc, rect.right /2, rect.bottom/2, NULL); ! 706: TextOut (hdc, 0, 0, TEXT("Hello"), 5); ! 707: break; ! 708: ! 709: ! 710: case IDM_MODETMRANGE: ! 711: BlamGlyphs (hdc, &tm, tm.tmFirstChar, tm.tmLastChar, &rect, TRUE); ! 712: break; ! 713: ! 714: case IDM_MODEALL: ! 715: /* the horz scroll bar has the number of segments stored as ! 716: * the scroll bar range, query and use it. ! 717: */ ! 718: GetScrollRange (hwnd, SB_HORZ, &ScrollMin, &ScrollMax); ! 719: ! 720: for (i = 0; i<= ScrollMax; i++) { ! 721: MoveToEx (hdc,rect.right, point.y, NULL); ! 722: LineTo (hdc, rect.left, point.y); ! 723: ! 724: SelectObject (hdc,GetStockObject (DEVICE_DEFAULT_FONT)); ! 725: nchar = wsprintf (buffer, TEXT("[%04x, %04x]"), (int)startCount[i], ! 726: (int)endCount[i]); ! 727: TextOut (hdc, 0,0,buffer, nchar); ! 728: SelectObject (hdc,hfont); ! 729: ! 730: ! 731: BlamGlyphs (hdc, &tm, startCount[i], endCount[i], &rect, TRUE); ! 732: ! 733: GetCurrentPositionEx (hdc, &point); ! 734: point.x = 0; ! 735: point.y += (tm.tmHeight + tm.tmExternalLeading); ! 736: MoveToEx (hdc, point.x, point.y, NULL); ! 737: if ((point.y+tm.tmHeight+tm.tmExternalLeading) > rect.bottom) { ! 738: point.x = point.y = 0; ! 739: EndPage (hdc); ! 740: StartPage (hdc); ! 741: MoveToEx (hdc, point.x, point.y, NULL); ! 742: } ! 743: } ! 744: break; /* end IDM_MODEALL */ ! 745: } /* end switch */ ! 746: ! 747: EndPage (hdc); ! 748: EndDoc (hdc); ! 749: ! 750: DeleteDC (hdc); ! 751: SetCursor (LoadCursor (NULL, IDC_ARROW)); ! 752: ! 753: } return TRUE; ! 754: ! 755: } /* end switch */ ! 756: ! 757: return (DefMDIChildProc(hwnd, message, wParam, lParam)); ! 758: } ! 759: ! 760: ! 761: ! 762: ! 763: /**************************************************************************\ ! 764: * ! 765: * function: BlamGlyphs ! 766: * ! 767: * input parameters: ! 768: * hdc with font selected into it. ! 769: * pointer to a text metric structure. ! 770: * start and end of code point range to print ! 771: * pointer to rectangle which serves as bounds. ! 772: * ! 773: * Starting at the current point, write one glyph after the other, starting ! 774: * with the "Start" parameter, and ending with the "End" parameter. If ! 775: * the next character will overrun on the right, start again on a new line. ! 776: * Special case Start = 0xfff which happens because the start/endCount ! 777: * arrays always end with this value. ! 778: * ! 779: * ! 780: // UNICODE NOTICE ! 781: // This function is held as unicode because it needs to display ! 782: // wide characters (i.e. need TextOutW). ! 783: * ! 784: * ! 785: \**************************************************************************/ ! 786: VOID BlamGlyphs (HDC hdc, PTEXTMETRIC ptm, USHORT Start, USHORT End, PRECT prect, BOOL printing) ! 787: { ! 788: USHORT i; ! 789: POINT point; ! 790: WCHAR outChar; ! 791: ! 792: if (Start == 0xffff) return; ! 793: ! 794: for (i = Start; i<=End; i++) { ! 795: ! 796: /* special case the non-spacing diacritic marks. U+0300 -> U+036F ! 797: * Write a space first, for them to 'modify.' ! 798: */ ! 799: if ( (0x0300 <= i) && (i <= 0x036F) ) { ! 800: outChar = (WCHAR) 0x0020; ! 801: TextOutW (hdc, 0,0, &outChar, 1); ! 802: } ! 803: ! 804: ! 805: outChar = (WCHAR) i; ! 806: TextOutW (hdc, 0,0, &outChar, 1); ! 807: ! 808: GetCurrentPositionEx (hdc, &point); ! 809: if (point.x > (prect->right - ptm->tmAveCharWidth)) { ! 810: point.x = 0; ! 811: point.y += (ptm->tmHeight + ptm->tmExternalLeading); ! 812: MoveToEx (hdc, point.x, point.y, NULL); ! 813: } ! 814: ! 815: if (printing) ! 816: if (point.y > (prect->bottom-(ptm->tmHeight+ptm->tmExternalLeading))) { ! 817: EndPage (hdc); ! 818: StartPage (hdc); ! 819: point.x = point.y = 0; ! 820: MoveToEx (hdc, point.x, point.y, NULL); ! 821: } ! 822: } ! 823: } ! 824: ! 825: ! 826: ! 827: ! 828: /**************************************************************************\ ! 829: * ! 830: * All of the code below is used for parsing "font data." It will only ! 831: * make sense if you have a copy of the True Type font spec. In short, ! 832: * we grab the 'cmap' table, look through it for a subtable, and then ! 833: * get two parallel arrays from the subtable. Complications arise because ! 834: * the true type data is "BIG ENDIAN" and NT is being run "little endian." ! 835: * For this reason, once we locate the short or long, we call Swap* to ! 836: * change the byte ordering. ! 837: * ! 838: \**************************************************************************/ ! 839: ! 840: ! 841: VOID SwapShort (PUSHORT); ! 842: VOID SwapULong (PULONG); ! 843: ! 844: ! 845: ! 846: typedef struct tagTABLE{ ! 847: USHORT platformID; ! 848: USHORT encodingID; ! 849: ULONG offset; ! 850: } TABLE, *PTABLE; ! 851: ! 852: typedef struct tagSUBTABLE{ ! 853: USHORT format; ! 854: USHORT length; ! 855: USHORT version; ! 856: USHORT segCountX2; ! 857: USHORT searchRange; ! 858: USHORT entrySelector; ! 859: USHORT rangeShift; ! 860: } SUBTABLE, *PSUBTABLE; ! 861: ! 862: ! 863: /* 'cmap' is passed in by value in a DWORD */ ! 864: #define CMAPHEX 0x636d6170 ! 865: #define NBYTES 256 ! 866: #define OFFSETERROR 0 ! 867: ! 868: ! 869: ! 870: /**************************************************************************\ ! 871: * ! 872: * function: CountUCSegments() ! 873: * ! 874: * input parameters: ! 875: * hdc - with the logical font set into it. ! 876: * prect - pointer to client rectangle. ! 877: * ! 878: * Global variables: ! 879: * startCount ! 880: * endCount ! 881: * ! 882: * returns: ! 883: * number of UC segments or ! 884: * SEGMENTERROR if there is some kind of error. ! 885: * ! 886: * essential side effect: ! 887: * Fills in global startCount, endCount arrays. ! 888: \**************************************************************************/ ! 889: int CountUCSegments (HDC hdc) ! 890: { ! 891: DWORD cbData; ! 892: USHORT aShort[2]; ! 893: DWORD nBytes; ! 894: USHORT i, nTables; ! 895: PTABLE pTable; ! 896: PSUBTABLE pSubTable; ! 897: ULONG offset,offsetFormat4; ! 898: USHORT segCount; ! 899: BYTE buffer[NBYTES]; ! 900: ! 901: ! 902: ! 903: ! 904: /* find number of "subtables", second long in cmap */ ! 905: nBytes=GetFontData (hdc, CMAPHEX, 0, aShort, 4); ! 906: if (nBytes == (DWORD)-1) { ! 907: MessageBox (NULL, MBGETFONTDATAERR,MBERROR , MBERRORFLAGS); ! 908: return SEGMENTERROR; ! 909: } ! 910: nTables = aShort[1]; ! 911: SwapShort (&nTables); ! 912: ! 913: ! 914: cbData = nTables * sizeof(TABLE); ! 915: if (cbData >NBYTES) { ! 916: MessageBox (NULL, TEXT("cbData >NBYTES"),MBERROR , MBERRORFLAGS); ! 917: return SEGMENTERROR; ! 918: } ! 919: ! 920: /* get array of subtables information. Check each one for 3,1*/ ! 921: nBytes=GetFontData (hdc, CMAPHEX, 4, buffer, cbData); ! 922: pTable = (PTABLE)buffer; ! 923: offsetFormat4 = OFFSETERROR; ! 924: for (i = 0; i< nTables; i++) { ! 925: ! 926: SwapShort (&(pTable->encodingID)); ! 927: SwapShort (&(pTable->platformID)); ! 928: ! 929: if ((pTable->platformID == 3)&&(pTable->encodingID == 1)) { ! 930: offsetFormat4 = pTable->offset; ! 931: SwapULong (&offsetFormat4); ! 932: break; ! 933: } ! 934: pTable++; ! 935: } ! 936: ! 937: /* verify that we got the correct offset to the FORMAT 4 subtable */ ! 938: if (offsetFormat4 == OFFSETERROR){ ! 939: MessageBox (NULL, TEXT("Can not find 3,1 subtable"),MBERROR , MBERRORFLAGS); ! 940: return SEGMENTERROR; ! 941: } ! 942: ! 943: /* Get the beginning of the subtable, especially the segment count */ ! 944: nBytes=GetFontData (hdc, CMAPHEX, offsetFormat4, buffer, sizeof(SUBTABLE)); ! 945: pSubTable = (PSUBTABLE) buffer; ! 946: SwapShort (&(pSubTable->format)); ! 947: SwapShort (&(pSubTable->segCountX2)); ! 948: ! 949: if (pSubTable->format != 4){ ! 950: MessageBox (NULL, TEXT("format !=4"), MBERROR, MBERRORFLAGS); ! 951: return SEGMENTERROR; ! 952: } ! 953: ! 954: segCount = pSubTable->segCountX2 / 2; ! 955: ! 956: if (segCount > MAXSEGMENTS){ ! 957: MessageBox (NULL, TEXT("segCount > MAXSEGMENTS"), MBERROR, MBERRORFLAGS); ! 958: return SEGMENTERROR; ! 959: } ! 960: ! 961: /* read in the array of endCount values */ ! 962: offset = offsetFormat4 ! 963: + (7 * sizeof (USHORT)); /* skip constant # bytes in subtable */ ! 964: cbData = segCount * sizeof (USHORT); ! 965: nBytes=GetFontData (hdc, CMAPHEX, offset, endCount, cbData ); ! 966: for (i = 0; i<segCount; i++) ! 967: SwapShort (& (endCount[i])); ! 968: ! 969: /* read in the array of startCount values */ ! 970: offset = offsetFormat4 ! 971: + (7 * sizeof (USHORT)) /* skip constant # bytes in subtable */ ! 972: + (segCount * sizeof (USHORT)) /* skip endCount array */ ! 973: + sizeof (USHORT); /* skip reservedPad */ ! 974: cbData = segCount * sizeof (USHORT); ! 975: nBytes=GetFontData (hdc, CMAPHEX, offset, startCount, cbData ); ! 976: for (i = 0; i<segCount; i++) ! 977: SwapShort (& (startCount[i])); ! 978: ! 979: ! 980: return segCount; ! 981: } ! 982: ! 983: ! 984: ! 985: ! 986: ! 987: ! 988: ! 989: ! 990: ! 991: ! 992: VOID SwapShort (PUSHORT p) ! 993: { ! 994: SHORT temp; ! 995: ! 996: temp =(SHORT)( HIBYTE (*p) + (LOBYTE(*p) << 8)); ! 997: *p = temp; ! 998: } ! 999: ! 1000: ! 1001: ! 1002: VOID SwapULong (PULONG p) ! 1003: { ! 1004: ULONG temp; ! 1005: ! 1006: temp = (LONG) ((BYTE) *p); ! 1007: temp <<= 8; ! 1008: *p >>=8; ! 1009: ! 1010: temp += (LONG) ((BYTE) *p); ! 1011: temp <<= 8; ! 1012: *p >>=8; ! 1013: ! 1014: temp += (LONG) ((BYTE) *p); ! 1015: temp <<= 8; ! 1016: *p >>=8; ! 1017: ! 1018: temp += (LONG) ((BYTE) *p); ! 1019: *p = temp; ! 1020: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.