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

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

unix.superglobalmegacorp.com

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