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

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

unix.superglobalmegacorp.com

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