home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / progwin / chap14 / justify.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-12  |  13.0 KB  |  373 lines

  1. /*----------------------------------------
  2.    JUSTIFY.C -- Justified Type Program
  3.                 (c) Charles Petzold, 1990
  4.   ----------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include <string.h>
  8. #include "justify.h"
  9.  
  10. typedef struct
  11.      {
  12.      short nNumFaces ;
  13.      char  szFaceNames [MAX_FACES] [LF_FACESIZE] ;
  14.      }
  15.      ENUMFACE ;
  16.  
  17. typedef struct
  18.      {
  19.      short      nNumSizes ;
  20.      short      xLogPixPerInch ;
  21.      short      yLogPixPerInch ;
  22.      LOGFONT    lf [MAX_SIZES] ;
  23.      TEXTMETRIC tm [MAX_SIZES] ;
  24.      }
  25.      ENUMSIZE ;
  26.  
  27. long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
  28. int  FAR PASCAL EnumAllFaces (LPLOGFONT, LPTEXTMETRIC, short, ENUMFACE FAR *) ;
  29. int  FAR PASCAL EnumAllSizes (LPLOGFONT, LPTEXTMETRIC, short, ENUMSIZE FAR *) ;
  30.  
  31. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  32.                     LPSTR lpszCmdLine, int nCmdShow)
  33.      {
  34.      static   char szAppName[] = "Justify" ;
  35.      HWND     hwnd ;
  36.      MSG      msg ;
  37.      WNDCLASS wndclass ;
  38.  
  39.      if (!hPrevInstance) 
  40.           {
  41.           wndclass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC ;
  42.           wndclass.lpfnWndProc   = WndProc ;
  43.           wndclass.cbClsExtra    = 0 ;
  44.           wndclass.cbWndExtra    = 0 ;
  45.           wndclass.hInstance     = hInstance ;
  46.           wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  47.           wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  48.           wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
  49.           wndclass.lpszMenuName  = szAppName ;
  50.           wndclass.lpszClassName = szAppName ;
  51.  
  52.           RegisterClass (&wndclass) ;
  53.           }
  54.      hwnd = CreateWindow (szAppName, "Justified Type",
  55.                           WS_OVERLAPPEDWINDOW,
  56.                           CW_USEDEFAULT, CW_USEDEFAULT,
  57.                           CW_USEDEFAULT, CW_USEDEFAULT,
  58.                           NULL, NULL, hInstance, NULL) ;
  59.  
  60.      ShowWindow (hwnd, nCmdShow) ;
  61.      UpdateWindow (hwnd) ;
  62.  
  63.      while (GetMessage (&msg, NULL, 0, 0))
  64.           {
  65.           TranslateMessage (&msg) ;
  66.           DispatchMessage (&msg) ;
  67.           }
  68.      return msg.wParam ;
  69.      }
  70.  
  71. int FAR PASCAL EnumAllFaces (LPLOGFONT lplf, LPTEXTMETRIC lptm,
  72.                              short nFontType, ENUMFACE FAR *lpef)
  73.      {
  74.      if (nFontType & RASTER_FONTTYPE)
  75.           {
  76.           lstrcpy (lpef->szFaceNames[lpef->nNumFaces], lplf->lfFaceName) ;
  77.           if (++lpef->nNumFaces == MAX_FACES)
  78.                return 0 ;
  79.           }
  80.      return 1 ;
  81.      }
  82.  
  83. int FAR PASCAL EnumAllSizes (LPLOGFONT lplf, LPTEXTMETRIC lptm,
  84.                              short nFontType, ENUMSIZE FAR *lpes)
  85.      {
  86.      if (lpes->xLogPixPerInch == lptm->tmDigitizedAspectX &&
  87.          lpes->yLogPixPerInch == lptm->tmDigitizedAspectY)
  88.           {
  89.           lpes->lf [lpes->nNumSizes] = *lplf ;
  90.           lpes->tm [lpes->nNumSizes] = *lptm ;
  91.           if (++lpes->nNumSizes == MAX_SIZES)
  92.                return 0 ;
  93.           }
  94.      return 1 ;
  95.      }
  96.  
  97. short MakeSizeMenu (HWND hwnd, FARPROC lpfnEnumAllSizes,
  98.                     ENUMSIZE *pes, char *szFaceName)
  99.      {
  100.      static LOGFONT lfBlank ;
  101.      char           szBuffer[20] ;
  102.      HDC            hdc ;
  103.      HMENU          hPopup ;
  104.      short          i ;
  105.  
  106.      hdc = GetDC (hwnd) ;
  107.      hPopup = GetSubMenu (GetMenu (hwnd), SIZE_MENU) ;
  108.  
  109.      pes->nNumSizes = 0 ;
  110.      EnumFonts (hdc, szFaceName, lpfnEnumAllSizes, (LPSTR) pes) ;
  111.      ReleaseDC (hwnd, hdc) ;
  112.  
  113.      while (GetMenuItemCount (hPopup) > 0)
  114.           DeleteMenu (hPopup, 0, MF_BYPOSITION) ;
  115.  
  116.      if (pes->nNumSizes)
  117.           for (i = 0 ; i < pes->nNumSizes ; i++)
  118.                {
  119.                wsprintf (szBuffer, "%i  %2d / %2d", i + 1,
  120.                     (pes->tm[i].tmHeight - pes->tm[i].tmInternalLeading + 10)
  121.                                                                         / 20,
  122.                     (pes->tm[i].tmHeight + 10) / 20) ;
  123.                AppendMenu (hPopup, 0, IDM_ISIZE + i, szBuffer) ;
  124.                }
  125.      else           /* no fonts found that match aspect ratio of display */
  126.           {
  127.           pes->lf[0] = lfBlank ;
  128.           strcpy (pes->lf[0].lfFaceName, szFaceName) ;
  129.           AppendMenu (hPopup, 0, IDM_ISIZE, "Default") ;
  130.           }
  131.  
  132.      CheckMenuItem (hPopup, IDM_ISIZE, MF_CHECKED) ;
  133.      return 0 ;
  134.      }
  135.  
  136. void DrawRuler (HDC hdc, POINT ptClient)
  137.      {
  138.      static short nRuleSize [16] = { 360, 72, 144, 72, 216, 72, 144, 72,
  139.                                      288, 72, 144, 72, 216, 72, 144, 72 } ;
  140.      short        i, j ;
  141.  
  142.      MoveTo (hdc, 0,          -360) ;
  143.      LineTo (hdc, ptClient.x, -360) ;
  144.      MoveTo (hdc, -360,          0) ;
  145.      LineTo (hdc, -360, ptClient.y) ;
  146.  
  147.      for (i = 0, j = 0 ; i <= ptClient.x ; i += 1440 / 16, j++)
  148.           {
  149.           MoveTo (hdc, i, -360) ;
  150.           LineTo (hdc, i, -360 - nRuleSize [j % 16]) ;
  151.           }
  152.      for (i = 0, j = 0 ; i <= ptClient.y ; i += 1440 / 16, j++)
  153.           {
  154.           MoveTo (hdc, -360, i) ;
  155.           LineTo (hdc, -360 - nRuleSize [j % 16], i) ;
  156.           }
  157.      }
  158.  
  159. void Justify (HDC hdc, HANDLE hResource, POINT ptClient, short nCurAlign)
  160.      {
  161.      DWORD  dwExtent ;
  162.      LPSTR  lpText, lpBegin, lpEnd ;
  163.      short  i, xStart, yStart, nBreakCount ;
  164.  
  165.      lpText = LockResource (hResource) ;
  166.  
  167.      yStart = 0 ;
  168.      do                            // for each text line
  169.           {
  170.           nBreakCount = 0 ;
  171.           while (*lpText == ' ')   // skip over leading blanks
  172.                lpText++ ;
  173.           lpBegin = lpText ;
  174.  
  175.           do                       // until the line is known
  176.                {
  177.                lpEnd = lpText ;
  178.  
  179.                while (*lpText != '\0' && *lpText++ != ' ') ;
  180.                if (*lpText == '\0')
  181.                     break ;
  182.                                    // for each space, calculate extents
  183.                nBreakCount++ ;
  184.                SetTextJustification (hdc, 0, 0) ;
  185.                dwExtent = GetTextExtent (hdc, lpBegin, lpText - lpBegin - 1) ;
  186.                }
  187.           while (LOWORD (dwExtent) < ptClient.x) ;
  188.  
  189.           nBreakCount-- ;
  190.           while (*(lpEnd - 1) == ' ')   // eliminate trailing blanks
  191.                {
  192.                lpEnd-- ;
  193.                nBreakCount-- ;
  194.                }
  195.  
  196.           if (*lpText == '\0' || nBreakCount <= 0)
  197.                lpEnd = lpText ;
  198.  
  199.           SetTextJustification (hdc, 0, 0) ;
  200.           dwExtent = GetTextExtent (hdc, lpBegin, lpEnd - lpBegin) ;
  201.  
  202.           if (nCurAlign == IDM_LEFT)         // use alignment for xStart
  203.                xStart = 0 ;
  204.  
  205.           else if (nCurAlign == IDM_RIGHT)
  206.                xStart = ptClient.x - LOWORD (dwExtent) ;
  207.  
  208.           else if (nCurAlign == IDM_CENTER)
  209.                xStart = (ptClient.x - LOWORD (dwExtent)) / 2 ;
  210.  
  211.           else
  212.                {
  213.                if (*lpText != '\0' && nBreakCount > 0)
  214.                     SetTextJustification (hdc, ptClient.x - LOWORD (dwExtent),
  215.                                                   nBreakCount) ;
  216.                xStart = 0 ;
  217.                }
  218.  
  219.           TextOut (hdc, xStart, yStart, lpBegin, lpEnd - lpBegin) ;
  220.           yStart += HIWORD (dwExtent) ;
  221.           lpText = lpEnd ;
  222.           }
  223.      while (*lpText && yStart < ptClient.y) ;
  224.  
  225.      GlobalUnlock (hResource) ;
  226.      }
  227.  
  228. long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  229.      {
  230.      static ENUMFACE ef ;
  231.      static ENUMSIZE es ;
  232.      static FARPROC  lpfnEnumAllFaces, lpfnEnumAllSizes ;
  233.      static HANDLE   hResource ;
  234.      static POINT    ptClient ;
  235.      static short    nCurSize, nCurFace, nCurAttr, nCurAlign = IDM_LEFT ;
  236.      HANDLE          hInstance ;
  237.      HDC             hdc ;
  238.      HFONT           hFont ;
  239.      HMENU           hMenu, hPopup ;
  240.      PAINTSTRUCT     ps ;
  241.      short           i ;
  242.  
  243.      switch (message)
  244.           {
  245.           case WM_CREATE:
  246.                hdc = GetDC (hwnd) ;
  247.                es.xLogPixPerInch = GetDeviceCaps (hdc, LOGPIXELSX) ;
  248.                es.yLogPixPerInch = GetDeviceCaps (hdc, LOGPIXELSY) ;
  249.  
  250.                               // Set Map Mode
  251.  
  252.                SetMapMode (hdc, MM_ANISOTROPIC) ;
  253.                SetWindowExt (hdc, 1440, 1440) ;
  254.                SetViewportExt (hdc, es.xLogPixPerInch, es.yLogPixPerInch) ;
  255.                SetWindowOrg (hdc, -720, -720) ;
  256.  
  257.                               // MakeProcInstance for 2 routines
  258.  
  259.                hInstance = ((LPCREATESTRUCT) lParam)-> hInstance ;
  260.                lpfnEnumAllFaces = MakeProcInstance (EnumAllFaces, hInstance) ;
  261.                lpfnEnumAllSizes = MakeProcInstance (EnumAllSizes, hInstance) ;
  262.  
  263.                               // Enumerate the Font Faces
  264.  
  265.                EnumFonts (hdc, NULL, lpfnEnumAllFaces, (LPSTR) &ef) ;
  266.                ReleaseDC (hwnd, hdc) ;
  267.  
  268.                               // Initialize the Menus
  269.  
  270.                hMenu  = GetMenu (hwnd) ;
  271.                hPopup = CreateMenu () ;
  272.  
  273.                for (i = 0 ; i < ef.nNumFaces ; i++)
  274.                     AppendMenu (hPopup, 0, IDM_IFACE + i, ef.szFaceNames[i]) ;
  275.  
  276.                ModifyMenu (hMenu, IDM_FACE, MF_POPUP, hPopup, "&FaceName") ;
  277.                CheckMenuItem (hMenu, IDM_IFACE, MF_CHECKED) ;
  278.  
  279.                nCurSize = MakeSizeMenu (hwnd, lpfnEnumAllSizes, &es,
  280.                                    ef.szFaceNames [nCurFace]) ;
  281.  
  282.                               // Load the Text Resource
  283.  
  284.                hResource = LoadResource (hInstance, 
  285.                            FindResource (hInstance, "Ismael", "TEXT")) ;
  286.                return 0 ;
  287.  
  288.           case WM_SIZE:
  289.                hdc = GetDC (hwnd) ;
  290.                ptClient = MAKEPOINT (lParam) ;
  291.                DPtoLP (hdc, &ptClient, 1) ;
  292.                ptClient.x -= 360 ;
  293.                ReleaseDC (hwnd, hdc) ;
  294.                return 0 ;
  295.  
  296.           case WM_COMMAND:
  297.                hMenu = GetMenu (hwnd) ;
  298.  
  299.                if (wParam >= IDM_IFACE && wParam < IDM_IFACE + MAX_FACES)
  300.                     {
  301.                     CheckMenuItem (hMenu, nCurFace + IDM_IFACE, MF_UNCHECKED) ;
  302.                     CheckMenuItem (hMenu, wParam, MF_CHECKED) ;
  303.                     nCurFace = wParam - IDM_IFACE ;
  304.  
  305.                     nCurSize = MakeSizeMenu (hwnd, lpfnEnumAllSizes, &es,
  306.                                         ef.szFaceNames [nCurFace]) ;
  307.                     }
  308.  
  309.                else if (wParam >= IDM_ISIZE && wParam < IDM_ISIZE + MAX_SIZES)
  310.                     {
  311.                     CheckMenuItem (hMenu, nCurSize + IDM_ISIZE, MF_UNCHECKED) ;
  312.                     CheckMenuItem (hMenu, wParam, MF_CHECKED) ;
  313.                     nCurSize = wParam - IDM_ISIZE ;
  314.                     }
  315.  
  316.                else switch (wParam)
  317.                     {
  318.                     case IDM_BOLD:
  319.                     case IDM_ITALIC:
  320.                     case IDM_STRIKE:
  321.                     case IDM_UNDER:
  322.                          CheckMenuItem (hMenu, wParam, MF_CHECKED &
  323.                               GetMenuState (hMenu, wParam, MF_BYCOMMAND) ?
  324.                                    MF_UNCHECKED : MF_CHECKED) ;
  325.                          nCurAttr ^= wParam ;
  326.                          break ;
  327.  
  328.                     case IDM_NORM:
  329.                          nCurAttr = 0 ;
  330.                          CheckMenuItem (hMenu, IDM_BOLD,   MF_UNCHECKED) ;
  331.                          CheckMenuItem (hMenu, IDM_ITALIC, MF_UNCHECKED) ;
  332.                          CheckMenuItem (hMenu, IDM_STRIKE, MF_UNCHECKED) ;
  333.                          CheckMenuItem (hMenu, IDM_UNDER,  MF_UNCHECKED) ;
  334.                          break ;
  335.  
  336.                     case IDM_LEFT:
  337.                     case IDM_RIGHT:
  338.                     case IDM_CENTER:
  339.                     case IDM_JUST:
  340.                          CheckMenuItem (hMenu, nCurAlign, MF_UNCHECKED) ;
  341.                          nCurAlign = wParam ;
  342.                          CheckMenuItem (hMenu, nCurAlign, MF_CHECKED) ;
  343.                          break ;
  344.                     }
  345.                InvalidateRect (hwnd, NULL, TRUE) ;
  346.                return 0 ;
  347.  
  348.           case WM_PAINT:
  349.                hdc = BeginPaint (hwnd, &ps) ;
  350.  
  351.                es.lf[nCurSize].lfWeight    = nCurAttr & IDM_BOLD ? 700 : 400 ;
  352.                es.lf[nCurSize].lfItalic    = (BYTE) (nCurAttr & IDM_ITALIC) ;
  353.                es.lf[nCurSize].lfUnderline = (BYTE) (nCurAttr & IDM_UNDER) ;
  354.                es.lf[nCurSize].lfStrikeOut = (BYTE) (nCurAttr & IDM_STRIKE) ;
  355.                                           
  356.                hFont = CreateFontIndirect (&es.lf[nCurSize]) ;
  357.                hFont = SelectObject (hdc, hFont) ;
  358.  
  359.                DrawRuler (hdc, ptClient) ;
  360.                Justify (hdc, hResource, ptClient, nCurAlign) ;
  361.  
  362.                DeleteObject (SelectObject (hdc, hFont)) ;
  363.                EndPaint (hwnd, &ps) ;
  364.                return 0 ;
  365.  
  366.           case WM_DESTROY:
  367.                FreeResource (hResource) ;
  368.                PostQuitMessage (0) ;
  369.                return 0 ;
  370.           }
  371.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  372.      }
  373.