home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / anwor032.zip / antiword.0.32 / findtext.c < prev    next >
C/C++ Source or Header  |  2001-06-11  |  7KB  |  294 lines

  1. /*
  2.  * findtext.c
  3.  * Copyright (C) 1998-2001 A.J. van Os; Released under GPL
  4.  *
  5.  * Description:
  6.  * Find the blocks that contain the text of MS Word files
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include "antiword.h"
  12.  
  13.  
  14. /*
  15.  * bAddTextBlocks - Add the blocks to the text block list
  16.  *
  17.  * Returns TRUE when successful, FALSE if not
  18.  */
  19. BOOL
  20. bAddTextBlocks(long lFirstOffset, long lTotalLength,
  21.     BOOL bUsesUnicode, unsigned short usPropMod,
  22.     long lStartBlock, const long *alBBD, size_t tBBDLen)
  23. {
  24.     text_block_type    tTextBlock;
  25.     long    lTextOffset, lIndex, lToGo, lOffset;
  26.  
  27.     fail(lFirstOffset < 0);
  28.     fail(lStartBlock < 0);
  29.     fail(alBBD == NULL);
  30.  
  31.     NO_DBG_HEX(lFirstOffset);
  32.     NO_DBG_DEC(lTotalLength);
  33.  
  34.     if (bUsesUnicode) {
  35.         /* One character equals two bytes */
  36.         NO_DBG_MSG("Uses Unicode");
  37.         lToGo = lTotalLength * 2;
  38.     } else {
  39.         /* One character equals one byte */
  40.         NO_DBG_MSG("Uses ASCII");
  41.         lToGo = lTotalLength;
  42.     }
  43.  
  44.     lTextOffset = lFirstOffset;
  45.     lOffset = lFirstOffset;
  46.     for (lIndex = lStartBlock;
  47.          lIndex != END_OF_CHAIN && lToGo > 0;
  48.          lIndex = alBBD[lIndex]) {
  49.         if (lIndex < 0 || lIndex >= (long)tBBDLen) {
  50.             werr(1, "The Big Block Depot is corrupt");
  51.         }
  52.         if (lOffset >= BIG_BLOCK_SIZE) {
  53.             lOffset -= BIG_BLOCK_SIZE;
  54.             continue;
  55.         }
  56.         tTextBlock.lFileOffset =
  57.             (lIndex + 1) * BIG_BLOCK_SIZE + lOffset;
  58.         tTextBlock.lTextOffset = lTextOffset;
  59.         tTextBlock.lLength = min(BIG_BLOCK_SIZE - lOffset, lToGo);
  60.         tTextBlock.bUsesUnicode = bUsesUnicode;
  61.         tTextBlock.usPropMod = usPropMod;
  62.         lOffset = 0;
  63.         if (!bAdd2TextBlockList(&tTextBlock)) {
  64.             DBG_HEX(tTextBlock.lFileOffset);
  65.             DBG_HEX(tTextBlock.lTextOffset);
  66.             DBG_DEC(tTextBlock.lLength);
  67.             DBG_DEC(tTextBlock.bUsesUnicode);
  68.             DBG_DEC(tTextBlock.usPropMod);
  69.             return FALSE;
  70.         }
  71.         lTextOffset += tTextBlock.lLength;
  72.         lToGo -= tTextBlock.lLength;
  73.     }
  74.     DBG_DEC_C(lToGo != 0, lToGo);
  75.     return lToGo == 0;
  76. } /* end of bAddTextBlocks */
  77.  
  78. /*
  79.  * bGet6DocumentText - make a list of the text blocks of Word 6/7 files
  80.  *
  81.  * Code for "fast saved" files.
  82.  *
  83.  * Returns TRUE when successful, FALSE if not
  84.  */
  85. BOOL
  86. bGet6DocumentText(FILE *pFile, BOOL bUsesUnicode, long lStartBlock,
  87.     const long *alBBD, size_t tBBDLen, const unsigned char *aucHeader)
  88. {
  89.     unsigned char    *aucBuffer;
  90.     long    lTextOffset, lTotLength, lBeginTextInfo;
  91.     size_t    tTextInfoLen, tOff;
  92.     int    iIndex, iType, iLen, iPieces;
  93.     unsigned short    usPropMod;
  94.  
  95.     DBG_MSG("bGet6DocumentText");
  96.  
  97.     fail(pFile == NULL);
  98.     fail(alBBD == NULL);
  99.     fail(aucHeader == NULL);
  100.  
  101.     lBeginTextInfo = (long)ulGetLong(0x160, aucHeader);    /* fcClx */
  102.     tTextInfoLen = (size_t)ulGetLong(0x164, aucHeader);    /* lcbClx */
  103.     DBG_HEX(lBeginTextInfo);
  104.     DBG_DEC(tTextInfoLen);
  105.  
  106.     aucBuffer = xmalloc(tTextInfoLen);
  107.     if (!bReadBuffer(pFile, lStartBlock,
  108.             alBBD, tBBDLen, BIG_BLOCK_SIZE,
  109.             aucBuffer, lBeginTextInfo, tTextInfoLen)) {
  110.         aucBuffer = xfree(aucBuffer);
  111.         return FALSE;
  112.     }
  113.     NO_DBG_PRINT_BLOCK(aucBuffer, tTextInfoLen);
  114.  
  115.     tOff = 0;
  116.     while (tOff < tTextInfoLen) {
  117.         iType = (int)ucGetByte(tOff, aucBuffer);
  118.         tOff++;
  119.         if (iType == 0) {
  120.             DBG_FIXME();
  121.             tOff++;
  122.             continue;
  123.         }
  124.         if (iType == 1) {
  125.             iLen = (int)usGetWord(tOff, aucBuffer);
  126.             vAdd2PropModList(aucBuffer + tOff);
  127.             tOff += iLen + 2;
  128.             continue;
  129.         }
  130.         if (iType != 2) {
  131.             werr(0, "Unknown type of 'fastsaved' format");
  132.             aucBuffer = xfree(aucBuffer);
  133.             return FALSE;
  134.         }
  135.         /* Type 2 */
  136.         iLen = (int)usGetWord(tOff, aucBuffer);
  137.         NO_DBG_DEC(iLen);
  138.         tOff += 4;
  139.         iPieces = (iLen - 4) / 12;
  140.         DBG_DEC(iPieces);
  141.         for (iIndex = 0; iIndex < iPieces; iIndex++) {
  142.             lTextOffset = (long)ulGetLong(
  143.                 tOff + (iPieces + 1) * 4 + iIndex * 8 + 2,
  144.                 aucBuffer);
  145.             usPropMod = usGetWord(
  146.                 tOff + (iPieces + 1) * 4 + iIndex * 8 + 6,
  147.                 aucBuffer);
  148.             lTotLength = (long)ulGetLong(
  149.                         tOff + (iIndex + 1) * 4,
  150.                         aucBuffer) -
  151.                     (long)ulGetLong(
  152.                         tOff + iIndex * 4,
  153.                         aucBuffer);
  154.             NO_DBG_HEX_C(usPropMod != 0, usPropMod);
  155.             if (!bAddTextBlocks(lTextOffset, lTotLength,
  156.                     bUsesUnicode, usPropMod,
  157.                     lStartBlock,
  158.                     alBBD, tBBDLen)) {
  159.                 aucBuffer = xfree(aucBuffer);
  160.                 return FALSE;
  161.             }
  162.         }
  163.         break;
  164.     }
  165.     aucBuffer = xfree(aucBuffer);
  166.     return TRUE;
  167. } /* end of bGet6DocumentText */
  168.  
  169. /*
  170.  * bGet8DocumentText - make a list of the text blocks of Word 8/97 files
  171.  *
  172.  * Returns TRUE when successful, FALSE if not
  173.  */
  174. BOOL
  175. bGet8DocumentText(FILE *pFile, const pps_info_type *pPPS,
  176.     const long *alBBD, size_t tBBDLen, const long *alSBD, size_t tSBDLen,
  177.     const unsigned char *aucHeader)
  178. {
  179.     const long    *alBlockDepot;
  180.     unsigned char    *aucBuffer;
  181.     long    lTextOffset, lTotLength, lBeginTextInfo, lLen;
  182.     long    lTableStartBlock, lTableSize, lIndex, lPieces;
  183.     size_t    tTextInfoLen, tBlockDepotLen, tBlockSize, tOff;
  184.     int    iType, iLen;
  185.     BOOL    bUsesUnicode;
  186.     unsigned short    usDocStatus, usPropMod;
  187.  
  188.     DBG_MSG("bGet8DocumentText");
  189.  
  190.     fail(pFile == NULL || pPPS == NULL);
  191.     fail(alBBD == NULL || alSBD == NULL);
  192.     fail(aucHeader == NULL);
  193.  
  194.       lBeginTextInfo = (long)ulGetLong(0x1a2, aucHeader);    /* fcClx */
  195.     tTextInfoLen = (size_t)ulGetLong(0x1a6, aucHeader);    /* lcbClx */
  196.     DBG_HEX(lBeginTextInfo);
  197.     DBG_DEC(tTextInfoLen);
  198.  
  199.     /* Use 0Table or 1Table? */
  200.     usDocStatus = usGetWord(0x0a, aucHeader);
  201.     if (usDocStatus & BIT(9)) {
  202.         lTableStartBlock = pPPS->t1Table.lSb;
  203.         lTableSize = pPPS->t1Table.lSize;
  204.     } else {
  205.         lTableStartBlock = pPPS->t0Table.lSb;
  206.         lTableSize = pPPS->t0Table.lSize;
  207.     }
  208.     DBG_DEC(lTableStartBlock);
  209.     if (lTableStartBlock < 0) {
  210.         DBG_DEC(lTableStartBlock);
  211.         return FALSE;
  212.     }
  213.     DBG_HEX(lTableSize);
  214.     if (lTableSize < MIN_SIZE_FOR_BBD_USE) {
  215.           /* Use the Small Block Depot */
  216.         alBlockDepot = alSBD;
  217.         tBlockDepotLen = tSBDLen;
  218.         tBlockSize = SMALL_BLOCK_SIZE;
  219.     } else {
  220.           /* Use the Big Block Depot */
  221.         alBlockDepot = alBBD;
  222.         tBlockDepotLen = tBBDLen;
  223.         tBlockSize = BIG_BLOCK_SIZE;
  224.     }
  225.     aucBuffer = xmalloc(tTextInfoLen);
  226.     if (!bReadBuffer(pFile, lTableStartBlock,
  227.             alBlockDepot, tBlockDepotLen, tBlockSize,
  228.             aucBuffer, lBeginTextInfo, tTextInfoLen)) {
  229.         aucBuffer = xfree(aucBuffer);
  230.         return FALSE;
  231.     }
  232.     NO_DBG_PRINT_BLOCK(aucBuffer, tTextInfoLen);
  233.  
  234.     tOff = 0;
  235.     while (tOff < tTextInfoLen) {
  236.         iType = (int)ucGetByte(tOff, aucBuffer);
  237.         tOff++;
  238.         if (iType == 0) {
  239.             DBG_FIXME();
  240.             tOff++;
  241.             continue;
  242.         }
  243.         if (iType == 1) {
  244.             iLen = (int)usGetWord(tOff, aucBuffer);
  245.             vAdd2PropModList(aucBuffer + tOff);
  246.             tOff += iLen + 2;
  247.             continue;
  248.         }
  249.         if (iType != 2) {
  250.             werr(0, "Unknown type of 'fastsaved' format");
  251.             aucBuffer = xfree(aucBuffer);
  252.             return FALSE;
  253.         }
  254.         /* Type 2 */
  255.         lLen = (long)ulGetLong(tOff, aucBuffer);
  256.         NO_DBG_DEC(lLen);
  257.         tOff += 4;
  258.         lPieces = (lLen - 4) / 12;
  259.         DBG_DEC(lPieces);
  260.         for (lIndex = 0; lIndex < lPieces; lIndex++) {
  261.             lTextOffset = (long)ulGetLong(
  262.                 tOff + (lPieces + 1) * 4 + lIndex * 8 + 2,
  263.                 aucBuffer);
  264.             usPropMod = usGetWord(
  265.                 tOff + (lPieces + 1) * 4 + lIndex * 8 + 6,
  266.                 aucBuffer);
  267.             lTotLength = (long)ulGetLong(
  268.                         tOff + (lIndex + 1) * 4,
  269.                         aucBuffer) -
  270.                     (long)ulGetLong(
  271.                         tOff + lIndex * 4,
  272.                         aucBuffer);
  273.             if ((lTextOffset & BIT(30)) == 0) {
  274.                 bUsesUnicode = TRUE;
  275.             } else {
  276.                 bUsesUnicode = FALSE;
  277.                 lTextOffset &= ~BIT(30);
  278.                 lTextOffset /= 2;
  279.             }
  280.             DBG_HEX_C(usPropMod != 0, usPropMod);
  281.             if (!bAddTextBlocks(lTextOffset, lTotLength,
  282.                     bUsesUnicode, usPropMod,
  283.                     pPPS->tWordDocument.lSb,
  284.                     alBBD, tBBDLen)) {
  285.                 aucBuffer = xfree(aucBuffer);
  286.                 return FALSE;
  287.             }
  288.         }
  289.         break;
  290.     }
  291.     aucBuffer = xfree(aucBuffer);
  292.     return TRUE;
  293. } /* end of bGet8DocumentText */
  294.