home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / fontedit / fontload.c < prev    next >
C/C++ Source or Header  |  1996-01-07  |  66KB  |  1,971 lines

  1. #include "windows.h"
  2. #include <windowsx.h>
  3. #include "fontedit.h"
  4. #include "fcntl.h"
  5. #include "memory.h"
  6. #include "stdio.h"
  7. #include "commdlg.h"
  8.  
  9.  
  10. /****************************************************************************/
  11. /*              Shared Variables                                            */
  12. /****************************************************************************/
  13. extern CHAR *PASCAL VerifyHeaderContents();/* checks integrity of header */
  14.  
  15. extern FontHeaderType font;             /* Structure of Font File Header */
  16. extern LONG lSizeOfOldGlyph20;          /* Old packed 2.0 glyph info size. */
  17. extern LONG lSizeOfOldGlyph30;             /* Old packed 3.0 glyph info size. */
  18. extern LONG lSizeOfOldFontHeader;       /* Old packed font header size. */
  19. extern LONG lSizeOfOldFontHeader30;     /* Old 3.0 packed font header size. */
  20. extern CHAR szFaceName[];               /* Face Name of Font */
  21. extern DWORD offsets[];                 /* Offsets Table */
  22.  
  23. extern BOOL fReadOnly;
  24. extern BOOL fChanged;                   /* Note if we did anything */
  25. extern BOOL fLoaded;                    /* Set if a font is loaded */
  26. extern INT iFontFormatPrev;             /* Set to the id of prev.font format */
  27. extern INT iFontFormat;             /* Set to the id of current font format */
  28.  
  29. extern HWND hFont;                      /* Handle to Show window */
  30. extern HWND hBox;                       /* Handle to Edit Window */
  31. extern HDC hMemDC;                      /* Handle to Memory Display Context */
  32. extern HBITMAP hBitmap;                 /* Handle to our work bit map */
  33. extern CHAR matBox [wBoxLim] [kBoxLim]; /* array to hold Box */
  34.  
  35. extern CHAR *vrgsz[];                   /* string table */
  36. extern OFSTRUCT ofstrFile;
  37. extern BOOL NewFile;                    /* flag indicating if file was opened
  38.                                            by selecting NEW on menu */
  39. FontHeaderType fontBuffer;          /* temporary buffer of Font File Header */
  40. WORD cHeader, cTable;
  41. HFILE nNewFile;                          /* NT file handle */
  42.  
  43.  
  44. /****************************************************************************/
  45. /*              Local Variables                                             */
  46. /****************************************************************************/
  47.  
  48. DWORD Proport(DWORD, DWORD, DWORD, DWORD);  /* Reproportions a value */
  49.  
  50. CHAR  *lpFontBody = NULL;  /* Pointer to Font Body */
  51. CHAR  *lpWork = NULL;      /* Pointer to Work Area */
  52. HDC hNewMemDC;
  53. HDC hBoxMemDC;
  54. HBITMAP hNewBitmap;
  55. HBITMAP hBoxBitmap;
  56. HCURSOR hOldCursor = NULL;      /* Holds Arrow while we show Hourglass */
  57. HCURSOR hHourGlass = NULL;
  58. DWORD oldMode;                   /* For StretchBltMode */
  59. BYTE  *lp1,  *lp2;    /* Pointers to bitmaps in format N */
  60.  
  61. FontHeader30  font30;
  62.  
  63. #define ALPHA_CNT        26
  64. #define TOTAL_WEIGHTS  1000
  65. #define FSF_FIXED             0x0001
  66. #define FSF_PROPORTIONAL      0x0002
  67.  
  68. SHORT widthweights[ALPHA_CNT + 1] =
  69.         {
  70.                  64,        /* a
  71.                  14,        /* b     */
  72.                  27,        /* c     */
  73.                  35,        /* d     */
  74.                 100,        /* e     */
  75.                  20,        /* f     */
  76.                  14,        /* g     */
  77.                  42,        /* h     */
  78.                  63,        /* i     */
  79.                  3 ,        /* j     */
  80.                  6 ,        /* k     */
  81.                  35,        /* l     */
  82.                  20,        /* m     */
  83.                  56,        /* n     */
  84.                  56,        /* o     */
  85.                  17,        /* p     */
  86.                  4 ,        /* q     */
  87.                  49,        /* r     */
  88.                  56,        /* s     */
  89.                  71,        /* t     */
  90.                  31,        /* u     */
  91.                  10,        /* v     */
  92.                  18,        /* w     */
  93.                  3 ,        /* x     */
  94.                  18,        /* y     */
  95.                  2 ,        /* z     */
  96.                 166,        /* space, must be last, to use with the following
  97.                                code */
  98.         };
  99.  
  100. /****************************************************************************/
  101. /*              Local Functions                                             */
  102. /****************************************************************************/
  103.  
  104. VOID NewAverage(VOID);
  105. BOOL GetNewMap(DWORD, DWORD);
  106. VOID UseNewMap(VOID);
  107. VOID ShrinkFont(DWORD, DWORD);
  108.  
  109. /****************************************************************************
  110.  * WORD ConvertToBitmapFormat(width, phase, height)
  111.  *
  112.  * purpose  : Takes a part of the font file and converts it to a string of
  113.  *            bytes for a single scan of bitmap for a character.
  114.  *
  115.  * params   : WORD width : width of the character in pixels(bits)
  116.  *            WORD phase : current deviation from byte alignment (pixels)
  117.  *            WORD height: height of character(pixels)
  118.  *
  119.  * returns  : WORD phase : new deviation from byte alignment (pixels)
  120.  *
  121.  * side effects : modifies pointers lp1 and lp2 (pointing to work space and
  122.  *                font body respectively)
  123.  *
  124.  ****************************************************************************/
  125. DWORD PASCAL
  126. ConvertToBitmapFormat(
  127.      DWORD width,     /* width of the character in pixels(bits) */
  128.      DWORD phase,     /* current deviation from byte alignment (pixels) */
  129.      DWORD height     /* height of character(pixels) */
  130.      )
  131. {
  132.       INT w;
  133.       WORD j;
  134.  
  135.       /* in the font file format characters are stored consecutively in
  136.          column-major ordering (columns of char 1 followed by columns of char
  137.          2 ... etc.). lp2 points to start of columns of current character.
  138.          lp1 points to start of row of bitmap for character. */
  139.  
  140.       for (w = width; w > 0; w -= 8){
  141.           if (phase == 0){
  142.           /*  easy case */
  143.               *lp1++ = *lp2;
  144.  
  145.               if (w < 8)
  146.                   phase = w;
  147.           }
  148.           else{
  149.  
  150.               --lp1;
  151.               j = (WORD)*lp1;
  152.               j <<= 8;
  153.               j |= (((WORD)*lp2) << (8 - phase));
  154.               *lp1++ = (BYTE)(j >> 8);
  155.               *lp1++ = (BYTE)j;
  156.               if (w < 8){
  157.                   phase += w;
  158.                   if (phase <= 8)
  159.                       lp1--;          /* back up pointer */
  160.                   phase &= 7;
  161.               }
  162.           }
  163.           lp2 += height;          /* move to next column */
  164.       }
  165.       return phase;
  166. }
  167.  
  168. /****************************************************************************
  169.  * char * VerifyTableContents()
  170.  *
  171.  * purpose  : scan the offsets table of file just read and check if
  172.  *            width and offsets lie within limits
  173.  *
  174.  * params    : none
  175.  *
  176.  * returns   : char * szError : ptr to Error message if table not OK
  177.  *                              NULL otherwise
  178.  *
  179.  * side effects : none
  180.  *
  181.  ****************************************************************************/
  182. CHAR * PASCAL
  183. VerifyTableContents(
  184.     VOID
  185.     )
  186. {
  187.      PBYTE          pjGlyphData;
  188.      GLYPHINFO_20 gi2T20;        /* temp ptr to a 2.0 style table*/
  189.      GLYPHINFO_30 gi3T30;        /* temp ptr to a 2.0 style table*/
  190.      INT i;
  191.  
  192.      /* separate loops written for the 2.0 and 3.0 font processing because
  193.         a single loop would involve too many checks (of font type) within
  194.         the loop and slow down processing  */
  195.      if (iFontFormat == ID_FORMAT2){
  196.          pjGlyphData = (lpFontBody +1);
  197.  
  198.         /* view table as 2.0 table */
  199.  
  200.          /* check that each and every width and offset lie within limits */
  201.  
  202.          for (i=0; i < (fontBuffer.LastChar - fontBuffer.FirstChar + 1); i++) {
  203.  
  204.               vGlyphInfo20FromBuffer (pjGlyphData, &gi2T20);
  205.  
  206.               if (gi2T20.GIwidth > 64)
  207.                   return vszTableWidthsBad;
  208.  
  209.               if ((gi2T20.GIoffset > (UINT)WORD_LIMIT) ||
  210.                   (gi2T20.GIoffset < 0) )
  211.                   return vszTableOffsetsBad;
  212.  
  213.               pjGlyphData += lSizeOfOldGlyph20;
  214.          }
  215.      }
  216.      else{
  217.  
  218.          pjGlyphData = lpFontBody;
  219.  
  220.             /* view table as 3.0 table */
  221.          /* check that each and every width and offset lie within limits */
  222.  
  223.          for (i=0; i< (fontBuffer.LastChar - fontBuffer.FirstChar +1); i++) {
  224.  
  225.               vGlyphInfo30FromBuffer (pjGlyphData, &gi3T30);
  226.  
  227.               if (gi3T30.GIwidth > 64)
  228.                   return vszTableWidthsBad;
  229.  
  230.               if (gi3T30.GIoffset < (DWORD)0)
  231.                   return vszTableOffsetsBad;
  232.  
  233.               pjGlyphData += lSizeOfOldGlyph30;
  234.          }
  235.      }
  236.      return NULL;
  237. }
  238.  
  239. /****************************************************************************
  240.  * char * FontLoad()
  241.  *
  242.  * purpose: reads in the specified font file and creates a work bitmap for
  243.  *          the editor. Also creates a local bitmap-offset table for easy
  244.  *          access to the characters in the bitmap
  245.  *
  246.  * params : pszFileName - File Name to open.
  247.  *
  248.  * returns: ptr to NULL string if Open goes off OK
  249.  *          ptr to error message string otherwise
  250.  *
  251.  * side effects: lots
  252.  *
  253.  ****************************************************************************/
  254. CHAR *
  255. FontLoad(
  256.     CHAR         *pszFileName,
  257.     OFSTRUCT    *pofsReOpenInfo
  258.     )
  259. {
  260.  
  261.     CHAR  *lpFontBodySav = NULL;  /* local pointer to font body */
  262.     DWORD len, fontlen;               /* length of font body (bytes)*/
  263.     UINT i;
  264.     INT mf;                      /* menu function ID */
  265.     DWORD iWorkLen;                   /* length of work area (bytes) */
  266.     HDC hDC;
  267.     CHAR * pszError;                   /* error msg if header is messed up */
  268.  
  269.     DWORD row, height, width,phase;
  270.     DWORD offset;
  271.     GLYPHINFO_20 gi2GlyphTable20;    /* Pointer into 2.0 style offsets table */
  272.     GLYPHINFO_30 gi3GlyphTable30;    /* Pointer into 3.0 style offsets table */
  273.     PBYTE     pjGlyphData;             /* Pointer to Glyph information buffer. */
  274.  
  275.     BYTE  cDummy [CCHEXTRA];         /* dummy buffer for unneeded 3.0 header
  276.                                     * info
  277.                                     */
  278.  
  279.     /* Put up an hourglass ... this may take a while */
  280.     if (!hHourGlass)
  281.         hHourGlass = LoadCursor(NULL, IDC_WAIT);        /* Get Hourglass */
  282.     hOldCursor = SetCursor(hHourGlass);         /* Show hourglass */
  283.  
  284.     /* open file for read. */
  285.     nNewFile = (HFILE)OpenFile (pszFileName, pofsReOpenInfo, OF_READ);
  286.     
  287.     if (nNewFile < 0) {
  288.  
  289.         return vszErrorOpeningFile;
  290.     }
  291.  
  292.     //- ReadFile:  Here is where we need to make some adjustments in order to
  293.     //- read the file in to a new DWORD aligned format.
  294.     {
  295.         BYTE    jBuffer [200];
  296.  
  297.  
  298.         /* Read the header */
  299.         if (_lread ((HFILE) nNewFile, (LPSTR)&jBuffer, lSizeOfOldFontHeader) !=
  300.                 (UINT)lSizeOfOldFontHeader) {
  301.  
  302.             _lclose((HFILE)nNewFile);
  303.             return vszErrorReadingHdr;
  304.         }
  305.  
  306.         //
  307.         // Call conversion routine to give us a properly aligned buffer.
  308.         //
  309.  
  310.         vFontStructFromBuffer (
  311.                  (PBYTE)&jBuffer,
  312.                  &fontBuffer
  313.                 );
  314.  
  315.     }
  316.  
  317.     /* Check the version number -- make sure it's a font */
  318.     switch (fontBuffer.Version)
  319.         {
  320.         case 0x200:
  321.                 iFontFormat = ID_FORMAT2;
  322.                 break;
  323.         case 0x300:        /* added 1/19/88 */
  324.                 iFontFormat = ID_FORMAT3;
  325.                 /* read in the extra fields into a dummy buffer ... they don't
  326.                  * mean anything to us  at this stage.
  327.                  */
  328.                 if ((_lread((HFILE)nNewFile, (LPSTR)cDummy, CCHEXTRA))
  329.                             != CCHEXTRA){
  330.                     _lclose((HFILE)nNewFile);
  331.                     return vszErrorReadingHdr;
  332.                 }
  333.  
  334.                 break;
  335.         default:                /* Anything else -- toughies */
  336.                 _lclose((HFILE)nNewFile);
  337.                 return vszUnknownFormat;
  338.         }
  339.  
  340.     /* check if contents of font header are sensible. If not,
  341.        give an error message and quit */
  342.  
  343.     if ((pszError = VerifyHeaderContents()) != NULL) {
  344.  
  345.         _lclose((HFILE)nNewFile);
  346.         return pszError;
  347.     }
  348.  
  349.     /* Ready to load -- Check if we will be overwriting */
  350.     if (fLoaded)
  351.     {
  352.         DeleteGlobalBitmap();
  353.         fLoaded = FALSE;
  354.     }
  355.  
  356.     /* Allocate space for font body and Face Name and read them in */
  357.     len= (fontBuffer.Size - lSizeOfOldFontHeader);  /* Compute size */
  358.  
  359.     if ((lpFontBody = (LPSTR)GlobalAlloc(GMEM_ZEROINIT, (LONG)len)) == 0) {
  360.  
  361.         _lclose((HFILE)nNewFile);
  362.         return vszNotEnoughMem;                       /* Get Handle to space */
  363.     }
  364.  
  365.     if (iFontFormat == ID_FORMAT3)
  366.         fontlen = len - CCHEXTRA;
  367.     else
  368.         fontlen = len;
  369.  
  370.     lpFontBodySav = lpFontBody;                    /* save ptr to font body */
  371.     while (fontlen >= (DWORD)SEGMENT_SIZE) {
  372.  
  373.         /*  file read method if font file size is 64k bytes or greater.
  374.             file is read in in chunks of 65536 (SEGMENT_SIZE), taking care to
  375.             position buffer ptr at 64k boundary each time */
  376.  
  377.         /* First read in the maximum number of bytes _lread can read (65534) */
  378.         if ((_lread((HFILE)nNewFile, lpFontBodySav, WORD_LIMIT)) == WORD_LIMIT) {
  379.  
  380.             lpFontBodySav += WORD_LIMIT; /* buffer ptr moved up by 64k bytes */
  381.             fontlen -= WORD_LIMIT;     /* fontlen = no of bytes left to read */
  382.  
  383.         } else {
  384.  
  385.             GlobalFree (lpFontBody);
  386.             _lclose((HFILE)nNewFile);
  387.             return vszErrorReadingBody;
  388.         }
  389.  
  390.         /* read in an additional two bytes to reach end of segment */
  391.         if ((_lread((HFILE)nNewFile, lpFontBodySav, 2)) == 2) {
  392.  
  393.             lpFontBodySav += 2; /* buffer ptr moved up by 2 bytes */
  394.             fontlen -= 2;       /* fontlen = no of bytes left to read */
  395.  
  396.         } else {
  397.  
  398.             GlobalFree (lpFontBody);
  399.             _lclose((HFILE)nNewFile);
  400.             return vszErrorReadingBody;
  401.         }
  402.     }
  403.  
  404.     /* read the partially filled segment  */
  405.     if ((_lread((HFILE)nNewFile, lpFontBodySav, (DWORD)fontlen)) != (UINT) fontlen) {
  406.  
  407.         GlobalFree (lpFontBody);
  408.         _lclose((HFILE)nNewFile);
  409.         return vszErrorReadingBody;
  410.     }
  411.  
  412.     /* Close the file */
  413.     _lclose((HFILE)nNewFile);
  414.  
  415.     /* check if the offset table entries are within allowable limits.
  416.        If not give an error message, clean up and quit */
  417.     if ((pszError = VerifyTableContents()) != NULL) {
  418.  
  419.         GlobalFree (lpFontBody);
  420.         return pszError;
  421.     }
  422.  
  423.     /* now that everything has been checked, move buffer to font */
  424.     font = fontBuffer;
  425.  
  426.     /* Make local copies of FaceName and Device Name */
  427.     if (font.Face){
  428.  
  429.         lstrcpy((LPSTR)szFaceName, lpFontBody + font.Face -
  430.                                          (iFontFormat == ID_FORMAT2 ?
  431.                                                     lSizeOfOldFontHeader   :
  432.                                                     lSizeOfOldFontHeader30-1));
  433.     } else {
  434.  
  435.         lstrcpy((LPSTR)szFaceName, (LPSTR)"");
  436.     }
  437.  
  438.     for (i = 0; i <= 256; i++)      /* Zero offsets Table for below */
  439.         offsets[i] = 0;
  440.  
  441.     /* compute work space needed if a 3.0 file. This has to be done since
  442.        3.0 files are compressed versions of 2.0 files and may need a
  443.        work bitmap bigger than the actual font body size */
  444.  
  445.     if (iFontFormat == ID_FORMAT3) {
  446.  
  447.         cTable = (WORD) (6 * (font.LastChar - font.FirstChar + 2));
  448.         iWorkLen = 0;
  449.  
  450.         pjGlyphData = lpFontBody;
  451.  
  452.         /* work bitmap size = sum of sizes of all characters in font */
  453.  
  454.         for (i = font.FirstChar; i <= font.LastChar; i++) {
  455.  
  456.              vGlyphInfo30FromBuffer (pjGlyphData, &gi3GlyphTable30);
  457.  
  458.              iWorkLen += ((gi3GlyphTable30.GIwidth +7) >> 3) * font.PixHeight;
  459.  
  460.              pjGlyphData += lSizeOfOldGlyph30;
  461.         }
  462.  
  463.     } else { /* 2.0 file */
  464.  
  465.         cTable = (WORD)(4 * (font.LastChar - font.FirstChar + 2));
  466.            /* compute table length */
  467.         iWorkLen = len;  /* work space for a 2.0 file is the same as the
  468.                              length of the font body */
  469.     }
  470.  
  471.     //- Add some extra space for dword alignment.
  472.     iWorkLen += (font.PixHeight * sizeof (DWORD));
  473.       /* Get work space */
  474.  
  475.     if ((lpWork = (LPSTR)GlobalAlloc (GMEM_ZEROINIT, (LONG)iWorkLen)) == 0) {
  476.  
  477.         GlobalFree (lpFontBody);
  478.         return vszNotEnoughMem;
  479.     }
  480.  
  481.     lp1 = lpWork;
  482.  
  483.     height = (DWORD) font.PixHeight;
  484.     offset = 0;
  485.     /* put the font file into bitmap format */
  486.     if (iFontFormat == ID_FORMAT2){         /* table in 2.0 format */
  487.         for (row = 0; row < height; row++){
  488.  
  489.              /* view table as a 2.0 style table */
  490.              pjGlyphData = lpFontBody + 1;
  491.  
  492.              phase = 0;
  493.  
  494.              for (i = 0; i < (UINT)(font.LastChar - font.FirstChar + 1); i++) {
  495.  
  496.                 vGlyphInfo20FromBuffer (pjGlyphData, &gi2GlyphTable20);
  497.  
  498.                 width = (DWORD) gi2GlyphTable20.GIwidth;
  499.  
  500.                 /* size of each table element = 4bytes */
  501.                 lp2 = lpFontBody + (gi2GlyphTable20.GIoffset -
  502.                             lSizeOfOldFontHeader) + row;
  503.  
  504.                 pjGlyphData += lSizeOfOldGlyph20;
  505.  
  506.                 /* offset ends up as the sum of the widths */
  507.                 if (row == 0)              /* Once is enough */
  508.                         offsets[i + font.FirstChar + 1] = offset += width;
  509.  
  510.                 /* create a single scan of bitmap for character */
  511.                 phase = ConvertToBitmapFormat (width, phase, height);
  512.              }
  513.              if ((lp1 - lpWork) & 1)
  514.                  *lp1++ = 0;             /* Round lp1 up to Word Boundary */
  515. #ifdef DWORDROUND
  516.              if ((lp1 - lpWork) & 2) {
  517.                  *lp1++ = 0;             /* Round lp1 up to DWord Boundary */
  518.                  *lp1++ = 0;             /* Round lp1 up to DWord Boundary */
  519.              }
  520. #endif
  521.              //if (((offset + 7) >> 3) & 1)
  522.                  //*lp1++ = 0;             /* Round lp1 up to Word Boundary */
  523.              //if (((offset + 7) >> 3) & 2) {
  524.                  //*lp1++ = 0;             /* Round lp1 up to DWord Boundary */
  525.                  //*lp1++ = 0;             /* Round lp1 up to DWord Boundary */
  526.              //}
  527.         }
  528.     }
  529.      /* separate loops written for the 2.0 and 3.0 font processing because
  530.         a single loop would involve too many checks (of font type) within
  531.         the loop and slow down processing  */
  532.     else {                                 /* table in 3.0 format */
  533.  
  534.         for (row = 0; row < height; row++){
  535.  
  536.              phase = 0;
  537.              /* view table as a 3.0 style table */
  538.              pjGlyphData = lpFontBody;
  539.  
  540.              for (i = 0; i < (UINT)(font.LastChar - font.FirstChar + 1); i++) {
  541.  
  542.                 vGlyphInfo30FromBuffer (pjGlyphData, &gi3GlyphTable30);
  543.  
  544.                 width = gi3GlyphTable30.GIwidth;
  545.  
  546.                   /* size of each table element = 6bytes */
  547.                 lp2 = lpFontBody + (gi3GlyphTable30.GIoffset -
  548.                         lSizeOfOldFontHeader30 +1) + row;
  549.  
  550.                 pjGlyphData += lSizeOfOldGlyph30;
  551.  
  552.                  /* offset ends up as the sum of the widths */
  553.                 if (row == 0)              /* Once is enough */
  554.                     offsets[i + font.FirstChar + 1] = offset += width;
  555.  
  556.                  /* create a single scan of bitmap for character */
  557.                 phase = ConvertToBitmapFormat (width, phase, height);
  558.              }
  559.              if ((lp1 - lpWork) & 1)
  560.                  *lp1++ = 0;             /* Round lp1 up to Word Boundary */
  561. #ifdef DWORDROUND
  562.              if ((lp1 - lpWork) & 2) {
  563.                  *lp1++ = 0;             /* Round lp1 up to DWord Boundary */
  564.                  *lp1++ = 0;             /* Round lp1 up to DWord Boundary */
  565.              }
  566. #endif
  567.         }
  568.     }
  569.              // FontLoad(): width byte is DWORD align
  570.     font.WidthBytes = (WORD) CJ_DIB_SCAN(offset);
  571.        /* fixup NEWFON error */
  572.  
  573.     GlobalFree(lpFontBody);
  574.     lpFontBody = lpWork;          /* So that below we free the other buffer */
  575.     /* Create a WINDOWS bitmap to move the font definition bits into */
  576.  
  577.     hDC = GetDC (hFont);                         /* DC to be compatible with */
  578.     hBitmap = CreateBitmap(
  579.                     (INT)font.WidthBytes << 3, /* Width of font in pixels */
  580.                     (INT)font.PixHeight,
  581.                     1, 1, (LPBYTE)NULL);
  582.     hMemDC = CreateCompatibleDC(hDC);           /* Create a DC */
  583.     SelectObject(hMemDC, hBitmap);              /* Relate the two of them */
  584.     ReleaseDC(hFont, hDC);                      /* Done with font DC */
  585.  
  586.     /* Move the bits in */
  587.     SetBitmapBits(hBitmap,
  588.           (DWORD)font.WidthBytes * (DWORD)font.PixHeight,(CHAR  *)lpWork);
  589.  
  590.     /* Free up the space we loaded the file into */
  591.     GlobalFree(lpFontBody);
  592.     fLoaded = TRUE;
  593.     {
  594.         HMENU hMenu;
  595.  
  596.         hMenu = GetMenu(hBox);  /* Gray menu if no clipboard bitmap */
  597.         mf = (font.Family & 1) ? MF_ENABLED : MF_GRAYED;
  598.         EnableMenuItem(hMenu, FONT_SAVE, MF_ENABLED);
  599.         EnableMenuItem(hMenu, FONT_SAVEAS, MF_ENABLED);
  600.         EnableMenuItem(hMenu, 1, MF_BYPOSITION | MF_ENABLED);
  601.         EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_ENABLED);
  602.         EnableMenuItem(hMenu, 3, MF_BYPOSITION | MF_ENABLED);
  603.         EnableMenuItem(hMenu, 4, MF_BYPOSITION | mf);
  604.         EnableMenuItem(hMenu, 5, MF_BYPOSITION | MF_ENABLED);
  605.         EnableMenuItem(hMenu, 6, MF_BYPOSITION | MF_ENABLED);
  606.         DrawMenuBar(hBox);
  607.     }
  608.     SetCursor(hOldCursor);              /* Restore regular cursor */
  609.     return "";
  610. }
  611.  
  612. /**************************************
  613.  * compares nBytes bytes of s1 and s2 *
  614.  **************************************/
  615. BOOL
  616. ByteCompare (
  617.     CHAR  *s1,
  618.     CHAR  *s2,
  619.     DWORD nBytes
  620.     )
  621. {
  622.     for ( ; nBytes > 0; nBytes--)
  623.         if (*s1++ != *s2++)
  624.             return FALSE;
  625.     return TRUE;
  626. }
  627.  
  628. /***********************************
  629.  * copies nBytes bytes of s2 to s1 *
  630.  ***********************************/
  631. BOOL
  632. ByteCopy(
  633.     CHAR  *s1,
  634.     CHAR  *s2,
  635.     LONG  nBytes
  636.     )
  637. {
  638.     for ( ; nBytes > 0; nBytes--)
  639.         *s1++ = *s2++;
  640.     return TRUE;
  641. }
  642.  
  643. /****************************************************************************
  644.  * VOID ConvertToFileFormat(width, phase, height)
  645.  *
  646.  * purpose  : Takes a part of the bitmap (corresponding to a single character)
  647.  *            and converts it to a string of bytes in the font file format
  648.  *
  649.  * params   : WORD width :  width of the character in pixels(bits)
  650.  *            WORD phase :  current deviation from byte alignment (pixels)
  651.  *            WORD height:  height of character(pixels)
  652.  *
  653.  * returns:   WORD phase :  new deviation from byte alignment (pixels)
  654.  *
  655.  * side effects : modifies pointers lp1 and lp2 (pointing to font body and work
  656.  *                space respectively)
  657.  *
  658.  ****************************************************************************/
  659. DWORD PASCAL
  660. ConvertToFileFormat(
  661.      DWORD width,
  662.      DWORD phase,
  663.      DWORD height
  664.      )
  665. {
  666.       INT w;
  667.  
  668.       for (w = width; w > 0; w -= 8){  /* for each byte of font */
  669.            if (phase == 0){             /* easy case */
  670.  
  671.                BYTE b;
  672.  
  673.                b = *lp1++;
  674.                if (w < 8){
  675.  
  676.                    phase = (DWORD) w;
  677.                    b >>= 8 - w;    /* Clear left side bits */
  678.                    b <<= 8 - w;
  679.                }
  680.                *lp2 = b;
  681.            }
  682.            else{
  683.  
  684.                DWORD j;
  685.  
  686.                lp1--;          /* Re-read byte prevously read */
  687.                //j = (DWORD) ((BYTE)*lp1++ << 8) | ((BYTE)*lp1++);
  688.                j = (DWORD)((BYTE)*lp1++ << 8);
  689.                j |= (DWORD) ((BYTE)*lp1++);
  690.                if (w < 8){
  691.  
  692.                    j >>= 16 - phase - (w & 7);  /* shove it right */
  693.                    j <<= 8 - (w & 7); /* Left justify in low byte */
  694.                    phase += (DWORD) w;
  695.                    if (phase <=  8)
  696.                        lp1--;         /* back up pointer */
  697.                    phase &= 7;
  698.                }
  699.                else
  700.                    j >>= 8 - phase;
  701.                *lp2 = (BYTE)j;
  702.            }
  703.            lp2 += height;          /* move to next column */
  704.        }
  705.        return phase;
  706. }
  707.  
  708. /****************************************************************************
  709.  * char * FontSave()
  710.  *
  711.  * purpose: saves the work bitmap in the required font file format (2.0 or
  712.  *          3.0 and cleans up
  713.  *
  714.  * params : none
  715.  *
  716.  * returns: ptr to a NULL string if Save goes off OK
  717.  *          ptr to error message string otherwise
  718.  *
  719.  * side effects: lots
  720.  *
  721.  ****************************************************************************/
  722.  
  723. CHAR *
  724. FontSave(
  725.     CHAR         *pszFileName,
  726.     OFSTRUCT    *pofsReOpenInfo
  727.     )
  728. {
  729.     DWORD bytecount;       /* number of bytes returned by lwrite */
  730.     DWORD size;            /* total size of font */
  731.  
  732.     WORD height, row;
  733.     DWORD i, fontlen;
  734.     DWORD cBody, cFont,cFontsav, cFace;
  735.     CHAR             *lpFont;          /* ponter to font body */
  736.     CHAR * sz;
  737.     DWORD iMax;
  738.     WORD widthsav;
  739.     PBYTE            pjGlyphData;
  740.     PBYTE            pjGlyphSave;
  741.     GLYPHINFO_20     gi2GlyphTable20;    /* 2.0 style Glyph data struct */
  742.     GLYPHINFO_30     gi3GlyphTable30;    /* 3.0 style Glyph data struct */
  743.  
  744.     NewAverage(); /* force ave width to be recomputed 8/17/87 BobM */
  745.  
  746.     /* reset file pointer */
  747.     nNewFile = (HFILE)OpenFile (pszFileName, pofsReOpenInfo, OF_WRITE | OF_REOPEN);
  748.  
  749.     if (nNewFile < (HFILE) 0) {
  750.  
  751.         return vszErrorOpeningFile;
  752.     }
  753.  
  754.     /* Put up an houglass ... this may take a while */
  755.     if (!hHourGlass)
  756.         hHourGlass = LoadCursor (NULL, IDC_WAIT);        /* Get Hourglass */
  757.     hOldCursor = SetCursor (hHourGlass);         /* Show hourglass */
  758.  
  759.     height = font.PixHeight;
  760.     cBody = (DWORD)height * (DWORD)font.WidthBytes;
  761.  
  762.     /* Recompute file size and update header */
  763.     if (iFontFormat == ID_FORMAT2)
  764.        cHeader = (WORD)(lSizeOfOldFontHeader +1);
  765.     else
  766.        cHeader = (WORD)(lSizeOfOldFontHeader30 - 1);
  767.  
  768.     /* if of 2.0 type, check if size will exceed 64kbytes. If yes, saving
  769.        in 2.0 format will result in loss of information (because offset table
  770.        of 2.0 file is composed of 16bit words). Warn user and ask if file can
  771.        be saved as a 3.0 file */
  772.  
  773.     if (iFontFormat == ID_FORMAT2)
  774.     {     
  775.         if (((DWORD)cHeader + (DWORD)(lSizeOfOldGlyph20 * (font.LastChar -
  776.             font.FirstChar+2)) + (DWORD)cBody) >= WORD_LIMIT)
  777.                if (MessageBox(hBox, vszTooBigFor20, vszWarning,
  778.                               IDOK | IDCANCEL |IDNO) == IDYES)
  779.                     iFontFormat = ID_FORMAT3;
  780.     }
  781.  
  782.     if (iFontFormat == ID_FORMAT2) {
  783.  
  784.         /* allocate space for a 2.0 style offsets table */
  785.         cTable = (WORD)(lSizeOfOldGlyph20 *
  786.                 (font.LastChar - font.FirstChar + 2));
  787.  
  788.     } else {
  789.  
  790.         /* allocate space for a 3.0 style offsets table */
  791.         cTable = (WORD)(lSizeOfOldGlyph30 *
  792.                 (font.LastChar - font.FirstChar + 2));
  793.     }
  794.  
  795.     pjGlyphData = (LPSTR)GlobalAlloc (GMEM_ZEROINIT, (DWORD)cTable);
  796.  
  797.     if (pjGlyphData == 0) {
  798.  
  799.         _lclose((HFILE)nNewFile);
  800.         return vszNotEnoughMem;
  801.     }
  802.  
  803.     pjGlyphSave = pjGlyphData;
  804.  
  805.     size = cHeader + cTable;
  806.     iMax = font.LastChar - font.FirstChar + 1;
  807.  
  808.     // Recreate maximum character width when the font is proportional
  809.     // since the WIDTH.. command may grow maxwidth but may not reduce.
  810.     if (font.Family & 1)
  811.     font.MaxWidth = 0;
  812.  
  813.     /* create offsets table of font file */
  814.     for (i = 0; i <= iMax; i++){
  815.  
  816.          DWORD width, charSize;
  817.  
  818.          width = offsets[i + font.FirstChar + 1] - offsets[i + font.FirstChar];
  819.  
  820.          if (i == iMax) {
  821.              width = 8;      /* Sentinal blank */
  822.          }
  823.  
  824.          if (iFontFormat == ID_FORMAT2){
  825.  
  826.             gi2GlyphTable20.GIwidth  = (SHORT)width;
  827.             gi2GlyphTable20.GIoffset = (SHORT)size;
  828.  
  829.             vBufferFromGlyphInfo20 (&gi2GlyphTable20, pjGlyphData);
  830.  
  831.             pjGlyphData += lSizeOfOldGlyph20;
  832.  
  833.          } else {
  834.  
  835.             gi3GlyphTable30.GIwidth  = (SHORT)width;
  836.             gi3GlyphTable30.GIoffset = (INT)size;
  837.  
  838.             vBufferFromGlyphInfo30 (&gi3GlyphTable30, pjGlyphData);
  839.  
  840.             pjGlyphData += lSizeOfOldGlyph30;
  841.          }
  842.         // update max width
  843.         if(font.Family & 1 ) {
  844.             if(width > font.MaxWidth )
  845.                 font.MaxWidth = (WORD)width ;
  846.         }
  847.         if(i == 0x81 && font.CharSet == SHIFTJIS_CHARSET) {
  848.             if(width * 2 > font.MaxWidth) {
  849.                 font.MaxWidth = (WORD)width * 2 ;
  850.             }
  851.         }
  852.  
  853.          charSize = height * ((width + 7) >> 3);  /* size in bytes */
  854.  
  855.          if ((size + charSize) < size){           /* Overflow? */
  856.  
  857.              GlobalFree (pjGlyphData);
  858.              _lclose((HFILE)nNewFile);
  859.              return vszFileTooLarge;
  860.  
  861.          }
  862.          size += charSize;
  863.     }
  864.  
  865.     /* Update stuff in the header */
  866.  
  867.     font.Face = (DWORD)size;
  868.     cFace = (WORD)lstrlen (szFaceName) + 1;   /* Allow for \0 */
  869.     size += cFace;
  870.     font.Size = (DWORD)size;                                /* new file size */
  871.     font.BitsOffset = (DWORD)(cHeader + cTable);
  872.     font.Device = (DWORD)NULL;                   /* Device Name must be NULL */
  873.     cFontsav = size - cHeader - cTable;
  874.     cFont =cFontsav;
  875.  
  876.     /* alloc extra byte for lp1 in case it needs it */
  877.     if (!(lpFontBody = (LPSTR)GlobalAlloc (GMEM_ZEROINIT, (LONG)cBody +
  878.             height * 4))) {
  879.  
  880.         _lclose((HFILE)nNewFile);
  881.         return vszNotEnoughMem;
  882.     }
  883.  
  884.     GetBitmapBits (hBitmap, (DWORD)cBody, lpFontBody);
  885.  
  886.     /* save current WidthBytes */
  887.     widthsav = font.WidthBytes;
  888.  
  889.     /*  MD - reset WidthBytes from computed width */
  890.     font.WidthBytes = (WORD) (cFont - cFace)/ height;
  891.  
  892.     /* Allocate a block to put bitmap into */
  893.     if ((lpFont = lpWork = GlobalAlloc (GMEM_ZEROINIT,(LONG)cFont)) == 0)
  894.     {
  895.         GlobalFree (lpFontBody);
  896.         _lclose((HFILE)nNewFile);
  897.         return vszNotEnoughMem;
  898.     }
  899.  
  900.     lp1 = lpFontBody;
  901.  
  902.     /* convert bitmap to file format */
  903.     if (iFontFormat == ID_FORMAT2){   /* offsets table in 2.0 format */
  904.         INT nChars;
  905.         nChars =  font.LastChar - font.FirstChar +1;
  906.  
  907.         for (row = 0; row < height; row++){
  908.  
  909.             DWORD phase;
  910.  
  911.             phase = 0;
  912.  
  913.             pjGlyphData = pjGlyphSave;
  914.  
  915.             for (i = 0; i < (DWORD) nChars; i++) {
  916.  
  917.                 INT width;
  918.  
  919.                 vGlyphInfo20FromBuffer (pjGlyphData, &gi2GlyphTable20);
  920.  
  921.                 width = gi2GlyphTable20.GIwidth;
  922.  
  923.                 lp2 = (BYTE  *)(lpWork + (gi2GlyphTable20.GIoffset -
  924.                         cHeader - cTable + row));
  925.  
  926.                 pjGlyphData += lSizeOfOldGlyph20;
  927.  
  928.                 phase = ConvertToFileFormat (width, phase, height);
  929.             }
  930.             if ((lp1 - lpWork) & 1)
  931.                  lp1++;             /* Round lp1 up to Word Boundary */
  932. #ifdef DWORDROUND
  933.             if ((lp1 - lpWork) & 2) {
  934.                  lp1++;             /* Round lp1 up to DWord Boundary */
  935.                  lp1++;             /* Round lp1 up to DWord Boundary */
  936.             }
  937. #endif
  938.             //if(((offsets[font.LastChar + 1] + 7) >> 3) & 1)
  939.                 //lp1++;          /* Round lp1 up to Word Boundary */
  940.         }
  941.     }
  942.      /* separate loops written for the 2.0 and 3.0 font processing because
  943.         a single loop would involve too many checks (of font type) within
  944.         the loop and slow down processing  */
  945.     else{  /* table in 3.0 format */
  946.  
  947.         INT nChars;
  948.         nChars =  font.LastChar - font.FirstChar +1;
  949.         for (row = 0; row < height; row++){
  950.  
  951.             DWORD phase;
  952.  
  953.             phase = 0;
  954.             pjGlyphData = pjGlyphSave;
  955.  
  956.             for (i = 0; i < (DWORD) nChars; i++) {
  957.  
  958.                 INT width;
  959.  
  960.                 vGlyphInfo30FromBuffer (pjGlyphData, &gi3GlyphTable30);
  961.  
  962.                 width = gi3GlyphTable30.GIwidth;
  963.  
  964.                 lp2 = (BYTE  *)(lpWork + (gi3GlyphTable30.GIoffset -
  965.                         cHeader - cTable + row));
  966.  
  967.                 pjGlyphData += lSizeOfOldGlyph30;
  968.  
  969.                 phase = ConvertToFileFormat (width, phase, height);
  970.             }
  971.             if ((lp1 - lpWork) & 1)
  972.                  lp1++;             /* Round lp1 up to Word Boundary */
  973. #ifdef DWORDROUND
  974.             if ((lp1 - lpWork) & 2) {
  975.                  lp1++;             /* Round lp1 up to DWord Boundary */
  976.                  lp1++;             /* Round lp1 up to DWord Boundary */
  977.             }
  978. #endif
  979.             //if(((offsets[font.LastChar + 1] + 7) >> 3) & 1)
  980.                 //lp1++;          /* Round lp1 up to Word Boundary */
  981.         }
  982.     }
  983.  
  984.     /* Restore start of data. */
  985.     pjGlyphData = pjGlyphSave;
  986.  
  987.     lp2 -= height - 1;              /* Back up to start of character */
  988.     for (i = 0; i < height; i++)
  989.          *lp2++ = 0;             /* Fill in guaranteed blank character */
  990.  
  991.     font.Version = 0x200;
  992.  
  993.     /******  code for compaction in 3.0 fmt borrowed from CMPCTFON ******/
  994.     if (iFontFormat== ID_FORMAT3){
  995.         DWORD iDefBitmapSize = 0;     /* size of default char */
  996.         DWORD cch = 0;                /* count of number of default char */
  997. #if 0
  998.         GLYPHINFO_30  *cur_char;  /* current element of offset table */
  999.         GLYPHINFO_30  *move_char;
  1000.             /* element from which moving is to be done */
  1001.         LONG iDefBitmapOffset;        /* offset of default char */
  1002.         INT iDefBitmapWidth;          /* width of default char */
  1003.         static LONG iEndOfBitmaps;    /* address of end of font body */
  1004.         INT iFirstC;                  /* first char in font */
  1005.         INT iLastC;                   /* last char in font */
  1006.         INT i,j;
  1007.         WORD width;
  1008.         CHAR  *rgbFont;         /* pointer to font body */
  1009.         DWORD Offset;
  1010.  
  1011.         GDI seems to understand compressed 2.0 external formats but not
  1012.         compressed 3.0 formats, and this is causing it to crash loading a 3.0
  1013.         format compressed font. Since compression does not affect the
  1014.         validity of the font, This code is disabled temporarily till
  1015.         this problem is verified. Again, the font is perfectly usable in this
  1016.         form, though a trifle bigger than desired -  LR 20/26/90
  1017.  
  1018.  
  1019.         Note that this will now not work after the conversion to NT.
  1020.         the glyph table needs to accessed as above.  t-davema 8/20/91
  1021.  
  1022.         iFirstC = font.FirstChar & 0x0ff;
  1023.         iLastC  = font.LastChar & 0x0ff;
  1024.  
  1025.         iEndOfBitmaps = (LONG)font.BitsOffset+((LONG)font.WidthBytes *
  1026.                 (LONG)font.PixHeight);
  1027.         rgbFont = (CHAR  *)lpFont;   /* start of font body */
  1028.         cur_char =(GLYPHINFO_30  *) lpTable; /* start of offset table */
  1029.  
  1030.         /* calculate some parameters for the default char */
  1031.         iDefBitmapOffset = cur_char[font.DefaultChar].GIoffset;
  1032.         iDefBitmapWidth  = cur_char[font.DefaultChar].GIwidth;
  1033.         iDefBitmapSize   = (DWORD)cur_char[font.DefaultChar+1].GIoffset
  1034.                                            - (DWORD)iDefBitmapOffset;
  1035.  
  1036.         /* scan the font body via the offsets table. If a default char
  1037.            is recognised, move all the bytes to it's right left by the
  1038.            size of the default char.Make all offset table entries of default
  1039.            char point to one image of the char (the earliest occuring image) */
  1040.         for (i = iFirstC; i <= iLastC; ++i) {
  1041.  
  1042.             /* important: Check for limiting conditions (in case break char
  1043.                was modified?)*/
  1044.             if (cur_char->GIoffset == iDefBitmapOffset){
  1045.                 cur_char++;
  1046.                 continue;
  1047.             }
  1048.  
  1049.             Offset = cur_char->GIoffset -cHeader -cTable;
  1050.             /* proceed to compare images only if widths are equal */
  1051.             if ((cur_char->GIwidth  == iDefBitmapWidth) &&
  1052.                 (ByteCompare (&rgbFont [Offset],
  1053.                 &rgbFont[iDefBitmapOffset-cHeader-cTable],
  1054.                                 (DWORD)iDefBitmapSize) == TRUE)){
  1055.  
  1056.                 /* set offset to earliest occurence of the default char */
  1057.                 if (cur_char->GIoffset <  iDefBitmapOffset){
  1058.                     iDefBitmapOffset = cur_char->GIoffset;
  1059.                 }
  1060.                 else    {
  1061.                     if (i != iLastC){
  1062.                         /* move bytes to right of default char left by the
  1063.                            size of the char */
  1064.                         ByteCopy (&rgbFont [ Offset],
  1065.                                   &rgbFont [ Offset+ iDefBitmapSize],
  1066.                                   (LONG)(iEndOfBitmaps -
  1067.                                   ((cur_char + 1)->GIoffset)));
  1068.  
  1069.                         /* correct the offset table entries */
  1070.                         move_char = cur_char + 1;
  1071.                         for (j=i; j < iLastC; ++j){
  1072.                              move_char->GIoffset -= (LONG)iDefBitmapSize;
  1073.                              move_char++;
  1074.                         }
  1075.                     }
  1076.                     iEndOfBitmaps -= iDefBitmapSize;
  1077.                     /* move End-of-font to the left */
  1078.                     cur_char->GIoffset = iDefBitmapOffset;
  1079.                     /* point offset of cuurent char to default char */
  1080.                     cch++;
  1081.                 }
  1082.             }
  1083.             cur_char++;
  1084.         }
  1085. #endif
  1086.         /* recalculate some font attributes */
  1087.         lp2   -= (cch * iDefBitmapSize + height);
  1088.         for (i = 0; i < height; i++)
  1089.             *lp2++ = 0;             /* Fill in guaranteed blank character */
  1090.  
  1091.         cFont -= cch * iDefBitmapSize;
  1092.         font.WidthBytes = (WORD) (cFont - cFace)/ height;
  1093.         font.Size = (DWORD) (cFont + cHeader + cTable);
  1094.         font.Face = font.Size - cFace ;
  1095.         font.Version = 0x300;
  1096.  
  1097.         /* copy info into 3.0 (new) format header and set the additional
  1098.            fields */
  1099.         ByteCopy ((LPSTR)&font30, (LPSTR)&font, (DWORD)sizeof (font));
  1100.         font30.fsFlags        = 0;
  1101.         font30.fsFlags = (font.Family & 1 ? FSF_PROPORTIONAL : FSF_FIXED);
  1102.         font30.fsAspace       = 0;
  1103.         font30.fsBspace       = 0;
  1104.         font30.fsCspace       = 0;
  1105.         font30.fsColorPointer = 0L;
  1106.         for (i = 0; i < 4 ; i++)
  1107.             font30.fsReserved[i] = 0L;
  1108.     }
  1109.  
  1110.     /* Add the FaceName, if any, to the end of the bitmap */
  1111.     lstrcpy((LPSTR)lp2, (LPSTR)szFaceName);
  1112.  
  1113.     /*
  1114.      * Again we need to do some tricky things to get the header output
  1115.      * correct.  We want to run it through the conversion backwards until
  1116.      * we get the packed structure.
  1117.      */
  1118.     {
  1119.         BYTE jOutputBuffer [sizeof (font30)];
  1120.  
  1121.         if (iFontFormat == ID_FORMAT2) {
  1122.  
  1123.             vBufferFromFontStruct (&font, (PBYTE)&jOutputBuffer);
  1124.  
  1125.         } else {
  1126.  
  1127.             vBufferFromFont30Struct (&font30, (PBYTE)&jOutputBuffer);
  1128.         }
  1129.  
  1130.         bytecount = _lwrite((HFILE)nNewFile, (PBYTE)&jOutputBuffer, (DWORD)cHeader);
  1131.     }
  1132.  
  1133.     /* Write out Header Information */
  1134.     if (bytecount == cHeader) {
  1135.  
  1136.             /* Write out OffsetsTable */
  1137.          if (cTable == 0 || (_lwrite((HFILE)nNewFile, pjGlyphData, (DWORD)cTable)
  1138.                 == (UINT)cTable)){
  1139.               /* Write out Body */
  1140.               fontlen = cFont;
  1141.               while (fontlen >= SEGMENT_SIZE){
  1142.  
  1143.                  /* file write method if font size is 64k or greater
  1144.                  file is written in chunks of 65536 bytes (SEGMENT_SIZE)-lr */
  1145.  
  1146.                  /* First write as many bytes as _lwrite will allow(65534) */
  1147.                   if (_lwrite((HFILE)nNewFile, (CHAR  *)lpFont, WORD_LIMIT) ==
  1148.                         WORD_LIMIT){
  1149.                       fontlen -= WORD_LIMIT;
  1150.                             /* fontlen = no of bytes left to write*/
  1151.                       lpFont+= WORD_LIMIT; /* buffer ptr moved up by 64k */
  1152.                   }
  1153.                   else
  1154.                       sz = vszErrorWritingBody;
  1155.  
  1156.                   /* write the two bytes remaining in the segment */
  1157.                   if (_lwrite((HFILE)nNewFile, (CHAR  *)lpFont, 2) == 2){
  1158.                       fontlen -= 2;  /* fontlen = no of bytes left to write*/
  1159.                       lpFont+= 2;    /* buffer ptr moved up by 2 */
  1160.                   }
  1161.                   else
  1162.                       sz = vszErrorWritingBody;
  1163.               }
  1164.               /* segment only partially filled. Write the remaining bytes */
  1165.               if (_lwrite((HFILE)nNewFile, (CHAR  *)lpFont, (DWORD)fontlen) ==
  1166.                     (UINT) fontlen){
  1167.                    fChanged = FALSE;
  1168.                    sz= "";
  1169.               }
  1170.               else
  1171.                   sz = vszErrorWritingBody;
  1172.          }
  1173.          else
  1174.              sz = vszErrorWritingOffsets;
  1175.     }
  1176.     else
  1177.          sz = vszErrorWritingHdr;
  1178.  
  1179.     /* hack: Restore saved value of widthbytes, eliminating a variety
  1180.        of minor scrolling problems that follow after a File/Save */
  1181.     font.WidthBytes = widthsav;
  1182.  
  1183.     _lclose((HFILE)nNewFile);
  1184.  
  1185.     /* Tidy up */
  1186.  
  1187.     GlobalFree(lpFontBody);
  1188.     GlobalFree(pjGlyphData);
  1189.     GlobalFree(lpWork);
  1190.  
  1191.     SetCursor(hOldCursor);              /* Restore regular cursor */
  1192.  
  1193.     return sz;
  1194. }
  1195.  
  1196. /****************************************************************************
  1197.  * BOOL ResizeWidths(wChar)
  1198.  *
  1199.  * params : WORD wChar : new width of a single character
  1200.  *
  1201.  * purpose: resize work bitmap according to new character width by stretching/
  1202.  *          compressing all characters as neccesary
  1203.  *
  1204.  * returns: none
  1205.  *
  1206.  * side effects: Work bitmap changes.Some header info (regarding font dimensions
  1207.  *               altered as well
  1208.  ****************************************************************************/
  1209.  
  1210.  
  1211. BOOL
  1212. ResizeWidths(
  1213.     DWORD wChar
  1214.     )
  1215. {
  1216.     DWORD width;
  1217.     DWORD offset, i;
  1218.  
  1219.     /* Create a new bitmap to move the font definition bits into */
  1220.     width = (font.LastChar - font.FirstChar + 1) * wChar; /* In pixels */
  1221.              // ResizeWidths(): width byte is DWORD align
  1222.     width = CJ_DIB_SCAN(width);
  1223.     if (!GetNewMap(width, font.PixHeight))
  1224.         return (FALSE);
  1225.  
  1226.     /* Move the bits in */
  1227.     offset = 0;
  1228.     oldMode = SetStretchBltMode(hNewMemDC, COLORONCOLOR);
  1229.     for (i = font.FirstChar; i <= font.LastChar; i++)
  1230.         {
  1231.  
  1232.         StretchBlt(hNewMemDC, offset, 0,
  1233.                 wChar, font.PixHeight,                  /* New character */
  1234.                 hMemDC, offsets[i], 0,
  1235.                 font.PixWidth, font.PixHeight,          /* Old character */
  1236.                 SRCCOPY);
  1237.         offsets[i] = offset;
  1238.         offset += wChar;
  1239.         }
  1240.     SetStretchBltMode(hNewMemDC, oldMode);
  1241.     offsets[font.LastChar + 1] = offset;
  1242.  
  1243.     UseNewMap();                /* Switch Pointers and release the space */
  1244.  
  1245.     font.HorizRes = (WORD) Proport(font.HorizRes, wChar, font.PixWidth, 999);
  1246.     font.WidthBytes = (WORD) width;            /* Misc. ajustments */
  1247.     font.PixWidth = font.AvgWidth = (font.MaxWidth = (WORD) wChar);
  1248.     font.MaxWidth = (WORD) wChar * 2;    // set MaxWidth as DBCS width.
  1249.  
  1250.     return (TRUE);
  1251. }
  1252.  
  1253.  
  1254. /****************************************************************************
  1255.  * BOOL SpreadWidths(wChar)
  1256.  *
  1257.  * purpose: spread/compress work bitmap (with variable width characters)
  1258.  *          in proportion with the maximum character width
  1259.  *
  1260.  * params : WORD wChar : new width of a character
  1261.  *
  1262.  * returns: none
  1263.  *
  1264.  * side effects: Work bitmap changes.Some header info (regarding font dimensions
  1265.  *               altered as well
  1266.  ****************************************************************************/
  1267.  
  1268. BOOL
  1269. SpreadWidths(
  1270.     DWORD wChar
  1271.     )
  1272. {
  1273.     DWORD offset, i;
  1274.     DWORD width, oldWidth, newWidths[257];
  1275.  
  1276.     /* Create a new bitmap to move the font definition bits into */
  1277.     width = 0;          /* Compute the new width */
  1278.     for (i = (DWORD) font.FirstChar; i <= (DWORD) font.LastChar; i++)
  1279.         {
  1280.         oldWidth = offsets[i + 1] - offsets[i];
  1281.         /* Compute new width to nearest whole number */
  1282.         newWidths[i] = Proport(oldWidth, wChar, font.MaxWidth, wBoxLim - 1);
  1283.         width += newWidths[i];
  1284.         }
  1285.              // SpreadWidths(): byte width is DWORD align
  1286.     width = CJ_DIB_SCAN(width);
  1287.     if (!GetNewMap(width, font.PixHeight))
  1288.         return(FALSE);
  1289.  
  1290.     /* Move the bits in */
  1291.     offset = 0;
  1292.     oldMode = SetStretchBltMode(hNewMemDC, COLORONCOLOR);
  1293.     for (i = font.FirstChar; i <= font.LastChar; i++)
  1294.         {
  1295.         oldWidth = offsets[i + 1] - offsets[i];
  1296.         StretchBlt(hNewMemDC, offset, 0,
  1297.                 newWidths[i], font.PixHeight,           /* New character */
  1298.                 hMemDC, offsets[i], 0,
  1299.                 oldWidth, font.PixHeight,               /* Old character */
  1300.                 SRCCOPY);
  1301.         offsets[i] = offset;
  1302.         offset += newWidths[i];
  1303.         }
  1304.     SetStretchBltMode(hNewMemDC, oldMode);
  1305.     offsets[font.LastChar + 1] = offset;
  1306.  
  1307.     UseNewMap();                /* Switch Pointers and release the space */
  1308.     font.HorizRes = (WORD) Proport(font.HorizRes, wChar, font.MaxWidth, 999);
  1309.     font.WidthBytes = (WORD) width;            /* Misc. ajustments */
  1310.     font.MaxWidth = (WORD) wChar;
  1311.     NewAverage();                       /* Compute new average width */
  1312.  
  1313.     return (TRUE);
  1314. }
  1315.  
  1316.  
  1317. /****************************************************************************
  1318.  * NewAverage()
  1319.  *
  1320.  * purpose: recalculate average width of a character in font
  1321.  *
  1322.  * params : none
  1323.  *
  1324.  * returns: none
  1325.  *
  1326.  * side effects: alters the average width parameter in font header
  1327.  *
  1328.  ****************************************************************************/
  1329. VOID
  1330. NewAverage(
  1331.     VOID
  1332.     )
  1333. {
  1334. #ifdef FOO
  1335.     WORD i, totalwidth;
  1336.     /* 12/23/85 -- use weighted avg of lower case letters (mikecr) */
  1337.  
  1338.     /* width of the space */
  1339.     totalwidth = (offsets[' ' + 1] - offsets[' ']) * widthweights[ALPHA_CNT];
  1340.  
  1341.     for (i = 0; i < ALPHA_CNT; i++)
  1342.             totalwidth += (offsets['a' + i + 1] - offsets['a' + i]) *
  1343.             widthweights[i];
  1344.  
  1345.     font.AvgWidth = totalwidth / TOTAL_WEIGHTS;
  1346.  
  1347.     /* round up if necessary */
  1348.     if (totalwidth % TOTAL_WEIGHTS >= (TOTAL_WEIGHTS >> 1))
  1349.             font.AvgWidth++;
  1350.  
  1351. #endif
  1352.  
  1353.     /* lets do a simple average here */
  1354.     font.AvgWidth = (WORD) (((offsets[font.LastChar+1] -
  1355.             offsets[font.FirstChar]) + (font.LastChar - font.FirstChar)/2) /
  1356.             (font.LastChar - font.FirstChar + 1));
  1357.  
  1358.     if (font.AvgWidth == 0) {
  1359.        font.AvgWidth++;
  1360.     }
  1361.     if (font.AvgWidth < 1) {
  1362.         font.AvgWidth = 1;
  1363.     }
  1364. }
  1365.  
  1366.  
  1367. /****************************************************************************
  1368.  * BOOL ResizeBody(width, height)
  1369.  *
  1370.  * purpose: adjust work bitmap according to new specified dimensions
  1371.  *
  1372.  * params : WORD width  : new width of font in pixels
  1373.  *          WORD height : new height of font in pixels
  1374.  *
  1375.  * returns: none
  1376.  *
  1377.  * side effects: Work bitmap changes.Some header info (regarding font dimensions
  1378.  *               altered as well
  1379.  ****************************************************************************/
  1380.  
  1381. BOOL
  1382. ResizeBody(
  1383.     DWORD width,
  1384.     DWORD height
  1385.     )
  1386. {
  1387.  
  1388.     /* Create a new bitmap to move the font definition bits into */
  1389.     if (!GetNewMap(width, height))
  1390.         return(FALSE);
  1391.  
  1392.     /* Move the bits in */
  1393.     oldMode = SetStretchBltMode(hNewMemDC, COLORONCOLOR);
  1394.     StretchBlt(hNewMemDC, 0, 0,
  1395.             width << 3, height,         /* New Char. */
  1396.             hMemDC, 0, 0,
  1397.             width << 3, font.PixHeight, /* Old Char. */
  1398.             SRCCOPY);
  1399.     SetStretchBltMode(hNewMemDC, oldMode);
  1400.  
  1401.     UseNewMap();                /* Switch Pointers and release the space */
  1402.  
  1403.     font.ExtLeading = (WORD) Proport(font.ExtLeading, height, font.PixHeight, 999);
  1404.     font.IntLeading = (WORD) Proport(font.IntLeading, height, font.PixHeight, 999);
  1405.     font.Ascent = (WORD) Proport(font.Ascent, height, font.PixHeight, 32);
  1406.     font.VertRes = (WORD) Proport(font.VertRes, height, font.PixHeight, 999);
  1407.     font.Points = (WORD) Proport(font.Points, height, font.PixHeight, 999);
  1408.     font.PixHeight = (WORD) height;            /* Fix misc. header values */
  1409.     font.WidthBytes = (WORD) width;
  1410.  
  1411.     return (TRUE);
  1412. }
  1413.  
  1414.  
  1415. /****************************************************************************
  1416.  * BOOL NewFirstChar(first)
  1417.  *
  1418.  * purpose: redefines first character in font and resizes work bitmap
  1419.  *          accordingly
  1420.  *
  1421.  * params : WORD first : new first character to be defined
  1422.  *
  1423.  * returns: none
  1424.  *
  1425.  * side effects: Work bitmap changes.Some header info (regarding font dimensions
  1426.  *               altered as well
  1427.  ****************************************************************************/
  1428.  
  1429. BOOL
  1430. NewFirstChar(
  1431.     DWORD first
  1432.     )
  1433. {
  1434.     DWORD  width, wDefault;
  1435.     DWORD offset, i;
  1436.     INT dw;
  1437.  
  1438.     if (first > font.FirstChar)         /* Smaller? */
  1439.         {
  1440.         ShrinkFont(first, font.LastChar);
  1441.         font.FirstChar = (BYTE) first;
  1442.         /*return(FALSE);*/
  1443.         return(TRUE);
  1444.         }
  1445.  
  1446.     /* If not smaller we must pad with the default character */
  1447.     wDefault = offsets[font.DefaultChar + 1] - offsets[font.DefaultChar];
  1448.     dw = wDefault * (font.FirstChar - first);           /* Extra width */
  1449.     width = offsets[font.LastChar + 1] + dw;    /* New width (pixels) */
  1450.              // NewFirstChar(): byte width is DWORD align
  1451.     width = CJ_DIB_SCAN(width);
  1452.     if (!GetNewMap(width, font.PixHeight))
  1453.         return(FALSE);           /* New work area */
  1454.  
  1455.     /* Move it in in two parts */
  1456.     /* First move in default characters */
  1457.     offset = 0;
  1458.     for (i = first; i < font.FirstChar; i++)
  1459.         {
  1460.         BitBlt(hNewMemDC, offset, 0,
  1461.                 wDefault, font.PixHeight,
  1462.                 hMemDC, offsets[font.DefaultChar], 0,
  1463.                 SRCCOPY);
  1464.         offsets[i] = offset;
  1465.         offset += wDefault;
  1466.         }
  1467.     /* Now move in the rest */
  1468.     BitBlt(hNewMemDC, offset, 0,
  1469.             offsets[font.LastChar + 1], font.PixHeight,
  1470.             hMemDC, 0, 0,
  1471.             SRCCOPY);
  1472.  
  1473.     UseNewMap();                /* Switch Pointers and release the space */
  1474.  
  1475.     /* Now fix up offsets table */
  1476.     for (i = font.FirstChar; i <= (DWORD)(font.LastChar + 1); i++)
  1477.         offsets[i] = offsets[i] + dw;           /* Shift the rest right */
  1478.     font.WidthBytes = (WORD) width;
  1479.     font.FirstChar = (BYTE) first;
  1480.  
  1481.     return (TRUE);
  1482. }
  1483.  
  1484.  
  1485. /****************************************************************************
  1486.  * ShrinkFont(first, last)
  1487.  *
  1488.  * purpose:  redefine the first and last charcter in the font and shrink
  1489.  *           work bitmap accordingly
  1490.  *
  1491.  * params :  WORD first : new first character to be defined
  1492.  *           WORD last  : new last character  "  "   "
  1493.  *
  1494.  * returns:  none
  1495.  *
  1496.  * side effects: Work bitmap changes.Some header info (regarding font dimensions
  1497.  *               altered as well
  1498.  ****************************************************************************/
  1499.  
  1500. VOID
  1501. ShrinkFont(
  1502.     DWORD first,
  1503.     DWORD last
  1504.     )
  1505. {
  1506.     DWORD width, widthPixels;
  1507.     DWORD i;
  1508.     INT dw;
  1509.  
  1510.     dw = offsets[first] - offsets[font.FirstChar];      /* left shift if any */
  1511.     widthPixels = offsets[last + 1] - offsets[first];   /* Width in pixels */
  1512.              // ShrinkFont(): byte width is DWORD align
  1513.     width = CJ_DIB_SCAN(widthPixels);
  1514.     if (!GetNewMap(width, font.PixHeight))
  1515.         return;           /* New work area.*/
  1516.  
  1517.     /* Now move the font into the reduced space */
  1518.  
  1519.     BitBlt(hNewMemDC, 0, 0,
  1520.             widthPixels, font.PixHeight,
  1521.             hMemDC, offsets[first], 0,
  1522.             SRCCOPY);
  1523.  
  1524.     UseNewMap();                /* Switch Pointers and release the space */
  1525.  
  1526.     if (dw)                             /* Ajust offsets */
  1527.         {
  1528.         for (i = first; i <= last + 1; i++)
  1529.             offsets[i] -= dw;
  1530.         }
  1531.  
  1532.     font.WidthBytes = (WORD) width;
  1533.  
  1534. }
  1535.  
  1536.  
  1537. /****************************************************************************
  1538.  * BOOL NewLastChar(last)
  1539.  *
  1540.  * purpose:  redefines the last character in the font
  1541.  *
  1542.  * params :  WORD last : number of character to be made the last character
  1543.  *
  1544.  * returns:  none
  1545.  *
  1546.  * side effects: Work bitmap changes.Some header info (regarding font dimensions
  1547.  *               altered as well
  1548.  *
  1549.  ****************************************************************************/
  1550.  
  1551. BOOL
  1552. NewLastChar(
  1553.     DWORD last
  1554.     )
  1555. {
  1556.     DWORD  width, wDefault;
  1557.     DWORD offset, i;
  1558.     INT dw;
  1559.  
  1560.     if (last < font.LastChar)           /* Smaller? */
  1561.         {
  1562.         ShrinkFont(font.FirstChar, last);
  1563.         font.LastChar = (BYTE) last;
  1564.         return(FALSE);
  1565.         }
  1566.  
  1567.     /* If not smaller we must pad with the default character */
  1568.     wDefault = offsets[font.DefaultChar + 1] - offsets[font.DefaultChar];
  1569.     dw = wDefault * (last - font.LastChar);             /* Extra width */
  1570.     offset = offsets[font.LastChar + 1];        /* Current end */
  1571.     width = offset + dw;                        /* New width (pixels) */
  1572.              // NewLastChar(): byte width is DWORD align
  1573.     width = CJ_DIB_SCAN(width);
  1574.     if (!GetNewMap(width, font.PixHeight))
  1575.         return(FALSE);           /* New work area */
  1576.  
  1577.     /* Move it in in two parts */
  1578.     /* First move in the existing font */
  1579.     BitBlt(hNewMemDC, 0, 0,
  1580.             offset, font.PixHeight,
  1581.             hMemDC, 0, 0,
  1582.             SRCCOPY);
  1583.     /* Then move in default characters */
  1584.     for (i = font.LastChar + 1; i <= last;)
  1585.         {
  1586.         BitBlt(hNewMemDC, offset, 0,
  1587.                 wDefault, font.PixHeight,
  1588.                 hMemDC, offsets[font.DefaultChar], 0,
  1589.                 SRCCOPY);
  1590.         offset += wDefault;
  1591.         offsets[++i] = offset;
  1592.         }
  1593.  
  1594.     UseNewMap();                /* Switch Pointers and release the space */
  1595.  
  1596.     font.WidthBytes = (WORD) width;
  1597.     font.LastChar = (BYTE) last;
  1598.  
  1599.     return (TRUE);
  1600. }
  1601.  
  1602.  
  1603. /****************************************************************************
  1604.  * BOOL CharWidth(iChar, wBox)
  1605.  *
  1606.  * purpose: resizes selected char according to new dimensions. (only for
  1607.  *          variable pitch)
  1608.  *
  1609.  * params : BYTE iChar : character to resize
  1610.  *          WORD wBox  : new width of char in pixels
  1611.  *
  1612.  * returns: none
  1613.  *
  1614.  * side effects: work bitmap pixel values and header info(regarding font
  1615.  *               dimensions) altered
  1616.  *
  1617.  ****************************************************************************/
  1618.  
  1619. BOOL
  1620. CharWidth(
  1621.     BYTE iChar,                             /* Character to change */
  1622.     DWORD wBox                               /* New width */
  1623.     )
  1624. {
  1625.     DWORD  width, nChars;
  1626.     DWORD  w1, w2, i;
  1627.     INT dw;
  1628.  
  1629.     nChars = font.LastChar - font.FirstChar + 1;        /* Character count */
  1630.     dw = wBox - (offsets[iChar + 1] - offsets[iChar]);  /* Width change */
  1631.     width = offsets[font.LastChar + 1] + dw;            /* New width (pixels) */
  1632.              // CharWidth(): byte width is DWORD align
  1633.     width = CJ_DIB_SCAN(width);
  1634.     if (!GetNewMap(width, font.PixHeight))
  1635.         return(FALSE);                   /* New work area */
  1636.  
  1637.     /* Move it in in two parts */
  1638.     /* First move up to and including iChar */
  1639.     w1 = offsets[iChar + 1];            /* Width (in pixels) to move */
  1640.     BitBlt(hNewMemDC, 0, 0,
  1641.             w1 + dw, font.PixHeight,
  1642.             hMemDC, 0, 0,
  1643.             SRCCOPY);
  1644.     /* Now move in the rest */
  1645.     if (iChar < (BYTE) font.LastChar)        /* Part to right of elision */
  1646.         {
  1647.         w2 = offsets[font.LastChar + 1] - offsets[iChar + 1];
  1648.         BitBlt(hNewMemDC, offsets[iChar] + wBox, 0,
  1649.                 w2, font.PixHeight,
  1650.                 hMemDC, offsets[iChar + 1], 0,
  1651.                 SRCCOPY);
  1652.         }
  1653.  
  1654.     UseNewMap();                /* Switch Pointers and release the space */
  1655.  
  1656.     /* Now fix up offsets table */
  1657.     for (i = iChar + 1;                         /* Where changes start */
  1658.         i <= (DWORD)(font.LastChar + 1); i++)            /* Ajust offsets */
  1659.         offsets[i] = offsets[i] + dw;           /*  .. by adding dw */
  1660.     font.WidthBytes = (WORD) width;
  1661.     NewAverage();
  1662.  
  1663.     return (TRUE);
  1664. }
  1665.  
  1666. /****************************************************************************
  1667.  * BoxToClipboard(ptA, width, height)
  1668.  *
  1669.  * purpose: write char (or part of it) to clipboard
  1670.  *
  1671.  * params : POINT ptA    : upper left coordinate
  1672.  *          DWORD width  : width of char in pixels
  1673.  *          DWORD height : height of char in pixels
  1674.  * returns: none
  1675.  *
  1676.  * side effects: none
  1677.  *
  1678.  ****************************************************************************/
  1679. VOID
  1680. BoxToClipboard(
  1681.     POINT ptA,                               /* Upper left point */
  1682.     DWORD width,
  1683.     DWORD height                      /* Size */
  1684.     )
  1685. {
  1686.     HDC hDC;
  1687.     DWORD x, y;
  1688.  
  1689.     hDC = GetDC(hFont);                         /* DC to be compatible with */
  1690.     hNewBitmap = CreateBitmap(
  1691.                     width, height,
  1692.                     1, 1, (LPBYTE)NULL);
  1693.     hNewMemDC = CreateCompatibleDC(hDC);                /* Create a DC */
  1694.     SelectObject(hNewMemDC, hNewBitmap);                /* Relate them */
  1695.     ReleaseDC(hFont, hDC);                      /* Done with font DC */
  1696.  
  1697.     for (x = 0; x < width; x++)
  1698.         for (y = 0; y < height; y++)
  1699.             SetPixel(hNewMemDC, x, y, matBox[x + ptA.x][y + ptA.y] == TRUE ?
  1700.             BLACK : WHITE);
  1701.  
  1702.     /* Now wake up Clipboard and empty it */
  1703.     if (!OpenClipboard(hFont))
  1704.         ErrorBox(hBox, vszCannotOpenClip); // , vszCopyingToClip);
  1705.     else        /* Ok: We got the Clipboard */
  1706.         {
  1707.         EmptyClipboard();
  1708.         SetClipboardData(CF_BITMAP, hNewBitmap);        /* Tell Clipboard */
  1709.         }
  1710.  
  1711.     /* Tidy things up */
  1712.     CloseClipboard();
  1713.     DeleteDC(hNewMemDC);
  1714. }
  1715.  
  1716.  
  1717. /****************************************************************************
  1718.  * WORD ClipboardToBox(ptA, width, height, fFit)
  1719.  *
  1720.  * purpose: copies char (or part of char ) from clipboard to work bitmap
  1721.  *          stretching it if need be
  1722.  *
  1723.  * params : PIONT ptA    : upper left coordinate
  1724.  *          DWORD width  : width of char in pixels
  1725.  *          DWORD height : height of char in pixels
  1726.  *          BOOL fFit   : flag to indicate if default width is to be used
  1727.  * returns: none
  1728.  *
  1729.  * side effects: pixel values of bitmap may change for char
  1730.  *
  1731.  ****************************************************************************/
  1732.  
  1733. DWORD
  1734. ClipboardToBox(
  1735.     POINT ptA,                               /* Upper left point */
  1736.     DWORD width,
  1737.     DWORD height,                     /* Size */
  1738.     BOOL fFit                               /* Use default width if TRUE */
  1739.     )
  1740. {
  1741.     BITMAP bitmap;
  1742.     HDC hDC;
  1743.     DWORD x, y;
  1744.     HANDLE hT;
  1745.  
  1746.     if (!OpenClipboard(hFont)) {
  1747.         ErrorBox(hBox, vszCannotOpenClip);
  1748.         return 0;
  1749.     }
  1750.     hNewBitmap = GetClipboardData(CF_BITMAP);
  1751.  
  1752.     /* Check if we got something like a character */
  1753.     if (GetObject(hNewBitmap, sizeof(BITMAP), (LPSTR)&bitmap) != sizeof(BITMAP))
  1754.         {   /* What did we get */
  1755.         ErrorBox(hBox, vszErrorClip);
  1756.         CloseClipboard();
  1757.         return 0;
  1758.     }
  1759.  
  1760.  
  1761.     if (fFit && ((WORD)bitmap.bmWidth <= font.MaxWidth))
  1762.         width = bitmap.bmWidth;
  1763.  
  1764.     hDC = GetDC(hFont);                         /* DC to be compatible with */
  1765.     hBoxBitmap = CreateBitmap(
  1766.                     width, height,
  1767.                     1, 1, (LPBYTE)NULL);
  1768.     hBoxMemDC = CreateCompatibleDC(hDC);                /* Create a DC */
  1769.     hT = SelectObject(hBoxMemDC, hBoxBitmap);           /* Relate them */
  1770.     if (hT == NULL || hDC == NULL || hBoxBitmap == NULL || hBoxMemDC == NULL) {
  1771.         ErrorBox(hBox, vszErrorClip);
  1772.     CloseClipboard();
  1773.     DeleteDC(hBoxMemDC);
  1774.     DeleteObject(hBoxBitmap);
  1775.         return 0;
  1776.     }
  1777.  
  1778.     /* Get a DC to relate to the Bitmap we just got */
  1779.     hNewMemDC = CreateCompatibleDC(hDC);                /* Create a DC */
  1780.     hT = SelectObject(hNewMemDC, hNewBitmap);           /* Relate them */
  1781.     ReleaseDC(hFont, hDC);                      /* Done with font DC */
  1782.     if (hT == NULL || hNewMemDC == NULL) {
  1783.         ErrorBox(hBox, vszErrorClip);
  1784.     CloseClipboard();
  1785.     DeleteDC(hNewMemDC);
  1786.     DeleteDC(hBoxMemDC);
  1787.     DeleteObject(hBoxBitmap);
  1788.         return 0;
  1789.     }
  1790.  
  1791.     /* Now StretchBlt whatever was on the clipboard into the character */
  1792.     oldMode = SetStretchBltMode(hBoxMemDC, COLORONCOLOR);
  1793.     fFit = StretchBlt(hBoxMemDC, 0, 0, width, height,
  1794.                 hNewMemDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);
  1795.     if (!fFit || !oldMode) {
  1796.         ErrorBox(hBox, vszErrorClip);
  1797.     CloseClipboard();
  1798.     DeleteDC(hNewMemDC);
  1799.     DeleteDC(hBoxMemDC);
  1800.     DeleteObject(hBoxBitmap);
  1801.         return 0;
  1802.     }
  1803.     (void)SetStretchBltMode(hBoxMemDC, oldMode);
  1804.     for (x = 0; x < width; x++)
  1805.         for (y = 0; y < height; y++)
  1806.             matBox[x + ptA.x] [y + ptA.y] = (CHAR)(GetPixel(hBoxMemDC, x, y) ?
  1807.                 0 : 1);
  1808.     /* Tidy things up */
  1809.     DeleteDC(hNewMemDC);
  1810.     DeleteDC(hBoxMemDC);
  1811.     DeleteObject(hBoxBitmap);
  1812.     CloseClipboard();
  1813.     return(width);
  1814. }
  1815.  
  1816.  
  1817. /****************************************************************************
  1818.  * ToClipboard(iChar, width, height)
  1819.  *
  1820.  * purpose: write char in edit box to clipboard
  1821.  *
  1822.  * params : BYTE iChar  : number of char to be copied to clipboard
  1823.  *          DWORD width  : width of char in pixels
  1824.  *          DWORD height : height of char in pixels
  1825.  *
  1826.  * returns: none
  1827.  *
  1828.  * side effects: none
  1829.  *
  1830.  ****************************************************************************/
  1831.  
  1832. VOID
  1833. ToClipboard(
  1834.     BYTE iChar,
  1835.     DWORD width,             /* Here in Pixels */
  1836.     DWORD height             /* Also in Pixels */
  1837.     )
  1838. {
  1839.     HDC hDC;
  1840.  
  1841.     hDC = GetDC(hFont);                         /* DC to be compatible with */
  1842.     hNewBitmap = CreateBitmap(
  1843.                     width,                      /* Width of font in pixels */
  1844.                     height,
  1845.                     1, 1, (LPBYTE)NULL);
  1846.     hNewMemDC = CreateCompatibleDC(hDC);                /* Create a DC */
  1847.     SelectObject(hNewMemDC, hNewBitmap);                /* Relate them */
  1848.     ReleaseDC(hFont, hDC);                      /* Done with font DC */
  1849.  
  1850.     BitBlt(hNewMemDC, 0, 0, width, height,      /* Move Character in */
  1851.             hMemDC, offsets[iChar], 0, NOTSRCCOPY);
  1852.  
  1853.     /* Now wake up Clipboard and empty it */
  1854.     if (!OpenClipboard(hFont))
  1855.         ErrorBox(hBox, vszCannotOpenClip); // , vszCopyingToClip);
  1856.     else        /* Ok: We got the Clipboard */
  1857.         {
  1858.         EmptyClipboard();
  1859.         SetClipboardData(CF_BITMAP, hNewBitmap);        /* Tell Clipboard */
  1860.         }
  1861.  
  1862.     /* Tidy things up */
  1863.     CloseClipboard();
  1864.     DeleteDC(hNewMemDC);
  1865. }
  1866.  
  1867.  
  1868. /****************************************************************************
  1869.  * GetNewMap(width, height)
  1870.  *
  1871.  * purpose: create new bitmap of the given width and height.
  1872.  *
  1873.  * params : WORD width  : width of bitmap in pixels
  1874.  *          WORD height : height of bitmap in pixels
  1875.  *
  1876.  * returns: TRUE if successful, FALSE otherwise
  1877.  *
  1878.  * side effects: Handle and DC values of new DC assigned
  1879.  *
  1880.  ****************************************************************************/
  1881.  
  1882. BOOL
  1883. GetNewMap(
  1884.     DWORD width,
  1885.     DWORD height              /* New size */
  1886.     )
  1887. {
  1888.     HDC hDC;
  1889.  
  1890.     if (height==0) /* Check if something stupid is happening */
  1891.         height=font.PixHeight; /* Fix it */
  1892.  
  1893.     /* Put up an houglass ... this may take a while */
  1894.     if (!hHourGlass)
  1895.         hHourGlass = LoadCursor(NULL, IDC_WAIT);        /* Get Hourglass */
  1896.     hOldCursor = SetCursor(hHourGlass);         /* Show hourglass */
  1897.  
  1898.     /* Create a new bitmap to move the font definition bits into */
  1899.     hDC = GetDC(hFont);                         /* DC to be compatible with */
  1900.     hNewBitmap = CreateBitmap(
  1901.                     width << 3,                 /* Width of font in pixels */
  1902.                     height,
  1903.                     1, 1, (LPBYTE)NULL);
  1904.     if (!hNewBitmap)
  1905.         {
  1906.         ErrorBox(hBox, vszNotEnoughMem); // , vszAllocatingSpace);
  1907.         ReleaseDC(hFont, hDC);    /* bug# 2380 */
  1908.         return FALSE;
  1909.         }
  1910.  
  1911.     hNewMemDC = CreateCompatibleDC(hDC);                /* Create a DC */
  1912.     SelectObject(hNewMemDC, hNewBitmap);                /* Relate them */
  1913.     ReleaseDC(hFont, hDC);                      /* Done with font DC */
  1914.     PatBlt(hNewMemDC, 0, 0, width << 3, height, BLACKNESS);     /* Clear it */
  1915.     return TRUE;
  1916. }
  1917.  
  1918.  
  1919. /****************************************************************************
  1920.  * UseNewMap()
  1921.  *
  1922.  * params : none
  1923.  *
  1924.  * purpose: discard old bitmap and replace it with new one
  1925.  *
  1926.  * returns: none
  1927.  *
  1928.  * side effects: Handle to old bitmap and handle to old bitmap DC replaced
  1929.  *               by those of new bitmap respectively
  1930.  *
  1931.  ****************************************************************************/
  1932.  
  1933. VOID
  1934. UseNewMap(
  1935.     VOID
  1936.     )
  1937. {
  1938.     DeleteDC(hMemDC);
  1939.     DeleteObject(hBitmap);              /* Release old space */
  1940.     hBitmap = hNewBitmap;
  1941.     hMemDC = hNewMemDC;              /* Release old space */
  1942.     SetCursor(hOldCursor);              /* Restore regular cursor */
  1943. }
  1944.  
  1945.  
  1946.  
  1947. VOID
  1948. DeleteGlobalBitmap(
  1949.     VOID
  1950.     )
  1951. {
  1952.     if (hMemDC)
  1953.         DeleteDC(hMemDC);
  1954.     if (hBitmap)
  1955.         DeleteObject(hBitmap);
  1956. }
  1957.  
  1958.  
  1959. DWORD
  1960. Proport(
  1961.     DWORD value,
  1962.     DWORD top,
  1963.     DWORD bottom,
  1964.     DWORD limit
  1965.     )
  1966.     /* Reproportion a value by the ratio top/bottom to the nearest integer
  1967.      * and make sure we are still in range */
  1968. {
  1969.     return min(limit, (DWORD)((1 + 2 * value * top) / (2 * bottom)));
  1970. }
  1971.