Annotation of mstools/samples/ttfonts/display.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

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