Annotation of mstools/samples/ntfonts/display.c, revision 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.