home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol12n05.zip / JUSTIF.ZIP / JUSTIFY.C next >
C/C++ Source or Header  |  1992-12-03  |  8KB  |  249 lines

  1. /*----------------------------------------
  2.    JUSTIFY.C -- Justify Bitmap Fonts
  3.                 (c) Charles Petzold, 1993
  4.   ----------------------------------------*/
  5.  
  6. #define INCL_WIN
  7. #define INCL_GPI
  8. #define INCL_DOS
  9. #include <os2.h>
  10. #include "justify.h"
  11. #include "bmf.h"
  12.  
  13. #define LCID_FONT   1L
  14.  
  15. MRESULT EXPENTRY ClientWndProc (HWND, ULONG, MPARAM, MPARAM) ;
  16.  
  17. int main (void)
  18.      {
  19.      static CHAR  szClientClass [] = "Justify" ;
  20.      static ULONG flFrameFlags = FCF_TITLEBAR      | FCF_SYSMENU  |
  21.                                  FCF_SIZEBORDER    | FCF_MINMAX   |
  22.                                  FCF_SHELLPOSITION | FCF_TASKLIST |
  23.                                  FCF_MENU ;
  24.      HAB          hab ;
  25.      HMQ          hmq ;
  26.      HWND         hwndFrame, hwndClient ;
  27.      QMSG         qmsg ;
  28.  
  29.      hab = WinInitialize (0) ;
  30.      hmq = WinCreateMsgQueue (hab, 0) ;
  31.  
  32.      WinRegisterClass (hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0) ;
  33.  
  34.      hwndFrame = WinCreateStdWindow (HWND_DESKTOP, WS_VISIBLE,
  35.                                      &flFrameFlags, szClientClass, NULL,
  36.                                      0L, 0, ID_RESOURCE, &hwndClient) ;
  37.  
  38.      while (WinGetMsg (hab, &qmsg, NULLHANDLE, 0, 0))
  39.           WinDispatchMsg (hab, &qmsg) ;
  40.  
  41.      WinDestroyWindow (hwndFrame) ;
  42.      WinDestroyMsgQueue (hmq) ;
  43.      WinTerminate (hab) ;
  44.      return 0 ;
  45.      }
  46.  
  47. VOID Justify (HPS hps, PCHAR pText, PRECTL prcl, SHORT nAlign, SHORT nSpace)
  48.      {
  49.      int      iBreakCount, iSurplus ;
  50.      PCHAR    pStart, pEnd ;
  51.      POINTL   ptlStart, aptlTextBox [TXTBOX_COUNT] ;
  52.  
  53.      ptlStart.y = prcl->yTop ;
  54.  
  55.      do                                 // until end of text
  56.           {
  57.           iBreakCount = 0 ;
  58.  
  59.           while (*pText == ' ')         // Skip over leading blanks
  60.                pText++ ;
  61.  
  62.           pStart = pText ;
  63.  
  64.           do                            // until line is known
  65.                {
  66.                while (*pText == ' ')    // Skip over leading blanks
  67.                     pText++ ;
  68.  
  69.                                         // Find next break point
  70.  
  71.                while (*pText != '\x0D' && *pText != ' ')
  72.                     pText++ ;
  73.  
  74.                                         // Determine text width
  75.  
  76.                GpiQueryTextBox (hps, pText - pStart, pStart,
  77.                                 TXTBOX_COUNT, aptlTextBox) ;
  78.  
  79.                          // Normal case: text less wide than column
  80.  
  81.                if (aptlTextBox[TXTBOX_CONCAT].x < (prcl->xRight - prcl->xLeft))
  82.                     {
  83.                     iBreakCount++ ;
  84.                     pEnd = pText ;
  85.                     }
  86.  
  87.                          // Text wider than window with only one word
  88.  
  89.                else if (iBreakCount == 0)
  90.                     {
  91.                     pEnd = pText ;
  92.                     break ;
  93.                     }
  94.  
  95.                          // Text wider than window, so fix up and get out
  96.                else
  97.                     {
  98.                     iBreakCount-- ;
  99.                     pText = pEnd ;
  100.                     break ;
  101.                     }
  102.                }
  103.           while (*pText != '\x0D') ;
  104.  
  105.                          // Get the final text box
  106.  
  107.           GpiQueryTextBox (hps, pEnd - pStart, pStart,
  108.                            TXTBOX_COUNT, aptlTextBox) ;
  109.  
  110.                          // Drop down by maximum ascender
  111.  
  112.           ptlStart.y -= aptlTextBox[TXTBOX_TOPLEFT].y ;
  113.  
  114.                          // Find surplus space in text line
  115.  
  116.           iSurplus = prcl->xRight - prcl->xLeft -
  117.                      aptlTextBox[TXTBOX_CONCAT].x ;
  118.  
  119.                         // Adjust starting position and
  120.                         // space and character spacing
  121.  
  122.           switch (nAlign)
  123.                {
  124.                case IDM_LEFT:
  125.                     ptlStart.x = prcl->xLeft ;
  126.                     break ;
  127.  
  128.                case IDM_RIGHT:
  129.                     ptlStart.x = prcl->xLeft + iSurplus ;
  130.                     break ;
  131.  
  132.                case IDM_CENTER:
  133.                     ptlStart.x = prcl->xLeft + iSurplus / 2 ;
  134.                     break ;
  135.  
  136.                case IDM_JUST:
  137.                     ptlStart.x = prcl->xLeft ;
  138.  
  139.                     if (*pText == '\x0D')
  140.                          break ;
  141.  
  142.                     if (iBreakCount > 0)
  143.                          GpiSetCharBreakExtra (hps,
  144.                               65536 * iSurplus /  iBreakCount) ;
  145.  
  146.                     else if (pEnd - pStart - 1 > 0)
  147.                          GpiSetCharExtra (hps,
  148.                               65536 * iSurplus / (pEnd - pStart - 1)) ;
  149.                     break ;
  150.                }
  151.  
  152.                          // Display the string & return to normal
  153.  
  154.           GpiCharStringAt (hps, &ptlStart, pEnd - pStart, pStart) ;
  155.           GpiSetCharExtra (hps, 0) ;
  156.           GpiSetCharBreakExtra (hps, 0) ;
  157.  
  158.                          // Drop down by maximum descender
  159.  
  160.           ptlStart.y += aptlTextBox[TXTBOX_BOTTOMLEFT].y ;
  161.  
  162.                          // Do additional line-spacing
  163.  
  164.           switch (nSpace)
  165.                {
  166.                case IDM_HALF:
  167.                     ptlStart.y -= (aptlTextBox[TXTBOX_TOPLEFT].y -
  168.                                    aptlTextBox[TXTBOX_BOTTOMLEFT].y) / 2 ;
  169.                     break ;
  170.  
  171.                case IDM_DOUBLE:
  172.                     ptlStart.y -= aptlTextBox[TXTBOX_TOPLEFT].y -
  173.                                   aptlTextBox[TXTBOX_BOTTOMLEFT].y ;
  174.                     break ;
  175.                }
  176.           }
  177.  
  178.      while (*pText != '\x0D' && ptlStart.y > prcl->yBottom) ;
  179.      }
  180.  
  181. MRESULT EXPENTRY ClientWndProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  182.      {
  183.      static HWND  hwndMenu ;
  184.      static PCHAR pText ;
  185.      static RECTL rcl ;
  186.      static SHORT nAlign = IDM_LEFT, nSpace = IDM_SINGLE ;
  187.      HPS          hps ;
  188.      
  189.      switch (msg)
  190.           {
  191.           case WM_CREATE:
  192.                DosGetResource (0, IDT_TEXT, IDT_TWAIN, (PPVOID) & pText) ;
  193.  
  194.                hwndMenu = WinWindowFromID (
  195.                               WinQueryWindow (hwnd, QW_PARENT), FID_MENU) ;
  196.                return 0 ;
  197.  
  198.           case WM_SIZE:
  199.                WinQueryWindowRect (hwnd, &rcl) ;
  200.                return 0 ;
  201.  
  202.           case WM_COMMAND:
  203.                switch (COMMANDMSG(&msg)->cmd)
  204.                     {
  205.                     case IDM_RIGHT:
  206.                     case IDM_LEFT:
  207.                     case IDM_CENTER:
  208.                     case IDM_JUST:
  209.                          WinCheckMenuItem (hwndMenu, nAlign, FALSE) ;
  210.                          nAlign = COMMANDMSG(&msg)->cmd ;
  211.                          WinCheckMenuItem (hwndMenu, nAlign, TRUE) ;
  212.  
  213.                          WinInvalidateRect (hwnd, NULL, FALSE) ;
  214.                          return 0 ;
  215.  
  216.                     case IDM_SINGLE:
  217.                     case IDM_HALF:
  218.                     case IDM_DOUBLE:
  219.                          WinCheckMenuItem (hwndMenu, nSpace, FALSE) ;
  220.                          nSpace = COMMANDMSG(&msg)->cmd ;
  221.                          WinCheckMenuItem (hwndMenu, nSpace, TRUE) ;
  222.  
  223.                          WinInvalidateRect (hwnd, NULL, FALSE) ;
  224.                          return 0 ;
  225.                     }
  226.                break ;
  227.  
  228.           case WM_PAINT:
  229.                hps = WinBeginPaint (hwnd, NULLHANDLE, NULL) ;
  230.                GpiErase (hps) ;
  231.  
  232.                CreateBitmapFont (hps, LCID_FONT, "Tms Rmn", 18, 0, 0) ;
  233.                GpiSetCharSet (hps, LCID_FONT) ;
  234.  
  235.                Justify (hps, pText, &rcl, nAlign, nSpace) ;
  236.  
  237.                GpiSetCharSet (hps, LCID_DEFAULT) ;
  238.                GpiDeleteSetId (hps, LCID_FONT) ;
  239.  
  240.                WinEndPaint (hps) ;
  241.                return 0 ;
  242.  
  243.           case WM_DESTROY:
  244.                DosFreeResource (pText) ;
  245.                return 0 ;
  246.           }
  247.      return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
  248.      }
  249.