Annotation of q_a/samples/uniput/display.c, revision 1.1.1.1

1.1       root        1: 
                      2: /******************************************************************************\
                      3: *       This is a part of the Microsoft Source Code Samples. 
                      4: *       Copyright (C) 1993 Microsoft Corporation.
                      5: *       All rights reserved. 
                      6: *       This source code is only intended as a supplement to 
                      7: *       Microsoft Development Tools and/or WinHelp documentation.
                      8: *       See these sources for detailed information regarding the 
                      9: *       Microsoft samples programs.
                     10: \******************************************************************************/
                     11: 
                     12: /**************************************************************************\
                     13: *  display.c -- module 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.