examples/PIPS/antiword/src/prop2.c

00001 /*
00002  * prop2.c
00003  * Copyright (C) 2002-2005 A.J. van Os; Released under GPL
00004  *
00005  * Description:
00006  * Read the property information from a WinWord 1 or 2 file
00007  */
00008 
00009 #include <string.h>
00010 #include "antiword.h"
00011 
00012 
00013 #define MAX_FILESIZE            0x2000000UL     /* 32 Mb */
00014 
00015 /*
00016  * iGet2InfoLength - the length of the information for WinWord 1/2 files
00017  */
00018 static int
00019 iGet2InfoLength(int iByteNbr, const UCHAR *aucGrpprl)
00020 {
00021         int     iTmp, iDel, iAdd;
00022 
00023         switch (ucGetByte(iByteNbr, aucGrpprl)) {
00024         case   3: case  15: case  78: case 152: case 154: case 155:
00025                 return 2 + (int)ucGetByte(iByteNbr + 1, aucGrpprl);
00026         case  16: case  17: case  18: case  19: case  21: case  22: case  26:
00027         case  27: case  28: case  30: case  31: case  32: case  33: case  34:
00028         case  35: case  36: case  38: case  39: case  40: case  41: case  42:
00029         case  43: case  45: case  46: case  47: case  48: case  49: case  68:
00030         case  71: case  72: case  82: case  83: case  96: case  97: case  98:
00031         case  99: case 115: case 116: case 119: case 120: case 123: case 124:
00032         case 129: case 130: case 131: case 132: case 135: case 136: case 139:
00033         case 140: case 141: case 142: case 143: case 144: case 145: case 146:
00034         case 147: case 148: case 153: case 159: case 161: case 162:
00035                 return 1 + 2;
00036         case  23:
00037                 iTmp = (int)ucGetByte(iByteNbr + 1, aucGrpprl);
00038                 if (iTmp == 255) {
00039                         iDel = (int)ucGetByte(iByteNbr + 2, aucGrpprl);
00040                         iAdd = (int)ucGetByte(
00041                                         iByteNbr + 3 + iDel * 4, aucGrpprl);
00042                         iTmp = 2 + iDel * 4 + iAdd * 3;
00043                 }
00044                 return 2 + iTmp;
00045         case  70:
00046                 return 1 + 3;
00047         case  95:
00048                 return 1 + 13;
00049         case 157: case 163:
00050                 return 1 + 5;
00051         case 158: case 160: case 164:
00052                 return 1 + 4;
00053         default:
00054                 return 1 + 1;
00055         }
00056 } /* end of iGet2InfoLength */
00057 
00058 /*
00059  * Build the lists with Document Property Information for WinWord 1/2 files
00060  */
00061 void
00062 vGet2DopInfo(FILE *pFile, const UCHAR *aucHeader)
00063 {
00064         document_block_type     tDocument;
00065         UCHAR   *aucBuffer;
00066         ULONG   ulBeginDocpInfo, ulTmp;
00067         size_t  tDocpInfoLen;
00068         USHORT  usTmp;
00069 
00070         ulBeginDocpInfo = ulGetLong(0x112, aucHeader); /* fcDop */
00071         DBG_HEX(ulBeginDocpInfo);
00072         tDocpInfoLen = (size_t)usGetWord(0x116, aucHeader); /* cbDop */
00073         DBG_DEC(tDocpInfoLen);
00074         if (tDocpInfoLen < 28) {
00075                 DBG_MSG("No Document information");
00076                 return;
00077         }
00078 
00079         aucBuffer = xmalloc(tDocpInfoLen);
00080         if (!bReadBytes(aucBuffer, tDocpInfoLen, ulBeginDocpInfo, pFile)) {
00081                 aucBuffer = xfree(aucBuffer);
00082                 return;
00083         }
00084 
00085         usTmp = usGetWord(0x00, aucBuffer);
00086         tDocument.ucHdrFtrSpecification = (UCHAR)(usTmp >> 8); /* grpfIhdt */
00087         tDocument.usDefaultTabWidth = usGetWord(0x0a, aucBuffer); /* dxaTab */
00088         ulTmp = ulGetLong(0x14, aucBuffer); /* dttmCreated */
00089         tDocument.tCreateDate = tConvertDTTM(ulTmp);
00090         ulTmp = ulGetLong(0x18, aucBuffer); /* dttmRevised */
00091         tDocument.tRevisedDate = tConvertDTTM(ulTmp);
00092         vCreateDocumentInfoList(&tDocument);
00093 
00094         aucBuffer = xfree(aucBuffer);
00095 } /* end of vGet2DopInfo */
00096 
00097 /*
00098  * Fill the section information block with information
00099  * from a WinWord 1/2 file.
00100  */
00101 static void
00102 vGet2SectionInfo(const UCHAR *aucGrpprl, size_t tBytes,
00103                 section_block_type *pSection)
00104 {
00105         int     iFodoOff, iInfoLen;
00106         USHORT  usCcol;
00107         UCHAR   ucTmp;
00108 
00109         fail(aucGrpprl == NULL || pSection == NULL);
00110 
00111         iFodoOff = 0;
00112         while (tBytes >= (size_t)iFodoOff + 1) {
00113                 switch (ucGetByte(iFodoOff, aucGrpprl)) {
00114                 case 117:       /* bkc */
00115                         ucTmp = ucGetByte(iFodoOff + 1, aucGrpprl);
00116                         DBG_DEC(ucTmp);
00117                         pSection->bNewPage = ucTmp != 0 && ucTmp != 1;
00118                         break;
00119                 case 119:       /* ccolM1 */
00120                         usCcol = 1 + usGetWord(iFodoOff + 1, aucGrpprl);
00121                         DBG_DEC(usCcol);
00122                         break;
00123                 case 128:       /* grpfIhdt */
00124                         pSection->ucHdrFtrSpecification =
00125                                         ucGetByte(iFodoOff + 1, aucGrpprl);
00126                         break;
00127                 default:
00128                         break;
00129                 }
00130                 iInfoLen = iGet2InfoLength(iFodoOff, aucGrpprl);
00131                 fail(iInfoLen <= 0);
00132                 iFodoOff += iInfoLen;
00133         }
00134 } /* end of vGet2SectionInfo */
00135 
00136 /*
00137  * Build the lists with Section Property Information for WinWord 1/2 files
00138  */
00139 void
00140 vGet2SepInfo(FILE *pFile, const UCHAR *aucHeader)
00141 {
00142         section_block_type      tSection;
00143         ULONG   *aulSectPage, *aulCharPos;
00144         UCHAR   *aucBuffer, *aucFpage;
00145         ULONG   ulBeginOfText, ulTextOffset, ulBeginSectInfo;
00146         size_t  tSectInfoLen, tIndex, tOffset, tLen, tBytes;
00147         UCHAR   aucTmp[1];
00148 
00149         fail(pFile == NULL || aucHeader == NULL);
00150 
00151         ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
00152         NO_DBG_HEX(ulBeginOfText);
00153         ulBeginSectInfo = ulGetLong(0x7c, aucHeader); /* fcPlcfsed */
00154         DBG_HEX(ulBeginSectInfo);
00155         tSectInfoLen = (size_t)usGetWord(0x80, aucHeader); /* cbPlcfsed */
00156         DBG_DEC(tSectInfoLen);
00157         if (tSectInfoLen < 4) {
00158                 DBG_DEC(tSectInfoLen);
00159                 return;
00160         }
00161 
00162         aucBuffer = xmalloc(tSectInfoLen);
00163         if (!bReadBytes(aucBuffer, tSectInfoLen, ulBeginSectInfo, pFile)) {
00164                 aucBuffer = xfree(aucBuffer);
00165                 return;
00166         }
00167         NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
00168 
00169         /* Read the Section Descriptors */
00170         tLen = (tSectInfoLen - 4) / 10;
00171         /* Save the section offsets */
00172         aulCharPos = xcalloc(tLen, sizeof(ULONG));
00173         for (tIndex = 0, tOffset = 0;
00174              tIndex < tLen;
00175              tIndex++, tOffset += 4) {
00176                 ulTextOffset = ulGetLong(tOffset, aucBuffer);
00177                 NO_DBG_HEX(ulTextOffset);
00178                 aulCharPos[tIndex] = ulBeginOfText + ulTextOffset;
00179                 NO_DBG_HEX(aulCharPos[tIndex]);
00180         }
00181         /* Save the Sepx offsets */
00182         aulSectPage = xcalloc(tLen, sizeof(ULONG));
00183         for (tIndex = 0, tOffset = (tLen + 1) * 4;
00184              tIndex < tLen;
00185              tIndex++, tOffset += 6) {
00186                 aulSectPage[tIndex] = ulGetLong(tOffset + 2, aucBuffer);
00187                 NO_DBG_HEX(aulSectPage[tIndex]); /* fcSepx */
00188         }
00189         aucBuffer = xfree(aucBuffer);
00190 
00191         /* Read the Section Properties */
00192         for (tIndex = 0; tIndex < tLen; tIndex++) {
00193                 if (aulSectPage[tIndex] == FC_INVALID) {
00194                         vDefault2SectionInfoList(aulCharPos[tIndex]);
00195                         continue;
00196                 }
00197                 /* Get the number of bytes to read */
00198                 if (!bReadBytes(aucTmp, 1, aulSectPage[tIndex], pFile)) {
00199                         continue;
00200                 }
00201                 tBytes = 1 + (size_t)ucGetByte(0, aucTmp);
00202                 NO_DBG_DEC(tBytes);
00203                 /* Read the bytes */
00204                 aucFpage = xmalloc(tBytes);
00205                 if (!bReadBytes(aucFpage, tBytes, aulSectPage[tIndex], pFile)) {
00206                         aucFpage = xfree(aucFpage);
00207                         continue;
00208                 }
00209                 NO_DBG_PRINT_BLOCK(aucFpage, tBytes);
00210                 /* Process the bytes */
00211                 vGetDefaultSection(&tSection);
00212                 vGet2SectionInfo(aucFpage + 1, tBytes - 1, &tSection);
00213                 vAdd2SectionInfoList(&tSection, aulCharPos[tIndex]);
00214                 aucFpage = xfree(aucFpage);
00215         }
00216         aulCharPos = xfree(aulCharPos);
00217         aulSectPage = xfree(aulSectPage);
00218 } /* end of vGet2SepInfo */
00219 
00220 /*
00221  * Build the list with Header/Footer Information for WinWord 1/2 files
00222  */
00223 void
00224 vGet2HdrFtrInfo(FILE *pFile, const UCHAR *aucHeader)
00225 {
00226         ULONG   *aulCharPos;
00227         UCHAR   *aucBuffer;
00228         ULONG   ulHdrFtrOffset, ulBeginHdrFtrInfo;
00229         size_t  tHdrFtrInfoLen, tIndex, tOffset, tLen;
00230 
00231         fail(pFile == NULL || aucHeader == NULL);
00232 
00233         ulBeginHdrFtrInfo = ulGetLong(0x9a, aucHeader); /* fcPlcfhdd */
00234         NO_DBG_HEX(ulBeginHdrFtrInfo);
00235         tHdrFtrInfoLen = (size_t)usGetWord(0x9e, aucHeader); /* cbPlcfhdd */
00236         NO_DBG_DEC(tHdrFtrInfoLen);
00237         if (tHdrFtrInfoLen < 8) {
00238                 DBG_DEC_C(tHdrFtrInfoLen != 0, tHdrFtrInfoLen);
00239                 return;
00240         }
00241 
00242         aucBuffer = xmalloc(tHdrFtrInfoLen);
00243         if (!bReadBytes(aucBuffer, tHdrFtrInfoLen, ulBeginHdrFtrInfo, pFile)) {
00244                 aucBuffer = xfree(aucBuffer);
00245                 return;
00246         }
00247         NO_DBG_PRINT_BLOCK(aucBuffer, tHdrFtrInfoLen);
00248 
00249         tLen = tHdrFtrInfoLen / 4 - 1;
00250         /* Save the header/footer offsets */
00251         aulCharPos = xcalloc(tLen, sizeof(ULONG));
00252         for (tIndex = 0, tOffset = 0;
00253              tIndex < tLen;
00254              tIndex++, tOffset += 4) {
00255                 ulHdrFtrOffset = ulGetLong(tOffset, aucBuffer);
00256                 NO_DBG_HEX(ulHdrFtrOffset);
00257                 aulCharPos[tIndex] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset);
00258                 NO_DBG_HEX(aulCharPos[tIndex]);
00259         }
00260         vCreat2HdrFtrInfoList(aulCharPos, tLen);
00261         aulCharPos = xfree(aulCharPos);
00262         aucBuffer = xfree(aucBuffer);
00263 } /* end of vGet2HdrFtrInfo */
00264 
00265 /*
00266  * Translate the rowinfo to a member of the row_info enumeration
00267  */
00268 row_info_enum
00269 eGet2RowInfo(int iFodo,
00270         const UCHAR *aucGrpprl, int iBytes, row_block_type *pRow)
00271 {
00272         int     iFodoOff, iInfoLen;
00273         int     iIndex, iSize, iCol;
00274         int     iPosCurr, iPosPrev;
00275         USHORT  usTmp;
00276         BOOL    bFound24_0, bFound24_1, bFound25_0, bFound25_1, bFound154;
00277 
00278         fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL);
00279 
00280         iFodoOff = 0;
00281         bFound24_0 = FALSE;
00282         bFound24_1 = FALSE;
00283         bFound25_0 = FALSE;
00284         bFound25_1 = FALSE;
00285         bFound154 = FALSE;
00286         while (iBytes >= iFodoOff + 1) {
00287                 iInfoLen = 0;
00288                 switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
00289                 case  24:       /* fIntable */
00290                         if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) {
00291                                 bFound24_1 = TRUE;
00292                         } else {
00293                                 bFound24_0 = TRUE;
00294                         }
00295                         break;
00296                 case  25:       /* fTtp */
00297                         if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) {
00298                                 bFound25_1 = TRUE;
00299                         } else {
00300                                 bFound25_0 = TRUE;
00301                         }
00302                         break;
00303                 case 30:        /* brcTop10 */
00304                         usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
00305                         usTmp &= 0x01ff;
00306                         NO_DBG_DEC(usTmp >> 6);
00307                         if (usTmp == 0) {
00308                                 pRow->ucBorderInfo &= ~TABLE_BORDER_TOP;
00309                         } else {
00310                                 pRow->ucBorderInfo |= TABLE_BORDER_TOP;
00311                         }
00312                         break;
00313                 case 31:        /* brcLeft10 */
00314                         usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
00315                         usTmp &= 0x01ff;
00316                         NO_DBG_DEC(usTmp >> 6);
00317                         if (usTmp == 0) {
00318                                 pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT;
00319                         } else {
00320                                 pRow->ucBorderInfo |= TABLE_BORDER_LEFT;
00321                         }
00322                         break;
00323                 case 32:        /* brcBottom10 */
00324                         usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
00325                         usTmp &= 0x01ff;
00326                         NO_DBG_DEC(usTmp >> 6);
00327                         if (usTmp == 0) {
00328                                 pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM;
00329                         } else {
00330                                 pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM;
00331                         }
00332                         break;
00333                 case 33:        /* brcRight10 */
00334                         usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
00335                         usTmp &= 0x01ff;
00336                         NO_DBG_DEC(usTmp >> 6);
00337                         if (usTmp == 0) {
00338                                 pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT;
00339                         } else {
00340                                 pRow->ucBorderInfo |= TABLE_BORDER_RIGHT;
00341                         }
00342                         break;
00343                 case 38:        /* brcTop */
00344                         usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
00345                         usTmp &= 0x0018;
00346                         NO_DBG_DEC(usTmp >> 3);
00347                         if (usTmp == 0) {
00348                                 pRow->ucBorderInfo &= ~TABLE_BORDER_TOP;
00349                         } else {
00350                                 pRow->ucBorderInfo |= TABLE_BORDER_TOP;
00351                         }
00352                         break;
00353                 case 39:        /* brcLeft */
00354                         usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
00355                         usTmp &= 0x0018;
00356                         NO_DBG_DEC(usTmp >> 3);
00357                         if (usTmp == 0) {
00358                                 pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT;
00359                         } else {
00360                                 pRow->ucBorderInfo |= TABLE_BORDER_LEFT;
00361                         }
00362                         break;
00363                 case 40:        /* brcBottom */
00364                         usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
00365                         usTmp &= 0x0018;
00366                         NO_DBG_DEC(usTmp >> 3);
00367                         if (usTmp == 0) {
00368                                 pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM;
00369                         } else {
00370                                 pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM;
00371                         }
00372                         break;
00373                 case 41:        /* brcRight */
00374                         usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
00375                         usTmp &= 0x0018;
00376                         NO_DBG_DEC(usTmp >> 3);
00377                         if (usTmp == 0) {
00378                                 pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT;
00379                         } else {
00380                                 pRow->ucBorderInfo |= TABLE_BORDER_RIGHT;
00381                         }
00382                         break;
00383                 case 152:       /* cDefTable10 */
00384                 case 154:       /* cDefTable */
00385                         iSize = (int)usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
00386                         if (iSize < 6 || iBytes < iFodoOff + 7) {
00387                                 DBG_DEC(iSize);
00388                                 DBG_DEC(iBytes);
00389                                 DBG_DEC(iFodoOff);
00390                                 iInfoLen = 1;
00391                                 break;
00392                         }
00393                         iCol = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
00394                         if (iCol < 1 ||
00395                             iBytes < iFodoOff + 3 + (iCol + 1) * 2) {
00396                                 DBG_DEC(iCol);
00397                                 DBG_DEC(iBytes);
00398                                 DBG_DEC(iFodoOff);
00399                                 DBG_DEC(ucGetByte(iFodo + iFodoOff, aucGrpprl));
00400                                 iInfoLen = 1;
00401                                 break;
00402                         }
00403                         if (iCol >= (int)elementsof(pRow->asColumnWidth)) {
00404                                 DBG_DEC(iCol);
00405                                 werr(1, "The number of columns is corrupt");
00406                         }
00407                         pRow->ucNumberOfColumns = (UCHAR)iCol;
00408                         iPosPrev = (int)(short)usGetWord(
00409                                         iFodo + iFodoOff + 4,
00410                                         aucGrpprl);
00411                         for (iIndex = 0; iIndex < iCol; iIndex++) {
00412                                 iPosCurr = (int)(short)usGetWord(
00413                                         iFodo + iFodoOff + 6 + iIndex * 2,
00414                                         aucGrpprl);
00415                                 pRow->asColumnWidth[iIndex] =
00416                                                 (short)(iPosCurr - iPosPrev);
00417                                 iPosPrev = iPosCurr;
00418                         }
00419                         bFound154 = TRUE;
00420                         break;
00421                 default:
00422                         break;
00423                 }
00424                 if (iInfoLen <= 0) {
00425                         iInfoLen =
00426                                 iGet2InfoLength(iFodo + iFodoOff, aucGrpprl);
00427                         fail(iInfoLen <= 0);
00428                 }
00429                 iFodoOff += iInfoLen;
00430         }
00431         if (bFound24_1 && bFound25_1 && bFound154) {
00432                 return found_end_of_row;
00433         }
00434         if (bFound24_0 && bFound25_0 && !bFound154) {
00435                 return found_not_end_of_row;
00436         }
00437         if (bFound24_1) {
00438                 return found_a_cell;
00439         }
00440         if (bFound24_0) {
00441                 return found_not_a_cell;
00442         }
00443         return found_nothing;
00444 } /* end of eGet2RowInfo */
00445 
00446 /*
00447  * Fill the style information block with information
00448  * from a WinWord 1/2 file.
00449  */
00450 void
00451 vGet2StyleInfo(int iFodo,
00452         const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle)
00453 {
00454         int     iFodoOff, iInfoLen;
00455         int     iTmp, iDel, iAdd;
00456         short   sTmp;
00457         UCHAR   ucTmp;
00458 
00459         fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL);
00460 
00461         NO_DBG_DEC(pStyle->usIstd);
00462 
00463         iFodoOff = 0;
00464         while (iBytes >= iFodoOff + 1) {
00465                 iInfoLen = 0;
00466                 switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
00467                 case   2:       /* istd */
00468                         sTmp = (short)ucGetByte(
00469                                         iFodo + iFodoOff + 1, aucGrpprl);
00470                         NO_DBG_DEC(sTmp);
00471                         break;
00472                 case   5:       /* jc */
00473                         pStyle->ucAlignment = ucGetByte(
00474                                         iFodo + iFodoOff + 1, aucGrpprl);
00475                         break;
00476                 case  12:       /* nfcSeqNumb */
00477                         pStyle->ucNFC = ucGetByte(
00478                                         iFodo + iFodoOff + 1, aucGrpprl);
00479                         break;
00480                 case  13:       /* nLvlAnm */
00481                         ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
00482                         pStyle->ucNumLevel = ucTmp;
00483                         pStyle->bNumPause =
00484                                 eGetNumType(ucTmp) == level_type_pause;
00485                         break;
00486                 case  15:       /* ChgTabsPapx */
00487                 case  23:       /* ChgTabs */
00488                         iTmp = (int)ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
00489                         if (iTmp < 2) {
00490                                 iInfoLen = 1;
00491                                 break;
00492                         }
00493                         NO_DBG_DEC(iTmp);
00494                         iDel = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
00495                         if (iTmp < 2 + 2 * iDel) {
00496                                 iInfoLen = 1;
00497                                 break;
00498                         }
00499                         NO_DBG_DEC(iDel);
00500                         iAdd = (int)ucGetByte(
00501                                 iFodo + iFodoOff + 3 + 2 * iDel, aucGrpprl);
00502                         if (iTmp < 2 + 2 * iDel + 2 * iAdd) {
00503                                 iInfoLen = 1;
00504                                 break;
00505                         }
00506                         NO_DBG_DEC(iAdd);
00507                         break;
00508                 case  16:       /* dxaRight */
00509                         pStyle->sRightIndent = (short)usGetWord(
00510                                         iFodo + iFodoOff + 1, aucGrpprl);
00511                         NO_DBG_DEC(pStyle->sRightIndent);
00512                         break;
00513                 case  17:       /* dxaLeft */
00514                         pStyle->sLeftIndent = (short)usGetWord(
00515                                         iFodo + iFodoOff + 1, aucGrpprl);
00516                         NO_DBG_DEC(pStyle->sLeftIndent);
00517                         break;
00518                 case  18:       /* Nest dxaLeft */
00519                         sTmp = (short)usGetWord(
00520                                         iFodo + iFodoOff + 1, aucGrpprl);
00521                         pStyle->sLeftIndent += sTmp;
00522                         if (pStyle->sLeftIndent < 0) {
00523                                 pStyle->sLeftIndent = 0;
00524                         }
00525                         NO_DBG_DEC(sTmp);
00526                         NO_DBG_DEC(pStyle->sLeftIndent);
00527                         break;
00528                 case  19:       /* dxaLeft1 */
00529                         pStyle->sLeftIndent1 = (short)usGetWord(
00530                                         iFodo + iFodoOff + 1, aucGrpprl);
00531                         NO_DBG_DEC(pStyle->sLeftIndent1);
00532                         break;
00533                 case  21:       /* dyaBefore */
00534                         pStyle->usBeforeIndent = usGetWord(
00535                                         iFodo + iFodoOff + 1, aucGrpprl);
00536                         NO_DBG_DEC(pStyle->usBeforeIndent);
00537                         break;
00538                 case  22:       /* dyaAfter */
00539                         pStyle->usAfterIndent = usGetWord(
00540                                         iFodo + iFodoOff + 1, aucGrpprl);
00541                         NO_DBG_DEC(pStyle->usAfterIndent);
00542                         break;
00543                 default:
00544                         break;
00545                 }
00546                 if (iInfoLen <= 0) {
00547                         iInfoLen =
00548                                 iGet2InfoLength(iFodo + iFodoOff, aucGrpprl);
00549                         fail(iInfoLen <= 0);
00550                 }
00551                 iFodoOff += iInfoLen;
00552         }
00553 } /* end of vGet2StyleInfo */
00554 
00555 /*
00556  * Build the lists with Paragraph Information for WinWord 1/2 files
00557  */
00558 void
00559 vGet2PapInfo(FILE *pFile, const UCHAR *aucHeader)
00560 {
00561         row_block_type          tRow;
00562         style_block_type        tStyle;
00563         USHORT  *ausParfPage;
00564         UCHAR   *aucBuffer;
00565         ULONG   ulCharPos, ulCharPosFirst, ulCharPosLast;
00566         ULONG   ulBeginParfInfo;
00567         size_t  tParfInfoLen, tParfPageNum, tOffset, tSize, tLenOld, tLen;
00568         int     iIndex, iIndex2, iRun, iFodo, iLen;
00569         row_info_enum   eRowInfo;
00570         USHORT  usParfFirstPage, usCount, usIstd;
00571         UCHAR   ucStc;
00572         UCHAR   aucFpage[BIG_BLOCK_SIZE];
00573 
00574         fail(pFile == NULL || aucHeader == NULL);
00575 
00576         ulBeginParfInfo = ulGetLong(0xa6, aucHeader); /* fcPlcfbtePapx */
00577         NO_DBG_HEX(ulBeginParfInfo);
00578         tParfInfoLen = (size_t)usGetWord(0xaa, aucHeader); /* cbPlcfbtePapx */
00579         NO_DBG_DEC(tParfInfoLen);
00580         if (tParfInfoLen < 4) {
00581                 DBG_DEC(tParfInfoLen);
00582                 return;
00583         }
00584 
00585         aucBuffer = xmalloc(tParfInfoLen);
00586         if (!bReadBytes(aucBuffer, tParfInfoLen, ulBeginParfInfo, pFile)) {
00587                 aucBuffer = xfree(aucBuffer);
00588                 return;
00589         }
00590         NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen);
00591 
00592         tLen = (tParfInfoLen - 4) / 6;
00593         ausParfPage = xcalloc(tLen, sizeof(USHORT));
00594         for (iIndex = 0, tOffset = (tLen + 1) * 4;
00595              iIndex < (int)tLen;
00596              iIndex++, tOffset += 2) {
00597                 ausParfPage[iIndex] = usGetWord(tOffset, aucBuffer);
00598                 NO_DBG_DEC(ausParfPage[iIndex]);
00599         }
00600         DBG_HEX(ulGetLong(0, aucBuffer));
00601         aucBuffer = xfree(aucBuffer);
00602         tParfPageNum = (size_t)usGetWord(0x144, aucHeader); /* cpnBtePap */
00603         DBG_DEC(tParfPageNum);
00604         if (tLen < tParfPageNum) {
00605                 /* Replace ParfPage by a longer version */
00606                 tLenOld = tLen;
00607                 usParfFirstPage = usGetWord(0x140, aucHeader); /* pnPapFirst */
00608                 DBG_DEC(usParfFirstPage);
00609                 tLen += tParfPageNum - 1;
00610                 tSize = tLen * sizeof(USHORT);
00611                 ausParfPage = xrealloc(ausParfPage, tSize);
00612                 /* Add new values */
00613                 usCount = usParfFirstPage + 1;
00614                 for (iIndex = (int)tLenOld; iIndex < (int)tLen; iIndex++) {
00615                         ausParfPage[iIndex] = usCount;
00616                         NO_DBG_DEC(ausParfPage[iIndex]);
00617                         usCount++;
00618                 }
00619         }
00620 
00621         (void)memset(&tRow, 0, sizeof(tRow));
00622         ulCharPosFirst = CP_INVALID;
00623         for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
00624                 if (!bReadBytes(aucFpage, BIG_BLOCK_SIZE,
00625                                 (ULONG)ausParfPage[iIndex] * BIG_BLOCK_SIZE,
00626                                 pFile)) {
00627                         break;
00628                 }
00629                 NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
00630                 iRun = (int)ucGetByte(0x1ff, aucFpage);
00631                 NO_DBG_DEC(iRun);
00632                 for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
00633                         if ((iRun + 1) * 4 + iIndex2 * 1 >= BIG_BLOCK_SIZE) {
00634                                 break;
00635                         }
00636                         NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage));
00637                         iFodo = 2 * (int)ucGetByte(
00638                                 (iRun + 1) * 4 + iIndex2 * 1, aucFpage);
00639                         if (iFodo <= 0) {
00640                                 continue;
00641                         }
00642 
00643                         iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
00644 
00645                         ucStc = ucGetByte(iFodo + 1, aucFpage);
00646                         usIstd = usStc2istd(ucStc);
00647 
00648                         vFillStyleFromStylesheet(usIstd, &tStyle);
00649                         vGet2StyleInfo(iFodo, aucFpage + 8, iLen - 8, &tStyle);
00650                         ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
00651                         NO_DBG_HEX(ulCharPos);
00652                         tStyle.ulFileOffset = ulCharPos;
00653                         vAdd2StyleInfoList(&tStyle);
00654 
00655                         eRowInfo = eGet2RowInfo(iFodo,
00656                                         aucFpage + 8, iLen - 8, &tRow);
00657 
00658                         switch(eRowInfo) {
00659                         case found_a_cell:
00660                                 if (ulCharPosFirst != CP_INVALID) {
00661                                         break;
00662                                 }
00663                                 ulCharPosFirst = ulGetLong(
00664                                                 iIndex2 * 4, aucFpage);
00665                                 NO_DBG_HEX(ulCharPosFirst);
00666                                 tRow.ulCharPosStart = ulCharPosFirst;
00667                                 tRow.ulFileOffsetStart = ulCharPosFirst;
00668                                 break;
00669                         case found_end_of_row:
00670                                 ulCharPosLast = ulGetLong(
00671                                                 iIndex2 * 4, aucFpage);
00672                                 NO_DBG_HEX(ulCharPosLast);
00673                                 tRow.ulCharPosEnd = ulCharPosLast;
00674                                 /* Add 1 for compatiblity with Word 6 and up */
00675                                 tRow.ulFileOffsetEnd = ulCharPosLast + 1;
00676                                 vAdd2RowInfoList(&tRow);
00677                                 (void)memset(&tRow, 0, sizeof(tRow));
00678                                 ulCharPosFirst = CP_INVALID;
00679                                 break;
00680                         case found_nothing:
00681                                 break;
00682                         default:
00683                                 DBG_DEC(eRowInfo);
00684                                 break;
00685                         }
00686                 }
00687         }
00688         ausParfPage = xfree(ausParfPage);
00689 } /* end of vGet2PapInfo */
00690 
00691 /*
00692  * Fill the font information block with information
00693  * from a WinWord 1 file.
00694  */
00695 void
00696 vGet1FontInfo(int iFodo,
00697         const UCHAR *aucGrpprl, size_t tBytes, font_block_type *pFont)
00698 {
00699         BOOL    bIcoChange, bFtcChange, bHpsChange, bKulChange;
00700         USHORT  usTmp;
00701         UCHAR   ucTmp;
00702         UCHAR   aucChpx[12];
00703 
00704         fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
00705 
00706         if (tBytes > sizeof(aucChpx)) {
00707                 NO_DBG_PRINT_BLOCK(aucGrpprl + iFodo, tBytes);
00708                 return;
00709         }
00710 
00711         /* Build the CHPX structure */
00712         (void)memset(aucChpx, 0, sizeof(aucChpx));
00713         (void)memcpy(aucChpx, aucGrpprl + iFodo, min(tBytes, sizeof(aucChpx)));
00714 
00715         usTmp = usGetWord(0, aucChpx);
00716         if ((usTmp & BIT(0)) != 0) {
00717                 pFont->usFontStyle ^= FONT_BOLD;
00718         }
00719         if ((usTmp & BIT(1)) != 0) {
00720                 pFont->usFontStyle ^= FONT_ITALIC;
00721         }
00722         if ((usTmp & BIT(2)) != 0) {
00723                 pFont->usFontStyle ^= FONT_STRIKE;
00724         }
00725         if ((usTmp & BIT(5)) != 0) {
00726                 pFont->usFontStyle ^= FONT_SMALL_CAPITALS;
00727         }
00728         if ((usTmp & BIT(6)) != 0) {
00729                 pFont->usFontStyle ^= FONT_CAPITALS;
00730         }
00731         if ((usTmp & BIT(7)) != 0) {
00732                 pFont->usFontStyle ^= FONT_HIDDEN;
00733         }
00734 
00735         ucTmp = ucGetByte(5, aucChpx);
00736         if (ucTmp != 0) {
00737                 if (ucTmp < 128) {
00738                         pFont->usFontStyle |= FONT_SUPERSCRIPT;
00739                         DBG_MSG("Superscript");
00740                 } else {
00741                         pFont->usFontStyle |= FONT_SUBSCRIPT;
00742                         DBG_MSG("Subscript");
00743                 }
00744         }
00745 
00746         bIcoChange = (usTmp & BIT(10)) != 0;
00747         bFtcChange = (usTmp & BIT(11)) != 0;
00748         bHpsChange = (usTmp & BIT(12)) != 0;
00749         bKulChange = (usTmp & BIT(13)) != 0;
00750 
00751         if (bFtcChange) {
00752                 usTmp = usGetWord(2, aucChpx);
00753                 if (usTmp <= (USHORT)UCHAR_MAX) {
00754                         pFont->ucFontNumber = (UCHAR)usTmp;
00755                 } else {
00756                         pFont->ucFontNumber = 0;
00757                 }
00758         }
00759 
00760         if (bHpsChange) {
00761                 pFont->usFontSize = (USHORT)ucGetByte(4, aucChpx);
00762         }
00763 
00764         if (bIcoChange || bKulChange) {
00765                 usTmp = usGetWord(6, aucChpx);
00766                 if (bIcoChange) {
00767                         pFont->ucFontColor = (UCHAR)((usTmp & 0x0f00) >> 8);
00768                         if (pFont->ucFontColor <= 7) {
00769                                 /* Add 1 for compatibility with Word 2 and up */
00770                                 pFont->ucFontColor++;
00771                         } else {
00772                                 DBG_DEC(pFont->ucFontColor);
00773                                 pFont->ucFontColor = 0;
00774                         }
00775                 }
00776                 if (bKulChange) {
00777                         usTmp = (usTmp & 0x7000) >> 12;
00778                         DBG_DEC_C(usTmp > 4, usTmp);
00779                         if (usTmp == 0) {
00780                                 pFont->usFontStyle &= ~FONT_UNDERLINE;
00781                         } else {
00782                                 pFont->usFontStyle |= FONT_UNDERLINE;
00783                         }
00784                 }
00785         }
00786 } /* end of vGet1FontInfo */
00787 
00788 /*
00789  * Fill the font information block with information
00790  * from a WinWord 1/2 file.
00791  */
00792 void
00793 vGet2FontInfo(int iFodo,
00794         const UCHAR *aucGrpprl, size_t tBytes, font_block_type *pFont)
00795 {
00796         BOOL    bIcoChange, bFtcChange, bHpsChange, bKulChange;
00797         USHORT  usTmp;
00798         UCHAR   ucTmp;
00799         UCHAR   aucChpx[18];
00800 
00801         fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
00802 
00803         if (tBytes > sizeof(aucChpx)) {
00804                 NO_DBG_PRINT_BLOCK(aucGrpprl + iFodo, tBytes);
00805                 return;
00806         }
00807 
00808         /* Build the CHPX structure */
00809         (void)memset(aucChpx, 0, sizeof(aucChpx));
00810         (void)memcpy(aucChpx, aucGrpprl + iFodo, min(tBytes, sizeof(aucChpx)));
00811 
00812         usTmp = usGetWord(0, aucChpx);
00813         if ((usTmp & BIT(0)) != 0) {
00814                 pFont->usFontStyle ^= FONT_BOLD;
00815         }
00816         if ((usTmp & BIT(1)) != 0) {
00817                 pFont->usFontStyle ^= FONT_ITALIC;
00818         }
00819         if (usTmp & BIT(3)) {
00820                 pFont->usFontStyle ^= FONT_MARKDEL;
00821         }
00822         if ((usTmp & BIT(5)) != 0) {
00823                 pFont->usFontStyle ^= FONT_SMALL_CAPITALS;
00824         }
00825         if ((usTmp & BIT(6)) != 0) {
00826                 pFont->usFontStyle ^= FONT_CAPITALS;
00827         }
00828         if ((usTmp & BIT(7)) != 0) {
00829                 pFont->usFontStyle ^= FONT_HIDDEN;
00830         }
00831         if (usTmp & BIT(10)) {
00832                 pFont->usFontStyle ^= FONT_STRIKE;
00833         }
00834 
00835         ucTmp = ucGetByte(10, aucChpx);
00836         DBG_MSG_C(ucTmp != 0 && ucTmp < 128, "Superscript");
00837         DBG_MSG_C(ucTmp >= 128, "Subscript");
00838 
00839         usTmp = usGetWord(2, aucChpx);
00840         if (usTmp == 0) {
00841                 /* No changes, nothing to do */
00842                 return;
00843         }
00844 
00845         bIcoChange = (usTmp & BIT(0)) != 0;
00846         bFtcChange = (usTmp & BIT(1)) != 0;
00847         bHpsChange = (usTmp & BIT(2)) != 0;
00848         bKulChange = (usTmp & BIT(3)) != 0;
00849 
00850         if (bFtcChange) {
00851                 usTmp = usGetWord(4, aucChpx);
00852                 if (usTmp <= (USHORT)UCHAR_MAX) {
00853                         pFont->ucFontNumber = (UCHAR)usTmp;
00854                 } else {
00855                         pFont->ucFontNumber = 0;
00856                 }
00857         }
00858 
00859         if (bHpsChange) {
00860                 pFont->usFontSize = usGetWord(6, aucChpx);
00861         }
00862 
00863         if (bIcoChange || bKulChange) {
00864                 ucTmp = ucGetByte(9, aucChpx);
00865                 if (bIcoChange) {
00866                         pFont->ucFontColor = ucTmp & 0x1f;
00867                         if (pFont->ucFontColor > 16) {
00868                                 DBG_DEC(pFont->ucFontColor);
00869                                 pFont->ucFontColor = 0;
00870                         }
00871                 }
00872                 if (bKulChange) {
00873                         ucTmp = (ucTmp & 0xe0) >> 5;
00874                         DBG_DEC_C(ucTmp > 4, ucTmp);
00875                         if (ucTmp == 0) {
00876                                 pFont->usFontStyle &= ~FONT_UNDERLINE;
00877                         } else {
00878                                 pFont->usFontStyle |= FONT_UNDERLINE;
00879                         }
00880                 }
00881         }
00882 } /* end of vGet2FontInfo */
00883 
00884 /*
00885  * Fill the picture information block with information from a WinWord 1 file.
00886  * Returns TRUE when successful, otherwise FALSE
00887  */
00888 static BOOL
00889 bGet1PicInfo(int iFodo,
00890         const UCHAR *aucGrpprl, size_t tBytes, picture_block_type *pPicture)
00891 {
00892         ULONG   ulTmp;
00893         UCHAR   aucChpx[12];
00894 
00895         fail(iFodo < 0 || aucGrpprl == NULL || pPicture == NULL);
00896 
00897         if (tBytes > sizeof(aucChpx)) {
00898                 NO_DBG_PRINT_BLOCK(aucGrpprl + iFodo, tBytes);
00899                 tBytes = sizeof(aucChpx);
00900         }
00901 
00902         /* Build the CHPX structure */
00903         (void)memset(aucChpx, 0, sizeof(aucChpx));
00904         (void)memcpy(aucChpx, aucGrpprl + iFodo, min(tBytes, sizeof(aucChpx)));
00905 
00906         ulTmp = ulGetLong(8, aucChpx);
00907         if (ulTmp != 0 && ulTmp < MAX_FILESIZE) {
00908                 pPicture->ulPictureOffset = ulTmp;
00909                 DBG_HEX(pPicture->ulPictureOffset);
00910                 return TRUE;
00911         }
00912         return FALSE;
00913 } /* end of bGet1PicInfo */
00914 
00915 /*
00916  * Fill the picture information block with information from a WinWord 2 file.
00917  * Returns TRUE when successful, otherwise FALSE
00918  */
00919 static BOOL
00920 bGet2PicInfo(int iFodo,
00921         const UCHAR *aucGrpprl, size_t tBytes, picture_block_type *pPicture)
00922 {
00923         ULONG   ulTmp;
00924         UCHAR   aucChpx[18];
00925 
00926         fail(iFodo < 0 || aucGrpprl == NULL || pPicture == NULL);
00927 
00928         if (tBytes > sizeof(aucChpx)) {
00929                 NO_DBG_PRINT_BLOCK(aucGrpprl + iFodo, tBytes);
00930                 tBytes = sizeof(aucChpx);
00931         }
00932 
00933         /* Build the CHPX structure */
00934         (void)memset(aucChpx, 0, sizeof(aucChpx));
00935         (void)memcpy(aucChpx, aucGrpprl + iFodo, min(tBytes, sizeof(aucChpx)));
00936 
00937         ulTmp = ulGetLong(14, aucChpx);
00938         if (ulTmp != 0 && ulTmp < MAX_FILESIZE) {
00939                 pPicture->ulPictureOffset = ulTmp;
00940                 DBG_HEX(pPicture->ulPictureOffset);
00941                 DBG_DEC(tBytes);
00942                 return TRUE;
00943         }
00944         return FALSE;
00945 } /* end of bGet2PicInfo */
00946 
00947 /*
00948  * Build the lists with Character Information for WinWord 1/2 files
00949  */
00950 void
00951 vGet2ChrInfo(FILE *pFile, int iWordVersion, const UCHAR *aucHeader)
00952 {
00953         font_block_type         tFont;
00954         picture_block_type      tPicture;
00955         USHORT  *ausCharPage;
00956         UCHAR   *aucBuffer;
00957         ULONG   ulFileOffset, ulCharPos, ulBeginCharInfo;
00958         size_t  tCharInfoLen, tOffset, tSize, tChrLen, tCharPageNum;
00959         size_t  tLenOld, tLen;
00960         int     iIndex, iIndex2, iRun, iFodo;
00961         BOOL    bSuccess1, bSuccess2;
00962         USHORT  usCharFirstPage, usCount, usIstd;
00963         UCHAR   aucFpage[BIG_BLOCK_SIZE];
00964 
00965         fail(pFile == NULL || aucHeader == NULL);
00966         fail(iWordVersion != 1 && iWordVersion != 2);
00967 
00968         ulBeginCharInfo = ulGetLong(0xa0, aucHeader); /* fcPlcfbteChpx */
00969         DBG_HEX(ulBeginCharInfo);
00970         tCharInfoLen = (size_t)usGetWord(0xa4, aucHeader); /* cbPlcfbteChpx */
00971         DBG_DEC(tCharInfoLen);
00972         if (tCharInfoLen < 4) {
00973                 DBG_DEC(tCharInfoLen);
00974                 return;
00975         }
00976 
00977         aucBuffer = xmalloc(tCharInfoLen);
00978         if (!bReadBytes(aucBuffer, tCharInfoLen, ulBeginCharInfo, pFile)) {
00979                 aucBuffer = xfree(aucBuffer);
00980                 return;
00981         }
00982         NO_DBG_PRINT_BLOCK(aucBuffer, tCharInfoLen);
00983 
00984         tLen = (tCharInfoLen - 4) / 6;
00985         ausCharPage = xcalloc(tLen, sizeof(USHORT));
00986         for (iIndex = 0, tOffset = (tLen + 1) * 4;
00987              iIndex < (int)tLen;
00988              iIndex++, tOffset += 2) {
00989                 ausCharPage[iIndex] = usGetWord(tOffset, aucBuffer);
00990                 NO_DBG_DEC(ausCharPage[iIndex]);
00991         }
00992         DBG_HEX(ulGetLong(0, aucBuffer));
00993         aucBuffer = xfree(aucBuffer);
00994         tCharPageNum = (size_t)usGetWord(0x142, aucHeader); /* cpnBteChp */
00995         DBG_DEC(tCharPageNum);
00996         if (tLen < tCharPageNum) {
00997                 /* Replace CharPage by a longer version */
00998                 tLenOld = tLen;
00999                 usCharFirstPage = usGetWord(0x13e, aucHeader); /* pnChrFirst */
01000                 NO_DBG_DEC(usCharFirstPage);
01001                 tLen += tCharPageNum - 1;
01002                 tSize = tLen * sizeof(USHORT);
01003                 ausCharPage = xrealloc(ausCharPage, tSize);
01004                 /* Add new values */
01005                 usCount = usCharFirstPage + 1;
01006                 for (iIndex = (int)tLenOld; iIndex < (int)tLen; iIndex++) {
01007                         ausCharPage[iIndex] = usCount;
01008                         NO_DBG_DEC(ausCharPage[iIndex]);
01009                         usCount++;
01010                 }
01011         }
01012 
01013         for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
01014                 if (!bReadBytes(aucFpage, BIG_BLOCK_SIZE,
01015                                 (ULONG)ausCharPage[iIndex] * BIG_BLOCK_SIZE,
01016                                 pFile)) {
01017                         break;
01018                 }
01019                 NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
01020                 iRun = (int)ucGetByte(0x1ff, aucFpage);
01021                 NO_DBG_DEC(iRun);
01022                 for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
01023                         if ((iRun + 1) * 4 + iIndex2 >= BIG_BLOCK_SIZE) {
01024                                 break;
01025                         }
01026                         ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
01027                         ulFileOffset = ulCharPos;
01028                         iFodo = 2 * (int)ucGetByte(
01029                                 (iRun + 1) * 4 + iIndex2, aucFpage);
01030 
01031                         tChrLen = (size_t)ucGetByte(iFodo, aucFpage);
01032 
01033                         usIstd = usGetIstd(ulFileOffset);
01034                         vFillFontFromStylesheet(usIstd, &tFont);
01035                         if (iFodo != 0) {
01036                                 if (iWordVersion == 1) {
01037                                         vGet1FontInfo(iFodo,
01038                                                 aucFpage + 1, tChrLen, &tFont);
01039                                 } else if (iWordVersion == 2) {
01040                                         vGet2FontInfo(iFodo,
01041                                                 aucFpage + 1, tChrLen, &tFont);
01042                                 }
01043                         }
01044                         tFont.ulFileOffset = ulFileOffset;
01045                         vAdd2FontInfoList(&tFont);
01046 
01047                         if (iFodo <= 0) {
01048                                 continue;
01049                         }
01050 
01051                         (void)memset(&tPicture, 0, sizeof(tPicture));
01052                         bSuccess1 = iWordVersion == 1 &&
01053                                         bGet1PicInfo(iFodo, aucFpage + 1,
01054                                                 tChrLen, &tPicture);
01055                         bSuccess2 = iWordVersion == 2 &&
01056                                         bGet2PicInfo(iFodo, aucFpage + 1,
01057                                                 tChrLen, &tPicture);
01058                         if (bSuccess1 || bSuccess2) {
01059                                 tPicture.ulFileOffset = ulFileOffset;
01060                                 tPicture.ulFileOffsetPicture =
01061                                                 tPicture.ulPictureOffset;
01062                                 vAdd2PictInfoList(&tPicture);
01063                         }
01064                 }
01065         }
01066         ausCharPage = xfree(ausCharPage);
01067 } /* end of vGet2ChrInfo */

Generated by  doxygen 1.6.2