Annotation of q_a/samples/uniput/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 to support the main MDI child windows.
        !            14: *
        !            15: * This module contains Window Procedure, openDisplay() and closeDisplay()
        !            16: *  routines.  Call openDisplay() one time per process before creating the
        !            17: *  first window, and call closeDisplay() one time at process termination.
        !            18: *
        !            19: * windows are created in main frame window procedure.
        !            20: *
        !            21: * design:  We have one window procedure here for potentially multiple
        !            22: *  MDI child windows.  The nCharPerLine, SqrHeight, and SqrWidth are
        !            23: *  stored on a per window basis.  Also, the window class is registered
        !            24: *  with the style CS_OWNDC.  For this reason, it is possible to select
        !            25: *  a logical font into the HDC, and it will be there each time you get
        !            26: *  the DC new for the window.  In this way we have a log font for each
        !            27: *  window without actually doing any work in this module.
        !            28: *
        !            29: *  Some of the data is global, and works for all of the windows.  The
        !            30: *  startcount & endcount arrays are a good example.  These are computed
        !            31: *  once when the font is created, but the values remain the same for each
        !            32: *  window.  Thus we have the following assumption:
        !            33: *
        !            34: *   1.  No fonts will be installed or removed while program is running.
        !            35: *       (CountUCSegments values remain valid for run time duration).
        !            36: *
        !            37: *
        !            38: *  There are WM_USER+ messages to set values for this window, and to
        !            39: *  notify it of global changes.  Looking at the create time, user message
        !            40: *  stream is helpful.  On the WM_CREATE message, we send ourselves a
        !            41: *  WMU_NEWFONT message to create a logical font and count the number of
        !            42: *  character ranges (segments).  Before returning from this message, we
        !            43: *  send ourselves a WMU_NEWRANGE message to set the title, and the
        !            44: *  horizontal scroll bar correctly.
        !            45: *
        !            46: *
        !            47: \**************************************************************************/
        !            48: #define UNICODE
        !            49: 
        !            50: #include <windows.h>
        !            51: #include "uniput.h"
        !            52: #include "display.h"
        !            53: 
        !            54: 
        !            55: /* global variables store the start and end codepoints for UC ranges. */
        !            56: #define MAXSEGMENTS  100
        !            57: USHORT *endCount= NULL;
        !            58: USHORT *startCount= NULL;
        !            59: 
        !            60: int CountUCSegments (HDC);
        !            61: /* error return value from CountUCSegments */
        !            62: #define SEGMENTERROR -1
        !            63: 
        !            64: 
        !            65: /* conversion between (x,y) pairs and rectangle index */
        !            66: int transXYtoIndex (int, int, int, int, int);
        !            67: int transIndextoRect (int, PRECT, int, int, int);
        !            68: 
        !            69: 
        !            70: /* window extra bytes for use to store window specific data (see register class) */
        !            71: #define GWLU_NCHAR        0
        !            72: #define GWLU_SQRHEIGHT    4
        !            73: #define GWLU_SQRWIDTH     8
        !            74: 
        !            75: 
        !            76: 
        !            77: 
        !            78: 
        !            79: /* Global logfont.  Used for CreateFontIndirect().
        !            80:  *  also regerenced in the uniput.c file.
        !            81:  */
        !            82: LOGFONT logfont = {
        !            83:       UCFONTHEIGHT ,
        !            84:       UCFONTWIDTH ,
        !            85:        0 ,
        !            86:        0 ,
        !            87:      400 ,
        !            88:        0 ,
        !            89:        0 ,
        !            90:        0 ,
        !            91:        UNICODE_CHARSET ,
        !            92:        0 ,
        !            93:        0 ,
        !            94:        2 ,
        !            95:        2 ,
        !            96:       TEXT("Lucida Sans Unicode")};
        !            97: 
        !            98: 
        !            99: /* Global, class specific data.
        !           100:  *  ought to allocate once per class, and free once at app exit time.
        !           101:  */
        !           102: HDC hdcMemXOR;
        !           103: HBITMAP hbmMemXOR;
        !           104: PVOID pbitsXOR, pbitsAND;
        !           105: 
        !           106: int FontWidth, FontHeight;
        !           107: int nSegments;
        !           108: 
        !           109: /**************************************************************************\
        !           110: *
        !           111: *  function:  openDisplay()
        !           112: *
        !           113: *  Global variables:
        !           114: *   HDC hdcMemXOR;
        !           115: *   HBITMAP hbmMemXOR;
        !           116: *   PVOID pbitsXOR, pbitsAND;
        !           117: *   int FontWidth, FontHeight;
        !           118: *   int nSegments;
        !           119: *
        !           120: *  returns:  TRUE - if success,  FALSE - if fail.
        !           121: *
        !           122: *  essential side effect:
        !           123: *   Registers window class, and initial global variables.
        !           124: \**************************************************************************/
        !           125: int openDisplay(VOID )
        !           126: {
        !           127: WNDCLASS  wc;
        !           128: static int cxCursor, cyCursor;
        !           129: HFONT hfont;
        !           130: 
        !           131:   /* Register the window class*/
        !           132:   wc.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
        !           133:   wc.lpfnWndProc = (WNDPROC)DisplayWndProc;
        !           134:   wc.cbClsExtra = 0;
        !           135:   wc.cbWndExtra = 12;
        !           136:   wc.hInstance = hInst;
        !           137:   wc.hIcon = LoadIcon(hInst, TEXT("uniputIcon"));
        !           138:   wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        !           139:   wc.hbrBackground = GetStockObject (WHITE_BRUSH);
        !           140:   wc.lpszMenuName = NULL;
        !           141:   wc.lpszClassName = DISPLAYCLASS;
        !           142: 
        !           143:   if (!RegisterClass(&wc)) return (FALSE);
        !           144: 
        !           145:   cxCursor = GetSystemMetrics (SM_CXCURSOR);
        !           146:   cyCursor = GetSystemMetrics (SM_CYCURSOR);
        !           147: 
        !           148:   /* get pointer to 0-init memory */
        !           149:   pbitsAND = (PVOID) LocalAlloc (LPTR, cxCursor*cyCursor/8);
        !           150: 
        !           151:   /* Create a memory DC to draw into for creating cursors. */
        !           152:   hdcMemXOR = CreateCompatibleDC (NULL);
        !           153:   hbmMemXOR = CreateBitmap (cxCursor,cyCursor,1,4,NULL);
        !           154:   SelectObject (hdcMemXOR, hbmMemXOR);
        !           155: 
        !           156:   /* set text modes for the memory HDC */
        !           157:   SetBkMode (hdcMemXOR, TRANSPARENT);
        !           158:   SetTextAlign (hdcMemXOR, TA_CENTER | TA_TOP);
        !           159: 
        !           160:   /* set a unicode font into the memory DC */
        !           161:   logfont.lfHeight = cyCursor  *2/3;  // HACK.. scale down Y
        !           162:   logfont.lfWidth  = cxCursor  *2/3;
        !           163:   hfont = CreateFontIndirect (&logfont);
        !           164:   SelectObject (hdcMemXOR, hfont);
        !           165: 
        !           166:   /* get pointer to be used later as pointer to bitmap bits */
        !           167:   pbitsXOR = (PVOID) LocalAlloc (LPTR, cxCursor*cyCursor/2);
        !           168: 
        !           169:   /* Assume that we got a unicode font.
        !           170:    *  Count the number of segments, and fill in the proper global
        !           171:    *  variables specifying the code point ranges covered.
        !           172:    */
        !           173:   nSegments = CountUCSegments (hdcMemXOR); /* slow computation */
        !           174: 
        !           175: 
        !           176:   /* verify that we have SOME ranges to work with */
        !           177:   if (nSegments == SEGMENTERROR) return FALSE;
        !           178: 
        !           179:   /* warn the user if we can't find the right font */
        !           180:   if (nSegments < 30)
        !           181:     MessageBox (NULL,
        !           182:         TEXT("Working with limited codepoint coverage. \n Install uclucida.ttf"),
        !           183:         TEXT("Warning: Lucida Sans Unicode font not found."), MB_OK);
        !           184: 
        !           185: 
        !           186: 
        !           187:   FontWidth  = UCFONTWIDTH;
        !           188:   FontHeight = UCFONTHEIGHT;
        !           189: 
        !           190:   return TRUE;
        !           191: }
        !           192: 
        !           193: /**************************************************************************\
        !           194: *
        !           195: *  function:  closeDisplay()
        !           196: *
        !           197: *  Global variables:
        !           198: *   HDC hdcMemXOR;
        !           199: *   HBITMAP hbmMemXOR;
        !           200: *   PVOID pbitsXOR, pbitsAND;
        !           201: *
        !           202: *  essential side effect:
        !           203: *   Frees global variables.
        !           204: \**************************************************************************/
        !           205: int closeDisplay(VOID)
        !           206: {
        !           207: HFONT hfont;
        !           208: 
        !           209:   hfont = SelectObject  (hdcMemXOR, GetStockObject(SYSTEM_FONT));
        !           210:   DeleteObject (hfont);
        !           211:   DeleteDC (hdcMemXOR);
        !           212:   DeleteObject (hbmMemXOR);
        !           213: 
        !           214:   LocalFree (LocalHandle (pbitsXOR));
        !           215:   LocalFree (LocalHandle (pbitsAND));
        !           216:   return TRUE;
        !           217: }
        !           218: 
        !           219: 
        !           220: /**************************************************************************\
        !           221: *
        !           222: *  function:  DisplayWndProc()
        !           223: *
        !           224: *  input parameters:  normal window procedure parameters.
        !           225: *
        !           226: \**************************************************************************/
        !           227: LRESULT CALLBACK DisplayWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        !           228: {
        !           229: static HFONT  hfont, hfontOld;
        !           230: 
        !           231: static HDC hdc;
        !           232: static RECT rect;
        !           233: static int iSeg;
        !           234: static TCHAR buffer[100];
        !           235: 
        !           236: /* rDown and index used as the user points to a square. */
        !           237: static RECT rDown;
        !           238: static int index;
        !           239: 
        !           240: static WCHAR DragDropChar;
        !           241: static HICON hIcon;
        !           242: 
        !           243: 
        !           244: 
        !           245:   switch (message) {
        !           246: 
        !           247:     /**********************************************************************\
        !           248:     *  WM_CREATE
        !           249:     *
        !           250:     * Set up the LOGFONT in the HDC for this window.
        !           251:     \**********************************************************************/
        !           252:     case WM_CREATE:
        !           253:       SendMessage (hwnd, WMU_SETNCHAR, 16, 0);
        !           254:       SendMessage (hwnd, WMU_NEWFONT, FontWidth, FontHeight);
        !           255:     break;
        !           256: 
        !           257: 
        !           258:     /**********************************************************************\
        !           259:     *  WM_DESTROY
        !           260:     *
        !           261:     * Get rid of the logical font we create for each display window.
        !           262:     *  relying here on CS_ONWDC
        !           263:     \**********************************************************************/
        !           264:     case WM_DESTROY:
        !           265:       hdc = GetDC (hwnd);
        !           266:       hfont = SelectObject  (hdc, GetStockObject(SYSTEM_FONT));
        !           267:       DeleteObject (hfont);
        !           268:       ReleaseDC (hwnd, hdc);
        !           269: 
        !           270:       if (startCount != NULL) LocalFree (LocalHandle (startCount));
        !           271:       if (endCount != NULL) LocalFree (LocalHandle (endCount));
        !           272: 
        !           273:     break;
        !           274: 
        !           275: 
        !           276: 
        !           277: 
        !           278: 
        !           279:     /**********************************************************************\
        !           280:     *  WMU_SETNCHAR
        !           281:     *
        !           282:     * wParam - nCharPerLine
        !           283:     *
        !           284:     \**********************************************************************/
        !           285:     case WMU_SETNCHAR:
        !           286:       SetWindowLong (hwnd, GWLU_NCHAR, (int) wParam);
        !           287:       InvalidateRect (hwnd, NULL, TRUE);
        !           288:     break;
        !           289: 
        !           290:     /**********************************************************************\
        !           291:     *  WMU_NEWFONT
        !           292:     *
        !           293:     * wParam - Width
        !           294:     * lParam - Height
        !           295:     *
        !           296:     * Create font, select it into the HDC, and reset ranges.
        !           297:     \**********************************************************************/
        !           298:     case WMU_NEWFONT: {
        !           299: 
        !           300:       hdc = GetDC(hwnd);
        !           301: 
        !           302:       FontWidth  = (int) wParam;
        !           303:       FontHeight = (int) lParam;
        !           304:       logfont.lfHeight = FontHeight;
        !           305:       logfont.lfWidth  = FontWidth;
        !           306: 
        !           307:       hfont = CreateFontIndirect (&logfont);
        !           308:       hfontOld = SelectObject (hdc, hfont);
        !           309:       DeleteObject (hfontOld);
        !           310: 
        !           311:       ReleaseDC (hwnd, hdc);
        !           312: 
        !           313: 
        !           314:       SetScrollRange (hwnd, SB_HORZ, 0, (nSegments-1), TRUE);
        !           315:       SetScrollPos (hwnd, SB_HORZ, 0, TRUE);
        !           316: 
        !           317:       SendMessage (hwnd, WMU_NEWRANGE, 0,0);
        !           318: 
        !           319:     } return TRUE;
        !           320: 
        !           321: 
        !           322:     /**********************************************************************\
        !           323:     *  WMU_NEWRANGE
        !           324:     *
        !           325:     *
        !           326:     * Range changes, or font size changes, or title status changes.
        !           327:     \**********************************************************************/
        !           328:     case WMU_NEWRANGE: {
        !           329:       int sqrHeight, sqrWidth;
        !           330:       TEXTMETRIC tm;
        !           331:       int i;
        !           332: 
        !           333:       hdc = GetDC(hwnd);
        !           334:       GetTextMetrics (hdc, &tm);
        !           335:       ReleaseDC (hwnd, hdc);
        !           336: 
        !           337:       /* index into the start, end arrays stored in scroll bar */
        !           338:       iSeg = GetScrollPos (hwnd, SB_HORZ);
        !           339: 
        !           340:       /* Set the window title text to show display range. */
        !           341:       wsprintf (buffer, TEXT("[%04x, %04x]"),
        !           342:                                   (int)startCount[iSeg],
        !           343:                                   (int)endCount[iSeg]);
        !           344: 
        !           345:       /* if we are supposed to look up the character range name,
        !           346:        *  then step through the ranges stored in the RangeName
        !           347:        *  table.  Find the correct one, and reset the buffer string.
        !           348:        */
        !           349:       if (gShowNames) {
        !           350:         for (i = 0; i< NRANGE; i++) {
        !           351:           if ((RangeName[i].start <= startCount[iSeg]) &&
        !           352:               ( startCount[iSeg] <= RangeName[i].end))
        !           353: 
        !           354:             wsprintf (buffer, TEXT("%s [%04x, %04x]"),
        !           355:                                   RangeName[i].String,
        !           356:                                   (int)startCount[iSeg],
        !           357:                                   (int)endCount[iSeg]);
        !           358: 
        !           359:         }
        !           360:       }
        !           361:       SetWindowText (hwnd, buffer);
        !           362: 
        !           363:       sqrHeight =  tm.tmHeight + tm.tmExternalLeading;
        !           364:       sqrWidth = tm.tmMaxCharWidth;
        !           365: 
        !           366:       SetWindowLong (hwnd, GWLU_SQRHEIGHT,sqrHeight);
        !           367:       SetWindowLong (hwnd, GWLU_SQRWIDTH, sqrWidth );
        !           368: 
        !           369:     } return TRUE;
        !           370: 
        !           371: 
        !           372: 
        !           373: 
        !           374: 
        !           375: 
        !           376: 
        !           377: 
        !           378: 
        !           379:     /**********************************************************************\
        !           380:     *  WM_LBUTTONDOWN
        !           381:     *
        !           382:     * Static, shared variables set in WM_LBUTTONDOWN:
        !           383:     *   rDown, hIcon, DragDropChar
        !           384:     *
        !           385:     \**********************************************************************/
        !           386:     case WM_LBUTTONDOWN: {
        !           387:       int x,y;
        !           388:       int nCharPerLine;
        !           389:       int sqrHeight, sqrWidth;
        !           390:       nCharPerLine = GetWindowLong (hwnd, GWLU_NCHAR);
        !           391:       sqrHeight    = GetWindowLong (hwnd, GWLU_SQRHEIGHT);
        !           392:       sqrWidth     = GetWindowLong (hwnd, GWLU_SQRWIDTH );
        !           393: 
        !           394: 
        !           395: 
        !           396:       x = (int)LOWORD (lParam);
        !           397:       y = (int)HIWORD (lParam);
        !           398: 
        !           399:       index = transXYtoIndex (x,y, sqrWidth, sqrHeight, nCharPerLine);
        !           400: 
        !           401:       /* verify that the index is within the shown segment range */
        !           402:       iSeg= GetScrollPos (hwnd, SB_HORZ);
        !           403:       if (index > (endCount[iSeg]- startCount[iSeg])) return 0;
        !           404: 
        !           405:       DragDropChar = index + startCount[iSeg];
        !           406: 
        !           407:       transIndextoRect (index, &rDown, sqrWidth, sqrHeight, nCharPerLine);
        !           408: 
        !           409:       hdc = GetDC (hwnd);
        !           410:       InvertRect (hdc, &rDown);
        !           411:       ReleaseDC (hwnd, hdc);
        !           412: 
        !           413: 
        !           414:       /* Create a cursor which represents the character.
        !           415:        * Global variables used:
        !           416:        *   HDC hdcMemXOR;
        !           417:        *   HBITMAP hbmMemXOR;
        !           418:        *   PVOID pbitsXOR, pbitsAND;
        !           419:        */
        !           420:       {
        !           421:       int cxCursor, cyCursor;
        !           422:       RECT rect;
        !           423: 
        !           424:       cxCursor = GetSystemMetrics (SM_CXCURSOR);
        !           425:       cyCursor = GetSystemMetrics (SM_CYCURSOR);
        !           426: 
        !           427:       rect.left = rect.top = 0;
        !           428:       rect.right = cxCursor; rect.bottom = cyCursor;
        !           429: 
        !           430: 
        !           431:       FrameRect (hdcMemXOR, &rect, GetStockObject (BLACK_BRUSH));
        !           432:       InflateRect (&rect, -1, -1);
        !           433:       FillRect (hdcMemXOR, &rect, GetStockObject (LTGRAY_BRUSH));
        !           434:       FrameRect (hdcMemXOR, &rect, GetStockObject (GRAY_BRUSH));
        !           435:       InflateRect (&rect, -1, -1);
        !           436:       SelectObject (hdcMemXOR, GetStockObject (WHITE_PEN));
        !           437:       MoveToEx (hdcMemXOR, rect.right, rect.top, NULL);
        !           438:       LineTo (hdcMemXOR,rect.left, rect.top);
        !           439:       LineTo (hdcMemXOR,rect.left, rect.bottom);
        !           440: 
        !           441:       ExtTextOut(hdcMemXOR, cxCursor/2,0, ETO_CLIPPED, &rect,
        !           442:                    (LPCWSTR)&DragDropChar, 1, NULL);
        !           443: 
        !           444:       GetBitmapBits (hbmMemXOR, cxCursor*cyCursor/2, pbitsXOR);
        !           445: 
        !           446:       hIcon = CreateIcon( GetModuleHandle(NULL),
        !           447:               cxCursor,cyCursor, 1,4,
        !           448:               pbitsAND,
        !           449:               pbitsXOR);
        !           450: 
        !           451:       SetCursor ((HCURSOR)hIcon);
        !           452:       }
        !           453: 
        !           454: 
        !           455: 
        !           456:       GdiFlush ();
        !           457:       SetCapture (hwnd);
        !           458:     } break;
        !           459: 
        !           460:     /**********************************************************************\
        !           461:     *  WM_LBUTTONUP
        !           462:     *
        !           463:     * Static, shared variables set in WM_LBUTTONDOWN:
        !           464:     *   rDown, hIcon, DragDropChar
        !           465:     *
        !           466:     \**********************************************************************/
        !           467:     case WM_LBUTTONUP: {
        !           468:       POINT p;
        !           469:       HWND hwndTarget, hwndTitle;
        !           470: #define NUMCHARS  255
        !           471:       TCHAR buffer[NUMCHARS];
        !           472: 
        !           473: 
        !           474:       if (GetCapture() == hwnd) {
        !           475: 
        !           476:         p.x = (int)(short)LOWORD (lParam);
        !           477:         p.y = (int)(short)HIWORD (lParam);
        !           478: 
        !           479:         ClientToScreen (hwnd, &p);
        !           480:         hwndTarget = WindowFromPoint (p);
        !           481: 
        !           482:         if ((GetWindowThreadProcessId (hwnd, NULL)) !=
        !           483:             (GetWindowThreadProcessId (hwndTarget, NULL))) {
        !           484: 
        !           485:           /* hack.  unipad has a client window which gets the chars,
        !           486:            *  but we want to display the frame windows text (title bar),
        !           487:            *  so try to get the parent of the target for Title purposes.
        !           488:            */
        !           489:           hwndTitle = (GetParent(hwndTarget)) ? GetParent(hwndTarget) : hwndTarget;
        !           490:           GetWindowText (hwndTitle, buffer, NUMCHARS);
        !           491: 
        !           492:           SendMessage (hwndTarget, WM_CHAR, (WPARAM) DragDropChar, 0);
        !           493:           SendMessage (hwndStatus, WMU_CHARACTER,
        !           494:                          (WPARAM) DragDropChar, (LPARAM)hwndTarget);
        !           495:           SendMessage (hwndStatus, WMU_SETTARGETNAME,
        !           496:                          (WPARAM) IsWindowUnicode (hwndTarget), (LPARAM)buffer);
        !           497:         } /* end different process */
        !           498: 
        !           499:         Beep (40,40);
        !           500: 
        !           501:         hdc = GetDC (hwnd);
        !           502:         InvertRect (hdc, &rDown);
        !           503:         ReleaseDC (hwnd, hdc);
        !           504:         GdiFlush ();
        !           505:         ReleaseCapture ();
        !           506:         SetCursor ((HCURSOR)LoadCursor (NULL, IDC_ARROW));
        !           507:         DestroyIcon (hIcon);
        !           508:       }
        !           509:     } break;
        !           510: 
        !           511: 
        !           512: 
        !           513:     /**********************************************************************\
        !           514:     *  WM_HSCROLL
        !           515:     *
        !           516:     * Step through the character ranges.
        !           517:     * In every case, inform the window the range has changed,
        !           518:     *  and invalidate it to force a repaint.
        !           519:     \**********************************************************************/
        !           520:     case WM_HSCROLL:
        !           521: 
        !           522:       switch (LOWORD(wParam)){
        !           523:         int OldPos, NewPos;
        !           524: 
        !           525:         case SB_PAGEDOWN:
        !           526:         case SB_LINEDOWN:
        !           527:           OldPos = GetScrollPos (hwnd, SB_HORZ);
        !           528:           SetScrollPos (hwnd, SB_HORZ, (OldPos+1), TRUE);
        !           529:           SendMessage (hwnd,WMU_NEWRANGE, 0,0);
        !           530:           InvalidateRect (hwnd, NULL, TRUE);
        !           531:         break;
        !           532: 
        !           533:         case SB_PAGEUP:
        !           534:         case SB_LINEUP:
        !           535:           OldPos = GetScrollPos (hwnd, SB_HORZ);
        !           536:           SetScrollPos (hwnd, SB_HORZ, (OldPos-1), TRUE);
        !           537:           SendMessage (hwnd,WMU_NEWRANGE, 0,0);
        !           538:           InvalidateRect (hwnd, NULL, TRUE);
        !           539:         break;
        !           540: 
        !           541:         case SB_THUMBPOSITION:
        !           542:           OldPos = GetScrollPos (hwnd, SB_HORZ);
        !           543:           NewPos = HIWORD (wParam);
        !           544:           SetScrollPos (hwnd, SB_HORZ, NewPos, TRUE);
        !           545:           SendMessage (hwnd,WMU_NEWRANGE, 0,0);
        !           546:           InvalidateRect (hwnd, NULL, TRUE);
        !           547:         break;
        !           548: 
        !           549:       }
        !           550: 
        !           551:     break;
        !           552: 
        !           553: 
        !           554: 
        !           555: 
        !           556: 
        !           557: 
        !           558: 
        !           559:     /**********************************************************************\
        !           560:     *  WM_SIZE
        !           561:     *
        !           562:     \**********************************************************************/
        !           563:     case WM_SIZE:
        !           564:       /* make sure that scroll metrics are ok */
        !           565:       SendMessage (hwnd, WMU_NEWRANGE, 0,0);
        !           566: 
        !           567:     break;  /* fall through to MDIChildProc */
        !           568: 
        !           569: 
        !           570:     /**********************************************************************\
        !           571:     *  WM_PAINT
        !           572:     *
        !           573:     \**********************************************************************/
        !           574:     case WM_PAINT: {
        !           575:       HDC hdc;
        !           576:       PAINTSTRUCT ps;
        !           577:       RECT rect;
        !           578:       POINT  point;
        !           579:       int i;
        !           580:       USHORT start, end;
        !           581:       WCHAR outChar;
        !           582:       USHORT codepoint;
        !           583:       int nCharPerLine;
        !           584:       int sqrHeight, sqrWidth;
        !           585:       nCharPerLine = GetWindowLong (hwnd, GWLU_NCHAR);
        !           586:       sqrHeight    = GetWindowLong (hwnd, GWLU_SQRHEIGHT);
        !           587:       sqrWidth     = GetWindowLong (hwnd, GWLU_SQRWIDTH );
        !           588: 
        !           589: 
        !           590:       hdc = BeginPaint(hwnd, &ps);
        !           591:       SetBkMode (hdc, TRANSPARENT);
        !           592: 
        !           593:       iSeg= GetScrollPos (hwnd, SB_HORZ);
        !           594:       start = startCount[iSeg];
        !           595:       end = endCount[iSeg];
        !           596: 
        !           597:       /* ensure that we are in a valid range... some fonts have problems */
        !           598:       if (start != 0xffff)
        !           599: 
        !           600:         for (codepoint = start, i=0; codepoint<=end; codepoint++,i++) {
        !           601: 
        !           602:           /* paint box and frame it */
        !           603:           transIndextoRect (i, &rect, sqrWidth, sqrHeight, nCharPerLine);
        !           604:           InflateRect (&rect, -1, -1);
        !           605:           FillRect (hdc, &rect, GetStockObject (LTGRAY_BRUSH));
        !           606:           InflateRect (&rect, 1, 1);
        !           607:           FrameRect (hdc, &rect, GetStockObject (GRAY_BRUSH));
        !           608:           InflateRect (&rect, -1, -1);
        !           609:           SelectObject (hdc, GetStockObject (WHITE_PEN));
        !           610:           MoveToEx (hdc, rect.right, rect.top, NULL);
        !           611:           LineTo (hdc,rect.left, rect.top);
        !           612:           LineTo (hdc,rect.left, rect.bottom);
        !           613: 
        !           614: 
        !           615: 
        !           616:           /* set point that we will draw glyph at */
        !           617:           point.x = (rect.right + rect.left)/2;
        !           618:           point.y = rect.top;
        !           619:           SetTextAlign (hdc, TA_CENTER | TA_TOP);
        !           620:           SetTextColor (hdc, PALETTEINDEX (0));
        !           621: 
        !           622: 
        !           623:           /* special case the non-spacing diacritic marks. U+0300 -> U+036F
        !           624:            *  Write a space first, for them to 'modify.'
        !           625:            */
        !           626:           if ( (0x0300 <= codepoint) && (codepoint <= 0x036F) ) {
        !           627:             outChar = (WCHAR) 0x0020;
        !           628:             TextOutW (hdc, 0,0, &outChar, 1);
        !           629:           }
        !           630: 
        !           631:           outChar = (WCHAR) codepoint;
        !           632:           ExtTextOut(hdc, point.x, point.y, ETO_CLIPPED, &rect, (LPCWSTR)&outChar, 1, NULL);
        !           633: 
        !           634: 
        !           635: 
        !           636:           /* fill in unicode code point in hex */
        !           637:           if (gShowhex) {
        !           638:             int nchar;
        !           639:             HANDLE hfonttemp;
        !           640: 
        !           641:             nchar = wsprintf (buffer, TEXT("%04x"), (int) codepoint);
        !           642:             hfonttemp = SelectObject (hdc,GetStockObject (SYSTEM_FIXED_FONT));
        !           643: 
        !           644:             point.y = rect.bottom;
        !           645:             SetTextAlign (hdc, TA_CENTER | TA_BOTTOM);
        !           646:             SetTextColor (hdc, PALETTEINDEX (5));
        !           647: 
        !           648:             TextOut( hdc, point.x, point.y,
        !           649:                           buffer, nchar);
        !           650:             SelectObject (hdc,hfonttemp);
        !           651:           }
        !           652: 
        !           653: 
        !           654:         } /* end for */
        !           655: 
        !           656:       EndPaint (hwnd, &ps);
        !           657:     } return FALSE; /* end WM_PAINT */
        !           658: 
        !           659: 
        !           660: 
        !           661: 
        !           662:   } /* end switch */
        !           663: 
        !           664:   return (DefMDIChildProc(hwnd, message, wParam, lParam));
        !           665: }
        !           666: 
        !           667: 
        !           668: 
        !           669: 
        !           670: /**************************************************************************\
        !           671: *
        !           672: * Need a mapping between the (x,y) pair, and the index of the square on
        !           673: *  the window.  Two routines provide this... one for each direction.
        !           674: *
        !           675: \**************************************************************************/
        !           676: 
        !           677: /**********************************************************************\
        !           678: *  transXYtoIndex
        !           679: *
        !           680: *  Given x & y values, return the index.
        !           681: *
        !           682: \**********************************************************************/
        !           683: int transXYtoIndex (int x, int y,
        !           684:      int sqrWidth, int sqrHeight, int nCharPerLine)
        !           685: {
        !           686:     x /= sqrWidth;
        !           687:     if (x < 0) x = 0;
        !           688:     if (x >= nCharPerLine) x = nCharPerLine-1;
        !           689: 
        !           690:     y /= sqrHeight;
        !           691:     if (y < 0) y = 0;
        !           692: 
        !           693:     return ( (y * nCharPerLine) + x);
        !           694: }
        !           695: 
        !           696: 
        !           697: /**********************************************************************\
        !           698: *  transIndextoRect
        !           699: *
        !           700: *  Given an index, i.e. the number of one of the squares on the display
        !           701: *   window, fill in the rectangle structure.
        !           702: *
        !           703: \**********************************************************************/
        !           704: int transIndextoRect (int index, PRECT pr,
        !           705:      int sqrWidth, int sqrHeight, int nCharPerLine)
        !           706: {
        !           707: int x,y;
        !           708: 
        !           709:     x = index % nCharPerLine;
        !           710:     y = index / nCharPerLine;
        !           711: 
        !           712:     pr->left = x*sqrWidth;
        !           713:     pr->top = y*sqrHeight;
        !           714:     pr->right = pr->left +sqrWidth;
        !           715:     pr->bottom = pr->top +sqrHeight;
        !           716: 
        !           717:     return TRUE;
        !           718: }
        !           719: 
        !           720: 
        !           721: 
        !           722: 
        !           723: 
        !           724: 
        !           725: /**************************************************************************\
        !           726: *
        !           727: * All of the code below is used for parsing 'font data.'  It will only
        !           728: *  make sense if you have a copy of the True Type font spec.  In short,
        !           729: *  we grab the 'cmap' table, look through it for a subtable, and then
        !           730: *  get two parallel arrays from the subtable.  Complications arise because
        !           731: *  the true type data is 'BIG ENDIAN' and NT is being run 'little endian.'
        !           732: *  For this reason, once we locate the short or long, we call Swap* to
        !           733: *  change the byte ordering.
        !           734: *
        !           735: \**************************************************************************/
        !           736: 
        !           737: 
        !           738: VOID SwapShort (PUSHORT);
        !           739: VOID SwapULong  (PULONG);
        !           740: 
        !           741: 
        !           742: 
        !           743: typedef struct tagTABLE{
        !           744:     USHORT platformID;
        !           745:     USHORT encodingID;
        !           746:     ULONG  offset;
        !           747: } TABLE, *PTABLE;
        !           748: 
        !           749: typedef struct tagSUBTABLE{
        !           750:     USHORT format;
        !           751:     USHORT length;
        !           752:     USHORT version;
        !           753:     USHORT segCountX2;
        !           754:     USHORT searchRange;
        !           755:     USHORT entrySelector;
        !           756:     USHORT rangeShift;
        !           757: } SUBTABLE, *PSUBTABLE;
        !           758: 
        !           759: 
        !           760: /* 'cmap' is passed in by value in a DWORD */
        !           761: #define CMAPHEX  0x70616d63
        !           762: #define NBYTES   256
        !           763: #define OFFSETERROR  0
        !           764: 
        !           765: 
        !           766: 
        !           767: /**************************************************************************\
        !           768: *
        !           769: *  function:  CountUCSegments()
        !           770: *
        !           771: *  input parameters:
        !           772: *   hdc - with the logical font set into it.
        !           773: *   prect - pointer to client rectangle.
        !           774: *
        !           775: *  Global variables:
        !           776: *   startCount
        !           777: *   endCount
        !           778: *
        !           779: *  returns:
        !           780: *   number of UC segments or
        !           781: *   SEGMENTERROR if there is some kind of error.
        !           782: *
        !           783: *  essential side effect:
        !           784: *   Fills in global startCount, endCount arrays.
        !           785: \**************************************************************************/
        !           786: int CountUCSegments (HDC hdc)
        !           787: {
        !           788: DWORD       cbData;
        !           789: USHORT      aShort[2];
        !           790: DWORD       nBytes;
        !           791: USHORT      i, nTables;
        !           792: PTABLE      pTable;
        !           793: PSUBTABLE   pSubTable;
        !           794: ULONG       offset,offsetFormat4;
        !           795: USHORT      segCount;
        !           796: BYTE        buffer[NBYTES];
        !           797: 
        !           798: 
        !           799: 
        !           800: 
        !           801:     /* find number of "subtables", second long in cmap */
        !           802:     nBytes=GetFontData (hdc, CMAPHEX, 0, aShort, 4);
        !           803:     if (nBytes == GDI_ERROR) {
        !           804:       MessageBox (NULL, MBGETFONTDATAERR,MBERROR , MBERRORFLAGS);
        !           805:       return SEGMENTERROR;
        !           806:     }
        !           807:     if (nBytes == 0) {
        !           808:       MessageBox (NULL, TEXT("No 'cmap' table."),MBERROR , MBERRORFLAGS);
        !           809:       return SEGMENTERROR;
        !           810:     }
        !           811:     nTables = aShort[1];
        !           812:     SwapShort (&nTables);
        !           813: 
        !           814: 
        !           815:     cbData = nTables * sizeof(TABLE);
        !           816:     if (cbData >NBYTES) {
        !           817:       MessageBox (NULL, TEXT("cbData >NBYTES"),MBERROR , MBERRORFLAGS);
        !           818:       return SEGMENTERROR;
        !           819:     }
        !           820: 
        !           821:     /* get array of subtables information.  Check each one for 3,1*/
        !           822:     nBytes=GetFontData (hdc, CMAPHEX, 4, buffer, cbData);
        !           823:     pTable = (PTABLE)buffer;
        !           824:     offsetFormat4 = OFFSETERROR;
        !           825:     for (i = 0; i< nTables; i++) {
        !           826: 
        !           827:         SwapShort (&(pTable->encodingID));
        !           828:         SwapShort (&(pTable->platformID));
        !           829: 
        !           830:         if ((pTable->platformID == 3)&&(pTable->encodingID == 1)) {
        !           831:           offsetFormat4 = pTable->offset;
        !           832:           SwapULong (&offsetFormat4);
        !           833:           break;
        !           834:         }
        !           835:         pTable++;
        !           836:     }
        !           837: 
        !           838:     /* verify that we got the correct offset to the FORMAT 4 subtable */
        !           839:     if (offsetFormat4 == OFFSETERROR){
        !           840:       MessageBox (NULL, TEXT("Can not find 3,1 subtable"),MBERROR , MBERRORFLAGS);
        !           841:       return SEGMENTERROR;
        !           842:     }
        !           843: 
        !           844:     /* Get the beginning of the subtable, especially the segment count */
        !           845:     nBytes=GetFontData (hdc, CMAPHEX, offsetFormat4, buffer, sizeof(SUBTABLE));
        !           846:     pSubTable = (PSUBTABLE) buffer;
        !           847:     SwapShort (&(pSubTable->format));
        !           848:     SwapShort (&(pSubTable->segCountX2));
        !           849: 
        !           850:     if (pSubTable->format != 4){
        !           851:       MessageBox (NULL, TEXT("format !=4"), MBERROR, MBERRORFLAGS);
        !           852:       return SEGMENTERROR;
        !           853:     }
        !           854: 
        !           855:     segCount = pSubTable->segCountX2 / 2;
        !           856: 
        !           857:     /* Now that we know how many segments that the font contains,
        !           858:      *  free up the old memory, and realloc. the two global arrays.
        !           859:      */
        !           860:     if (startCount != NULL) LocalFree (LocalHandle (startCount));
        !           861:     if (endCount != NULL) LocalFree (LocalHandle (endCount));
        !           862:     startCount = LocalAlloc (LPTR, segCount * sizeof(USHORT));
        !           863:     endCount = LocalAlloc (LPTR, segCount * sizeof(USHORT));
        !           864: 
        !           865:     if ((startCount == NULL) || (endCount == NULL)) {
        !           866:       MessageBox (NULL, TEXT("LocalAlloc failed"), MBERROR, MBERRORFLAGS);
        !           867:       return SEGMENTERROR;
        !           868:     }
        !           869: 
        !           870:     /* read in the array of endCount values */
        !           871:     offset = offsetFormat4
        !           872:            + (7 * sizeof (USHORT));  /* skip constant # bytes in subtable */
        !           873:     cbData = segCount * sizeof (USHORT);
        !           874:     nBytes=GetFontData (hdc, CMAPHEX, offset, endCount, cbData );
        !           875:     for (i = 0; i<segCount; i++)
        !           876:         SwapShort (& (endCount[i]));
        !           877: 
        !           878:     /* read in the array of startCount values */
        !           879:     offset = offsetFormat4
        !           880:            + (7 * sizeof (USHORT))   /* skip constant # bytes in subtable */
        !           881:            + (segCount * sizeof (USHORT)) /* skip endCount array */
        !           882:            + sizeof (USHORT);             /* skip reservedPad */
        !           883:     cbData = segCount * sizeof (USHORT);
        !           884:     nBytes=GetFontData (hdc, CMAPHEX, offset, startCount, cbData );
        !           885:     for (i = 0; i<segCount; i++)
        !           886:         SwapShort (& (startCount[i]));
        !           887: 
        !           888: 
        !           889:     return segCount;
        !           890: }
        !           891: 
        !           892: 
        !           893: 
        !           894: 
        !           895: 
        !           896: 
        !           897: 
        !           898: 
        !           899: 
        !           900: 
        !           901: VOID SwapShort (PUSHORT p)
        !           902: {
        !           903: SHORT temp;
        !           904: 
        !           905:     temp =(SHORT)( HIBYTE (*p) + (LOBYTE(*p) << 8));
        !           906:     *p = temp;
        !           907: }
        !           908: 
        !           909: 
        !           910: 
        !           911: VOID SwapULong (PULONG p)
        !           912: {
        !           913: ULONG temp;
        !           914: 
        !           915:     temp = (LONG) ((BYTE) *p);
        !           916:     temp <<= 8;
        !           917:     *p >>=8;
        !           918: 
        !           919:     temp += (LONG) ((BYTE) *p);
        !           920:     temp <<= 8;
        !           921:     *p >>=8;
        !           922: 
        !           923:     temp += (LONG) ((BYTE) *p);
        !           924:     temp <<= 8;
        !           925:     *p >>=8;
        !           926: 
        !           927:     temp += (LONG) ((BYTE) *p);
        !           928:     *p = temp;
        !           929: }

unix.superglobalmegacorp.com

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