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

  1. /*
  2.  * prop8.c
  3.  * Copyright (C) 1998-2001 A.J. van Os; Released under GPL
  4.  *
  5.  * Description:
  6.  * Read the property information from a MS Word 8, 9 or 10 file
  7.  *
  8.  * Word 8 is better known as Word 97
  9.  * Word 9 is better known as Word 2000
  10.  * Word 10 is better known as Word 2002 or as Word XP
  11.  */
  12.  
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include "antiword.h"
  16.  
  17.  
  18. /*
  19.  * iGet8InfoLength - the length of the information for Word 8/9/10 files
  20.  */
  21. static int
  22. iGet8InfoLength(int iByteNbr, const unsigned char *aucFpage)
  23. {
  24.     int    iTmp, iDel, iAdd;
  25.     unsigned short    usOpCode;
  26.  
  27.     usOpCode = usGetWord(iByteNbr, aucFpage);
  28.  
  29.     switch (usOpCode & 0xe000) {
  30.     case 0x0000: case 0x2000:
  31.         return 3;
  32.     case 0x4000: case 0x8000: case 0xa000:
  33.         return 4;
  34.     case 0xe000:
  35.         return 5;
  36.     case 0x6000:
  37.         return 6;
  38.     case 0xc000:
  39.         iTmp = (int)ucGetByte(iByteNbr + 2, aucFpage);
  40.         if (usOpCode == 0xc615 && iTmp == 255) {
  41.             iDel = (int)ucGetByte(iByteNbr + 3, aucFpage);
  42.             iAdd = (int)ucGetByte(
  43.                     iByteNbr + 4 + iDel * 4, aucFpage);
  44.             iTmp = 2 + iDel * 4 + iAdd * 3;
  45.         }
  46.         return 3 + iTmp;
  47.     default:
  48.         DBG_HEX(usOpCode);
  49.         DBG_FIXME();
  50.         return 1;
  51.     }
  52. } /* end of iGet8InfoLength */
  53.  
  54. /*
  55.  * Translate the rowinfo to a member of the row_info enumeration
  56.  */
  57. row_info_enum
  58. eGet8RowInfo(int iFodo,
  59.     const unsigned char *aucGrpprl, int iBytes, row_block_type *pRow)
  60. {
  61.     int    iFodoOff, iInfoLen;
  62.     int    iIndex, iSize, iCol;
  63.     int    iPosCurr, iPosPrev;
  64.     BOOL    bFound2416_0, bFound2416_1, bFound2417_0, bFound2417_1;
  65.     BOOL    bFoundd608;
  66.  
  67.     fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL);
  68.  
  69.     iFodoOff = 0;
  70.     bFound2416_0 = FALSE;
  71.     bFound2416_1 = FALSE;
  72.     bFound2417_0 = FALSE;
  73.     bFound2417_1 = FALSE;
  74.     bFoundd608 = FALSE;
  75.     while (iBytes >= iFodoOff + 2) {
  76.         iInfoLen = 0;
  77.         switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
  78.         case 0x2416:    /* fIntable */
  79.             if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
  80.                 bFound2416_1 = TRUE;
  81.             } else {
  82.                 bFound2416_0 = TRUE;
  83.             }
  84.             break;
  85.         case 0x2417:    /* fTtp */
  86.             if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
  87.                 bFound2417_1 = TRUE;
  88.             } else {
  89.                 bFound2417_0 = TRUE;
  90.             }
  91.             break;
  92.         case 0xd608:    /* cDefTable */
  93.             iSize = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
  94.             if (iSize < 6 || iBytes < iFodoOff + 8) {
  95.                 DBG_DEC(iSize);
  96.                 DBG_DEC(iFodoOff);
  97.                 iInfoLen = 2;
  98.                 break;
  99.             }
  100.             iCol = (int)ucGetByte(iFodo + iFodoOff + 4, aucGrpprl);
  101.             if (iCol < 1 ||
  102.                 iBytes < iFodoOff + 4 + (iCol + 1) * 2) {
  103.                 DBG_DEC(iCol);
  104.                 DBG_DEC(iFodoOff);
  105.                 iInfoLen = 2;
  106.                 break;
  107.             }
  108.             if (iCol >= (int)elementsof(pRow->asColumnWidth)) {
  109.                 werr(1, "The number of columns is corrupt");
  110.             }
  111.             pRow->ucNumberOfColumns = (unsigned char)iCol;
  112.             pRow->iColumnWidthSum = 0;
  113.             iPosPrev = (int)(short)usGetWord(
  114.                     iFodo + iFodoOff + 5,
  115.                     aucGrpprl);
  116.             for (iIndex = 0; iIndex < iCol; iIndex++) {
  117.                 iPosCurr = (int)(short)usGetWord(
  118.                     iFodo + iFodoOff + 7 + iIndex * 2,
  119.                     aucGrpprl);
  120.                 pRow->asColumnWidth[iIndex] =
  121.                         (short)(iPosCurr - iPosPrev);
  122.                 pRow->iColumnWidthSum +=
  123.                     pRow->asColumnWidth[iIndex];
  124.                 iPosPrev = iPosCurr;
  125.             }
  126.             bFoundd608 = TRUE;
  127.             break;
  128.         default:
  129.             break;
  130.         }
  131.         if (iInfoLen <= 0) {
  132.             iInfoLen =
  133.                 iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
  134.             fail(iInfoLen <= 0);
  135.         }
  136.         iFodoOff += iInfoLen;
  137.     }
  138.     if (bFound2416_1 && bFound2417_1 && bFoundd608) {
  139.         return found_end_of_row;
  140.     }
  141.     if (bFound2416_0 && bFound2417_0 && !bFoundd608) {
  142.         return found_not_end_of_row;
  143.     }
  144.     if (bFound2416_1) {
  145.         return found_a_cell;
  146.     }
  147.     if (bFound2416_0) {
  148.         return found_not_a_cell;
  149.     }
  150.     return found_nothing;
  151. } /* end of eGet8RowInfo */
  152.  
  153. /*
  154.  * Fill the style information block with information
  155.  * from a Word 8/9/10 file.
  156.  * Returns TRUE when successful, otherwise FALSE
  157.  */
  158. static BOOL
  159. bGet8StyleInfo(int iFodo, const unsigned char *aucFpage,
  160.         style_block_type *pStyle)
  161. {
  162.     int    iBytes, iFodoOff, iInfoLen;
  163.     int    iTmp, iDel, iAdd;
  164.     short    sTmp;
  165.  
  166.     fail(iFodo <= 0 || aucFpage == NULL || pStyle == NULL);
  167.  
  168.     iBytes = 2 * (int)ucGetByte(iFodo, aucFpage);
  169.     iFodoOff = 3;
  170.     if (iBytes == 0) {
  171.         iFodo++;
  172.         iBytes = 2 * (int)ucGetByte(iFodo, aucFpage);
  173.     }
  174.     NO_DBG_DEC(iBytes);
  175.     if (iBytes < 2) {
  176.         return FALSE;
  177.     }
  178.     (void)memset(pStyle, 0, sizeof(*pStyle));
  179.     sTmp = (short)usGetWord(iFodo + 1, aucFpage);
  180.     if (sTmp >= 0 && sTmp <= (short)UCHAR_MAX) {
  181.         pStyle->ucStyle = (unsigned char)sTmp;
  182.     }
  183.     NO_DBG_DEC(pStyle->ucStyle);
  184.     while (iBytes >= iFodoOff + 2) {
  185.         iInfoLen = 0;
  186.         switch (usGetWord(iFodo + iFodoOff, aucFpage)) {
  187.         case 0x2403:    /* jc */
  188.             pStyle->ucAlignment = ucGetByte(
  189.                     iFodo + iFodoOff + 2, aucFpage);
  190.             break;
  191.         case 0x260a:    /* ilvl */
  192.             pStyle->bInList = TRUE;
  193.             pStyle->ucListLevel =
  194.                 ucGetByte(iFodo + iFodoOff + 2, aucFpage);
  195.             NO_DBG_DEC(pStyle->ucListLevel);
  196.             break;
  197.         case 0x4600:    /* istd */
  198.             sTmp = (short)usGetWord(iFodo + iFodoOff + 2, aucFpage);
  199.             NO_DBG_DEC(sTmp);
  200.             NO_DBG_DEC(pStyle->ucStyle);
  201.             break;
  202.         case 0x460b:    /* ilfo */
  203.             NO_DBG_DEC(usGetWord(iFodo + iFodoOff + 2, aucFpage));
  204.             break;
  205.         case 0x4610: /* Nest dxaLeft */
  206.             sTmp = (short)usGetWord(iFodo + iFodoOff + 2, aucFpage);
  207.             pStyle->sLeftIndent += sTmp;
  208.             if (pStyle->sLeftIndent < 0) {
  209.                 pStyle->sLeftIndent = 0;
  210.             }
  211.             DBG_DEC(sTmp);
  212.             DBG_DEC(pStyle->sLeftIndent);
  213.             break;
  214.         case 0x6c0d:    /* ChgTabsPapx */
  215.             iTmp = (int)ucGetByte(iFodo + iFodoOff + 2, aucFpage);
  216.             if (iTmp < 2) {
  217.                 iInfoLen = 1;
  218.                 break;
  219.             }
  220.             DBG_DEC(iTmp);
  221.             iDel = (int)ucGetByte(iFodo + iFodoOff + 3, aucFpage);
  222.             if (iTmp < 2 + 2 * iDel) {
  223.                 iInfoLen = 1;
  224.                 break;
  225.             }
  226.             DBG_DEC(iDel);
  227.             iAdd = (int)ucGetByte(
  228.                 iFodo + iFodoOff + 4 + 2 * iDel, aucFpage);
  229.             if (iTmp < 2 + 2 * iDel + 2 * iAdd) {
  230.                 iInfoLen = 1;
  231.                 break;
  232.             }
  233.             DBG_DEC(iAdd);
  234.             break;
  235.         case 0x840e:    /* dxaRight */
  236.             pStyle->sRightIndent = (short)usGetWord(
  237.                     iFodo + iFodoOff + 2, aucFpage);
  238.             NO_DBG_DEC(pStyle->sRightIndent);
  239.             break;
  240.         case 0x840f:    /* dxaLeft */
  241.             pStyle->sLeftIndent = (short)usGetWord(
  242.                     iFodo + iFodoOff + 2, aucFpage);
  243.             NO_DBG_DEC(pStyle->sLeftIndent);
  244.             break;
  245.         case 0xc63e:    /* anld */
  246.             iTmp = (int)ucGetByte(
  247.                     iFodo + iFodoOff + 2, aucFpage);
  248.             if (iTmp < 84) {
  249.                 DBG_DEC(iTmp);
  250.                 break;
  251.             }
  252.             pStyle->ucListType = ucGetByte(
  253.                     iFodo + iFodoOff + 3, aucFpage);
  254.             pStyle->bInList = TRUE;
  255.             pStyle->ucListCharacter = ucGetByte(
  256.                     iFodo + iFodoOff + 23, aucFpage);
  257.             break;
  258.         default:
  259.             break;
  260.         }
  261.         if (iInfoLen <= 0) {
  262.             iInfoLen =
  263.                 iGet8InfoLength(iFodo + iFodoOff, aucFpage);
  264.             fail(iInfoLen <= 0);
  265.         }
  266.         iFodoOff += iInfoLen;
  267.     }
  268.     return TRUE;
  269. } /* end of bGet8StyleInfo */
  270.  
  271. /*
  272.  * Build the lists with Paragraph Information for Word 8/9/10 files
  273.  */
  274. void
  275. vGet8PapInfo(FILE *pFile, const pps_info_type *pPPS,
  276.     const long *alBBD, size_t tBBDLen, const long *alSBD, size_t tSBDLen,
  277.     const unsigned char *aucHeader)
  278. {
  279.     row_block_type        tRow;
  280.     style_block_type    tStyle;
  281.     long        *alParfPage;
  282.     const long    *alBlockDepot;
  283.     unsigned char    *aucBuffer;
  284.     long    lParmOffset, lParmOffsetFirst, lParmOffsetLast;
  285.     long    lBeginParfInfo, lTableSize, lTableStartBlock;
  286.     size_t    tParfInfoLen, tBlockDepotLen;
  287.     size_t    tBlockSize, tOffset, tSize, tLen;
  288.     int    iIndex, iIndex2, iRun, iFodo, iLen;
  289.     row_info_enum    eRowInfo;
  290.     unsigned short    usDocStatus;
  291.     unsigned char    aucFpage[BIG_BLOCK_SIZE];
  292.  
  293.     fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
  294.     fail(alBBD == NULL || alSBD == NULL);
  295.  
  296.     lBeginParfInfo = (long)ulGetLong(0x102, aucHeader); /* fcPlcfbtePapx */
  297.     NO_DBG_HEX(lBeginParfInfo);
  298.     tParfInfoLen = (size_t)ulGetLong(0x106, aucHeader); /* lcbPlcfbtePapx */
  299.     NO_DBG_DEC(tParfInfoLen);
  300.     if (tParfInfoLen < 4) {
  301.         DBG_DEC(tParfInfoLen);
  302.         return;
  303.     }
  304.  
  305.     /* Use 0Table or 1Table? */
  306.     usDocStatus = usGetWord(0x0a, aucHeader);
  307.     if (usDocStatus & BIT(9)) {
  308.         lTableStartBlock = pPPS->t1Table.lSb;
  309.         lTableSize = pPPS->t1Table.lSize;
  310.     } else {
  311.         lTableStartBlock = pPPS->t0Table.lSb;
  312.         lTableSize = pPPS->t0Table.lSize;
  313.     }
  314.     DBG_DEC(lTableStartBlock);
  315.     if (lTableStartBlock < 0) {
  316.         DBG_DEC(lTableStartBlock);
  317.         DBG_MSG("No paragraph information");
  318.         return;
  319.     }
  320.     DBG_HEX(lTableSize);
  321.     if (lTableSize < MIN_SIZE_FOR_BBD_USE) {
  322.           /* Use the Small Block Depot */
  323.         alBlockDepot = alSBD;
  324.         tBlockDepotLen = tSBDLen;
  325.         tBlockSize = SMALL_BLOCK_SIZE;
  326.     } else {
  327.           /* Use the Big Block Depot */
  328.         alBlockDepot = alBBD;
  329.         tBlockDepotLen = tBBDLen;
  330.         tBlockSize = BIG_BLOCK_SIZE;
  331.     }
  332.     aucBuffer = xmalloc(tParfInfoLen);
  333.     if (!bReadBuffer(pFile, lTableStartBlock,
  334.             alBlockDepot, tBlockDepotLen, tBlockSize,
  335.             aucBuffer, lBeginParfInfo, tParfInfoLen)) {
  336.         aucBuffer = xfree(aucBuffer);
  337.         return;
  338.     }
  339.     NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen);
  340.  
  341.     tLen = (tParfInfoLen / 4 - 1) / 2;
  342.     tSize = tLen * sizeof(long);
  343.     alParfPage = xmalloc(tSize);
  344.     for (iIndex = 0, tOffset = (tLen + 1) * 4;
  345.          iIndex < (int)tLen;
  346.          iIndex++, tOffset += 4) {
  347.          alParfPage[iIndex] = (long)ulGetLong(tOffset, aucBuffer);
  348.          NO_DBG_DEC(alParfPage[iIndex]);
  349.     }
  350.     DBG_HEX(ulGetLong(0, aucBuffer));
  351.     aucBuffer = xfree(aucBuffer);
  352.     aucBuffer = NULL;
  353.     NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
  354.  
  355.     (void)memset(&tStyle, 0, sizeof(tStyle));
  356.     (void)memset(&tRow, 0, sizeof(tRow));
  357.     lParmOffsetFirst = -1;
  358.     for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
  359.         fail(alParfPage[iIndex] > LONG_MAX / BIG_BLOCK_SIZE);
  360.         if (!bReadBuffer(pFile, pPPS->tWordDocument.lSb,
  361.                 alBBD, tBBDLen, BIG_BLOCK_SIZE,
  362.                 aucFpage,
  363.                 alParfPage[iIndex] * BIG_BLOCK_SIZE,
  364.                 BIG_BLOCK_SIZE)) {
  365.             break;
  366.         }
  367.         NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
  368.         iRun = (int)ucGetByte(0x1ff, aucFpage);
  369.         NO_DBG_DEC(iRun);
  370.         for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
  371.             NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage));
  372.             iFodo = 2 * (int)ucGetByte(
  373.                 (iRun + 1) * 4 + iIndex2 * 13, aucFpage);
  374.             if (iFodo <= 0) {
  375.                 continue;
  376.             }
  377.  
  378.             if (bGet8StyleInfo(iFodo, aucFpage, &tStyle)) {
  379.                 lParmOffset = (long)ulGetLong(
  380.                         iIndex2 * 4, aucFpage);
  381.                 NO_DBG_HEX(lParmOffset);
  382.                 tStyle.lFileOffset = lTextOffset2FileOffset(
  383.                             lParmOffset);
  384.                 vAdd2StyleInfoList(&tStyle);
  385.                 (void)memset(&tStyle, 0, sizeof(tStyle));
  386.             }
  387.  
  388.             iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
  389.             if (iLen == 0) {
  390.                 iFodo++;
  391.                 iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
  392.             }
  393.             eRowInfo = eGet8RowInfo(iFodo,
  394.                     aucFpage + 3, iLen - 3, &tRow);
  395.             switch (eRowInfo) {
  396.             case found_a_cell:
  397.                 if (lParmOffsetFirst >= 0) {
  398.                     break;
  399.                 }
  400.                 lParmOffsetFirst = (long)ulGetLong(
  401.                         iIndex2 * 4, aucFpage);
  402.                 NO_DBG_HEX(lParmOffsetFirst);
  403.                 tRow.lTextOffsetStart = lParmOffsetFirst;
  404.                 tRow.lFileOffsetStart = lTextOffset2FileOffset(
  405.                             lParmOffsetFirst);
  406.                 DBG_HEX_C(tRow.lFileOffsetStart < 0,
  407.                             lParmOffsetFirst);
  408.                 break;
  409.             case found_end_of_row:
  410.                 lParmOffsetLast = (long)ulGetLong(
  411.                         iIndex2 * 4, aucFpage);
  412.                 NO_DBG_HEX(lParmOffsetLast);
  413.                 tRow.lTextOffsetEnd = lParmOffsetLast;
  414.                 tRow.lFileOffsetEnd = lTextOffset2FileOffset(
  415.                             lParmOffsetLast);
  416.                 DBG_HEX_C(tRow.lFileOffsetEnd < 0,
  417.                             lParmOffsetLast);
  418.                 vAdd2RowInfoList(&tRow);
  419.                 (void)memset(&tRow, 0, sizeof(tRow));
  420.                 lParmOffsetFirst = -1;
  421.                 break;
  422.             case found_nothing:
  423.                 break;
  424.             default:
  425.                 DBG_DEC(eRowInfo);
  426.                 break;
  427.             }
  428.         }
  429.     }
  430.     alParfPage = xfree(alParfPage);
  431. } /* end of vGet8PapInfo */
  432.  
  433. /*
  434.  * Fill the font information block with information
  435.  * from a Word 8/9/10 file.
  436.  * Returns TRUE when successful, otherwise FALSE
  437.  */
  438. static BOOL
  439. bGet8FontInfo(int iFodo, const unsigned char *aucFpage,
  440.         font_block_type *pFont)
  441. {
  442.     int    iBytes, iFodoOff, iInfoLen;
  443.     unsigned short    usTmp;
  444.     short        sTmp;
  445.     unsigned char    ucTmp;
  446.  
  447.     fail(iFodo <= 0 || aucFpage == NULL || pFont == NULL);
  448.  
  449.     iBytes = (int)ucGetByte(iFodo, aucFpage);
  450.     iFodoOff = 1;
  451.     if (iBytes == 0) {
  452.         iFodo++;
  453.         iBytes = 2 * (int)ucGetByte(iFodo, aucFpage);
  454.     }
  455.     NO_DBG_DEC(iBytes);
  456.     if (iBytes < 2) {
  457.         return FALSE;
  458.     }
  459.     (void)memset(pFont, 0, sizeof(*pFont));
  460.     pFont->sFontsize = DEFAULT_FONT_SIZE;
  461.     while (iBytes >= iFodoOff + 2) {
  462.         switch (usGetWord(iFodo + iFodoOff, aucFpage)) {
  463.         case 0x0835:    /* fBold */
  464.             ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucFpage);
  465.             switch (ucTmp) {
  466.             case   0:    /* Unset */
  467.                 pFont->ucFontstyle &= ~FONT_BOLD;
  468.                 break;
  469.             case   1:    /* Set */
  470.                 pFont->ucFontstyle |= FONT_BOLD;
  471.                 break;
  472.             case 128:    /* Unchanged */
  473.                 break;
  474.             case 129:    /* Negation */
  475.                 pFont->ucFontstyle ^= FONT_BOLD;
  476.                 break;
  477.             default:
  478.                 DBG_DEC(ucTmp);
  479.                 DBG_FIXME();
  480.                 break;
  481.             }
  482.             break;
  483.         case 0x0836:    /* fItalic */
  484.             ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucFpage);
  485.             switch (ucTmp) {
  486.             case   0:    /* Unset */
  487.                 pFont->ucFontstyle &= ~FONT_ITALIC;
  488.                 break;
  489.             case   1:    /* Set */
  490.                 pFont->ucFontstyle |= FONT_ITALIC;
  491.                 break;
  492.             case 128:    /* Unchanged */
  493.                 break;
  494.             case 129:    /* Negation */
  495.                 pFont->ucFontstyle ^= FONT_ITALIC;
  496.                 break;
  497.             default:
  498.                 DBG_DEC(ucTmp);
  499.                 DBG_FIXME();
  500.                 break;
  501.             }
  502.             break;
  503.         case 0x0837:    /* fStrike */
  504.             ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucFpage);
  505.             switch (ucTmp) {
  506.             case   0:    /* Unset */
  507.                 pFont->ucFontstyle &= ~FONT_STRIKE;
  508.                 break;
  509.             case   1:    /* Set */
  510.                 pFont->ucFontstyle |= FONT_STRIKE;
  511.                 break;
  512.             case 128:    /* Unchanged */
  513.                 break;
  514.             case 129:    /* Negation */
  515.                 pFont->ucFontstyle ^= FONT_STRIKE;
  516.                 break;
  517.             default:
  518.                 DBG_DEC(ucTmp);
  519.                 DBG_FIXME();
  520.                 break;
  521.             }
  522.             break;
  523.         case 0x083a:    /* fSmallCaps */
  524.             ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucFpage);
  525.             switch (ucTmp) {
  526.             case   0:    /* Unset */
  527.                 pFont->ucFontstyle &= ~FONT_SMALL_CAPITALS;
  528.                 break;
  529.             case   1:    /* Set */
  530.                 pFont->ucFontstyle |= FONT_SMALL_CAPITALS;
  531.                 break;
  532.             case 128:    /* Unchanged */
  533.                 break;
  534.             case 129:    /* Negation */
  535.                 pFont->ucFontstyle ^= FONT_SMALL_CAPITALS;
  536.                 break;
  537.             default:
  538.                 DBG_DEC(ucTmp);
  539.                 DBG_FIXME();
  540.                 break;
  541.             }
  542.             break;
  543.         case 0x083b:    /* fCaps */
  544.             ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucFpage);
  545.             switch (ucTmp) {
  546.             case   0:    /* Unset */
  547.                 pFont->ucFontstyle &= ~FONT_CAPITALS;
  548.                 break;
  549.             case   1:    /* Set */
  550.                 pFont->ucFontstyle |= FONT_CAPITALS;
  551.                 break;
  552.             case 128:    /* Unchanged */
  553.                 break;
  554.             case 129:    /* Negation */
  555.                 pFont->ucFontstyle ^= FONT_CAPITALS;
  556.                 break;
  557.             default:
  558.                 DBG_DEC(ucTmp);
  559.                 DBG_FIXME();
  560.                 break;
  561.             }
  562.             break;
  563.         case 0x083c:    /* fVanish */
  564.             ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucFpage);
  565.             switch (ucTmp) {
  566.             case   0:    /* Unset */
  567.                 pFont->ucFontstyle &= ~FONT_HIDDEN;
  568.                 break;
  569.             case   1:    /* Set */
  570.                 pFont->ucFontstyle |= FONT_HIDDEN;
  571.                 break;
  572.             case 128:    /* Unchanged */
  573.                 break;
  574.             case 129:    /* Negation */
  575.                 pFont->ucFontstyle ^= FONT_HIDDEN;
  576.                 break;
  577.             default:
  578.                 DBG_DEC(ucTmp);
  579.                 DBG_FIXME();
  580.                 break;
  581.             }
  582.             break;
  583.         case 0x2a32:    /* cDefault */
  584.             pFont->ucFontstyle &= FONT_HIDDEN;
  585.             pFont->ucFontcolor = FONT_COLOR_DEFAULT;
  586.             break;
  587.         case 0x2a3e:    /* cKul */
  588.             ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucFpage);
  589.             if (ucTmp != 0 && ucTmp != 5) {
  590.                 NO_DBG_MSG("Underline text");
  591.                 pFont->ucFontstyle |= FONT_UNDERLINE;
  592.                 if (ucTmp == 6) {
  593.                     DBG_MSG("Bold text");
  594.                     pFont->ucFontstyle |= FONT_BOLD;
  595.                 }
  596.             }
  597.             break;
  598.         case 0x2a42:    /* cIco */
  599.             pFont->ucFontcolor =
  600.                 ucGetByte(iFodo + iFodoOff + 2, aucFpage);
  601.             NO_DBG_DEC(pFont->ucFontcolor);
  602.             break;
  603.         case 0x4a30:    /* cIstd */
  604.             sTmp = (short)usGetWord(iFodo + iFodoOff + 2, aucFpage);
  605.             DBG_DEC(sTmp);
  606.             break;
  607.         case 0x4a43:    /* cHps */
  608.             usTmp = usGetWord(iFodo + iFodoOff + 2, aucFpage);
  609.             if (usTmp > (unsigned short)SHRT_MAX) {
  610.                 pFont->sFontsize = SHRT_MAX;
  611.             } else {
  612.                 pFont->sFontsize = (short)usTmp;
  613.             }
  614.             NO_DBG_DEC(pFont->sFontsize);
  615.             break;
  616.         case 0x4a51:    /* cFtc */
  617.             usTmp = usGetWord(iFodo + iFodoOff + 2, aucFpage);
  618.             if (usTmp <= (unsigned short)UCHAR_MAX) {
  619.                 pFont->ucFontnumber = (unsigned char)usTmp;
  620.             }
  621.             break;
  622.         default:
  623.             break;
  624.         }
  625.         iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucFpage);
  626.         fail(iInfoLen <= 0);
  627.         iFodoOff += iInfoLen;
  628.     }
  629.     return TRUE;
  630. } /* end of bGet8FontInfo */
  631.  
  632. /*
  633.  * Fill the picture information block with information
  634.  * from a Word 8/9/10 file.
  635.  * Returns TRUE when successful, otherwise FALSE
  636.  */
  637. static BOOL
  638. bGet8PicInfo(int iFodo, const unsigned char *aucFpage,
  639.         picture_block_type *pPicture)
  640. {
  641.     int    iBytes, iFodoOff, iInfoLen;
  642.     BOOL    bFound;
  643.     unsigned char    ucTmp;
  644.  
  645.     fail(iFodo <= 0 || aucFpage == NULL || pPicture == NULL);
  646.  
  647.     iBytes = (int)ucGetByte(iFodo, aucFpage);
  648.     iFodoOff = 1;
  649.     if (iBytes == 0) {
  650.         iFodo++;
  651.         iBytes = 2 * (int)ucGetByte(iFodo, aucFpage);
  652.     }
  653.     NO_DBG_DEC(iBytes);
  654.     if (iBytes < 2) {
  655.         return FALSE;
  656.     }
  657.     bFound = FALSE;
  658.     (void)memset(pPicture, 0, sizeof(*pPicture));
  659.     while (iBytes >= iFodoOff + 2) {
  660.         switch (usGetWord(iFodo + iFodoOff, aucFpage)) {
  661.         case 0x0806:
  662.             ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucFpage);
  663.             if (ucTmp == 0x01) {
  664.                 /* Not a picture, but a form field */
  665.                 return FALSE;
  666.             }
  667.             DBG_DEC_C(ucTmp != 0, ucTmp);
  668.             break;
  669.         case 0x080a:
  670.             ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucFpage);
  671.             if (ucTmp == 0x01) {
  672.                 /* Not a picture, but an OLE object */
  673.                 return FALSE;
  674.             }
  675.             DBG_DEC_C(ucTmp != 0, ucTmp);
  676.             break;
  677.         case 0x6a03:
  678.             pPicture->lPictureOffset = (long)ulGetLong(
  679.                     iFodo + iFodoOff + 2, aucFpage);
  680.             bFound = TRUE;
  681.             break;
  682.         default:
  683.             break;
  684.         }
  685.         iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucFpage);
  686.         fail(iInfoLen <= 0);
  687.         iFodoOff += iInfoLen;
  688.     }
  689.     return bFound;
  690. } /* end of bGet8PicInfo */
  691.  
  692. /*
  693.  * Build the lists with Character Information for Word 8/9/10 files
  694.  */
  695. void
  696. vGet8ChrInfo(FILE *pFile, const pps_info_type *pPPS,
  697.     const long *alBBD, size_t tBBDLen, const long *alSBD, size_t tSBDLen,
  698.     const unsigned char *aucHeader)
  699. {
  700.     font_block_type        tFont;
  701.     picture_block_type    tPicture;
  702.     long        *alCharPage;
  703.     const long    *alBlockDepot;
  704.     unsigned char    *aucBuffer;
  705.     long    lFileOffset, lParmOffset, lBeginCharInfo;
  706.     long    lTableSize, lTableStartBlock;
  707.     size_t    tCharInfoLen, tBlockDepotLen;
  708.     size_t    tOffset, tBlockSize, tSize, tLen;
  709.     int    iIndex, iIndex2, iRun, iFodo;
  710.     unsigned short    usDocStatus;
  711.     unsigned char    aucFpage[BIG_BLOCK_SIZE];
  712.  
  713.     fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
  714.     fail(alBBD == NULL || alSBD == NULL);
  715.  
  716.     lBeginCharInfo = (long)ulGetLong(0xfa, aucHeader); /* fcPlcfbteChpx */
  717.     NO_DBG_HEX(lBeginCharInfo);
  718.     tCharInfoLen = (size_t)ulGetLong(0xfe, aucHeader); /* lcbPlcfbteChpx */
  719.     NO_DBG_DEC(tCharInfoLen);
  720.     if (tCharInfoLen < 4) {
  721.         DBG_DEC(tCharInfoLen);
  722.         return;
  723.     }
  724.  
  725.     /* Use 0Table or 1Table? */
  726.     usDocStatus = usGetWord(0x0a, aucHeader);
  727.     if (usDocStatus & BIT(9)) {
  728.         lTableStartBlock = pPPS->t1Table.lSb;
  729.         lTableSize = pPPS->t1Table.lSize;
  730.     } else {
  731.         lTableStartBlock = pPPS->t0Table.lSb;
  732.         lTableSize = pPPS->t0Table.lSize;
  733.     }
  734.     DBG_DEC(lTableStartBlock);
  735.     if (lTableStartBlock < 0) {
  736.         DBG_DEC(lTableStartBlock);
  737.         DBG_MSG("No character information");
  738.         return;
  739.     }
  740.     DBG_HEX(lTableSize);
  741.     if (lTableSize < MIN_SIZE_FOR_BBD_USE) {
  742.           /* Use the Small Block Depot */
  743.         alBlockDepot = alSBD;
  744.         tBlockDepotLen = tSBDLen;
  745.         tBlockSize = SMALL_BLOCK_SIZE;
  746.     } else {
  747.           /* Use the Big Block Depot */
  748.         alBlockDepot = alBBD;
  749.         tBlockDepotLen = tBBDLen;
  750.         tBlockSize = BIG_BLOCK_SIZE;
  751.     }
  752.     aucBuffer = xmalloc(tCharInfoLen);
  753.     if (!bReadBuffer(pFile, lTableStartBlock,
  754.             alBlockDepot, tBlockDepotLen, tBlockSize,
  755.             aucBuffer, lBeginCharInfo, tCharInfoLen)) {
  756.         aucBuffer = xfree(aucBuffer);
  757.         return;
  758.     }
  759.     NO_DBG_PRINT_BLOCK(aucBuffer, tCharInfoLen);
  760.  
  761.     tLen = (tCharInfoLen / 4 - 1) / 2;
  762.     tSize = tLen * sizeof(long);
  763.     alCharPage = xmalloc(tSize);
  764.     for (iIndex = 0, tOffset = (tLen + 1) * 4;
  765.          iIndex < (int)tLen;
  766.          iIndex++, tOffset += 4) {
  767.          alCharPage[iIndex] = (long)ulGetLong(tOffset, aucBuffer);
  768.          NO_DBG_DEC(alCharPage[iIndex]);
  769.     }
  770.     DBG_HEX(ulGetLong(0, aucBuffer));
  771.     aucBuffer = xfree(aucBuffer);
  772.     aucBuffer = NULL;
  773.     NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
  774.  
  775.     (void)memset(&tFont, 0, sizeof(tFont));
  776.     for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
  777.         fail(alCharPage[iIndex] > LONG_MAX / BIG_BLOCK_SIZE);
  778.         if (!bReadBuffer(pFile, pPPS->tWordDocument.lSb,
  779.                 alBBD, tBBDLen, BIG_BLOCK_SIZE,
  780.                 aucFpage,
  781.                 alCharPage[iIndex] * BIG_BLOCK_SIZE,
  782.                 BIG_BLOCK_SIZE)) {
  783.             break;
  784.         }
  785.         NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
  786.         iRun = (int)ucGetByte(0x1ff, aucFpage);
  787.         NO_DBG_DEC(iRun);
  788.         for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
  789.             lParmOffset = (long)ulGetLong(
  790.                         iIndex2 * 4, aucFpage);
  791.             lFileOffset = lTextOffset2FileOffset(lParmOffset);
  792.             iFodo = 2 * (int)ucGetByte(
  793.                 (iRun + 1) * 4 + iIndex2, aucFpage);
  794.             if (iFodo == 0) {
  795.                 NO_DBG_HEX(lParmOffset);
  796.                 vReset2FontInfoList(lFileOffset);
  797.             } else {
  798.                 if (bGet8FontInfo(iFodo, aucFpage, &tFont)) {
  799.                     tFont.lFileOffset = lFileOffset;
  800.                     vAdd2FontInfoList(&tFont);
  801.                 }
  802.             }
  803.             (void)memset(&tFont, 0, sizeof(tFont));
  804.             if (iFodo <= 0) {
  805.                 continue;
  806.             }
  807.             if (bGet8PicInfo(iFodo, aucFpage, &tPicture)) {
  808.                 tPicture.lFileOffset = lFileOffset;
  809.                 tPicture.lFileOffsetPicture =
  810.                     lDataOffset2FileOffset(
  811.                         tPicture.lPictureOffset);
  812.                 vAdd2PicInfoList(&tPicture);
  813.             }
  814.             (void)memset(&tPicture, 0, sizeof(tPicture));
  815.         }
  816.     }
  817.     alCharPage = xfree(alCharPage);
  818. } /* end of vGet8ChrInfo */
  819.