home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / anwor032.zip / antiword.0.32 / fonts.c < prev    next >
C/C++ Source or Header  |  2001-07-21  |  14KB  |  567 lines

  1. /*
  2.  * fonts.c
  3.  * Copyright (C) 1998-2000 A.J. van Os; Released under GPL
  4.  *
  5.  * Description:
  6.  * Functions to deal with fonts (generic)
  7.  */
  8.  
  9. #include <ctype.h>
  10. #include <string.h>
  11. #include "antiword.h"
  12.  
  13. /* Font Translation Table */
  14. static size_t        tFontTableRecords = 0;
  15. static font_table_type    *pFontTable = NULL;
  16.  
  17. /*
  18.  * Find the given font in the font table
  19.  *
  20.  * returns the index into the FontTable, -1 if not found
  21.  */
  22. int
  23. iGetFontByNumber(int iWordFontnumber, unsigned char ucFontstyle)
  24. {
  25.     int    iIndex;
  26.  
  27.     for (iIndex = 0; iIndex < (int)tFontTableRecords; iIndex++) {
  28.         if (iWordFontnumber ==
  29.                 (int)pFontTable[iIndex].ucWordFontnumber &&
  30.             ucFontstyle == pFontTable[iIndex].ucFontstyle &&
  31.             pFontTable[iIndex].szOurFontname[0] != '\0') {
  32.             return iIndex;
  33.         }
  34.     }
  35.     return -1;
  36. } /* end of iGetFontByNumber */
  37.  
  38. /*
  39.  * szGetOurFontName - Get our font name
  40.  *
  41.  * return our font name from the given index, NULL if not found
  42.  */
  43. const char *
  44. szGetOurFontname(int iIndex)
  45. {
  46.     if (iIndex < 0 || iIndex >= (int)tFontTableRecords) {
  47.         return NULL;
  48.     }
  49.     return pFontTable[iIndex].szOurFontname;
  50. } /* end of szGetOurFontname */
  51.  
  52. /*
  53.  * Find the given font in the font table
  54.  *
  55.  * returns the Word font number, -1 if not found
  56.  */
  57. int
  58. iFontname2Fontnumber(const char *szOurFontname, unsigned char ucFontstyle)
  59. {
  60.     int    iIndex;
  61.  
  62.     for (iIndex = 0; iIndex < (int)tFontTableRecords; iIndex++) {
  63.         if (pFontTable[iIndex].ucFontstyle == ucFontstyle &&
  64.             STREQ(pFontTable[iIndex].szOurFontname, szOurFontname)) {
  65.             return (int)pFontTable[iIndex].ucWordFontnumber;
  66.         }
  67.     }
  68.     return -1;
  69. } /* end of iGetFontByName */
  70.  
  71. /*
  72.  * See if the fontname from the Word file matches the fontname from the
  73.  * font translation file.
  74.  * If iBytesPerChar is one than szWord is in ISO-8859-x (Word 6/7),
  75.  * if iBytesPerChar is two than szWord is in Unicode (Word 8/97).
  76.  */
  77. static BOOL
  78. bFontEqual(const char *szWord, const char *szTable, int iBytesPerChar)
  79. {
  80.     const char    *pcTmp1, *pcTmp2;
  81.  
  82.     fail(szWord == NULL || szTable == NULL);
  83.     fail(iBytesPerChar != 1 && iBytesPerChar != 2);
  84.  
  85.     for (pcTmp1 = szWord, pcTmp2 = szTable;
  86.          *pcTmp1 != '\0';
  87.          pcTmp1 += iBytesPerChar, pcTmp2++) {
  88.         if (ulToUpper((unsigned long)*pcTmp1) !=
  89.             ulToUpper((unsigned long)*pcTmp2)) {
  90.             return FALSE;
  91.         }
  92.     }
  93.     return *pcTmp2 == '\0';
  94. } /* end of bFontEqual */
  95.  
  96. /*
  97.  * vCreateFontTable - Create and initialize the internal font table
  98.  */
  99. static void
  100. vCreateFontTable(void)
  101. {
  102.     font_table_type    *pTmp;
  103.     size_t    tSize;
  104.     int    iNbr;
  105.  
  106.     if (tFontTableRecords == 0) {
  107.         pFontTable = NULL;
  108.         return;
  109.     }
  110.  
  111.     /* Create the font table */
  112.     tSize = tFontTableRecords * sizeof(*pFontTable);
  113.     pFontTable = xmalloc(tSize);
  114.     /* Initialize the font table */
  115.     (void)memset(pFontTable, 0, tSize);
  116.     for (iNbr = 0, pTmp = pFontTable;
  117.          pTmp < pFontTable + tFontTableRecords;
  118.          iNbr++, pTmp++) {
  119.         pTmp->ucWordFontnumber = (unsigned char)(iNbr / 4);
  120.         switch (iNbr % 4) {
  121.         case 0:
  122.             pTmp->ucFontstyle = FONT_REGULAR;
  123.             break;
  124.         case 1:
  125.             pTmp->ucFontstyle = FONT_BOLD;
  126.             break;
  127.         case 2:
  128.             pTmp->ucFontstyle = FONT_ITALIC;
  129.             break;
  130.         case 3:
  131.             pTmp->ucFontstyle = FONT_BOLD|FONT_ITALIC;
  132.             break;
  133.         default:
  134.             DBG_DEC(iNbr);
  135.             break;
  136.         }
  137.     }
  138. } /* end of vCreateFontTable */
  139.  
  140. /*
  141.  * vMinimizeFontTable - make the font table as small as possible
  142.  */
  143. static void
  144. vMinimizeFontTable(void)
  145. {
  146.     const font_block_type    *pFont;
  147.     font_table_type        *pTmp;
  148.     int    iUnUsed;
  149.     BOOL    bMustAddTableFont;
  150.  
  151.     NO_DBG_MSG("vMinimizeFontTable");
  152.  
  153.     if (pFontTable == NULL || tFontTableRecords == 0) {
  154.         return;
  155.     }
  156.  
  157. #if 0
  158.     DBG_MSG("Before");
  159.     DBG_DEC(tFontTableRecords);
  160.     for (pTmp = pFontTable;
  161.          pTmp < pFontTable + tFontTableRecords;
  162.          pTmp++) {
  163.         DBG_DEC(pTmp->ucWordFontnumber);
  164.         DBG_HEX(pTmp->ucFontstyle);
  165.         DBG_MSG(pTmp->szWordFontname);
  166.         DBG_MSG(pTmp->szOurFontname);
  167.     }
  168. #endif /* DEBUG */
  169.  
  170.     /* Default font/style is by definition in use */
  171.     pFontTable[0].ucInUse = 1;
  172.  
  173.     /* See which fonts/styles are really being used */
  174.     bMustAddTableFont = TRUE;
  175.     pFont = NULL;
  176.     while((pFont = pGetNextFontInfoListItem(pFont)) != NULL) {
  177.         pTmp = pFontTable + 4 * (int)pFont->ucFontnumber;
  178.         if (bIsBold(pFont->ucFontstyle)) {
  179.             pTmp++;
  180.         }
  181.         if (bIsItalic(pFont->ucFontstyle)) {
  182.             pTmp += 2;
  183.         }
  184.         if (pTmp >= pFontTable + tFontTableRecords) {
  185.             continue;
  186.         }
  187.         if (STREQ(pTmp->szOurFontname, TABLE_FONT)) {
  188.             /* The table font is already present */
  189.             bMustAddTableFont = FALSE;
  190.         }
  191.         pTmp->ucInUse = 1;
  192.     }
  193.  
  194.     /* Remove the unused font entries from the font table */
  195.     iUnUsed = 0;
  196.     for (pTmp = pFontTable;
  197.          pTmp < pFontTable + tFontTableRecords;
  198.          pTmp++) {
  199.         if (pTmp->ucInUse == 0) {
  200.             iUnUsed++;
  201.             continue;
  202.         }
  203.         if (iUnUsed > 0) {
  204.             fail(pTmp - iUnUsed <= pFontTable);
  205.             *(pTmp - iUnUsed) = *pTmp;
  206.         }
  207.     }
  208.     tFontTableRecords -= (size_t)iUnUsed;
  209.     if (bMustAddTableFont) {
  210.         pTmp = pFontTable + tFontTableRecords;
  211.           pTmp->ucWordFontnumber = (pTmp - 1)->ucWordFontnumber + 1;
  212.         pTmp->ucFontstyle = FONT_REGULAR;
  213.         pTmp->ucInUse = 1;
  214.         strcpy(pTmp->szWordFontname, "Extra Table Font");
  215.         strcpy(pTmp->szOurFontname, TABLE_FONT);
  216.         tFontTableRecords++;
  217.         iUnUsed--;
  218.     }
  219.     if (iUnUsed > 0) {
  220.         /* Resize the font table */
  221.         pFontTable = xrealloc(pFontTable,
  222.                 tFontTableRecords * sizeof(*pFontTable));
  223.     }
  224. #if 0
  225.     /* Report the used but untranslated fontnames */
  226.     for (pTmp = pFontTable;
  227.          pTmp < pFontTable + tFontTableRecords;
  228.          pTmp++) {
  229.         if (pTmp->szOurFontname[0] == '\0') {
  230.             DBG_MSG(pTmp->szWordFontname);
  231.             werr(0, "%s is not in the FontNames file",
  232.                 pTmp->szWordFontname);
  233.         }
  234.     }
  235. #endif /* 0 */
  236. #if defined(DEBUG)
  237.     DBG_MSG("After");
  238.     DBG_DEC(tFontTableRecords);
  239.     for (pTmp = pFontTable;
  240.          pTmp < pFontTable + tFontTableRecords;
  241.          pTmp++) {
  242.         DBG_DEC(pTmp->ucWordFontnumber);
  243.         DBG_HEX(pTmp->ucFontstyle);
  244.         DBG_MSG(pTmp->szWordFontname);
  245.         DBG_MSG(pTmp->szOurFontname);
  246.     }
  247. #endif /* DEBUG */
  248. } /* end of vMinimizeFontTable */
  249.  
  250. /*
  251.  * bReadFontFile - read and check a line from the font translation file
  252.  *
  253.  * returns TRUE when a correct line has been read, otherwise FALSE
  254.  */
  255. static BOOL
  256. bReadFontFile(FILE *pFontTableFile, char *szWordFont,
  257.     int *piItalic, int *piBold, char *szOurFont, int *piSpecial)
  258. {
  259.     char    *pcTmp;
  260.     int    iFields;
  261.     char    szLine[81];
  262.  
  263.     fail(szWordFont == NULL || szOurFont == NULL);
  264.     fail(piItalic == NULL || piBold == NULL || piSpecial == NULL);
  265.  
  266.     while (fgets(szLine, (int)sizeof(szLine), pFontTableFile) != NULL) {
  267.         if (szLine[0] == '#' ||
  268.             szLine[0] == '\n' ||
  269.             szLine[0] == '\r') {
  270.             continue;
  271.         }
  272.         iFields = sscanf(szLine, "%[^,],%d,%d,%1s%[^,],%d",
  273.                 szWordFont, piItalic, piBold,
  274.                 &szOurFont[0], &szOurFont[1], piSpecial);
  275.         if (iFields != 6) {
  276.             pcTmp = strchr(szLine, '\r');
  277.             if (pcTmp != NULL) {
  278.                 *pcTmp = '\0';
  279.             }
  280.             pcTmp = strchr(szLine, '\n');
  281.             if (pcTmp != NULL) {
  282.                 *pcTmp = '\0';
  283.             }
  284.             DBG_DEC(iFields);
  285.             werr(0, "Syntax error in: '%s'", szLine);
  286.             continue;
  287.         }
  288.         if (strlen(szWordFont) >=
  289.                     sizeof(pFontTable[0].szWordFontname) ||
  290.             strlen(szOurFont) >=
  291.                     sizeof(pFontTable[0].szOurFontname)) {
  292.             continue;
  293.         }
  294.         /* The current line passed all the tests */
  295.         return TRUE;
  296.     }
  297.     return FALSE;
  298. } /* end of bReadFontFile */
  299.  
  300. /*
  301.  * vCreate6FontTable - create a font table from Word 6/7
  302.  */
  303. void
  304. vCreate6FontTable(FILE *pFile, long lStartBlock,
  305.     const long *alBBD, size_t tBBDLen,
  306.     const unsigned char *aucHeader)
  307. {
  308.     FILE    *pFontTableFile;
  309.     font_table_type    *pTmp;
  310.     char    *szFont, *szAltFont;
  311.     unsigned char    *aucBuffer;
  312.     long    lBeginFontInfo;
  313.     size_t    tFontInfoLen;
  314.     int    iPos, iRecLen, iOffsetAltName;
  315.     int    iBold, iItalic, iSpecial;
  316.     char    szWordFont[81], szOurFont[81];
  317.  
  318.     fail(pFile == NULL || aucHeader == NULL);
  319.     fail(lStartBlock < 0);
  320.     fail(alBBD == NULL);
  321.  
  322.     pFontTableFile = pOpenFontTableFile();
  323.     if (pFontTableFile == NULL) {
  324.         /* No translation table file, no translation table */
  325.         return;
  326.     }
  327.  
  328.     lBeginFontInfo = (long)ulGetLong(0xd0, aucHeader);
  329.     DBG_HEX(lBeginFontInfo);
  330.     tFontInfoLen = (size_t)ulGetLong(0xd4, aucHeader);
  331.     DBG_DEC(tFontInfoLen);
  332.     fail(tFontInfoLen < 9);
  333.  
  334.     aucBuffer = xmalloc(tFontInfoLen);
  335.     if (!bReadBuffer(pFile, lStartBlock,
  336.             alBBD, tBBDLen, BIG_BLOCK_SIZE,
  337.             aucBuffer, lBeginFontInfo, tFontInfoLen)) {
  338.         aucBuffer = xfree(aucBuffer);
  339.         (void)fclose(pFontTableFile);
  340.         return;
  341.     }
  342.     DBG_DEC(usGetWord(0, aucBuffer));
  343.  
  344.     /* Compute the maximum number of entries in the font table */
  345.     tFontTableRecords = 0;
  346.     iPos = 2;
  347.     while (iPos + 6 < (int)tFontInfoLen) {
  348.         iRecLen = (int)ucGetByte(iPos, aucBuffer);
  349.         NO_DBG_DEC(iRecLen);
  350.         iOffsetAltName = (int)ucGetByte(iPos + 5, aucBuffer);
  351.         NO_DBG_MSG(aucBuffer + iPos + 6);
  352.         NO_DBG_MSG_C(iOffsetAltName > 0,
  353.                 aucBuffer + iPos + 6 + iOffsetAltName);
  354.         iPos += iRecLen + 1;
  355.         tFontTableRecords++;
  356.     }
  357.     tFontTableRecords *= 4;    /* Regular, Bold, Italic and Bold/italic */
  358.     tFontTableRecords++;    /* One extra for the table-font */
  359.     vCreateFontTable();
  360.  
  361.     /* Read the font translation file */
  362.     while (bReadFontFile(pFontTableFile, szWordFont,
  363.             &iItalic, &iBold, szOurFont, &iSpecial)) {
  364.         pTmp = pFontTable;
  365.         if (iBold != 0) {
  366.             pTmp++;
  367.         }
  368.         if (iItalic != 0) {
  369.             pTmp += 2;
  370.         }
  371.         iPos = 2;
  372.         while (iPos + 6 < (int)tFontInfoLen) {
  373.             iRecLen = (int)ucGetByte(iPos, aucBuffer);
  374.             szFont = (char *)aucBuffer + iPos + 6;
  375.             iOffsetAltName = (int)ucGetByte(iPos + 5, aucBuffer);
  376.             if (iOffsetAltName <= 0) {
  377.                 szAltFont = NULL;
  378.             } else {
  379.                 szAltFont = szFont + iOffsetAltName;
  380.                 NO_DBG_MSG(szFont);
  381.                 NO_DBG_MSG(szAltFont);
  382.             }
  383.             if (bFontEqual(szFont, szWordFont, 1) ||
  384.                 (szAltFont != NULL &&
  385.                  bFontEqual(szAltFont, szWordFont, 1)) ||
  386.                 (pTmp->szWordFontname[0] == '\0' &&
  387.                  szWordFont[0] == '*' &&
  388.                  szWordFont[1] == '\0')) {
  389.                   strncpy(pTmp->szWordFontname, szFont,
  390.                       sizeof(pTmp->szWordFontname) - 1);
  391.                   pTmp->szWordFontname[sizeof(
  392.                       pTmp->szWordFontname) - 1] = '\0';
  393.                 strcpy(pTmp->szOurFontname, szOurFont);
  394.             }
  395.             pTmp += 4;
  396.             iPos += iRecLen + 1;
  397.         }
  398.     }
  399.     vMinimizeFontTable();
  400.     aucBuffer = xfree(aucBuffer);
  401.     (void)fclose(pFontTableFile);
  402. } /* end of vCreate6FontTable */
  403.  
  404. /*
  405.  * vCreate8FontTable - create a font table from Word 8/97
  406.  */
  407. void
  408. vCreate8FontTable(FILE *pFile, const pps_info_type *pPPS,
  409.     const long *alBBD, size_t tBBDLen, const long *alSBD, size_t tSBDLen,
  410.     const unsigned char *aucHeader)
  411. {
  412.     FILE    *pFontTableFile;
  413.     font_table_type    *pTmp;
  414.     const long    *alBlockDepot;
  415.     char        *szFont, *szAltFont;
  416.     unsigned char    *aucBuffer;
  417.     long    lTableSize, lTableStartBlock, lBeginFontInfo;
  418.     size_t    tFontInfoLen, tBlockDepotLen, tBlockSize;
  419.     int    iPos, iRecLen, iOffsetAltName;
  420.     int    iBold, iItalic, iSpecial;
  421.     unsigned short    usDocStatus;
  422.     char    szWordFont[81], szOurFont[81];
  423.  
  424.     fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
  425.     fail(alBBD == NULL || alSBD == NULL);
  426.  
  427.     pFontTableFile = pOpenFontTableFile();
  428.     if (pFontTableFile == NULL) {
  429.         /* No translation table file, no translation table */
  430.         return;
  431.     }
  432.  
  433.     lBeginFontInfo = (long)ulGetLong(0x112, aucHeader);
  434.     DBG_HEX(lBeginFontInfo);
  435.     tFontInfoLen = (size_t)ulGetLong(0x116, aucHeader);
  436.     DBG_DEC(tFontInfoLen);
  437.     fail(tFontInfoLen < 46);
  438.  
  439.     /* Use 0Table or 1Table? */
  440.     usDocStatus = usGetWord(0x0a, aucHeader);
  441.     if (usDocStatus & BIT(9)) {
  442.         lTableStartBlock = pPPS->t1Table.lSb;
  443.         lTableSize = pPPS->t1Table.lSize;
  444.     } else {
  445.         lTableStartBlock = pPPS->t0Table.lSb;
  446.         lTableSize = pPPS->t0Table.lSize;
  447.     }
  448.     DBG_DEC(lTableStartBlock);
  449.     if (lTableStartBlock < 0) {
  450.         DBG_DEC(lTableStartBlock);
  451.         DBG_MSG("No fontname table");
  452.         return;
  453.     }
  454.     DBG_HEX(lTableSize);
  455.     if (lTableSize < MIN_SIZE_FOR_BBD_USE) {
  456.           /* Use the Small Block Depot */
  457.         alBlockDepot = alSBD;
  458.         tBlockDepotLen = tSBDLen;
  459.         tBlockSize = SMALL_BLOCK_SIZE;
  460.     } else {
  461.           /* Use the Big Block Depot */
  462.         alBlockDepot = alBBD;
  463.         tBlockDepotLen = tBBDLen;
  464.         tBlockSize = BIG_BLOCK_SIZE;
  465.     }
  466.     aucBuffer = xmalloc(tFontInfoLen);
  467.     if (!bReadBuffer(pFile, lTableStartBlock,
  468.             alBlockDepot, tBlockDepotLen, tBlockSize,
  469.             aucBuffer, lBeginFontInfo, tFontInfoLen)) {
  470.         aucBuffer = xfree(aucBuffer);
  471.         (void)fclose(pFontTableFile);
  472.         return;
  473.     }
  474.     NO_DBG_PRINT_BLOCK(aucBuffer, tFontInfoLen);
  475.  
  476.     /* Get the maximum number of entries in the font table */
  477.     tFontTableRecords = (size_t)usGetWord(0, aucBuffer);
  478.     tFontTableRecords *= 4;    /* Regular, Bold, Italic and Bold/italic */
  479.     tFontTableRecords++;    /* One extra for the table-font */
  480.     vCreateFontTable();
  481.  
  482.     /* Read the font translation file */
  483.     while (bReadFontFile(pFontTableFile, szWordFont,
  484.             &iItalic, &iBold, szOurFont, &iSpecial)) {
  485.         pTmp = pFontTable;
  486.         if (iBold != 0) {
  487.             pTmp++;
  488.         }
  489.         if (iItalic != 0) {
  490.             pTmp += 2;
  491.         }
  492.         iPos = 4;
  493.         while (iPos + 40 < (int)tFontInfoLen) {
  494.             iRecLen = (int)ucGetByte(iPos, aucBuffer);
  495.             szFont = (char *)aucBuffer + iPos + 40;
  496.             iOffsetAltName = (int)unilen(szFont);
  497.             if (iPos + 40 + iOffsetAltName + 4 >= iRecLen) {
  498.                 szAltFont = NULL;
  499.             } else {
  500.                 szAltFont = szFont + iOffsetAltName + 2;
  501.                 NO_DBG_UNICODE(szFont);
  502.                 NO_DBG_UNICODE(szAltFont);
  503.             }
  504.             if (bFontEqual(szFont, szWordFont, 2) ||
  505.                 (szAltFont != NULL &&
  506.                  bFontEqual(szAltFont, szWordFont, 2)) ||
  507.                 (pTmp->szWordFontname[0] == '\0' &&
  508.                  szWordFont[0] == '*' &&
  509.                  szWordFont[1] == '\0')) {
  510.                 (void)unincpy(pTmp->szWordFontname, szFont,
  511.                     sizeof(pTmp->szWordFontname) - 1);
  512.                 pTmp->szWordFontname[sizeof(
  513.                     pTmp->szWordFontname) - 1] = '\0';
  514.                 (void)strcpy(pTmp->szOurFontname, szOurFont);
  515.             }
  516.             pTmp += 4;
  517.             iPos += iRecLen + 1;
  518.         }
  519.     }
  520.     vMinimizeFontTable();
  521.     aucBuffer = xfree(aucBuffer);
  522.     (void)fclose(pFontTableFile);
  523. } /* end of vCreate8FontTable */
  524.  
  525. void
  526. vDestroyFontTable(void)
  527. {
  528.     DBG_MSG("vDestroyFontTable");
  529.  
  530.     pFontTable = xfree(pFontTable);
  531.     tFontTableRecords = 0;
  532. } /* end of vDestroyFontTable */
  533.  
  534. /*
  535.  * pGetNextFontTableRecord
  536.  *
  537.  * returns the next record in the table or NULL if there is no next record
  538.  */
  539. const font_table_type *
  540. pGetNextFontTableRecord(const font_table_type *pRecordCurr)
  541. {
  542.     int    iIndexCurr;
  543.  
  544.     if (pRecordCurr == NULL) {
  545.         /* No current record, so start with the first */
  546.         return &pFontTable[0];
  547.     }
  548.  
  549.     iIndexCurr = pRecordCurr - pFontTable;
  550.     if (iIndexCurr + 1 < (int)tFontTableRecords) {
  551.         /* There is a next record */
  552.         return &pFontTable[iIndexCurr + 1];
  553.     }
  554.     return NULL;
  555. } /* end of pGetNextFontTableRecord */
  556.  
  557. /*
  558.  * tGetFontTableLength
  559.  *
  560.  * returns the number of records in the font table
  561.  */
  562. size_t
  563. tGetFontTableLength(void)
  564. {
  565.     return tFontTableRecords;
  566. } /* end of tGetFontTableLength */
  567.