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