diff options
Diffstat (limited to 'sw/source/filter/ww8/dump/ww8scan.cxx')
-rw-r--r-- | sw/source/filter/ww8/dump/ww8scan.cxx | 6674 |
1 files changed, 6674 insertions, 0 deletions
diff --git a/sw/source/filter/ww8/dump/ww8scan.cxx b/sw/source/filter/ww8/dump/ww8scan.cxx new file mode 100644 index 000000000000..9b90b721697a --- /dev/null +++ b/sw/source/filter/ww8/dump/ww8scan.cxx @@ -0,0 +1,6674 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ww8scan.cxx,v $ + * $Revision: 1.16 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ + + +#ifndef __SGI_STL_ALGORITHM +#include <algorithm> +#endif +#ifndef __SGI_STL_FUNCTIONAL +#include <functional> +#endif + +#include <string.h> // memset() +#include <osl/endian.h> +#include <rtl/tencinfo.h> + +#ifdef DUMP + +#define ERR_SWG_READ_ERROR 1234 +#define ASSERT( a, b ) + +#else // dump +#include <swerror.h> // ERR_WW6_... +#include <errhdl.hxx> // ASSERT() +#include <swtypes.hxx> // DELETEZ + +#endif // dump +#include <tools/debug.hxx> +#include "ww8scan.hxx" + +#define ASSERT_RET_ON_FAIL( aCon, aError, aRet ) \ + ASSERT(aCon, aError); \ + if (!(aCon)) \ + return aRet; + +//-begin +namespace SL +{ +# define IMPLCONSTSTRINGARRAY(X) const char a##X[] = "" #X "" + IMPLCONSTSTRINGARRAY(ObjectPool); + IMPLCONSTSTRINGARRAY(1Table); + IMPLCONSTSTRINGARRAY(0Table); + IMPLCONSTSTRINGARRAY(Data); + IMPLCONSTSTRINGARRAY(CheckBox); + IMPLCONSTSTRINGARRAY(TextBox); + IMPLCONSTSTRINGARRAY(TextField); + IMPLCONSTSTRINGARRAY(MSMacroCmds); +} + +template<class C> bool wwString<C>::TestBeltAndBraces(const SvStream& rStrm) +{ + bool bRet = false; + sal_uInt32 nOldPos = rStrm.Tell(); + SvStream &rMutableStrm = const_cast<SvStream &>(rStrm); + sal_uInt32 nLen = rMutableStrm.Seek(STREAM_SEEK_TO_END); + rMutableStrm.Seek(nOldPos); + C nBelt; + rMutableStrm >> nBelt; + nBelt *= sizeof(C); + if (nOldPos + sizeof(C) + nBelt + sizeof(C) <= nLen && + !rStrm.GetError() && !rStrm.IsEof()) + { + rMutableStrm.SeekRel(nBelt); + if (!rStrm.GetError()) + { + C cBraces; + rMutableStrm >> cBraces; + if (!rMutableStrm.GetError() && cBraces == 0) + bRet = true; + } + } + rMutableStrm.Seek(nOldPos); + return bRet; +} + +template<class C> class wwSortedArray +{ +private: + //The array e.g. of sprms. + C *mpWwSprmTab; + size_t mnNoElems; +public: + wwSortedArray(C *pWwSprmTab, size_t nNoElems) + : mpWwSprmTab(pWwSprmTab), mnNoElems(nNoElems) + { + ASSERT(mnNoElems && pWwSprmTab, "WW8: empty Array: Don't do that"); + std::sort(mpWwSprmTab, mpWwSprmTab + mnNoElems); +#ifdef DEBUG + bool bBroken=false; + rtl::OUString sError; + const C *pIter = mpWwSprmTab; + const C *pBeforeEnd = mpWwSprmTab + mnNoElems - 1; + while (pIter < pBeforeEnd) + { + if (*pIter == *(pIter+1)) + { + if (!bBroken) + { + sError = rtl::OUString::createFromAscii( + "WW8: Duplicate in list, almost certainly don't want that!\n" + "(You will not see this message again unless you restart)\n" + "Extra entries are...\n"); + bBroken=true; + } + + size_t nSize = sizeof(C); + const sal_uInt8 *pHack = + reinterpret_cast<const sal_uInt8 *>(&(*pIter)); + for (size_t i=0; i < nSize; ++i) + { + sError += rtl::OUString::valueOf( + static_cast<sal_Int32>(pHack[i]), 16); + sError += rtl::OUString::valueOf(sal_Unicode(' ')); + } + sError += rtl::OUString::valueOf(sal_Unicode('\n')); + while (*pIter == *(pIter+1) && pIter < pBeforeEnd) + ++pIter; + } + else + ++pIter; + } + if (bBroken) + DbgError(rtl::OUStringToOString(sError, RTL_TEXTENCODING_ASCII_US)); +#endif + } + + //Find an entry, return its address if found and 0 if not + const C *search(C aSrch) const; +}; + +template<class C> const C *wwSortedArray<C>::search(C aSrch) const +{ + std::pair<C *, C *> aPair = + std::equal_range(mpWwSprmTab, mpWwSprmTab + mnNoElems, aSrch); + if (aPair.first != aPair.second) + return aPair.first; + else + return 0; +} + +bool operator==(const SprmInfo &rFirst, const SprmInfo &rSecond) +{ + return (rFirst.nId == rSecond.nId); +} + +bool operator<(const SprmInfo &rFirst, const SprmInfo &rSecond) +{ + return (rFirst.nId < rSecond.nId); +} + +const wwSprmSearcher *wwSprmParser::GetWW6SprmSearcher() +{ + //double lock me + // WW7- Sprms + static SprmInfo aSprms[] = + { + { 0, 0, L_FIX}, // "Default-sprm", wird uebersprungen + { 2, 2, L_FIX}, // "sprmPIstd", pap.istd (style code) + { 3, 3, L_VAR}, // "sprmPIstdPermute pap.istd permutation + { 4, 1, L_FIX}, // "sprmPIncLv1" pap.istddifference + { 5, 1, L_FIX}, // "sprmPJc" pap.jc (justification) + { 6, 1, L_FIX}, // "sprmPFSideBySide" pap.fSideBySide + { 7, 1, L_FIX}, // "sprmPFKeep" pap.fKeep + { 8, 1, L_FIX}, // "sprmPFKeepFollow " pap.fKeepFollow + { 9, 1, L_FIX}, // "sprmPPageBreakBefore" pap.fPageBreakBefore + { 10, 1, L_FIX}, // "sprmPBrcl" pap.brcl + { 11, 1, L_FIX}, // "sprmPBrcp" pap.brcp + { 12, 0, L_VAR}, // "sprmPAnld" pap.anld (ANLD structure) + { 13, 1, L_FIX}, // "sprmPNLvlAnm" pap.nLvlAnm nn + { 14, 1, L_FIX}, // "sprmPFNoLineNumb" pap.fNoLnn + { 15, 0, L_VAR}, // "?sprmPChgTabsPapx" pap.itbdMac, ... + { 16, 2, L_FIX}, // "sprmPDxaRight" pap.dxaRight + { 17, 2, L_FIX}, // "sprmPDxaLeft" pap.dxaLeft + { 18, 2, L_FIX}, // "sprmPNest" pap.dxaLeft + { 19, 2, L_FIX}, // "sprmPDxaLeft1" pap.dxaLeft1 + { 20, 4, L_FIX}, // "sprmPDyaLine" pap.lspd an LSPD + { 21, 2, L_FIX}, // "sprmPDyaBefore" pap.dyaBefore + { 22, 2, L_FIX}, // "sprmPDyaAfter" pap.dyaAfter + { 23, 0, L_VAR}, // "?sprmPChgTabs" pap.itbdMac, pap.rgdxaTab, ... + { 24, 1, L_FIX}, // "sprmPFInTable" pap.fInTable + { 25, 1, L_FIX}, // "sprmPTtp" pap.fTtp + { 26, 2, L_FIX}, // "sprmPDxaAbs" pap.dxaAbs + { 27, 2, L_FIX}, // "sprmPDyaAbs" pap.dyaAbs + { 28, 2, L_FIX}, // "sprmPDxaWidth" pap.dxaWidth + { 29, 1, L_FIX}, // "sprmPPc" pap.pcHorz, pap.pcVert + { 30, 2, L_FIX}, // "sprmPBrcTop10" pap.brcTop BRC10 + { 31, 2, L_FIX}, // "sprmPBrcLeft10" pap.brcLeft BRC10 + { 32, 2, L_FIX}, // "sprmPBrcBottom10" pap.brcBottom BRC10 + { 33, 2, L_FIX}, // "sprmPBrcRight10" pap.brcRight BRC10 + { 34, 2, L_FIX}, // "sprmPBrcBetween10" pap.brcBetween BRC10 + { 35, 2, L_FIX}, // "sprmPBrcBar10" pap.brcBar BRC10 + { 36, 2, L_FIX}, // "sprmPFromText10" pap.dxaFromText dxa + { 37, 1, L_FIX}, // "sprmPWr" pap.wr wr + { 38, 2, L_FIX}, // "sprmPBrcTop" pap.brcTop BRC + { 39, 2, L_FIX}, // "sprmPBrcLeft" pap.brcLeft BRC + { 40, 2, L_FIX}, // "sprmPBrcBottom" pap.brcBottom BRC + { 41, 2, L_FIX}, // "sprmPBrcRight" pap.brcRight BRC + { 42, 2, L_FIX}, // "sprmPBrcBetween" pap.brcBetween BRC + { 43, 2, L_FIX}, // "sprmPBrcBar" pap.brcBar BRC word + { 44, 1, L_FIX}, // "sprmPFNoAutoHyph" pap.fNoAutoHyph + { 45, 2, L_FIX}, // "sprmPWHeightAbs" pap.wHeightAbs w + { 46, 2, L_FIX}, // "sprmPDcs" pap.dcs DCS + { 47, 2, L_FIX}, // "sprmPShd" pap.shd SHD + { 48, 2, L_FIX}, // "sprmPDyaFromText" pap.dyaFromText dya + { 49, 2, L_FIX}, // "sprmPDxaFromText" pap.dxaFromText dxa + { 50, 1, L_FIX}, // "sprmPFLocked" pap.fLocked 0 or 1 byte + { 51, 1, L_FIX}, // "sprmPFWidowControl" pap.fWidowControl 0 or 1 byte + { 52, 0, L_FIX}, // "?sprmPRuler 52" + { 64, 0, L_VAR}, // rtl property ? + { 65, 1, L_FIX}, // "sprmCFStrikeRM" chp.fRMarkDel 1 or 0 bit + { 66, 1, L_FIX}, // "sprmCFRMark" chp.fRMark 1 or 0 bit + { 67, 1, L_FIX}, // "sprmCFFldVanish" chp.fFldVanish 1 or 0 bit + { 68, 0, L_VAR}, // "sprmCPicLocation" chp.fcPic and chp.fSpec + { 69, 2, L_FIX}, // "sprmCIbstRMark" chp.ibstRMark index into sttbRMark + { 70, 4, L_FIX}, // "sprmCDttmRMark" chp.dttm DTTM long + { 71, 1, L_FIX}, // "sprmCFData" chp.fData 1 or 0 bit + { 72, 2, L_FIX}, // "sprmCRMReason" chp.idslRMReason an index to a table + { 73, 3, L_FIX}, // "sprmCChse" chp.fChsDiff and chp.chse + { 74, 0, L_VAR}, // "sprmCSymbol" chp.fSpec, chp.chSym and chp.ftcSym + { 75, 1, L_FIX}, // "sprmCFOle2" chp.fOle2 1 or 0 bit + { 79, 0, L_VAR}, // unknown + { 80, 2, L_FIX}, // "sprmCIstd" chp.istd istd, see stylesheet definition + { 81, 0, L_VAR}, // "sprmCIstdPermute" chp.istd permutation vector + { 82, 0, L_VAR}, // "sprmCDefault" whole CHP + { 83, 0, L_FIX}, // "sprmCPlain" whole CHP + { 85, 1, L_FIX}, // "sprmCFBold" chp.fBold 0,1, 128, or 129 + { 86, 1, L_FIX}, // "sprmCFItalic" chp.fItalic 0,1, 128, or 129 + { 87, 1, L_FIX}, // "sprmCFStrike" chp.fStrike 0,1, 128, or 129 + { 88, 1, L_FIX}, // "sprmCFOutline" chp.fOutline 0,1, 128, or 129 + { 89, 1, L_FIX}, // "sprmCFShadow" chp.fShadow 0,1, 128, or 129 + { 90, 1, L_FIX}, // "sprmCFSmallCaps" chp.fSmallCaps 0,1, 128, or 129 + { 91, 1, L_FIX}, // "sprmCFCaps" chp.fCaps 0,1, 128, or 129 + { 92, 1, L_FIX}, // "sprmCFVanish" chp.fVanish 0,1, 128, or 129 + { 93, 2, L_FIX}, // "sprmCFtc" chp.ftc ftc word + { 94, 1, L_FIX}, // "sprmCKul" chp.kul kul byte + { 95, 3, L_FIX}, // "sprmCSizePos" chp.hps, chp.hpsPos + { 96, 2, L_FIX}, // "sprmCDxaSpace" chp.dxaSpace dxa + { 97, 2, L_FIX}, // "sprmCLid" chp.lid LID + { 98, 1, L_FIX}, // "sprmCIco" chp.ico ico byte + { 99, 2, L_FIX}, // "sprmCHps" chp.hps hps !word! + {100, 1, L_FIX}, // "sprmCHpsInc" chp.hps + {101, 2, L_FIX}, // "sprmCHpsPos" chp.hpsPos hps !word! + {102, 1, L_FIX}, // "sprmCHpsPosAdj" chp.hpsPos hps + {103, 0, L_VAR}, // "?sprmCMajority" chp.fBold, chp.fItalic, ... + {104, 1, L_FIX}, // "sprmCIss" chp.iss iss + {105, 0, L_VAR}, // "sprmCHpsNew50" chp.hps hps variable width + {106, 0, L_VAR}, // "sprmCHpsInc1" chp.hps complex + {107, 2, L_FIX}, // "sprmCHpsKern" chp.hpsKern hps + {108, 0, L_VAR}, // "sprmCMajority50" chp.fBold, chp.fItalic, ... + {109, 2, L_FIX}, // "sprmCHpsMul" chp.hps percentage to grow hps + {110, 2, L_FIX}, // "sprmCCondHyhen" chp.ysri ysri + {111, 2, L_FIX}, // unknown + {112, 2, L_FIX}, // unknown + {113, 0, L_VAR}, // rtl property ? + {115, 0, L_VAR}, // rtl property ? + {116, 0, L_VAR}, // unknown + {117, 1, L_FIX}, // "sprmCFSpec" chp.fSpec 1 or 0 bit + {118, 1, L_FIX}, // "sprmCFObj" chp.fObj 1 or 0 bit + {119, 1, L_FIX}, // "sprmPicBrcl" pic.brcl brcl (see PIC definition) + {120,12, L_VAR}, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft, + {121, 2, L_FIX}, // "sprmPicBrcTop" pic.brcTop BRC word + {122, 2, L_FIX}, // "sprmPicBrcLeft" pic.brcLeft BRC word + {123, 2, L_FIX}, // "sprmPicBrcBottom" pic.brcBottom BRC word + {124, 2, L_FIX}, // "sprmPicBrcRight" pic.brcRight BRC word + {131, 1, L_FIX}, // "sprmSScnsPgn" sep.cnsPgn cns byte + {132, 1, L_FIX}, // "sprmSiHeadingPgn" sep.iHeadingPgn + {133, 0, L_VAR}, // "sprmSOlstAnm" sep.olstAnm OLST variable length + {136, 3, L_FIX}, // "sprmSDxaColWidth" sep.rgdxaColWidthSpacing complex + {137, 3, L_FIX}, // "sprmSDxaColSpacing" sep.rgdxaColWidthSpacing + {138, 1, L_FIX}, // "sprmSFEvenlySpaced" sep.fEvenlySpaced 1 or 0 + {139, 1, L_FIX}, // "sprmSFProtected" sep.fUnlocked 1 or 0 byte + {140, 2, L_FIX}, // "sprmSDmBinFirst" sep.dmBinFirst word + {141, 2, L_FIX}, // "sprmSDmBinOther" sep.dmBinOther word + {142, 1, L_FIX}, // "sprmSBkc" sep.bkc bkc byte + {143, 1, L_FIX}, // "sprmSFTitlePage" sep.fTitlePage 0 or 1 byte + {144, 2, L_FIX}, // "sprmSCcolumns" sep.ccolM1 # of cols - 1 word + {145, 2, L_FIX}, // "sprmSDxaColumns" sep.dxaColumns dxa word + {146, 1, L_FIX}, // "sprmSFAutoPgn" sep.fAutoPgn obsolete byte + {147, 1, L_FIX}, // "sprmSNfcPgn" sep.nfcPgn nfc byte + {148, 2, L_FIX}, // "sprmSDyaPgn" sep.dyaPgn dya short + {149, 2, L_FIX}, // "sprmSDxaPgn" sep.dxaPgn dya short + {150, 1, L_FIX}, // "sprmSFPgnRestart" sep.fPgnRestart 0 or 1 byte + {151, 1, L_FIX}, // "sprmSFEndnote" sep.fEndnote 0 or 1 byte + {152, 1, L_FIX}, // "sprmSLnc" sep.lnc lnc byte + {153, 1, L_FIX}, // "sprmSGprfIhdt" sep.grpfIhdt grpfihdt + {154, 2, L_FIX}, // "sprmSNLnnMod" sep.nLnnMod non-neg int. word + {155, 2, L_FIX}, // "sprmSDxaLnn" sep.dxaLnn dxa word + {156, 2, L_FIX}, // "sprmSDyaHdrTop" sep.dyaHdrTop dya word + {157, 2, L_FIX}, // "sprmSDyaHdrBottom" sep.dyaHdrBottom dya word + {158, 1, L_FIX}, // "sprmSLBetween" sep.fLBetween 0 or 1 byte + {159, 1, L_FIX}, // "sprmSVjc" sep.vjc vjc byte + {160, 2, L_FIX}, // "sprmSLnnMin" sep.lnnMin lnn word + {161, 2, L_FIX}, // "sprmSPgnStart" sep.pgnStart pgn word + {162, 1, L_FIX}, // "sprmSBOrientation" sep.dmOrientPage dm byte + {163, 0, L_FIX}, // "?SprmSBCustomize 163" + {164, 2, L_FIX}, // "sprmSXaPage" sep.xaPage xa word + {165, 2, L_FIX}, // "sprmSYaPage" sep.yaPage ya word + {166, 2, L_FIX}, // "sprmSDxaLeft" sep.dxaLeft dxa word + {167, 2, L_FIX}, // "sprmSDxaRight" sep.dxaRight dxa word + {168, 2, L_FIX}, // "sprmSDyaTop" sep.dyaTop dya word + {169, 2, L_FIX}, // "sprmSDyaBottom" sep.dyaBottom dya word + {170, 2, L_FIX}, // "sprmSDzaGutter" sep.dzaGutter dza word + {171, 2, L_FIX}, // "sprmSDMPaperReq" sep.dmPaperReq dm word + {179, 0, L_VAR}, // rtl property ? + {181, 0, L_VAR}, // rtl property ? + {182, 2, L_FIX}, // "sprmTJc" tap.jc jc (low order byte is significant) + {183, 2, L_FIX}, // "sprmTDxaLeft" tap.rgdxaCenter dxa word + {184, 2, L_FIX}, // "sprmTDxaGapHalf" tap.dxaGapHalf, tap.rgdxaCenter + {185, 1, L_FIX}, // "sprmTFCantSplit" tap.fCantSplit 1 or 0 byte + {186, 1, L_FIX}, // "sprmTTableHeader" tap.fTableHeader 1 or 0 byte + {187,12, L_FIX}, // "sprmTTableBorders" tap.rgbrcTable complex 12 bytes + {188, 0, L_VAR}, // "sprmTDefTable10" tap.rgdxaCenter, tap.rgtc complex + {189, 2, L_FIX}, // "sprmTDyaRowHeight" tap.dyaRowHeight dya word + {190, 0, L_VAR2},// "sprmTDefTable" tap.rgtc complex + {191, 1, L_VAR}, // "sprmTDefTableShd" tap.rgshd complex + {192, 4, L_FIX}, // "sprmTTlp" tap.tlp TLP 4 bytes + {193, 5, L_FIX}, // "sprmTSetBrc" tap.rgtc[].rgbrc complex 5 bytes + {194, 4, L_FIX}, // "sprmTInsert" tap.rgdxaCenter,tap.rgtc complex + {195, 2, L_FIX}, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc complex + {196, 4, L_FIX}, // "sprmTDxaCol" tap.rgdxaCenter complex + {197, 2, L_FIX}, // "sprmTMerge" tap.fFirstMerged, tap.fMerged complex + {198, 2, L_FIX}, // "sprmTSplit" tap.fFirstMerged, tap.fMerged complex + {199, 5, L_FIX}, // "sprmTSetBrc10" tap.rgtc[].rgbrc complex 5 bytes + {200, 4, L_FIX} // "sprmTSetShd", tap.rgshd complex 4 bytes + }; + + static wwSprmSearcher aSprmSrch(aSprms, sizeof(aSprms) / sizeof(aSprms[0])); + return &aSprmSrch; +}; + +const wwSprmSearcher *wwSprmParser::GetWW8SprmSearcher() +{ + //double lock me + //WW8+ Sprms + static SprmInfo aSprms[] = + { + { 0, 0, L_FIX}, // "Default-sprm"/ wird uebersprungen + {0x4600, 2, L_FIX}, // "sprmPIstd" pap.istd;istd (style code);short; + {0xC601, 0, L_VAR}, // "sprmPIstdPermute" pap.istd;permutation vector + {0x2602, 1, L_FIX}, // "sprmPIncLvl" pap.istd, pap.lvl;difference + // between istd of base PAP and istd of PAP to be + // produced + {0x2403, 1, L_FIX}, // "sprmPJc" pap.jc;jc (justification);byte; + {0x2404, 1, L_FIX}, // "sprmPFSideBySide" pap.fSideBySide;0 or 1;byte; + {0x2405, 1, L_FIX}, // "sprmPFKeep" pap.fKeep;0 or 1;byte; + {0x2406, 1, L_FIX}, // "sprmPFKeepFollow" pap.fKeepFollow;0 or 1;byte; + {0x2407, 1, L_FIX}, // "sprmPFPageBreakBefore" pap.fPageBreakBefore; + // 0 or 1 + {0x2408, 1, L_FIX}, // "sprmPBrcl" pap.brcl;brcl;byte; + {0x2409, 1, L_FIX}, // "sprmPBrcp" pap.brcp;brcp;byte; + {0x260A, 1, L_FIX}, // "sprmPIlvl" pap.ilvl;ilvl;byte; + {0x460B, 2, L_FIX}, // "sprmPIlfo" pap.ilfo;ilfo (list index) ;short; + {0x240C, 1, L_FIX}, // "sprmPFNoLineNumb" pap.fNoLnn;0 or 1;byte; + {0xC60D, 0, L_VAR}, // "sprmPChgTabsPapx" pap.itbdMac, pap.rgdxaTab, + // pap.rgtbd;complex + {0x840E, 2, L_FIX}, // "sprmPDxaRight" pap.dxaRight;dxa;word; + {0x840F, 2, L_FIX}, // "sprmPDxaLeft" pap.dxaLeft;dxa;word; + {0x4610, 2, L_FIX}, // "sprmPNest" pap.dxaLeft;dxa + {0x8411, 2, L_FIX}, // "sprmPDxaLeft1" pap.dxaLeft1;dxa;word; + {0x6412, 4, L_FIX}, // "sprmPDyaLine" pap.lspd;an LSPD, a long word + // structure consisting of a short of dyaLine + // followed by a short of fMultLinespace + {0xA413, 2, L_FIX}, // "sprmPDyaBefore" pap.dyaBefore;dya;word; + {0xA414, 2, L_FIX}, // "sprmPDyaAfter" pap.dyaAfter;dya;word; + {0xC615, 0, L_VAR}, // "sprmPChgTabs" pap.itbdMac, pap.rgdxaTab, + // pap.rgtbd;complex + {0x2416, 1, L_FIX}, // "sprmPFInTable" pap.fInTable;0 or 1;byte; + {0x2417, 1, L_FIX}, // "sprmPFTtp" pap.fTtp;0 or 1;byte; + {0x8418, 2, L_FIX}, // "sprmPDxaAbs" pap.dxaAbs;dxa;word; + {0x8419, 2, L_FIX}, // "sprmPDyaAbs" pap.dyaAbs;dya;word; + {0x841A, 2, L_FIX}, // "sprmPDxaWidth" pap.dxaWidth;dxa;word; + {0x261B, 1, L_FIX}, // "sprmPPc" pap.pcHorz, pap.pcVert;complex + {0x461C, 2, L_FIX}, // "sprmPBrcTop10" pap.brcTop;BRC10;word; + {0x461D, 2, L_FIX}, // "sprmPBrcLeft10" pap.brcLeft;BRC10;word; + {0x461E, 2, L_FIX}, // "sprmPBrcBottom10" pap.brcBottom;BRC10;word; + {0x461F, 2, L_FIX}, // "sprmPBrcRight10" pap.brcRight;BRC10;word; + {0x4620, 2, L_FIX}, // "sprmPBrcBetween10" pap.brcBetween;BRC10;word; + {0x4621, 2, L_FIX}, // "sprmPBrcBar10" pap.brcBar;BRC10;word; + {0x4622, 2, L_FIX}, // "sprmPDxaFromText10" pap.dxaFromText;dxa;word; + {0x2423, 1, L_FIX}, // "sprmPWr" pap.wr;wr + {0x6424, 4, L_FIX}, // "sprmPBrcTop" pap.brcTop;BRC;long; + {0x6425, 4, L_FIX}, // "sprmPBrcLeft" pap.brcLeft;BRC;long; + {0x6426, 4, L_FIX}, // "sprmPBrcBottom" pap.brcBottom;BRC;long; + {0x6427, 4, L_FIX}, // "sprmPBrcRight" pap.brcRight;BRC;long; + {0x6428, 4, L_FIX}, // "sprmPBrcBetween" pap.brcBetween;BRC;long; + {0x6629, 4, L_FIX}, // "sprmPBrcBar" pap.brcBar;BRC;long; + {0x242A, 1, L_FIX}, // "sprmPFNoAutoHyph" pap.fNoAutoHyph;0 or 1;byte; + {0x442B, 2, L_FIX}, // "sprmPWHeightAbs" pap.wHeightAbs;w;word; + {0x442C, 2, L_FIX}, // "sprmPDcs" pap.dcs;DCS;short; + {0x442D, 2, L_FIX}, // "sprmPShd" pap.shd;SHD;word; + {0x842E, 2, L_FIX}, // "sprmPDyaFromText" pap.dyaFromText;dya;word; + {0x842F, 2, L_FIX}, // "sprmPDxaFromText" pap.dxaFromText;dxa;word; + {0x2430, 1, L_FIX}, // "sprmPFLocked" pap.fLocked;0 or 1;byte; + {0x2431, 1, L_FIX}, // "sprmPFWidowControl" pap.fWidowControl;0 or 1 + {0xC632, 0, L_VAR}, // "sprmPRuler" ;;variable length; + {0x2433, 1, L_FIX}, // "sprmPFKinsoku" pap.fKinsoku;0 or 1;byte; + {0x2434, 1, L_FIX}, // "sprmPFWordWrap" pap.fWordWrap;0 or 1;byte; + {0x2435, 1, L_FIX}, // "sprmPFOverflowPunct" pap.fOverflowPunct;0 or 1 + {0x2436, 1, L_FIX}, // "sprmPFTopLinePunct" pap.fTopLinePunct;0 or 1 + {0x2437, 1, L_FIX}, // "sprmPFAutoSpaceDE" pap.fAutoSpaceDE;0 or 1 + {0x2438, 1, L_FIX}, // "sprmPFAutoSpaceDN" pap.fAutoSpaceDN;0 or 1 + {0x4439, 2, L_FIX}, // "sprmPWAlignFont" pap.wAlignFont;iFa + {0x443A, 2, L_FIX}, // "sprmPFrameTextFlow" pap.fVertical pap.fBackward + // pap.fRotateFont;complex + {0x243B, 1, L_FIX}, // "sprmPISnapBaseLine" obsolete: not applicable in + // Word97 and later versions; + {0xC63E, 0, L_VAR}, // "sprmPAnld" pap.anld;;variable length; + {0xC63F, 0, L_VAR}, // "sprmPPropRMark" pap.fPropRMark;complex + {0x2640, 1, L_FIX}, // "sprmPOutLvl" pap.lvl;has no effect if pap.istd + // is < 1 or is > 9 + {0x2441, 1, L_FIX}, // "sprmPFBiDi" ;;byte; + {0x2443, 1, L_FIX}, // "sprmPFNumRMIns" pap.fNumRMIns;1 or 0;bit; + {0x2444, 1, L_FIX}, // "sprmPCrLf" ;;byte; + {0xC645, 0, L_VAR}, // "sprmPNumRM" pap.numrm;;variable length; + {0x6645, 4, L_FIX}, // "sprmPHugePapx" fc in the data stream to locate + // the huge grpprl + {0x6646, 4, L_FIX}, // "sprmPHugePapx" fc in the data stream to locate + // the huge grpprl + {0x2447, 1, L_FIX}, // "sprmPFUsePgsuSettings" pap.fUsePgsuSettings; + // 1 or 0 + {0x2448, 1, L_FIX}, // "sprmPFAdjustRight" pap.fAdjustRight;1 or 0;byte; + {0x0800, 1, L_FIX}, // "sprmCFRMarkDel" chp.fRMarkDel;1 or 0;bit; + {0x0801, 1, L_FIX}, // "sprmCFRMark" chp.fRMark;1 or 0;bit; + {0x0802, 1, L_FIX}, // "sprmCFFldVanish" chp.fFldVanish;1 or 0;bit; + {0x6A03, 4, L_FIX}, // "sprmCPicLocation" chp.fcPic and chp.fSpec; + {0x4804, 2, L_FIX}, // "sprmCIbstRMark" chp.ibstRMark;index into + // sttbRMark + {0x6805, 4, L_FIX}, // "sprmCDttmRMark" chp.dttmRMark;DTTM;long; + {0x0806, 1, L_FIX}, // "sprmCFData" chp.fData;1 or 0;bit; + {0x4807, 2, L_FIX}, // "sprmCIdslRMark" chp.idslRMReason;an index to a + // table of strings defined in Word 6.0 + // executables;short; + {0xEA08, 1, L_FIX}, // "sprmCChs" chp.fChsDiff and chp.chse; + {0x6A09, 4, L_FIX}, // "sprmCSymbol" chp.fSpec, chp.xchSym and + // chp.ftcSym + {0x080A, 1, L_FIX}, // "sprmCFOle2" chp.fOle2;1 or 0;bit; + {0x480B, 0, L_FIX}, // "sprmCIdCharType" obsolete: not applicable in + // Word97 and later versions;;; + {0x2A0C, 1, L_FIX}, // "sprmCHighlight" chp.fHighlight, + // chp.icoHighlight;ico (fHighlight is set to 1 iff + // ico is not 0) + {0x680E, 4, L_FIX}, // "sprmCObjLocation" chp.fcObj;FC;long; + {0x2A10, 0, L_FIX}, // "sprmCFFtcAsciSymb" ;;; + {0x4A30, 2, L_FIX}, // "sprmCIstd" chp.istd;istd, see stylesheet def + {0xCA31, 0, L_VAR}, // "sprmCIstdPermute" chp.istd;permutation vector + {0x2A32, 0, L_VAR}, // "sprmCDefault" whole CHP;none;variable length; + {0x2A33, 0, L_FIX}, // "sprmCPlain" whole CHP;none;0; + {0x2A34, 1, L_FIX}, // "sprmCKcd" ;;; + {0x0835, 1, L_FIX}, // "sprmCFBold" chp.fBold;0,1, 128, or 129 + {0x0836, 1, L_FIX}, // "sprmCFItalic" chp.fItalic;0,1, 128, or 129 + {0x0837, 1, L_FIX}, // "sprmCFStrike" chp.fStrike;0,1, 128, or 129 + {0x0838, 1, L_FIX}, // "sprmCFOutline" chp.fOutline;0,1, 128, or 129 + {0x0839, 1, L_FIX}, // "sprmCFShadow" chp.fShadow;0,1, 128, or 129 + {0x083A, 1, L_FIX}, // "sprmCFSmallCaps" chp.fSmallCaps;0,1, 128, or 129 + {0x083B, 1, L_FIX}, // "sprmCFCaps" chp.fCaps;0,1, 128, or 129 + {0x083C, 1, L_FIX}, // "sprmCFVanish" chp.fVanish;0,1, 128, or 129 + {0x4A3D, 2, L_FIX}, // "sprmCFtcDefault" ;ftc, only used internally + {0x2A3E, 1, L_FIX}, // "sprmCKul" chp.kul;kul;byte; + {0xEA3F, 3, L_FIX}, // "sprmCSizePos" chp.hps, chp.hpsPos;3 bytes; + {0x8840, 2, L_FIX}, // "sprmCDxaSpace" chp.dxaSpace;dxa;word; + {0x4A41, 2, L_FIX}, // "sprmCLid" ;only used internally never stored + {0x2A42, 1, L_FIX}, // "sprmCIco" chp.ico;ico;byte; + {0x4A43, 2, L_FIX}, // "sprmCHps" chp.hps;hps + {0x2A44, 1, L_FIX}, // "sprmCHpsInc" chp.hps; + {0x4845, 2, L_FIX}, // "sprmCHpsPos" chp.hpsPos;hps;short; (doc wrong) + {0x2A46, 1, L_FIX}, // "sprmCHpsPosAdj" chp.hpsPos;hps + {0xCA47, 0, L_VAR}, // "sprmCMajority" chp.fBold, chp.fItalic, + // chp.fSmallCaps, chp.fVanish, chp.fStrike, + // chp.fCaps, chp.rgftc, chp.hps, chp.hpsPos, + // chp.kul, chp.dxaSpace, chp.ico, + // chp.rglid;complex;variable length, length byte + // plus size of following grpprl; + {0x2A48, 1, L_FIX}, // "sprmCIss" chp.iss;iss;byte; + {0xCA49, 0, L_VAR}, // "sprmCHpsNew50" chp.hps;hps;variable width + {0xCA4A, 0, L_VAR}, // "sprmCHpsInc1" chp.hps;complex + {0x484B, 2, L_FIX}, // "sprmCHpsKern" chp.hpsKern;hps;short; + {0xCA4C, 2, L_FIX}, // "sprmCMajority50" chp.fBold, chp.fItalic, + // chp.fSmallCaps, chp.fVanish, chp.fStrike, + // chp.fCaps, chp.ftc, chp.hps, chp.hpsPos, chp.kul, + // chp.dxaSpace, chp.ico,;complex + {0x4A4D, 2, L_FIX}, // "sprmCHpsMul" chp.hps;percentage to grow hps + {0x484E, 2, L_FIX}, // "sprmCYsri" chp.ysri;ysri;short; + {0x4A4F, 2, L_FIX}, // "sprmCRgFtc0" chp.rgftc[0];ftc for ASCII text + {0x4A50, 2, L_FIX}, // "sprmCRgFtc1" chp.rgftc[1];ftc for Far East text + {0x4A51, 2, L_FIX}, // "sprmCRgFtc2" chp.rgftc[2];ftc for non-FE text + {0x4852, 2, L_FIX}, // "sprmCCharScale" + {0x2A53, 1, L_FIX}, // "sprmCFDStrike" chp.fDStrike;;byte; + {0x0854, 1, L_FIX}, // "sprmCFImprint" chp.fImprint;1 or 0;bit; + {0x0855, 1, L_FIX}, // "sprmCFSpec" chp.fSpec ;1 or 0;bit; + {0x0856, 1, L_FIX}, // "sprmCFObj" chp.fObj;1 or 0;bit; + {0xCA57, 0, L_VAR}, // "sprmCPropRMark" chp.fPropRMark, + // chp.ibstPropRMark, chp.dttmPropRMark;Complex + {0x0858, 1, L_FIX}, // "sprmCFEmboss" chp.fEmboss;1 or 0;bit; + {0x2859, 1, L_FIX}, // "sprmCSfxText" chp.sfxtText;text animation;byte; + {0x085A, 1, L_FIX}, // "sprmCFBiDi" ;;; + {0x085B, 1, L_FIX}, // "sprmCFDiacColor" ;;; + {0x085C, 1, L_FIX}, // "sprmCFBoldBi" ;;; + {0x085D, 1, L_FIX}, // "sprmCFItalicBi" ;;; + {0x4A5E, 2, L_FIX}, + {0x485F, 2, L_FIX}, // "sprmCLidBi" ;;; + {0x4A60, 1, L_FIX}, // "sprmCIcoBi" ;;; + {0x4A61, 2, L_FIX}, // "sprmCHpsBi" ;;; + {0xCA62, 0, L_VAR}, // "sprmCDispFldRMark" chp.fDispFldRMark, + // chp.ibstDispFldRMark, chp.dttmDispFldRMark ; + {0x4863, 2, L_FIX}, // "sprmCIbstRMarkDel" chp.ibstRMarkDel;index into + // sttbRMark;short; + {0x6864, 4, L_FIX}, // "sprmCDttmRMarkDel" chp.dttmRMarkDel;DTTM;long; + {0x6865, 4, L_FIX}, // "sprmCBrc" chp.brc;BRC;long; + {0x4866, 2, L_FIX}, // "sprmCShd" chp.shd;SHD;short; + {0x4867, 2, L_FIX}, // "sprmCIdslRMarkDel" chp.idslRMReasonDel;an index + // to a table of strings defined in Word 6.0 + // executables;short; + {0x0868, 1, L_FIX}, // "sprmCFUsePgsuSettings" + // chp.fUsePgsuSettings;1 or 0 + {0x486B, 2, L_FIX}, // "sprmCCpg" ;;word; + {0x486D, 2, L_FIX}, // "sprmCRgLid0" chp.rglid[0];LID: for non-FE text + {0x486E, 2, L_FIX}, // "sprmCRgLid1" chp.rglid[1];LID: for Far East text + {0x286F, 1, L_FIX}, // "sprmCIdctHint" chp.idctHint;IDCT: + {0x2E00, 1, L_FIX}, // "sprmPicBrcl" pic.brcl;brcl (see PIC definition) + {0xCE01, 0, L_VAR}, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft, + // pic.dyaCropTop pic.dxaCropRight, + // pic.dyaCropBottom;Complex + {0x6C02, 4, L_FIX}, // "sprmPicBrcTop" pic.brcTop;BRC;long; + {0x6C03, 4, L_FIX}, // "sprmPicBrcLeft" pic.brcLeft;BRC;long; + {0x6C04, 4, L_FIX}, // "sprmPicBrcBottom" pic.brcBottom;BRC;long; + {0x6C05, 4, L_FIX}, // "sprmPicBrcRight" pic.brcRight;BRC;long; + {0x3000, 1, L_FIX}, // "sprmScnsPgn" sep.cnsPgn;cns;byte; + {0x3001, 1, L_FIX}, // "sprmSiHeadingPgn" sep.iHeadingPgn;heading number + // level;byte; + {0xD202, 0, L_VAR}, // "sprmSOlstAnm" sep.olstAnm;OLST;variable length; + {0xF203, 3, L_FIX}, // "sprmSDxaColWidth" sep.rgdxaColWidthSpacing; + {0xF204, 3, L_FIX}, // "sprmSDxaColSpacing" sep.rgdxaColWidthSpacing; + // complex + {0x3005, 1, L_FIX}, // "sprmSFEvenlySpaced" sep.fEvenlySpaced;1 or 0 + {0x3006, 1, L_FIX}, // "sprmSFProtected" sep.fUnlocked;1 or 0;byte; + {0x5007, 2, L_FIX}, // "sprmSDmBinFirst" sep.dmBinFirst;;word; + {0x5008, 2, L_FIX}, // "sprmSDmBinOther" sep.dmBinOther;;word; + {0x3009, 1, L_FIX}, // "sprmSBkc" sep.bkc;bkc;byte; + {0x300A, 1, L_FIX}, // "sprmSFTitlePage" sep.fTitlePage;0 or 1;byte; + {0x500B, 2, L_FIX}, // "sprmSCcolumns" sep.ccolM1;# of cols - 1;word; + {0x900C, 2, L_FIX}, // "sprmSDxaColumns" sep.dxaColumns;dxa;word; + {0x300D, 1, L_FIX}, // "sprmSFAutoPgn" sep.fAutoPgn;obsolete;byte; + {0x300E, 1, L_FIX}, // "sprmSNfcPgn" sep.nfcPgn;nfc;byte; + {0xB00F, 2, L_FIX}, // "sprmSDyaPgn" sep.dyaPgn;dya;short; + {0xB010, 2, L_FIX}, // "sprmSDxaPgn" sep.dxaPgn;dya;short; + {0x3011, 1, L_FIX}, // "sprmSFPgnRestart" sep.fPgnRestart;0 or 1;byte; + {0x3012, 1, L_FIX}, // "sprmSFEndnote" sep.fEndnote;0 or 1;byte; + {0x3013, 1, L_FIX}, // "sprmSLnc" sep.lnc;lnc;byte; + {0x3014, 1, L_FIX}, // "sprmSGprfIhdt" sep.grpfIhdt;grpfihdt + {0x5015, 2, L_FIX}, // "sprmSNLnnMod" sep.nLnnMod;non-neg int.;word; + {0x9016, 2, L_FIX}, // "sprmSDxaLnn" sep.dxaLnn;dxa;word; + {0xB017, 2, L_FIX}, // "sprmSDyaHdrTop" sep.dyaHdrTop;dya;word; + {0xB018, 2, L_FIX}, // "sprmSDyaHdrBottom" sep.dyaHdrBottom;dya;word; + {0x3019, 1, L_FIX}, // "sprmSLBetween" sep.fLBetween;0 or 1;byte; + {0x301A, 1, L_FIX}, // "sprmSVjc" sep.vjc;vjc;byte; + {0x501B, 2, L_FIX}, // "sprmSLnnMin" sep.lnnMin;lnn;word; + {0x501C, 2, L_FIX}, // "sprmSPgnStart" sep.pgnStart;pgn;word; + {0x301D, 1, L_FIX}, // "sprmSBOrientation" sep.dmOrientPage;dm;byte; + {0x301E, 1, L_FIX}, // "sprmSBCustomize" ;;; + {0xB01F, 2, L_FIX}, // "sprmSXaPage" sep.xaPage;xa;word; + {0xB020, 2, L_FIX}, // "sprmSYaPage" sep.yaPage;ya;word; + {0xB021, 2, L_FIX}, // "sprmSDxaLeft" sep.dxaLeft;dxa;word; + {0xB022, 2, L_FIX}, // "sprmSDxaRight" sep.dxaRight;dxa;word; + {0x9023, 2, L_FIX}, // "sprmSDyaTop" sep.dyaTop;dya;word; + {0x9024, 2, L_FIX}, // "sprmSDyaBottom" sep.dyaBottom;dya;word; + {0xB025, 2, L_FIX}, // "sprmSDzaGutter" sep.dzaGutter;dza;word; + {0x5026, 2, L_FIX}, // "sprmSDmPaperReq" sep.dmPaperReq;dm;word; + {0xD227, 0, L_VAR}, // "sprmSPropRMark" sep.fPropRMark, + // sep.ibstPropRMark, sep.dttmPropRMark ;complex + {0x3228, 1, L_FIX}, // "sprmSFBiDi" ;;; + {0x3229, 1, L_FIX}, // "sprmSFFacingCol" ;;; + {0x322A, 1, L_FIX}, // "sprmSFRTLGutter", set to one if gutter is on + // right + {0x702B, 4, L_FIX}, // "sprmSBrcTop" sep.brcTop;BRC;long; + {0x702C, 4, L_FIX}, // "sprmSBrcLeft" sep.brcLeft;BRC;long; + {0x702D, 4, L_FIX}, // "sprmSBrcBottom" sep.brcBottom;BRC;long; + {0x702E, 4, L_FIX}, // "sprmSBrcRight" sep.brcRight;BRC;long; + {0x522F, 2, L_FIX}, // "sprmSPgbProp" sep.pgbProp;;word; + {0x7030, 4, L_FIX}, // "sprmSDxtCharSpace" sep.dxtCharSpace;dxt;long; + {0x9031, 2, L_FIX}, // "sprmSDyaLinePitch" + // sep.dyaLinePitch;dya; WRONG:long; RIGHT:short; ! + {0x5032, 2, L_FIX}, // "sprmSClm" ;;; + {0x5033, 2, L_FIX}, // "sprmSTextFlow" sep.wTextFlow;complex + {0x5400, 2, L_FIX}, // "sprmTJc" tap.jc;jc;word (low order byte is + // significant); + {0x9601, 2, L_FIX}, // "sprmTDxaLeft" tap.rgdxaCenter + {0x9602, 2, L_FIX}, // "sprmTDxaGapHalf" tap.dxaGapHalf, + // tap.rgdxaCenter + {0x3403, 1, L_FIX}, // "sprmTFCantSplit" tap.fCantSplit;1 or 0;byte; + {0x3404, 1, L_FIX}, // "sprmTTableHeader" tap.fTableHeader;1 or 0;byte; + {0xD605, 0, L_VAR}, // "sprmTTableBorders" tap.rgbrcTable;complex + {0xD606, 0, L_VAR}, // "sprmTDefTable10" tap.rgdxaCenter, + // tap.rgtc;complex + {0x9407, 2, L_FIX}, // "sprmTDyaRowHeight" tap.dyaRowHeight;dya;word; + {0xD608, 0, L_VAR}, // "sprmTDefTable" tap.rgtc;complex + {0xD609, 0, L_VAR}, // "sprmTDefTableShd" tap.rgshd;complex + {0x740A, 4, L_FIX}, // "sprmTTlp" tap.tlp;TLP;4 bytes; + {0x560B, 1, L_FIX}, // "sprmTFBiDi" ;;; + {0x740C, 1, L_FIX}, // "sprmTHTMLProps" ;;; + {0xD620, 0, L_VAR}, // "sprmTSetBrc" tap.rgtc[].rgbrc;complex + {0x7621, 4, L_FIX}, // "sprmTInsert" tap.rgdxaCenter, tap.rgtc;complex + {0x5622, 2, L_FIX}, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc;complex + {0x7623, 4, L_FIX}, // "sprmTDxaCol" tap.rgdxaCenter;complex + {0x5624, 0, L_VAR}, // "sprmTMerge" tap.fFirstMerged, tap.fMerged; + {0x5625, 0, L_VAR}, // "sprmTSplit" tap.fFirstMerged, tap.fMerged; + {0xD626, 0, L_VAR}, // "sprmTSetBrc10" tap.rgtc[].rgbrc;complex + {0x7627, 0, L_VAR}, // "sprmTSetShd" tap.rgshd;complex + {0x7628, 0, L_VAR}, // "sprmTSetShdOdd" tap.rgshd;complex + {0x7629, 0, L_VAR}, // "sprmTTextFlow" tap.rgtc[].fVerticaltap, + // rgtc[].fBackwardtap, rgtc[].fRotateFont;0 or 10 + // or 10 or 1;word; + {0xD62A, 1, L_FIX}, // "sprmTDiagLine" ;;; + {0xD62B, 0, L_VAR}, // "sprmTVertMerge" tap.rgtc[].vertMerge + {0xD62C, 0, L_VAR}, // "sprmTVertAlign" tap.rgtc[].vertAlign + {0xCA78, 0, L_VAR}, // undocumented "sprmCDoubleLine ?" + {0x6649, 4, L_FIX}, // undocumented + {0xF614, 3, L_FIX}, // undocumented + {0xD612, 0, L_VAR}, // undocumented, new background colours. + {0xD613, 0, L_VAR}, // undocumented + {0xD61A, 0, L_VAR}, // undocumented + {0xD61B, 0, L_VAR}, // undocumented + {0xD61C, 0, L_VAR}, // undocumented + {0xD61D, 0, L_VAR}, // undocumented + {0xD632, 0, L_VAR}, // undocumented + {0xD634, 0, L_VAR}, // undocumented + {0xD238, 0, L_VAR}, // undocumented sep + {0xC64E, 0, L_VAR}, // undocumented + {0xC64F, 0, L_VAR}, // undocumented + {0xC650, 0, L_VAR}, // undocumented + {0xC651, 0, L_VAR}, // undocumented + {0xF661, 3, L_FIX}, // undocumented + {0x4873, 2, L_FIX}, // undocumented + {0x4874, 2, L_FIX}, // undocumented + {0x6463, 4, L_FIX}, // undocumented + {0x2461, 1, L_FIX}, // undoc, must be asian version of "sprmPJc" + {0x845D, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaRight" + {0x845E, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaLeft" + {0x8460, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaLeft1" + {0x3615, 1, L_FIX}, // undocumented + {0x360D, 1, L_FIX}, // undocumented + {0x703A, 4, L_FIX}, // undocumented, sep, perhaps related to textgrids ? + {0x303B, 1, L_FIX}, // undocumented, sep + {0x244B, 1, L_FIX}, // undocumented, subtable "sprmPFInTable" equiv ? + {0x244C, 1, L_FIX}, // undocumented, subtable "sprmPFTtp" equiv ? + {0x940E, 2, L_FIX}, // undocumented + {0x940F, 2, L_FIX}, // undocumented + {0x9410, 2, L_FIX}, // undocumented + {0x6815, 4, L_FIX}, // undocumented + {0x6816, 4, L_FIX}, // undocumented + {0x6870, 4, L_FIX}, // undocumented, text colour + {0xC64D, 0, L_VAR}, // undocumented, para back colour + {0x6467, 4, L_FIX}, // undocumented + {0x646B, 4, L_FIX}, // undocumented + {0xF617, 3, L_FIX}, // undocumented + {0xD660, 0, L_VAR}, // undocumented, something to do with colour. + {0xD670, 0, L_VAR}, // undocumented, something to do with colour. + {0xCA71, 0, L_VAR}, // undocumented, text backcolour + {0x303C, 1, L_FIX}, // undocumented, sep + {0x245B, 1, L_FIX}, // undocumented, para autobefore + {0x245C, 1, L_FIX} // undocumented, para autoafter + }; + + static wwSprmSearcher aSprmSrch(aSprms, sizeof(aSprms) / sizeof(aSprms[0])); + return &aSprmSrch; +}; + +wwSprmParser::wwSprmParser(int nVersion) : mnVersion(nVersion) +{ + ASSERT((mnVersion >= 6 && mnVersion <= 8), "Impossible value for version"); + + mnDelta = (8 > mnVersion) ? 0 : 1; + + if (mnVersion < 8) + mpKnownSprms = GetWW6SprmSearcher(); + else + mpKnownSprms = GetWW8SprmSearcher(); +} + +SprmInfo wwSprmParser::GetSprmInfo(sal_uInt16 nId) const +{ + // Find sprm + SprmInfo aSrch; + aSrch.nId = nId; + const SprmInfo* pFound = mpKnownSprms->search(aSrch); + if (pFound == 0) + { + ASSERT(mnVersion >= 8, + "Unknown ww6 sprm, dangerous, report to development"); + + aSrch.nId = 0; + aSrch.nLen = 0; + //All the unknown ww7 sprms appear to be variable (which makes sense) + aSrch.nVari = L_VAR; + + if (mnVersion == 8) //We can recover perfectly in this case + { + aSrch.nVari = L_FIX; + switch (nId >> 13) + { + case 0: + case 1: + aSrch.nLen = 1; + break; + case 2: + aSrch.nLen = 2; + break; + case 3: + aSrch.nLen = 4; + break; + case 4: + case 5: + aSrch.nLen = 2; + break; + case 6: + aSrch.nLen = 0; + aSrch.nVari = L_VAR; + break; + case 7: + default: + aSrch.nLen = 3; + break; + } + } + + pFound = &aSrch; + } + return *pFound; +} + +//-end + +inline BYTE Get_Byte( BYTE *& p ) +{ + BYTE n = SVBT8ToByte( *(SVBT8*)p ); + p += 1; + return n; +} + +inline USHORT Get_UShort( BYTE *& p ) +{ + USHORT n = SVBT16ToShort( *(SVBT16*)p ); + p += 2; + return n; +} + +inline short Get_Short( BYTE *& p ) +{ + return Get_UShort(p); +} + +inline ULONG Get_ULong( BYTE *& p ) +{ + ULONG n = SVBT32ToUInt32( *(SVBT32*)p ); + p += 4; + return n; +} + +inline long Get_Long( BYTE *& p ) +{ + return Get_ULong(p); +} + +WW8SprmIter::WW8SprmIter(const BYTE* pSprms_, long nLen_, + const wwSprmParser &rParser) + : mrSprmParser(rParser), pSprms( pSprms_), nRemLen( nLen_) +{ + UpdateMyMembers(); +} + +void WW8SprmIter::SetSprms(const BYTE* pSprms_, long nLen_) +{ + pSprms = pSprms_; + nRemLen = nLen_; + UpdateMyMembers(); +} + +const BYTE* WW8SprmIter::operator ++( int ) +{ + if (nRemLen > 0) + { + pSprms += nAktSize; + nRemLen -= nAktSize; + UpdateMyMembers(); + } + return pSprms; +} + +void WW8SprmIter::UpdateMyMembers() +{ + if (pSprms && nRemLen > 0) + { + nAktId = mrSprmParser.GetSprmId(pSprms); + pAktParams = pSprms + mrSprmParser.DistanceToData(nAktId); + nAktSize = mrSprmParser.GetSprmSize(nAktId, pSprms); + } + else + { + nAktId = 0; + pAktParams = 0; + nAktSize = 0; + nRemLen = 0; + } +} + +const BYTE* WW8SprmIter::FindSprm(USHORT nId) +{ + while(GetSprms()) + { + if( GetAktId() == nId ) + return GetAktParams(); // SPRM found! + operator ++(0); + } + + return 0; // SPRM _not_ found +} + +//----------------------------------------- +// temporaerer Test +//----------------------------------------- +// WW8PLCFx_PCDAttrs halten sich an WW8PLCF_Pcd fest und besitzen deshalb keine +// eigenen Iteratoren. Alle sich auf Iteratoren beziehenden Methoden +// sind deshalb Dummies. + +WW8PLCFx_PCDAttrs::WW8PLCFx_PCDAttrs(BYTE nVersion, WW8PLCFx_PCD* pPLCFx_PCD, + const WW8ScannerBase* pBase) + : WW8PLCFx(nVersion, true), pPcdI(pPLCFx_PCD->GetPLCFIter()), + pPcd(pPLCFx_PCD), pGrpprls(pBase->pPieceGrpprls), + nGrpprls(pBase->nPieceGrpprls) +{ +} + +ULONG WW8PLCFx_PCDAttrs::GetIdx() const +{ + return 0; +} + +void WW8PLCFx_PCDAttrs::SetIdx( ULONG ) +{ +} + +bool WW8PLCFx_PCDAttrs::SeekPos(WW8_CP ) +{ + return true; +} + +WW8PLCFx& WW8PLCFx_PCDAttrs::operator ++( int ) +{ + return *this; +} + +WW8_CP WW8PLCFx_PCDAttrs::Where() +{ + return ( pPcd ) ? pPcd->Where() : LONG_MAX; +} + +void WW8PLCFx_PCDAttrs::GetSprms(WW8PLCFxDesc* p) +{ + void* pData; + + p->bRealLineEnd = false; + if ( !pPcdI || !pPcdI->Get(p->nStartPos, p->nEndPos, pData) ) + { + // PLCF fully processed + p->nStartPos = p->nEndPos = LONG_MAX; + p->pMemPos = 0; + p->nSprmsLen = 0; + return; + } + + UINT16 nPrm = SVBT16ToShort( ( (WW8_PCD*)pData )->prm ); + if ( nPrm & 1 ) + { + // PRM Variant 2 + UINT16 nSprmIdx = nPrm >> 1; + + if( nSprmIdx >= nGrpprls ) + { + // Invalid Index + p->nStartPos = p->nEndPos = LONG_MAX; + p->pMemPos = 0; + p->nSprmsLen = 0; + return; + } + const BYTE* pSprms = pGrpprls[ nSprmIdx ]; + + p->nSprmsLen = SVBT16ToShort( pSprms ); // Length + pSprms += 2; + p->pMemPos = pSprms; // Position + } + else + { + // PRM Variante 1: Sprm wird direkt in Member-Var abgelegt + /* + Dies sind die Attr, die in der Piece-Table stehen, statt im Text ! + */ + + if(8 > GetVersion()) + { + aShortSprm[0] = (BYTE)( ( nPrm & 0xfe) >> 1 ); + aShortSprm[1] = (BYTE)( nPrm >> 8 ); + p->nSprmsLen = ( nPrm ) ? 2 : 0; // Laenge + + // store Postion of internal mini storage in Data Pointer + p->pMemPos = aShortSprm; + } + else + { + p->pMemPos = 0; + p->nSprmsLen = 0; + BYTE nSprmListIdx = (BYTE)((nPrm & 0xfe) >> 1); + if( nSprmListIdx ) + { + // process Sprm Id Matching as explained in MS Doku + // + // ''Property Modifier(variant 1) (PRM)'' + // see file: s62f39.htm + // + // Since isprm is 7 bits, rgsprmPrm can hold 0x80 entries. + static const USHORT aSprmId[0x80] = + { + // sprmNoop, sprmNoop, sprmNoop, sprmNoop + 0x0000,0x0000,0x0000,0x0000, + // sprmPIncLvl, sprmPJc, sprmPFSideBySide, sprmPFKeep + 0x2402,0x2403,0x2404,0x2405, + // sprmPFKeepFollow, sprmPFPageBreakBefore, sprmPBrcl, + // sprmPBrcp + 0x2406,0x2407,0x2408,0x2409, + // sprmPIlvl, sprmNoop, sprmPFNoLineNumb, sprmNoop + 0x260A,0x0000,0x240C,0x0000, + // sprmNoop, sprmNoop, sprmNoop, sprmNoop + 0x0000,0x0000,0x0000,0x0000, + // sprmNoop, sprmNoop, sprmNoop, sprmNoop + 0x0000,0x0000,0x0000,0x0000, + // sprmPFInTable, sprmPFTtp, sprmNoop, sprmNoop + 0x2416,0x2417,0x0000,0x0000, + // sprmNoop, sprmPPc, sprmNoop, sprmNoop + 0x0000,0x261B,0x0000,0x0000, + // sprmNoop, sprmNoop, sprmNoop, sprmNoop + 0x0000,0x0000,0x0000,0x0000, + // sprmNoop, sprmPWr, sprmNoop, sprmNoop + 0x0000,0x2423,0x0000,0x0000, + // sprmNoop, sprmNoop, sprmNoop, sprmNoop + 0x0000,0x0000,0x0000,0x0000, + // sprmPFNoAutoHyph, sprmNoop, sprmNoop, sprmNoop + 0x242A,0x0000,0x0000,0x0000, + // sprmNoop, sprmNoop, sprmPFLocked, sprmPFWidowControl + 0x0000,0x0000,0x2430,0x2431, + // sprmNoop, sprmPFKinsoku, sprmPFWordWrap, + // sprmPFOverflowPunct + 0x0000,0x2433,0x2434,0x2435, + // sprmPFTopLinePunct, sprmPFAutoSpaceDE, + // sprmPFAutoSpaceDN, sprmNoop + 0x2436,0x2437,0x2438,0x0000, + // sprmNoop, sprmPISnapBaseLine, sprmNoop, sprmNoop + 0x0000,0x243B,0x000,0x0000, + // sprmNoop, sprmCFStrikeRM, sprmCFRMark, sprmCFFldVanish + 0x0000,0x0800,0x0801,0x0802, + // sprmNoop, sprmNoop, sprmNoop, sprmCFData + 0x0000,0x0000,0x0000,0x0806, + // sprmNoop, sprmNoop, sprmNoop, sprmCFOle2 + 0x0000,0x0000,0x0000,0x080A, + // sprmNoop, sprmCHighlight, sprmCFEmboss, sprmCSfxText + 0x0000,0x2A0C,0x0858,0x2859, + // sprmNoop, sprmNoop, sprmNoop, sprmCPlain + 0x0000,0x0000,0x0000,0x2A33, + // sprmNoop, sprmCFBold, sprmCFItalic, sprmCFStrike + 0x0000,0x0835,0x0836,0x0837, + // sprmCFOutline, sprmCFShadow, sprmCFSmallCaps, sprmCFCaps, + 0x0838,0x0839,0x083a,0x083b, + // sprmCFVanish, sprmNoop, sprmCKul, sprmNoop, + 0x083C,0x0000,0x2A3E,0x0000, + // sprmNoop, sprmNoop, sprmCIco, sprmNoop, + 0x0000,0x0000,0x2A42,0x0000, + // sprmCHpsInc, sprmNoop, sprmCHpsPosAdj, sprmNoop, + 0x2A44,0x0000,0x2A46,0x0000, + // sprmCIss, sprmNoop, sprmNoop, sprmNoop, + 0x2A48,0x0000,0x0000,0x0000, + // sprmNoop, sprmNoop, sprmNoop, sprmNoop, + 0x0000,0x0000,0x0000,0x0000, + // sprmNoop, sprmNoop, sprmNoop, sprmCFDStrike, + 0x0000,0x0000,0x0000,0x2A53, + // sprmCFImprint, sprmCFSpec, sprmCFObj, sprmPicBrcl, + 0x0854,0x0855,0x0856,0x2E00, + // sprmPOutLvl, sprmPFBiDi, sprmNoop, sprmNoop, + 0x2640,0x2441,0x0000,0x0000, + // sprmNoop, sprmNoop, sprmPPnbrRMarkNot + 0x0000,0x0000,0x0000,0x0000 + }; + + // find real Sprm Id: + USHORT nSprmId = aSprmId[ nSprmListIdx ]; + + if( nSprmId ) + { + // move Sprm Id and Sprm Param to internal mini storage: + aShortSprm[0] = (BYTE)( ( nSprmId & 0x00ff) ); + aShortSprm[1] = (BYTE)( ( nSprmId & 0xff00) >> 8 ); + aShortSprm[2] = (BYTE)( nPrm >> 8 ); + + // store Sprm Length in member: + p->nSprmsLen = ( nPrm ) ? 3 : 0; + + // store Postion of internal mini storage in Data Pointer + p->pMemPos = aShortSprm; + } + } + } + } +} + +//------------------------------------------------------------------------ + +WW8PLCFx_PCD::WW8PLCFx_PCD(BYTE nVersion, WW8PLCFpcd* pPLCFpcd, + WW8_CP nStartCp, bool bVer67P) + : WW8PLCFx(nVersion, false), nClipStart(-1) +{ + // eigenen Iterator konstruieren + pPcdI = new WW8PLCFpcd_Iter(*pPLCFpcd, nStartCp); + bVer67= bVer67P; +} + +WW8PLCFx_PCD::~WW8PLCFx_PCD() +{ + // pPcd-Dtor which in called from WW8ScannerBase + delete pPcdI; +} + +ULONG WW8PLCFx_PCD::GetIMax() const +{ + return pPcdI ? pPcdI->GetIMax() : 0; +} + +ULONG WW8PLCFx_PCD::GetIdx() const +{ + return pPcdI ? pPcdI->GetIdx() : 0; +} + +void WW8PLCFx_PCD::SetIdx( ULONG nIdx ) +{ + if (pPcdI) + pPcdI->SetIdx( nIdx ); +} + +bool WW8PLCFx_PCD::SeekPos(WW8_CP nCpPos) +{ + return pPcdI ? pPcdI->SeekPos( nCpPos ) : false; +} + +WW8_CP WW8PLCFx_PCD::Where() +{ + return pPcdI ? pPcdI->Where() : LONG_MAX; +} + +long WW8PLCFx_PCD::GetNoSprms( long& rStart, long& rEnd, long& rLen ) +{ + void* pData; + rLen = 0; + + if ( !pPcdI || !pPcdI->Get(rStart, rEnd, pData) ) + { + rStart = rEnd = LONG_MAX; + return -1; + } + return pPcdI->GetIdx(); +} + +WW8PLCFx& WW8PLCFx_PCD::operator ++( int ) +{ + if (pPcdI) + (*pPcdI)++; + else + ASSERT( !this, "pPcdI fehlt"); + return *this; +} + +WW8_FC WW8PLCFx_PCD::AktPieceStartCp2Fc( WW8_CP nCp ) +{ + WW8_CP nCpStart, nCpEnd; + void* pData; + + if ( !pPcdI->Get(nCpStart, nCpEnd, pData) ) + { + ASSERT( !this, "AktPieceStartCp2Fc() with false Cp found (1)" ); + return LONG_MAX; + } + + ASSERT( nCp >= nCpStart && nCp < nCpEnd, + "AktPieceCp2Fc() with false Cp found (2)" ); + + if( nCp < nCpStart ) + nCp = nCpStart; + if( nCp >= nCpEnd ) + nCp = nCpEnd - 1; + + bool bIsUnicode = false; + WW8_FC nFC = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc ); + if( !bVer67 ) + nFC = WW8PLCFx_PCD::TransformPieceAddress( nFC, bIsUnicode ); + + return nFC + (nCp - nCpStart) * (bIsUnicode ? 2 : 1); +} + + +void WW8PLCFx_PCD::AktPieceFc2Cp( long& rStartPos, long& rEndPos, + const WW8ScannerBase *pSBase ) +{ + //No point going anywhere with this + if ((rStartPos == LONG_MAX) && (rEndPos == LONG_MAX)) + return; + + rStartPos = pSBase->WW8Fc2Cp( rStartPos ); + rEndPos = pSBase->WW8Fc2Cp( rEndPos ); +} + +WW8_CP WW8PLCFx_PCD::AktPieceStartFc2Cp( WW8_FC nStartPos ) +{ + WW8_CP nCpStart, nCpEnd; + void* pData; + if ( !pPcdI->Get( nCpStart, nCpEnd, pData ) ) + { + ASSERT( !this, "AktPieceStartFc2Cp() - Fehler" ); + return LONG_MAX; + } + bool bIsUnicode = false; + INT32 nFcStart = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc ); + if( !bVer67 ) + nFcStart = WW8PLCFx_PCD::TransformPieceAddress( nFcStart, bIsUnicode ); + + INT32 nUnicodeFactor = bIsUnicode ? 2 : 1; + + if( nStartPos < nFcStart ) + nStartPos = nFcStart; + + if( nStartPos >= nFcStart + (nCpEnd - nCpStart) * nUnicodeFactor ) + nStartPos = nFcStart + (nCpEnd - nCpStart - 1) * nUnicodeFactor; + + return nCpStart + (nStartPos - nFcStart) / nUnicodeFactor; +} + +//----------------------------------------- +// Hilfsroutinen fuer alle +//----------------------------------------- + +DateTime WW8ScannerBase::WW8DTTM2DateTime(long lDTTM) +{ + /* + mint short :6 0000003F minutes (0-59) + hr short :5 000007C0 hours (0-23) + dom short :5 0000F800 days of month (1-31) + mon short :4 000F0000 months (1-12) + yr short :9 1FF00000 years (1900-2411)-1900 + wdy short :3 E0000000 weekday(Sunday=0 + Monday=1 + ( wdy can be ignored ) Tuesday=2 + Wednesday=3 + Thursday=4 + Friday=5 + Saturday=6) + */ + DateTime aDateTime(Date( 0 ), Time( 0 )); + if( lDTTM ) + { + USHORT lMin = (USHORT)(lDTTM & 0x0000003F); + lDTTM >>= 6; + USHORT lHour= (USHORT)(lDTTM & 0x0000001F); + lDTTM >>= 5; + USHORT lDay = (USHORT)(lDTTM & 0x0000001F); + lDTTM >>= 5; + USHORT lMon = (USHORT)(lDTTM & 0x0000000F); + lDTTM >>= 4; + USHORT lYear= (USHORT)(lDTTM & 0x000001FF) + 1900; + aDateTime = DateTime(Date(lDay, lMon, lYear), Time(lHour, lMin)); + } + return aDateTime; +} + +short WW8_BRC::DetermineBorderProperties(bool bVer67, short *pSpace, + BYTE *pCol, short *pIdx) const +{ + /* + Word does not factor the width of the border into the width/height + stored in the information for graphic/table/object widths, so we need + to figure out this extra width here and utilize the returned size in + our calculations + */ + short nMSTotalWidth; + BYTE nCol; + short nIdx,nSpace; + if( bVer67 ) + { + UINT16 aBrc1 = SVBT16ToShort(aBits1); + nCol = ((aBrc1 >> 6) & 0x1f); // aBor.ico + nSpace = (aBrc1 & 0xF800) >> 11; + + nMSTotalWidth = aBrc1 & 0x07; + nIdx = (aBrc1 & 0x18) >> 3; + //Dashed/Dotted unsets double/thick + if (nMSTotalWidth > 5) + { + nMSTotalWidth=1; + nIdx = 1; + } + nMSTotalWidth *= nIdx; + nMSTotalWidth *= 15; + } + else + { + nIdx = aBits1[1]; + nCol = aBits2[0]; // aBor.ico + nSpace = aBits2[1] & 0x1F; //space between line and object + + //Specification in 8ths of a point, 1 Point = 20 Twips, so by 2.5 + nMSTotalWidth = aBits1[ 0 ] * 20 / 8; + + //Figure out the real size of the border according to word + switch (nIdx) + { + //Note that codes over 25 are undocumented, and I can't create + //these 4 here in the wild. + default: + case 2: + case 4: + case 5: + case 22: + DBG_WARNING("Can't create these from the menus, please report"); + case 1: + case 6: + case 7: + case 8: + case 9: + case 23: //Only 3pt in the menus, but honours the size setting. + break; + case 3: + /* + double line is three times the width of an ordinary line, + except for the smallest 1/4 point size which appears to have + exactly the same total border width as a 1/2 point size + ordinary line, i.e. twice the nominal line width + */ + nMSTotalWidth = (nMSTotalWidth == 5) ? + nMSTotalWidth*2 : nMSTotalWidth*3; + break; + case 10: + /* + triple line is five times the width of an ordinary line, + except that the smallest 1/4 point size appears to have + exactly the same total border width as a 3/4 point size + ordinary line, i.e. three times the nominal line width. The + second smallest 1/2 point size appears to have exactly the + total border width as a 2 1/4 border, i.e 4.5 times the size. + */ + if (nMSTotalWidth == 5) + nMSTotalWidth*=3; + else if (nMSTotalWidth == 10) + nMSTotalWidth = nMSTotalWidth*9/2; + else + nMSTotalWidth*=5; + break; + case 11: + case 12: + /* + small gap thin thick and thick thin appears to have a 3/4 + point line, a 3/4 point gap and a thick line of the specified + width + */ + nMSTotalWidth = nMSTotalWidth + 15*2; + break; + case 13: + /* + thin thick thin appears to have two outside 3/4 point lines, + two 3/4 point gaps and a thick line of the specified width + */ + nMSTotalWidth = nMSTotalWidth + 15*4; + break; + case 14: + case 15: + /* + medium gap thin thick and thick thin appears to have a line + 50% of the thick line, and an equal sized gap and then the + thick line of the specified width. But it appears to only + use one of the existing predefined widths for the thin line, + so the closest smallest existing border to the halved thick + line is used. + */ + switch (nMSTotalWidth) + { + case 45: //2 1/4, closest to half is 1 + nMSTotalWidth += 20 + (nMSTotalWidth-1)/2; + break; + case 5: + case 10: + nMSTotalWidth += 5; + break; + case 15: //3/4, closest to half is 1/4 + nMSTotalWidth += 5 + (nMSTotalWidth-1)/2; + break; + default: + nMSTotalWidth*=2; + break; + } + break; + case 16: + /* + medium gap thin thick thin appears to have a line + 50% of the thick line, and an equal sized gap and then the + thick line of the specified width. But it appears to only + use one of the existing predefined widths for the thin + line, so the closest smallest existing border to the halved + thick line is used. Though some fudging at smaller sizes is + still required. + */ + switch (nMSTotalWidth) + { + case 45: //2 1/4, closest to half is 1 + nMSTotalWidth += nMSTotalWidth + 20 * 2; + break; + case 20: + case 15: + nMSTotalWidth += nMSTotalWidth + 7 * 2; + break; + case 10: + case 5: + nMSTotalWidth += 5 + 4; + break; + default: + nMSTotalWidth*=3; + break; + } + break; + case 17: + case 18: + /* + large gap thin thick and thick thin appears to have a thick + line of 1 1/2 pt and a narrow of 3/4 point, with a distance + between the two of the explicitly set line width + */ + nMSTotalWidth+=15+30; + break; + case 19: + /* + large gap thin thick thin appears to have a thick line of 1 + 1/2 pt and two narrows of 3/4 point, with a distance between + the two of the explicitly set line width, though the narrowest + line appears to behave as if it was even smaller + */ + if (nMSTotalWidth == 5) + nMSTotalWidth = 3; + nMSTotalWidth = nMSTotalWidth*2 + 15*2 + 30; + break; + case 20: + /* + wave, the dimensions appear to be created by the drawing of + the wave, so we have only two possibilites in the menus, 3/4 + point is equal to solid 3 point. This calculation seems to + match well to results. + */ + nMSTotalWidth +=45; + break; + case 21: + /* + double wave, the dimensions appear to be created by the + drawing of the wave, so we have only one possibilites in the + menus, that of 3/4 point is equal to solid 3 point. This + calculation seems to match well to results. + */ + nMSTotalWidth += 45*2; + break; + case 24: + case 25: + /* + emboss and engrave consist of a three lines, the central is of + the explicit point width, the other two (of equal size to each + other are the shadows and are either 3/4 pt of 1 1/2 depending + on if the central line is greater of less than 2 1/4 pt + */ + if (nMSTotalWidth <= 45) + nMSTotalWidth += 2*15; + else + nMSTotalWidth += 2*30; + break; + } + } + + if (pIdx) + *pIdx = nIdx; + if (pSpace) + *pSpace = nSpace*20; + if (pCol) + *pCol = nCol; + return nMSTotalWidth; +} + +WW8_CP WW8ScannerBase::WW8Fc2Cp( WW8_FC nFcPos ) const +{ + WW8_CP nFallBackCpEnd = LONG_MAX; + if( nFcPos == LONG_MAX ) + return nFallBackCpEnd; + + bool bIsUnicode = false; + if( pPieceIter ) // Complex File ? + { + ULONG nOldPos = pPieceIter->GetIdx(); + + for (pPieceIter->SetIdx(0); + pPieceIter->GetIdx() < pPieceIter->GetIMax();(*pPieceIter)++) + { + long nCpStart, nCpEnd; + void* pData; + if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) ) + { // ausserhalb PLCFfpcd ? + ASSERT( !this, "PLCFpcd-WW8Fc2Cp() ging schief" ); + break; + } + INT32 nFcStart = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc ); + if( 8 <= pWw8Fib->nVersion ) + nFcStart = WW8PLCFx_PCD::TransformPieceAddress( nFcStart, + bIsUnicode ); + INT32 nLen = (nCpEnd - nCpStart) * (bIsUnicode ? 2 : 1); + + /* + If this cp is inside this piece, or its the last piece and we are + on the very last cp of that piece + */ + if (nFcPos >= nFcStart) + { + // found + WW8_CP nTempCp = + nCpStart + ((nFcPos - nFcStart) / (bIsUnicode ? 2 : 1)); + if (nFcPos < nFcStart + nLen) + { + pPieceIter->SetIdx( nOldPos ); + return nTempCp; + } + else if (nFcPos == nFcStart + nLen) + { + //Keep this cp as its on a piece boundary because we might + //need it if tests fail + nFallBackCpEnd = nTempCp; + } + } + } + // not found + pPieceIter->SetIdx( nOldPos ); // not found + /* + If it was not found, then this is because it has fallen between two + stools, i.e. either it is the last cp/fc of the last piece, or it is + the last cp/fc of a disjoint piece. + */ + return nFallBackCpEnd; + } + // No complex file + if (pWw8Fib->fExtChar) + bIsUnicode=true; + return ((nFcPos - pWw8Fib->fcMin) / (bIsUnicode ? 2 : 1)); +} + +WW8_FC WW8ScannerBase::WW8Cp2Fc(WW8_CP nCpPos, bool* pIsUnicode, + WW8_CP* pNextPieceCp, bool* pTestFlag) const +{ + if( pTestFlag ) + *pTestFlag = true; + if( LONG_MAX == nCpPos ) + return LONG_MAX; + + bool bIsUnicode; + if( !pIsUnicode ) + pIsUnicode = &bIsUnicode; + + if( pPieceIter ) + { // Complex File + if( pNextPieceCp ) + *pNextPieceCp = LONG_MAX; + + if( !pPieceIter->SeekPos( nCpPos ) ) + { + if( pTestFlag ) + *pTestFlag = false; + else + ASSERT( !this, "Falscher CP an WW8Cp2Fc() uebergeben" ); + return LONG_MAX; + } + long nCpStart, nCpEnd; + void* pData; + if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) ) + { + if( pTestFlag ) + *pTestFlag = false; + else + ASSERT( !this, "PLCFfpcd-Get ging schief" ); + return LONG_MAX; + } + if( pNextPieceCp ) + *pNextPieceCp = nCpEnd; + + WW8_FC nRet = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc ); + if (8 > pWw8Fib->nVersion) + *pIsUnicode = false; + else + nRet = WW8PLCFx_PCD::TransformPieceAddress( nRet, *pIsUnicode ); + + + nRet += (nCpPos - nCpStart) * (*pIsUnicode ? 2 : 1); + + return nRet; + } + + // No complex file + if (pWw8Fib->fExtChar) + *pIsUnicode = true; + else + *pIsUnicode = false; + return pWw8Fib->fcMin + nCpPos * (*pIsUnicode ? 2 : 1); +} + +//----------------------------------------- +// class WW8ScannerBase +//----------------------------------------- + +WW8PLCFpcd* WW8ScannerBase::OpenPieceTable( SvStream* pStr, const WW8Fib* pWwF ) +{ + if ( ((8 > pWw8Fib->nVersion) && !pWwF->fComplex) || !pWwF->lcbClx ) + return 0; + + WW8_FC nClxPos = pWwF->fcClx; + INT32 nClxLen = pWwF->lcbClx; + INT32 nLeft = nClxLen; + INT16 nGrpprl = 0; + BYTE clxt; + + pStr->Seek( nClxPos ); + while( 1 ) // Zaehle Zahl der Grpprls + { + *pStr >> clxt; + nLeft--; + if( 2 == clxt ) // PLCFfpcd ? + break; // PLCFfpcd gefunden + if( 1 == clxt ) // clxtGrpprl ? + nGrpprl++; + UINT16 nLen; + *pStr >> nLen; + nLeft -= 2 + nLen; + if( nLeft < 0 ) + return 0; // schiefgegangen + pStr->SeekRel( nLen ); // ueberlies grpprl + } + pStr->Seek( nClxPos ); + nLeft = nClxLen; + pPieceGrpprls = new BYTE*[nGrpprl + 1]; + memset( pPieceGrpprls, 0, ( nGrpprl + 1 ) * 4 ); + nPieceGrpprls = nGrpprl; + INT16 nAktGrpprl = 0; // lies Grpprls ein + while( 1 ) + { + *pStr >> clxt; + nLeft--; + if( 2 == clxt) // PLCFfpcd ? + break; // PLCFfpcd gefunden + UINT16 nLen; + *pStr >> nLen; + nLeft -= 2 + nLen; + if( nLeft < 0 ) + return 0; // schiefgegangen + if( 1 == clxt ) // clxtGrpprl ? + { + BYTE* p = new BYTE[nLen+2]; // alloziere + ShortToSVBT16(nLen, p); // trage Laenge ein + pStr->Read( p+2, nLen ); // lies grpprl + pPieceGrpprls[nAktGrpprl++] = p; // trage in Array ein + } + else + pStr->SeekRel( nLen ); // ueberlies nicht-Grpprl + } + // lies Piece Table PLCF ein + INT32 nPLCFfLen; + *pStr >> nPLCFfLen; + ASSERT( 65536 > nPLCFfLen, "PLCFfpcd ueber 64 k" ); + return new WW8PLCFpcd( pStr, pStr->Tell(), nPLCFfLen, 8 ); +} + +void WW8ScannerBase::DeletePieceTable() +{ + if( pPieceGrpprls ) + { + for( BYTE** p = pPieceGrpprls; *p; p++ ) + delete[] (*p); + delete[] pPieceGrpprls; + pPieceGrpprls = 0; + } +} + +WW8ScannerBase::WW8ScannerBase( SvStream* pSt, SvStream* pTblSt, + SvStream* pDataSt, const WW8Fib* pWwFib ) + : pWw8Fib(pWwFib), pMainFdoa(0), pHdFtFdoa(0), pMainTxbx(0), + pMainTxbxBkd(0), pHdFtTxbx(0), pHdFtTxbxBkd(0), pMagicTables(0), + pPieceGrpprls(0) +{ + pPiecePLCF = OpenPieceTable( pTblSt, pWw8Fib ); // Complex + if( pPiecePLCF ) + { + pPieceIter = new WW8PLCFpcd_Iter( *pPiecePLCF ); + pPLCFx_PCD = new WW8PLCFx_PCD( pWwFib->nVersion, pPiecePLCF, 0, + 8 > pWw8Fib->nVersion ); + pPLCFx_PCDAttrs = new WW8PLCFx_PCDAttrs( pWwFib->nVersion, pPLCFx_PCD, + this); + } + else + { + pPieceIter = 0; + pPLCFx_PCD = 0; + pPLCFx_PCDAttrs = 0; + } + + // pChpPLCF and pPapPLCF may NOT be created before pPLCFx_PCD !! + pChpPLCF = new WW8PLCFx_Cp_FKP( pSt, pTblSt, pDataSt, *this, CHP ); // CHPX + pPapPLCF = new WW8PLCFx_Cp_FKP( pSt, pTblSt, pDataSt, *this, PAP ); // PAPX + + pSepPLCF = new WW8PLCFx_SEPX( pSt, pTblSt, *pWwFib, 0 ); // SEPX + + // Footnotes + pFtnPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->nVersion, 0, + pWwFib->fcPlcffndRef, pWwFib->lcbPlcffndRef, pWwFib->fcPlcffndTxt, + pWwFib->lcbPlcffndTxt, 2 ); + // Endnotes + pEdnPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->nVersion, 0, + pWwFib->fcPlcfendRef, pWwFib->lcbPlcfendRef, pWwFib->fcPlcfendTxt, + pWwFib->lcbPlcfendTxt, 2 ); + // Anmerkungen + pAndPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->nVersion, 0, + pWwFib->fcPlcfandRef, pWwFib->lcbPlcfandRef, pWwFib->fcPlcfandTxt, + pWwFib->lcbPlcfandTxt, (8 > pWwFib->nVersion) ? 20 : 30 ); + + // Fields Main Text + pFldPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_MAINTEXT); + // Fields Header / Footer + pFldHdFtPLCF= new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_HDFT); + // Fields Footnote + pFldFtnPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_FTN); + // Fields Endnote + pFldEdnPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_EDN); + // Fields Anmerkungen + pFldAndPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_AND); + // Fields in Textboxes in Main Text + pFldTxbxPLCF= new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_TXBX); + // Fields in Textboxes in Header / Footer + pFldTxbxHdFtPLCF = new WW8PLCFx_FLD(pTblSt,*pWwFib,MAN_TXBX_HDFT); + + // Note: 6 stands for "6 OR 7", 7 stands for "ONLY 7" + switch( pWw8Fib->nVersion ) + { + case 6: + case 7: + if( pWwFib->fcPlcfdoaMom && pWwFib->lcbPlcfdoaMom ) + { + pMainFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfdoaMom, + pWwFib->lcbPlcfdoaMom, 6 ); + } + if( pWwFib->fcPlcfdoaHdr && pWwFib->lcbPlcfdoaHdr ) + { + pHdFtFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfdoaHdr, + pWwFib->lcbPlcfdoaHdr, 6 ); + } + break; + case 8: + if( pWwFib->fcPlcfspaMom && pWwFib->lcbPlcfspaMom ) + { + pMainFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfspaMom, + pWwFib->lcbPlcfspaMom, 26 ); + } + if( pWwFib->fcPlcfspaHdr && pWwFib->lcbPlcfspaHdr ) + { + pHdFtFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfspaHdr, + pWwFib->lcbPlcfspaHdr, 26 ); + } + // PLCF fuer TextBox-Break-Deskriptoren im Maintext + if( pWwFib->fcPlcftxbxBkd && pWwFib->lcbPlcftxbxBkd ) + { + pMainTxbxBkd = new WW8PLCFspecial( pTblSt, + pWwFib->fcPlcftxbxBkd, pWwFib->lcbPlcftxbxBkd, 0); + } + // PLCF fuer TextBox-Break-Deskriptoren im Header-/Footer-Bereich + if( pWwFib->fcPlcfHdrtxbxBkd && pWwFib->lcbPlcfHdrtxbxBkd ) + { + pHdFtTxbxBkd = new WW8PLCFspecial( pTblSt, + pWwFib->fcPlcfHdrtxbxBkd, pWwFib->lcbPlcfHdrtxbxBkd, 0); + } + // Sub table cp positions + if (pWwFib->fcMagicTable && pWwFib->lcbMagicTable) + { + pMagicTables = new WW8PLCFspecial( pTblSt, + pWwFib->fcMagicTable, pWwFib->lcbMagicTable, 4); + } + break; + default: + ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" ); + break; + } + + // PLCF fuer TextBox-Stories im Maintext + long nLenTxBxS = (8 > pWw8Fib->nVersion) ? 0 : 22; + if( pWwFib->fcPlcftxbxTxt && pWwFib->lcbPlcftxbxTxt ) + { + pMainTxbx = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcftxbxTxt, + pWwFib->lcbPlcftxbxTxt, nLenTxBxS ); + } + + // PLCF fuer TextBox-Stories im Header-/Footer-Bereich + if( pWwFib->fcPlcfHdrtxbxTxt && pWwFib->lcbPlcfHdrtxbxTxt ) + { + pHdFtTxbx = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfHdrtxbxTxt, + pWwFib->lcbPlcfHdrtxbxTxt, nLenTxBxS ); + } + + pBook = new WW8PLCFx_Book(pTblSt, *pWwFib); +} + +WW8ScannerBase::~WW8ScannerBase() +{ + DeletePieceTable(); + delete pPLCFx_PCDAttrs; + delete pPLCFx_PCD; + delete pPieceIter; + delete pPiecePLCF; + delete pBook; + delete pFldEdnPLCF; + delete pFldFtnPLCF; + delete pFldAndPLCF; + delete pFldHdFtPLCF; + delete pFldPLCF; + delete pFldTxbxPLCF; + delete pFldTxbxHdFtPLCF; + delete pEdnPLCF; + delete pFtnPLCF; + delete pAndPLCF; + delete pSepPLCF; + delete pPapPLCF; + delete pChpPLCF; + // vergessene Schaeflein + delete pMainFdoa; + delete pHdFtFdoa; + delete pMainTxbx; + delete pMainTxbxBkd; + delete pHdFtTxbx; + delete pHdFtTxbxBkd; + delete pMagicTables; +} + +//----------------------------------------- +// Fields +//----------------------------------------- +static bool WW8SkipField(WW8PLCFspecial& rPLCF) +{ + void* pData; + long nP; + + if (!rPLCF.Get(nP, pData)) // Ende des PLCFspecial ? + return false; + + rPLCF++; + + if((((BYTE*)pData)[0] & 0x1f ) != 0x13 ) // Kein Anfang ? + return true; // Bei Fehler nicht abbrechen + + if( !rPLCF.Get( nP, pData ) ) + return false; + + + while((((BYTE*)pData)[0] & 0x1f ) == 0x13 ) + { + // immer noch neue (nested) Anfaenge ? + WW8SkipField( rPLCF ); // nested Field im Beschreibungsteil + if( !rPLCF.Get( nP, pData ) ) + return false; + } + + if((((BYTE*)pData)[0] & 0x1f ) == 0x14 ) + { + + // Field Separator ? + rPLCF++; + + if( !rPLCF.Get( nP, pData ) ) + return false; + + while ((((BYTE*)pData)[0] & 0x1f ) == 0x13) + { + // immer noch neue (nested) Anfaenge ? + WW8SkipField( rPLCF ); // nested Field im Resultatteil + if( !rPLCF.Get( nP, pData ) ) + return false; + } + } + rPLCF++; + + return true; +} + +static bool WW8GetFieldPara(WW8PLCFspecial& rPLCF, WW8FieldDesc& rF) +{ + void* pData; + ULONG nOldIdx = rPLCF.GetIdx(); + + rF.nLen = rF.nId = rF.nOpt = rF.bCodeNest = rF.bResNest = 0; + + if( !rPLCF.Get( rF.nSCode, pData ) ) // Ende des PLCFspecial ? + goto Err; + + rPLCF++; + + if((((BYTE*)pData)[0] & 0x1f ) != 0x13 ) // Kein Anfang ? + goto Err; + + rF.nId = ((BYTE*)pData)[1]; + + if( !rPLCF.Get( rF.nLCode, pData ) ) + goto Err; + + rF.nSRes = rF.nLCode; // Default + rF.nSCode++; // ohne Marken + rF.nLCode -= rF.nSCode; // Pos zu Laenge + + while((((BYTE*)pData)[0] & 0x1f ) == 0x13 ) + { + // immer noch neue (nested) Anfaenge ? + WW8SkipField( rPLCF ); // nested Field im Beschreibungsteil + rF.bCodeNest = true; + if( !rPLCF.Get( rF.nSRes, pData ) ) + goto Err; + } + + if((((BYTE*)pData)[0] & 0x1f ) == 0x14 ){ // Field Separator ? + rPLCF++; + + if( !rPLCF.Get( rF.nLRes, pData ) ) + goto Err; + + while((((BYTE*)pData)[0] & 0x1f ) == 0x13 ) + { + // immer noch neue (nested) Anfaenge ? + WW8SkipField( rPLCF ); // nested Field im Resultatteil + rF.bResNest = true; + if( !rPLCF.Get( rF.nLRes, pData ) ) + goto Err; + } + rF.nLen = rF.nLRes - rF.nSCode + 2; // nLRes ist noch die Endposition + rF.nLRes -= rF.nSRes; // nun: nLRes = Laenge + rF.nSRes++; // Endpos encl. Marken + rF.nLRes--; + + }else{ + rF.nLRes = 0; // Kein Result vorhanden + rF.nLen = rF.nSRes - rF.nSCode + 2; // Gesamtlaenge + } + + rPLCF++; + if((((BYTE*)pData)[0] & 0x1f ) == 0x15 ) + { + // Field Ende ? + // INDEX-Fld hat Bit7 gesetzt!?! + rF.nOpt = ((BYTE*)pData)[1]; // Ja -> Flags uebernehmen + }else{ + rF.nId = 0; // Nein -> Feld ungueltig + } + + rPLCF.SetIdx( nOldIdx ); + return true; +Err: + rPLCF.SetIdx( nOldIdx ); + return false; +} + + +//----------------------------------------- + + +// WW8ReadPString liest einen Pascal-String ein und gibt ihn zurueck. Der +// Pascal- String hat am Ende ein \0, der aber im Laengenbyte nicht +// mitgezaehlt wird. Der Speicher fuer den Pascalstring wird alloziert. +String WW8ReadPString(SvStream& rStrm, rtl_TextEncoding eEnc, + bool bAtEndSeekRel1) +{ + ByteString aByteStr; + UINT8 b; + rStrm >> b; + + if (b) + { + // Alloc methode automatically sets Zero at the end + sal_Char* pByteData = aByteStr.AllocBuffer( b ); + + ULONG nWasRead = rStrm.Read( pByteData, b ); + if( nWasRead != b ) + aByteStr.ReleaseBufferAccess(static_cast<xub_StrLen>(nWasRead)); + } + + if( bAtEndSeekRel1 ) + rStrm.SeekRel( 1 ); // ueberspringe das Null-Byte am Ende. + + + return String( aByteStr, eEnc ); +} + +String WW8Read_xstz(SvStream& rStrm, USHORT nChars, bool bAtEndSeekRel1) +{ + UINT16 b; + + if( nChars ) + b = nChars; + else + rStrm >> b; + + String aStr; + if (b) + { + // Alloc methode automatically sets Zero at the end + sal_Unicode* pData = aStr.AllocBuffer( b ); + + ULONG nWasRead = rStrm.Read( (sal_Char*)pData, b * 2 ); + if( nWasRead != static_cast<ULONG>(b*2) ) + { + b = static_cast<UINT16>(nWasRead / 2); + aStr.ReleaseBufferAccess( b ); + pData = aStr.GetBufferAccess(); + } + +#ifdef OSL_BIGENDIAN + ULONG n; + sal_Unicode *pWork; + for( n = 0, pWork = pData; n < b; ++n, ++pWork ) + *pWork = SWAPSHORT( *pWork ); +#endif // ifdef OSL_BIGENDIAN + } + + if( bAtEndSeekRel1 ) + rStrm.SeekRel( 2 ); // ueberspringe das Null-Character am Ende. + + return aStr; +} + +static ULONG SafeReadString(ByteString &rStr,USHORT nLen,SvStream &rStrm) +{ + ULONG nWasRead=0; + if (nLen) + { + nWasRead = rStrm.Read( rStr.AllocBuffer( nLen ), nLen); + if( nWasRead != nLen ) + rStr.ReleaseBufferAccess(static_cast<xub_StrLen>(nWasRead)); + } + return nWasRead; +} + +USHORT WW8ScannerBase::WW8ReadString( SvStream& rStrm, String& rStr, + WW8_CP nAktStartCp, long nTotalLen, rtl_TextEncoding eEnc ) const +{ + // Klartext einlesen, der sich ueber mehrere Pieces erstrecken kann + rStr.Erase(); + + long nTotalRead = 0; + WW8_CP nBehindTextCp = nAktStartCp + nTotalLen; + WW8_CP nNextPieceCp = nBehindTextCp; // Initialisierung wichtig fuer Ver6 + do + { + bool bIsUnicode, bPosOk; + WW8_FC fcAct = WW8Cp2Fc(nAktStartCp,&bIsUnicode,&nNextPieceCp,&bPosOk); + + // vermutlich uebers Dateiende hinaus gezielt, macht nix! + if( !bPosOk ) + break; + + rStrm.Seek( fcAct ); + + long nLen = ( (nNextPieceCp < nBehindTextCp) ? nNextPieceCp + : nBehindTextCp ) - nAktStartCp; + + if( 0 >= nLen ) + break; + + if( nLen > USHRT_MAX - 1 ) + nLen = USHRT_MAX - 1; + + if( bIsUnicode ) + rStr.Append(WW8Read_xstz(rStrm, (USHORT)nLen, false)); + else + { + // Alloc method automatically sets Zero at the end + ByteString aByteStr; + SafeReadString(aByteStr,(USHORT)nLen,rStrm); + rStr += String( aByteStr, eEnc ); + } + nTotalRead += nLen; + nAktStartCp += nLen; + if ( nTotalRead != rStr.Len() ) + break; + } + while( nTotalRead < nTotalLen ); + + return rStr.Len(); +} + +//----------------------------------------- +// WW8PLCFspecial +//----------------------------------------- + +// Bei nStartPos < 0 wird das erste Element des PLCFs genommen +WW8PLCFspecial::WW8PLCFspecial(SvStream* pSt, long nFilePos, long nPLCF, + long nStruct, long nStartPos, bool bNoEnd) + : nIdx(0), nStru(nStruct) +{ + nIMax = ( nPLCF - 4 ) / ( 4 + nStruct ); + // Pointer auf Pos- u. Struct-Array + pPLCF_PosArray = new INT32[ ( nPLCF + 3 ) / 4 ]; + + long nOldPos = pSt->Tell(); + + pSt->Seek( nFilePos ); + pSt->Read( pPLCF_PosArray, nPLCF ); +#ifdef OSL_BIGENDIAN + for( nIdx = 0; nIdx <= nIMax; nIdx++ ) + pPLCF_PosArray[nIdx] = SWAPLONG( pPLCF_PosArray[nIdx] ); + nIdx = 0; +#endif // OSL_BIGENDIAN + if( bNoEnd ) + nIMax++; + if( nStruct ) // Pointer auf Inhalts-Array + pPLCF_Contents = (BYTE*)&pPLCF_PosArray[nIMax + 1]; + else + pPLCF_Contents = 0; // kein Inhalt + if( nStartPos >= 0 ) + SeekPos( nStartPos ); + + pSt->Seek( nOldPos ); +} + +// WW8PLCFspecial::SeekPos() stellt den WW8PLCFspecial auf die Stelle nPos, wobei auch noch der +// Eintrag benutzt wird, der vor nPos beginnt und bis hinter nPos reicht. +// geeignet fuer normale Attribute. Allerdings wird der Attributanfang nicht +// auf die Position nPos korrigiert. +bool WW8PLCFspecial::SeekPos(long nP) +{ + if( nP < pPLCF_PosArray[0] ) + { + nIdx = 0; + return false; // Not found: nP unterhalb kleinstem Eintrag + } + + // Search from beginning? + if( (1 > nIdx) || (nP < pPLCF_PosArray[ nIdx-1 ]) ) + nIdx = 1; + + long nI = nIdx ? nIdx : 1; + long nEnd = nIMax; + + for(int n = (1==nIdx ? 1 : 2); n; --n ) + { + for( ; nI <=nEnd; ++nI) + { // Suchen mit um 1 erhoehtem Index + if( nP < pPLCF_PosArray[nI] ) + { // Position gefunden + nIdx = nI - 1; // nI - 1 ist der richtige Index + return true; // ... und fertig + } + } + nI = 1; + nEnd = nIdx-1; + } + nIdx = nIMax; // Nicht gefunden, groesser als alle Eintraege + return false; +} + +// WW8PLCFspecial::SeekPosExact() wie SeekPos(), aber es wird sichergestellt, +// dass kein Attribut angeschnitten wird, d.h. das naechste gelieferte +// Attribut beginnt auf oder hinter nPos. Wird benutzt fuer Felder + +// Bookmarks. +bool WW8PLCFspecial::SeekPosExact(long nP) +{ + if( nP < pPLCF_PosArray[0] ) + { + nIdx = 0; + return false; // Not found: nP unterhalb kleinstem Eintrag + } + // Search from beginning? + if( nP <=pPLCF_PosArray[nIdx] ) + nIdx = 0; + + long nI = nIdx ? nIdx-1 : 0; + long nEnd = nIMax; + + for(int n = (0==nIdx ? 1 : 2); n; --n ) + { + for( ; nI < nEnd; ++nI) + { + if( nP <=pPLCF_PosArray[nI] ) + { // Position gefunden + nIdx = nI; // nI ist der richtige Index + return true; // ... und fertig + } + } + nI = 0; + nEnd = nIdx; + } + nIdx = nIMax; // Not found, groesser als alle Eintraege + return false; +} + +bool WW8PLCFspecial::Get(long& rPos, void*& rpValue) const +{ + return GetData( nIdx, rPos, rpValue ); +} + +bool WW8PLCFspecial::GetData(long nInIdx, long& rPos, void*& rpValue) const +{ + if ( nInIdx >= nIMax ) + { + rPos = LONG_MAX; + return false; + } + rPos = pPLCF_PosArray[nInIdx]; + rpValue = pPLCF_Contents ? (void*)&pPLCF_Contents[nInIdx * nStru] : 0; + return true; +} + +//----------------------------------------- +// WW8PLCF z.B. fuer SEPX +//----------------------------------------- + +// Ctor fuer *andere* als Fkps +// Bei nStartPos < 0 wird das erste Element des PLCFs genommen +WW8PLCF::WW8PLCF( SvStream* pSt, long nFilePos, long nPLCF, long nStruct, + long nStartPos ) :nIdx( 0 ), nStru( nStruct ) +{ + ASSERT( nPLCF, "WW8PLCF: nPLCF ist Null!" ); + + nIMax = ( nPLCF - 4 ) / ( 4 + nStruct ); + + ReadPLCF( pSt, nFilePos, nPLCF ); + + if( nStartPos >= 0 ) + SeekPos( nStartPos ); +} + +// Ctor *nur* fuer Fkps +// Die letzten 2 Parameter sind fuer PLCF.Chpx und PLCF.Papx noetig. ist ncpN +// != 0, dann wird ein unvollstaendiger PLCF vervollstaendigt. Das ist bei +// WW6 bei Resourcenmangel und bei WordPad (W95) immer noetig. Bei nStartPos +// < 0 wird das erste Element des PLCFs genommen +WW8PLCF::WW8PLCF( SvStream* pSt, long nFilePos, long nPLCF, long nStruct, + long nStartPos, long nPN, long ncpN ) :nIdx( 0 ), nStru( nStruct ) +{ + nIMax = ( nPLCF - 4 ) / ( 4 + nStruct ); + + if( nIMax >= (long) ncpN ) + ReadPLCF( pSt, nFilePos, nPLCF ); + else + GeneratePLCF( pSt, nPN, ncpN ); + + if( nStartPos >= 0 ) + SeekPos( nStartPos ); +} + +void WW8PLCF::ReadPLCF( SvStream* pSt, long nFilePos, long nPLCF ) +{ + // Pointer auf Pos-Array + pPLCF_PosArray = new INT32[ ( nPLCF + 3 ) / 4 ]; + + long nOldPos = pSt->Tell(); + + pSt->Seek( nFilePos ); + pSt->Read( pPLCF_PosArray, nPLCF ); +#ifdef OSL_BIGENDIAN + for( nIdx = 0; nIdx <= nIMax; nIdx++ ) + pPLCF_PosArray[nIdx] = SWAPLONG( pPLCF_PosArray[nIdx] ); + nIdx = 0; +#endif // OSL_BIGENDIAN + // Pointer auf Inhalts-Array + pPLCF_Contents = (BYTE*)&pPLCF_PosArray[nIMax + 1]; + + pSt->Seek( nOldPos ); +} + +void WW8PLCF::GeneratePLCF( SvStream* pSt, long nPN, long ncpN ) +{ + ASSERT( nIMax < (long)ncpN, "Pcl.Fkp: Warum ist PLCF zu gross ?" ); + nIMax = ncpN; + long nSiz = 6 * nIMax + 4; + pPLCF_PosArray = new INT32[ ( nSiz + 3 ) / 4 ]; // Pointer auf Pos-Array + memset( pPLCF_PosArray, 0, (size_t)nSiz ); + + INT32 nFc; + USHORT i; + + for( i = 0; i < ncpN; i++ ){ // Baue FC-Eintraege + pSt->Seek( ( nPN + i ) << 9 ); // erster FC-Eintrag jedes Fkp + *pSt >> nFc; + pPLCF_PosArray[i] = nFc; + } + ULONG nLastFkpPos = ( ( nPN + nIMax - 1 ) << 9 ); + pSt->Seek( nLastFkpPos + 511 ); // Anz. Fkp-Eintraege des letzten Fkp + BYTE nb; + *pSt >> nb; + pSt->Seek( nLastFkpPos + nb * 4 ); // letzer FC-Eintrag des letzten Fkp + *pSt >> nFc; + pPLCF_PosArray[nIMax] = nFc; // Ende des letzten Fkp + + // Pointer auf Inhalts-Array + pPLCF_Contents = (BYTE*)&pPLCF_PosArray[nIMax + 1]; + BYTE* p = pPLCF_Contents; + + for( i = 0; i < ncpN; i++ ) // Baue PNs + { + ShortToSVBT16(nPN + i, p); + p+=2; + } +} + +bool WW8PLCF::SeekPos(long nPos) +{ + long nP = nPos; + + if( nP < pPLCF_PosArray[0] ) + { + nIdx = 0; + // Nicht gefunden: nPos unterhalb kleinstem Eintrag + return false; + } + + // Search from beginning? + if( (1 > nIdx) || (nP < pPLCF_PosArray[ nIdx-1 ]) ) + nIdx = 1; + + long nI = nIdx ? nIdx : 1; + long nEnd = nIMax; + + for(int n = (1==nIdx ? 1 : 2); n; --n ) + { + for( ; nI <=nEnd; ++nI) // Suchen mit um 1 erhoehtem Index + { + if( nP < pPLCF_PosArray[nI] ) // Position gefunden + { + nIdx = nI - 1; // nI - 1 ist der richtige Index + return true; // ... und fertig + } + } + nI = 1; + nEnd = nIdx-1; + } + + nIdx = nIMax; // Nicht gefunden, groesser als alle Eintraege + return false; +} + +bool WW8PLCF::Get(long& rStart, long& rEnd, void*& rpValue) const +{ + if ( nIdx >= nIMax ) + { + rStart = rEnd = LONG_MAX; + return false; + } + rStart = pPLCF_PosArray[ nIdx ]; + rEnd = pPLCF_PosArray[ nIdx + 1 ]; + rpValue = (void*)&pPLCF_Contents[nIdx * nStru]; + return true; +} + +long WW8PLCF::Where() const +{ + if ( nIdx >= nIMax ) + return LONG_MAX; + + return pPLCF_PosArray[nIdx]; +} + +//----------------------------------------- +// WW8PLCFpcd +//----------------------------------------- + +WW8PLCFpcd::WW8PLCFpcd( SvStream* pSt, long nFilePos, long nPLCF, long nStruct ) + :nStru( nStruct ) +{ + nIMax = ( nPLCF - 4 ) / ( 4 + nStruct ); + pPLCF_PosArray = new INT32[ ( nPLCF + 3 ) / 4 ]; // Pointer auf Pos-Array + + long nOldPos = pSt->Tell(); + + pSt->Seek( nFilePos ); + pSt->Read( pPLCF_PosArray, nPLCF ); +#ifdef OSL_BIGENDIAN + for( long nI = 0; nI <= nIMax; nI++ ) + pPLCF_PosArray[nI] = SWAPLONG( pPLCF_PosArray[nI] ); +#endif // OSL_BIGENDIAN + + // Pointer auf Inhalts-Array + pPLCF_Contents = (BYTE*)&pPLCF_PosArray[nIMax + 1]; + + pSt->Seek( nOldPos ); +} + +// Bei nStartPos < 0 wird das erste Element des PLCFs genommen +WW8PLCFpcd_Iter::WW8PLCFpcd_Iter( WW8PLCFpcd& rPLCFpcd, long nStartPos ) + :rPLCF( rPLCFpcd ), nIdx( 0 ) +{ + if( nStartPos >= 0 ) + SeekPos( nStartPos ); +} + +bool WW8PLCFpcd_Iter::SeekPos(long nPos) +{ + long nP = nPos; + + if( nP < rPLCF.pPLCF_PosArray[0] ) + { + nIdx = 0; + return false; // Nicht gefunden: nPos unterhalb kleinstem Eintrag + } + // Search from beginning? + if( (1 > nIdx) || (nP < rPLCF.pPLCF_PosArray[ nIdx-1 ]) ) + nIdx = 1; + + long nI = nIdx ? nIdx : 1; + long nEnd = rPLCF.nIMax; + + for(int n = (1==nIdx ? 1 : 2); n; --n ) + { + for( ; nI <=nEnd; ++nI) + { // Suchen mit um 1 erhoehtem Index + if( nP < rPLCF.pPLCF_PosArray[nI] ) + { // Position gefunden + nIdx = nI - 1; // nI - 1 ist der richtige Index + return true; // ... und fertig + } + } + nI = 1; + nEnd = nIdx-1; + } + nIdx = rPLCF.nIMax; // Nicht gefunden, groesser als alle Eintraege + return false; +} + +bool WW8PLCFpcd_Iter::Get(long& rStart, long& rEnd, void*& rpValue) const +{ + if( nIdx >= rPLCF.nIMax ) + { + rStart = rEnd = LONG_MAX; + return false; + } + rStart = rPLCF.pPLCF_PosArray[nIdx]; + rEnd = rPLCF.pPLCF_PosArray[nIdx + 1]; + rpValue = (void*)&rPLCF.pPLCF_Contents[nIdx * rPLCF.nStru]; + return true; +} + +long WW8PLCFpcd_Iter::Where() const +{ + if ( nIdx >= rPLCF.nIMax ) + return LONG_MAX; + + return rPLCF.pPLCF_PosArray[nIdx]; +} + +//----------------------------------------- +bool WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator< + (const WW8PLCFx_Fc_FKP::WW8Fkp::Entry& rSecond) const +{ + return (mnFC < rSecond.mnFC); +} + +WW8PLCFx_Fc_FKP::WW8Fkp::WW8Fkp(BYTE nFibVer, SvStream* pSt, SvStream* pDataSt, + long _nFilePos, long nItemSiz, ePLCFT ePl, WW8_FC nStartFc) + : nItemSize(nItemSiz), nFilePos(_nFilePos), nIdx(0), ePLCF(ePl), + maSprmParser(nFibVer) +{ + long nOldPos = pSt->Tell(); + + pSt->Seek(nFilePos); + pSt->Read(maRawData, 512); + nIMax = maRawData[511]; + + sal_uInt8 *pStart = maRawData; + // Pointer to Offset-Location in maRawData + sal_uInt8* pOfs = maRawData + (nIMax + 1) * 4; + + for (nIdx = 0; nIdx < nIMax; ++nIdx) + { + USHORT nOfs = (*(pOfs + nIdx * nItemSize)) * 2; + Entry aEntry(Get_Long(pStart)); + + if (nOfs) + { + switch (ePLCF) + { + case CHP: + aEntry.mnLen = maRawData[nOfs]; + aEntry.mpData = maRawData + nOfs + 1; + break; + case PAP: + sal_uInt8 nDelta = 0; + + aEntry.mnLen = maRawData[nOfs]; + if (8 <= nFibVer && !aEntry.mnLen) + { + aEntry.mnLen = maRawData[ nOfs+1 ]; + nDelta++; + } + + aEntry.mnIStd = SVBT16ToShort(maRawData+nOfs+1+nDelta); + + aEntry.mpData = maRawData + nOfs + 3+ nDelta; + + USHORT nSpId = maSprmParser.GetSprmId(aEntry.mpData); + + if (0x6645 == nSpId || 0x6646 == nSpId) + { + UINT32 nCurr = pDataSt->Tell(); + + UINT32 nPos = SVBT32ToUInt32(aEntry.mpData + 2); + pDataSt->Seek(nPos); + *pDataSt >> aEntry.mnLen; + aEntry.mpData = new sal_uInt8[aEntry.mnLen]; + aEntry.mbMustDelete = true; + pDataSt->Read(aEntry.mpData, aEntry.mnLen); + + pDataSt->Seek( nCurr ); + } + else + { + aEntry.mnLen *= 2; + aEntry.mnLen -= 2; + } + break; + } + } + + maEntries.push_back(aEntry); + } + + //one more FC than grrpl entries + maEntries.push_back(Entry(Get_Long(pStart))); + + //#104773#, we expect them sorted, but it appears possible + //for them to arive unsorted + std::sort(maEntries.begin(), maEntries.end()); + + nIdx = 0; + + if (nStartFc >= 0) + SeekPos(nStartFc); + + pSt->Seek(nOldPos); +} + +WW8PLCFx_Fc_FKP::WW8Fkp::Entry::Entry(const Entry &rEntry) + : mnFC(rEntry.mnFC), mnLen(rEntry.mnLen), mnIStd(rEntry.mnIStd), + mbMustDelete(rEntry.mbMustDelete) +{ + if (mbMustDelete) + { + mpData = new sal_uInt8[mnLen]; + memcpy(mpData, rEntry.mpData, mnLen); + } + else + mpData = rEntry.mpData; +} + +WW8PLCFx_Fc_FKP::WW8Fkp::Entry& + WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator=(const Entry &rEntry) +{ + if (mbMustDelete) + delete[] mpData; + + mnFC = rEntry.mnFC; + mnLen = rEntry.mnLen; + mnIStd = rEntry.mnIStd; + mbMustDelete = rEntry.mbMustDelete; + + if (mbMustDelete) + { + mpData = new sal_uInt8[mnLen]; + memcpy(mpData, rEntry.mpData, mnLen); + } + else + mpData = rEntry.mpData; + return *this; +} + +WW8PLCFx_Fc_FKP::WW8Fkp::Entry::~Entry() +{ + if (mbMustDelete) + delete[] mpData; +} + +void WW8PLCFx_Fc_FKP::WW8Fkp::Reset(WW8_FC nFc) +{ + SetIdx(0); + if (nFc >= 0) + SeekPos(nFc); +} + +bool WW8PLCFx_Fc_FKP::WW8Fkp::SeekPos(WW8_FC nFc) +{ + if (nFc < maEntries[0].mnFC) + { + nIdx = 0; + return false; // Nicht gefunden: nPos unterhalb kleinstem Eintrag + } + // Search from beginning? + if( (1 > nIdx) || (nFc < maEntries[nIdx-1].mnFC) ) + nIdx = 1; + + long nI = nIdx ? nIdx : 1; + long nEnd = nIMax; + + for(int n = (1==nIdx ? 1 : 2); n; --n ) + { + for( ; nI <=nEnd; ++nI) + { // Suchen mit um 1 erhoehtem Index + if (nFc < maEntries[nI].mnFC) + { // Position gefunden + nIdx = nI - 1; // nI - 1 ist der richtige Index + return true; // ... und fertig + } + } + nI = 1; + nEnd = nIdx-1; + } + nIdx = nIMax; // Nicht gefunden, groesser als alle Eintraege + return false; +} + +BYTE* WW8PLCFx_Fc_FKP::WW8Fkp::Get( WW8_FC& rStart, WW8_FC& rEnd, long& rLen ) + const +{ + rLen = 0; + + if( nIdx >= nIMax ) + { + rStart = LONG_MAX; + return 0; + } + + rStart = maEntries[nIdx].mnFC; + rEnd = maEntries[nIdx + 1].mnFC; + + BYTE* pSprms = GetLenAndIStdAndSprms( rLen ); + return pSprms; +} + +void WW8PLCFx_Fc_FKP::WW8Fkp::SetIdx( ULONG nI ) +{ + if( nI < nIMax) + nIdx = (short)nI; +} + +BYTE* WW8PLCFx_Fc_FKP::WW8Fkp::GetLenAndIStdAndSprms(long& rLen) const +{ + rLen = maEntries[nIdx].mnLen; + return maEntries[nIdx].mpData; +} + +const BYTE* WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm( USHORT nId ) +{ + if( nIdx >= nIMax ) + return 0; + + long nLen; + BYTE* pSprms = GetLenAndIStdAndSprms( nLen ); + + WW8SprmIter aIter(pSprms, nLen, maSprmParser); + return aIter.FindSprm(nId); +} + +bool WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm(USHORT nId, + std::vector<const BYTE *> &rResult) +{ + if (nIdx >= nIMax) + return false; + + long nLen; + BYTE* pSprms = GetLenAndIStdAndSprms( nLen ); + + WW8SprmIter aIter(pSprms, nLen, maSprmParser); + + while(aIter.GetSprms()) + { + if (aIter.GetAktId() == nId) + rResult.push_back(aIter.GetAktParams()); + aIter++; + }; + return !rResult.empty(); +} + +//----------------------------------------- +void WW8PLCFx::GetSprms( WW8PLCFxDesc* p ) +{ + ASSERT( !this, "Falsches GetSprms gerufen" ); + p->nStartPos = p->nEndPos = LONG_MAX; + p->pMemPos = 0; + p->nSprmsLen = 0; + p->bRealLineEnd = false; + return; +} + +long WW8PLCFx::GetNoSprms( long& rStart, long& rEnd, long& rLen ) +{ + ASSERT( !this, "Falsches GetNoSprms gerufen" ); + rStart = rEnd = LONG_MAX; + rLen = 0; + return 0; +} + +// ...Idx2: Default: ignorieren +ULONG WW8PLCFx::GetIdx2() const +{ + return 0; +} + +void WW8PLCFx::SetIdx2(ULONG ) +{ +} + +class SamePos : + public std::unary_function<const WW8PLCFx_Fc_FKP::WW8Fkp *, bool> +{ +private: + long mnPo; +public: + SamePos(long nPo) : mnPo(nPo) {}; + bool operator()(const WW8PLCFx_Fc_FKP::WW8Fkp *pFkp) + {return mnPo == pFkp->GetFilePos();} +}; + +//----------------------------------------- +bool WW8PLCFx_Fc_FKP::NewFkp() +{ + long nPLCFStart, nPLCFEnd; + void* pPage; + + static const int WW8FkpSizeTabVer6[ PLCF_END ] = + { + 1, 7, 0 /*, 0, 0, 0*/ + }; + static const int WW8FkpSizeTabVer8[ PLCF_END ] = + { + 1, 13, 0 /*, 0, 0, 0*/ + }; + const int* pFkpSizeTab; + switch (GetVersion()) + { + case 6: + case 7: + pFkpSizeTab = WW8FkpSizeTabVer6; + break; + case 8: + pFkpSizeTab = WW8FkpSizeTabVer8; + break; + default: + // Programm-Fehler! + ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" ); + return false; + } + + if (!pPLCF->Get( nPLCFStart, nPLCFEnd, pPage )) + { + pFkp = 0; + return false; // PLCF fertig abgearbeitet + } + (*pPLCF)++; + long nPo = SVBT16ToShort( (BYTE *)pPage ); + nPo <<= 9; // shift als LONG + + long nAktFkpFilePos = pFkp ? pFkp->GetFilePos() : -1; + if (nAktFkpFilePos == nPo) + pFkp->Reset(GetStartFc()); // #79464# // + else + { + myiter aIter = + std::find_if(maFkpCache.begin(), maFkpCache.end(), SamePos(nPo)); + if (aIter != maFkpCache.end()) + { + pFkp = *aIter; + pFkp->Reset(GetStartFc()); + } + else if ((pFkp = new WW8Fkp(GetVersion(), pFKPStrm, pDataStrm, nPo, + pFkpSizeTab[ ePLCF ], ePLCF, GetStartFc()))) + { + maFkpCache.push_back(pFkp); + + if (maFkpCache.size() > eMaxCache) + { + delete maFkpCache.front(); + maFkpCache.pop_front(); + } + } + } + + SetStartFc( -1 ); // Nur das erste Mal + return true; +} + +WW8PLCFx_Fc_FKP::WW8PLCFx_Fc_FKP(SvStream* pSt, SvStream* pTblSt, + SvStream* pDataSt, const WW8Fib& rFib, ePLCFT ePl, WW8_FC nStartFcL) + : WW8PLCFx(rFib.nVersion, true), pFKPStrm(pSt), pDataStrm(pDataSt), + pFkp(0), ePLCF(ePl), pPCDAttrs(0) +{ + SetStartFc(nStartFcL); + long nLenStruct = (8 > rFib.nVersion) ? 2 : 4; + if (ePl == CHP) + { + pPLCF = new WW8PLCF(pTblSt, rFib.fcPlcfbteChpx, rFib.lcbPlcfbteChpx, + nLenStruct, GetStartFc(), rFib.pnChpFirst, rFib.cpnBteChp); + } + else + { + pPLCF = new WW8PLCF(pTblSt, rFib.fcPlcfbtePapx, rFib.lcbPlcfbtePapx, + nLenStruct, GetStartFc(), rFib.pnPapFirst, rFib.cpnBtePap); + } +} + +WW8PLCFx_Fc_FKP::~WW8PLCFx_Fc_FKP() +{ + myiter aEnd = maFkpCache.end(); + for (myiter aIter = maFkpCache.begin(); aIter != aEnd; ++aIter) + delete *aIter; + delete pPLCF; + delete pPCDAttrs; +} + +ULONG WW8PLCFx_Fc_FKP::GetIdx() const +{ + ULONG u = pPLCF->GetIdx() << 8; + if (pFkp) + u |= pFkp->GetIdx(); + return u; +} + +void WW8PLCFx_Fc_FKP::SetIdx( ULONG nIdx ) +{ + if( !( nIdx & 0xffffff00L ) ) + { + pPLCF->SetIdx( nIdx >> 8 ); + pFkp = 0; + } + else + { //Es gab einen Fkp + //Lese PLCF um 1 Pos zurueck, um die Adresse des Fkp wiederzubekommen + pPLCF->SetIdx( ( nIdx >> 8 ) - 1 ); + if ( NewFkp() ) // und lese Fkp wieder ein + pFkp->SetIdx( nIdx & 0xff ); // Dann stelle Fkp-Pos wieder ein + } +} + +bool WW8PLCFx_Fc_FKP::SeekPos(WW8_FC nFcPos) +{ + // StartPos for next Where() + SetStartFc( nFcPos ); + + // find StartPos for next pPLCF->Get() + bool bRet = pPLCF->SeekPos(nFcPos); + + // make FKP invalid? + long nPLCFStart, nPLCFEnd; + void* pPage; + if( pFkp && pPLCF->Get( nPLCFStart, nPLCFEnd, pPage ) ) + { + long nPo = SVBT16ToShort( (BYTE *)pPage ); + nPo <<= 9; // shift als LONG + if (nPo != pFkp->GetFilePos()) + pFkp = 0; + else + pFkp->SeekPos( nFcPos ); + } + return bRet; +} + +WW8_FC WW8PLCFx_Fc_FKP::Where() +{ + if( !pFkp ) + { + if( !NewFkp() ) + return LONG_MAX; + } + WW8_FC nP = pFkp->Where(); + if( nP != LONG_MAX ) + return nP; + + pFkp = 0; // FKP beendet -> hole neuen + return Where(); // am einfachsten rekursiv +} + +BYTE* WW8PLCFx_Fc_FKP::GetSprmsAndPos(WW8_FC& rStart, WW8_FC& rEnd, long& rLen) +{ + rLen = 0; // Default + rStart = rEnd = LONG_MAX; + + if( !pFkp ) // Fkp not there ? + { + if( !NewFkp() ) + return 0; + } + + BYTE* pPos = pFkp->Get( rStart, rEnd, rLen ); + if( rStart == LONG_MAX ) //Not found + return 0; + return pPos; +} + +WW8PLCFx& WW8PLCFx_Fc_FKP::operator ++( int ) +{ + if( !pFkp ) + { + if( !NewFkp() ) + return *this; + } + + (*pFkp)++; + if( pFkp->Where() == LONG_MAX ) + NewFkp(); + + return *this; +} + +USHORT WW8PLCFx_Fc_FKP::GetIstd() const +{ + return pFkp ? pFkp->GetIstd() : 0xFFFF; +} + +void WW8PLCFx_Fc_FKP::GetPCDSprms( WW8PLCFxDesc& rDesc ) +{ + rDesc.pMemPos = 0; + rDesc.nSprmsLen = 0; + if( pPCDAttrs ) + { + if( !pFkp ) + { + DBG_WARNING( + "+Problem: GetPCDSprms: NewFkp necessay (not possible!)" ); + if( !NewFkp() ) + return; + } + pPCDAttrs->GetSprms(&rDesc); + } +} + +const BYTE* WW8PLCFx_Fc_FKP::HasSprm( USHORT nId ) +{ + // const waere schoener, aber dafuer muesste NewFkp() ersetzt werden oder + // wegfallen + if( !pFkp ) + { + DBG_WARNING( "+Motz: HasSprm: NewFkp noetig ( kein const moeglich )" ); + // Passiert bei BugDoc 31722 + if( !NewFkp() ) + return 0; + } + + const BYTE* pRes = pFkp->HasSprm( nId ); + + if( !pRes ) + { + WW8PLCFxDesc aDesc; + GetPCDSprms( aDesc ); + + if (aDesc.pMemPos) + { + WW8SprmIter aIter(aDesc.pMemPos, aDesc.nSprmsLen, + pFkp->GetSprmParser()); + pRes = aIter.FindSprm(nId); + } + } + + return pRes; +} + +bool WW8PLCFx_Fc_FKP::HasSprm(USHORT nId, std::vector<const BYTE *> &rResult) +{ + // const waere schoener, aber dafuer muesste NewFkp() ersetzt werden oder + // wegfallen + if (!pFkp) + { + DBG_WARNING( "+Motz: HasSprm: NewFkp noetig ( kein const moeglich )" ); + // Passiert bei BugDoc 31722 + if( !NewFkp() ) + return 0; + } + + pFkp->HasSprm(nId, rResult); + + WW8PLCFxDesc aDesc; + GetPCDSprms( aDesc ); + + if (aDesc.pMemPos) + { + WW8SprmIter aIter(aDesc.pMemPos, aDesc.nSprmsLen, + pFkp->GetSprmParser()); + while(aIter.GetSprms()) + { + if (aIter.GetAktId() == nId) + rResult.push_back(aIter.GetAktParams()); + aIter++; + }; + } + return !rResult.empty(); +} + +//----------------------------------------- + +WW8PLCFx_Cp_FKP::WW8PLCFx_Cp_FKP( SvStream* pSt, SvStream* pTblSt, + SvStream* pDataSt, const WW8ScannerBase& rBase, ePLCFT ePl ) + : WW8PLCFx_Fc_FKP(pSt, pTblSt, pDataSt, *rBase.pWw8Fib, ePl, + rBase.WW8Cp2Fc(0)), rSBase(rBase), nAttrStart(-1), nAttrEnd(-1), + bLineEnd(false), + bComplex( (7 < rBase.pWw8Fib->nVersion) || (0 != rBase.pWw8Fib->fComplex) ) +{ + ResetAttrStartEnd(); + + pPcd = rSBase.pPiecePLCF ? new WW8PLCFx_PCD( rBase.pWw8Fib->nVersion, + rBase.pPiecePLCF, 0, ((6 == GetVersion()) || (7 == GetVersion())) ) + : 0; + + /* + Make a copy of the piece attributes for so that the calls to HasSprm on a + Fc_FKP will be able to take into account the current piece attributes, + despite the fact that such attributes can only be found through a cp based + mechanism. + */ + if (pPcd) + { + pPCDAttrs = rSBase.pPLCFx_PCDAttrs ? new WW8PLCFx_PCDAttrs( + rSBase.pWw8Fib->nVersion, pPcd, &rSBase) : 0; + } + + pPieceIter = rSBase.pPieceIter; +} + +WW8PLCFx_Cp_FKP::~WW8PLCFx_Cp_FKP() +{ + delete pPcd; +} + +void WW8PLCFx_Cp_FKP::ResetAttrStartEnd() +{ + nAttrStart = -1; + nAttrEnd = -1; + bLineEnd = false; +} + +ULONG WW8PLCFx_Cp_FKP::GetPCDIMax() const +{ + return pPcd ? pPcd->GetIMax() : 0; +} + +ULONG WW8PLCFx_Cp_FKP::GetPCDIdx() const +{ + return pPcd ? pPcd->GetIdx() : 0; +} + +void WW8PLCFx_Cp_FKP::SetPCDIdx( ULONG nIdx ) +{ + if( pPcd ) + pPcd->SetIdx( nIdx ); +} + +bool WW8PLCFx_Cp_FKP::SeekPos(WW8_CP nCpPos) +{ + if( pPcd ) // Complex + { + if( !pPcd->SeekPos( nCpPos ) ) // Piece setzen + return false; + if (pPCDAttrs && !pPCDAttrs->GetIter()->SeekPos(nCpPos)) + return false; + return WW8PLCFx_Fc_FKP::SeekPos(pPcd->AktPieceStartCp2Fc(nCpPos)); + } + // KEINE Piece-Table !!! + return WW8PLCFx_Fc_FKP::SeekPos( rSBase.WW8Cp2Fc(nCpPos) ); +} + +WW8_CP WW8PLCFx_Cp_FKP::Where() +{ + WW8_FC nFc = WW8PLCFx_Fc_FKP::Where(); + if( pPcd ) + return pPcd->AktPieceStartFc2Cp( nFc ); // Piece ermitteln + return rSBase.WW8Fc2Cp( nFc ); // KEINE Piece-Table !!! +} + +void WW8PLCFx_Cp_FKP::GetSprms(WW8PLCFxDesc* p) +{ + WW8_CP nOrigCp = p->nStartPos; + + if (!GetDirty()) //Normal case + { + p->pMemPos = WW8PLCFx_Fc_FKP::GetSprmsAndPos(p->nStartPos, p->nEndPos, + p->nSprmsLen); + } + else + { + /* + #93702# + For the odd case where we have a location in a fastsaved file which + does not have an entry in the FKP, perhaps its para end is in the next + piece, or perhaps the cp just doesn't exist at all in this document. + AdvSprm doesn't know so it sets the PLCF as dirty and we figure out + in this method what the situation is + + It doesn't exist then the piece iterator will not be able to find it. + Otherwise our cool fastsave algorithm can be brought to bear on the + problem. + */ + ULONG nOldPos = pPieceIter->GetIdx(); + bool bOk = pPieceIter->SeekPos(nOrigCp); + pPieceIter->SetIdx( nOldPos ); + if (!bOk) + return; + } + + if( pPcd ) // Piece-Table vorhanden !!! + { + // Init ( noch kein ++ gerufen ) + if( (nAttrStart > nAttrEnd) || (nAttrStart == -1) ) + { + p->bRealLineEnd = (ePLCF == PAP); + + if ( ((ePLCF == PAP ) || (ePLCF == CHP)) && (nOrigCp != LONG_MAX) ) + { + bool bIsUnicode=false; + /* + To find the end of a paragraph for a character in a + complex format file. + + It is necessary to know the piece that contains the + character and the FC assigned to the character. + */ + + //We set the piece iterator to the piece that contains the + //character, now we have the correct piece for this character + ULONG nOldPos = pPieceIter->GetIdx(); + p->nStartPos = nOrigCp; + pPieceIter->SeekPos( p->nStartPos); + + //This is the FC assigned to the character, but we already + //have the result of the next stage, so we can skip this step + //WW8_FC nStartFc = rSBase.WW8Cp2Fc(p->nStartPos, &bIsUnicode); + + /* + Using the FC of the character, first search the FKP that + describes the character to find the smallest FC in the rgfc + that is larger than the character FC. + */ + //But the search has already been done, the next largest FC is + //p->nEndPos. + WW8_FC nOldEndPos = p->nEndPos; + + /* + If the FC found in the FKP is less than or equal to the limit + FC of the piece, the end of the paragraph that contains the + character is at the FKP FC minus 1. + */ + long nCpStart, nCpEnd; + void* pData; + pPieceIter->Get(nCpStart, nCpEnd, pData); + + WW8_FC nLimitFC = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc ); + WW8_FC nBeginLimitFC = nLimitFC; + if( 8 <= GetVersion() ) + { + nBeginLimitFC = + WW8PLCFx_PCD::TransformPieceAddress(nLimitFC, + bIsUnicode); + } + nLimitFC = nBeginLimitFC + + (nCpEnd - nCpStart) * (bIsUnicode ? 2 : 1); + + if (nOldEndPos <= nLimitFC) + { + p->nEndPos = nCpEnd - + (nLimitFC-nOldEndPos) / (bIsUnicode ? 2 : 1); + } + else + { + if (ePLCF == CHP) + p->nEndPos = nCpEnd; + else + { + /* + If the FKP FC that was found was greater than the FC + of the end of the piece, scan piece by piece toward + the end of the document until a piece is found that + contains a paragraph end mark. + */ + + /* + It's possible to check if a piece contains a paragraph + mark by using the FC of the beginning of the piece to + search in the FKPs for the smallest FC in the FKP rgfc + that is greater than the FC of the beginning of the + piece. If the FC found is less than or equal to the + limit FC of the piece, then the character that ends + the paragraph is the character immediately before the + FKP fc + */ + + (*pPieceIter)++; + + for (;pPieceIter->GetIdx() < pPieceIter->GetIMax(); + (*pPieceIter)++) + { + if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) ) + { + ASSERT( !this, "piece iter broken!" ); + break; + } + bIsUnicode = false; + INT32 nFcStart=SVBT32ToUInt32(((WW8_PCD*)pData)->fc); + + if( 8 <= GetVersion() ) + { + nFcStart = + WW8PLCFx_PCD::TransformPieceAddress( + nFcStart,bIsUnicode ); + } + nLimitFC = nFcStart + (nCpEnd - nCpStart) * + (bIsUnicode ? 2 : 1); + + //if it doesn't exist, skip it + if (!SeekPos(nCpStart)) + continue; + + WW8_FC nOne,nSmallest; + p->pMemPos = WW8PLCFx_Fc_FKP::GetSprmsAndPos(nOne, + nSmallest, p->nSprmsLen); + + if (nSmallest <= nLimitFC) + { + p->nEndPos = nCpEnd - + (nLimitFC-nSmallest) / (bIsUnicode ? 2 : 1); + break; + } + } + } + } + pPieceIter->SetIdx( nOldPos ); + } + else + pPcd->AktPieceFc2Cp( p->nStartPos, p->nEndPos,&rSBase ); + } + else + { + p->nStartPos = nAttrStart; + p->nEndPos = nAttrEnd; + p->bRealLineEnd = bLineEnd; + } + } + else // KEINE Piece-Table !!! + { + p->nStartPos = rSBase.WW8Fc2Cp( p->nStartPos ); + p->nEndPos = rSBase.WW8Fc2Cp( p->nEndPos ); + p->bRealLineEnd = ePLCF == PAP; + } +} + +WW8PLCFx& WW8PLCFx_Cp_FKP::operator ++( int ) +{ + WW8PLCFx_Fc_FKP::operator ++( 0 ); + // !pPcd: Notbremse + if ( !bComplex || !pPcd ) + return *this; + + if( GetPCDIdx() >= GetPCDIMax() ) // End of PLCF + { + nAttrStart = nAttrEnd = LONG_MAX; + return *this; + } + + long nFkpLen; // Fkp-Eintrag + // Fkp-Eintrag holen + WW8PLCFx_Fc_FKP::GetSprmsAndPos(nAttrStart, nAttrEnd, nFkpLen); + + pPcd->AktPieceFc2Cp( nAttrStart, nAttrEnd, &rSBase ); + bLineEnd = (ePLCF == PAP); + return *this; +} + +//----------------------------------------- +//----------------------------------------- + +WW8PLCFx_SEPX::WW8PLCFx_SEPX(SvStream* pSt, SvStream* pTblSt, + const WW8Fib& rFib, WW8_CP nStartCp) + : WW8PLCFx(rFib.nVersion, true), maSprmParser(rFib.nVersion), pStrm(pSt), + nArrMax(256), nSprmSiz(0) +{ + pPLCF = rFib.lcbPlcfsed + ? new WW8PLCF(pTblSt, rFib.fcPlcfsed, rFib.lcbPlcfsed, 12, nStartCp) + : 0; + + pSprms = new BYTE[nArrMax]; // maximum length +} + +WW8PLCFx_SEPX::~WW8PLCFx_SEPX() +{ + delete pPLCF; + delete[] pSprms; +} + +ULONG WW8PLCFx_SEPX::GetIdx() const +{ + return pPLCF ? pPLCF->GetIdx() : 0; +} + +void WW8PLCFx_SEPX::SetIdx( ULONG nIdx ) +{ + if( pPLCF ) pPLCF->SetIdx( nIdx ); +} + +bool WW8PLCFx_SEPX::SeekPos(WW8_CP nCpPos) +{ + return pPLCF ? pPLCF->SeekPos( nCpPos ) : 0; +} + +WW8_CP WW8PLCFx_SEPX::Where() +{ + return pPLCF ? pPLCF->Where() : 0; +} + +void WW8PLCFx_SEPX::GetSprms(WW8PLCFxDesc* p) +{ + if( !pPLCF ) return; + + void* pData; + + p->bRealLineEnd = false; + if (!pPLCF->Get( p->nStartPos, p->nEndPos, pData )) + { + p->nStartPos = p->nEndPos = LONG_MAX; // PLCF fertig abgearbeitet + p->pMemPos = 0; + p->nSprmsLen = 0; + } + else + { + long nPo = SVBT32ToUInt32( (BYTE*)pData+2 ); + if (nPo == -1L) + { + p->nStartPos = p->nEndPos = LONG_MAX; // Sepx empty + p->pMemPos = 0; + p->nSprmsLen = 0; + } + else + { + pStrm->Seek( nPo ); + *pStrm >> nSprmSiz; // read len + + if( nSprmSiz > nArrMax ) + { // passt nicht + delete[] pSprms; + nArrMax = nSprmSiz; // Hole mehr Speicher + pSprms = new BYTE[nArrMax]; + } + pStrm->Read( pSprms, nSprmSiz ); // read Sprms + + p->nSprmsLen = nSprmSiz; + p->pMemPos = pSprms; // return Position + } + } +} + +WW8PLCFx& WW8PLCFx_SEPX::operator ++( int ) +{ + if( pPLCF ) + (*pPLCF)++; + return *this; +} + +const BYTE* WW8PLCFx_SEPX::HasSprm( USHORT nId ) const +{ + return HasSprm( nId, pSprms, nSprmSiz); +} + +const BYTE* WW8PLCFx_SEPX::HasSprm( USHORT nId, const BYTE* pOtherSprms, + long nOtherSprmSiz ) const +{ + const BYTE *pRet = 0; + if (pPLCF) + { + WW8SprmIter aIter(pOtherSprms, nOtherSprmSiz, maSprmParser); + pRet = aIter.FindSprm(nId); + } + return pRet; +} + +bool WW8PLCFx_SEPX::Find4Sprms(USHORT nId1,USHORT nId2,USHORT nId3,USHORT nId4, + BYTE*& p1, BYTE*& p2, BYTE*& p3, BYTE*& p4) const +{ + if( !pPLCF ) + return 0; + + bool bFound = false; + p1 = 0; + p2 = 0; + p3 = 0; + p4 = 0; + + BYTE* pSp = pSprms; + USHORT i=0; + while (i + maSprmParser.MinSprmLen() <= nSprmSiz) + { + // Sprm gefunden? + USHORT nAktId = maSprmParser.GetSprmId(pSp); + bool bOk = true; + if( nAktId == nId1 ) + p1 = pSp + maSprmParser.DistanceToData(nId1); + else if( nAktId == nId2 ) + p2 = pSp + maSprmParser.DistanceToData(nId2); + else if( nAktId == nId3 ) + p3 = pSp + maSprmParser.DistanceToData(nId3); + else if( nAktId == nId4 ) + p4 = pSp + maSprmParser.DistanceToData(nId4); + else + bOk = false; + bFound |= bOk; + // erhoehe Zeiger, so dass er auf naechsten Sprm zeigt + USHORT x = maSprmParser.GetSprmSize(nAktId, pSp); + i += x; + pSp += x; + } + return bFound; +} + +const BYTE* WW8PLCFx_SEPX::HasSprm( USHORT nId, BYTE n2nd ) const +{ + if( !pPLCF ) + return 0; + + BYTE* pSp = pSprms; + + USHORT i=0; + while (i + maSprmParser.MinSprmLen() <= nSprmSiz) + { + // Sprm gefunden? + USHORT nAktId = maSprmParser.GetSprmId(pSp); + if (nAktId == nId) + { + BYTE *pRet = pSp + maSprmParser.DistanceToData(nId); + if (*pRet == n2nd) + return pRet; + } + // erhoehe Zeiger, so dass er auf naechsten Sprm zeigt + USHORT x = maSprmParser.GetSprmSize(nAktId, pSp); + i += x; + pSp += x; + } + + return 0; // Sprm nicht gefunden +} + +//----------------------------------------- +WW8PLCFx_SubDoc::WW8PLCFx_SubDoc(SvStream* pSt, BYTE nVersion, + WW8_CP nStartCp, long nFcRef, long nLenRef, long nFcTxt, long nLenTxt, + long nStruct) + : WW8PLCFx(nVersion, false), pRef(0), pTxt(0) +{ + if( nLenRef && nLenTxt ) + { + pRef = new WW8PLCF( pSt, nFcRef, nLenRef, nStruct, nStartCp ); + pTxt = new WW8PLCF( pSt, nFcTxt, nLenTxt, 0, nStartCp ); + } +} + +WW8PLCFx_SubDoc::~WW8PLCFx_SubDoc() +{ + delete pRef; + delete pTxt; +} + +ULONG WW8PLCFx_SubDoc::GetIdx() const +{ + // Wahrscheinlich pTxt... nicht noetig + if( pRef ) + return ( pRef->GetIdx() << 16 | pTxt->GetIdx() ); + return 0; +} + +void WW8PLCFx_SubDoc::SetIdx( ULONG nIdx ) +{ + if( pRef ) + { + pRef->SetIdx( nIdx >> 16 ); + // Wahrscheinlich pTxt... nicht noetig + pTxt->SetIdx( nIdx & 0xFFFF ); + } +} + +bool WW8PLCFx_SubDoc::SeekPos( WW8_CP nCpPos ) +{ + return ( pRef ) ? pRef->SeekPos( nCpPos ) : false; +} + +WW8_CP WW8PLCFx_SubDoc::Where() +{ + return ( pRef ) ? pRef->Where() : LONG_MAX; +} + +long WW8PLCFx_SubDoc::GetNoSprms( WW8_CP& rStart, long& rEnd, long& rLen ) +{ + void* pData; + long nSt, nE; + rEnd = LONG_MAX; + + if ( !pRef ) + { + rStart = LONG_MAX; // Es gibt keine Noten + rLen = 0; + return -1; + } + + ULONG nNr = pRef->GetIdx(); + + if (!pRef->Get( rStart, nE, pData )) + { + rStart = LONG_MAX; // PLCF fertig abgearbeitet + rLen = 0; + return -1; + } + pTxt->SetIdx( nNr ); + + if(!pTxt->Get( nSt, rLen, pData )) + { + rStart = LONG_MAX; // PLCF fertig abgearbeitet + rLen = 0; + return -1; + } + + rLen -= nSt; + return nSt; +} + +WW8PLCFx& WW8PLCFx_SubDoc::operator ++( int ) +{ + if( pRef && pTxt ) + { + (*pRef)++; + (*pTxt)++; + } + return *this; +} + +//----------------------------------------- +// Felder +//----------------------------------------- + +WW8PLCFx_FLD::WW8PLCFx_FLD( SvStream* pSt, const WW8Fib& rMyFib, short nType) + : WW8PLCFx(rMyFib.nVersion, true), pPLCF(0), rFib(rMyFib) +{ + long nFc, nLen; + + switch( nType ) + { + case MAN_HDFT: + nFc = rFib.fcPlcffldHdr; + nLen = rFib.lcbPlcffldHdr; + break; + case MAN_FTN: + nFc = rFib.fcPlcffldFtn; + nLen = rFib.lcbPlcffldFtn; + break; + case MAN_EDN: + nFc = rFib.fcPlcffldEdn; + nLen = rFib.lcbPlcffldEdn; + break; + case MAN_AND: + nFc = rFib.fcPlcffldAtn; + nLen = rFib.lcbPlcffldAtn; + break; + case MAN_TXBX: + nFc = rFib.fcPlcffldTxbx; + nLen = rFib.lcbPlcffldTxbx; + break; + case MAN_TXBX_HDFT: + nFc = rFib.fcPlcffldHdrTxbx; + nLen = rFib.lcbPlcffldHdrTxbx; + break; + default: + nFc = rFib.fcPlcffldMom; + nLen = rFib.lcbPlcffldMom; + break; + } + + if( nLen ) + pPLCF = new WW8PLCFspecial( pSt, nFc, nLen, 2 ); +} + +WW8PLCFx_FLD::~WW8PLCFx_FLD() +{ + delete pPLCF; +} + +ULONG WW8PLCFx_FLD::GetIdx() const +{ + return pPLCF ? pPLCF->GetIdx() : 0; +} + +void WW8PLCFx_FLD::SetIdx( ULONG nIdx ) +{ + if( pPLCF ) + pPLCF->SetIdx( nIdx ); +} + +bool WW8PLCFx_FLD::SeekPos(WW8_CP nCpPos) +{ + return pPLCF ? pPLCF->SeekPosExact( nCpPos ) : false; +} + +WW8_CP WW8PLCFx_FLD::Where() +{ + return pPLCF ? pPLCF->Where() : LONG_MAX; +} + +bool WW8PLCFx_FLD::StartPosIsFieldStart() +{ + void* pData; + long nTest; + if ( + (!pPLCF || !pPLCF->Get(nTest, pData) || + ((((BYTE*)pData)[0] & 0x1f) != 0x13)) + ) + return false; + return true; +} + +bool WW8PLCFx_FLD::EndPosIsFieldEnd() +{ + bool bRet = false; + + if (pPLCF) + { + long n = pPLCF->GetIdx(); + + (*pPLCF)++; + + void* pData; + long nTest; + if ( pPLCF->Get(nTest, pData) && ((((BYTE*)pData)[0] & 0x1f) == 0x15) ) + bRet = true; + + pPLCF->SetIdx(n); + } + + return bRet; +} + +void WW8PLCFx_FLD::GetSprms(WW8PLCFxDesc* p) +{ + p->nStartPos = p->nEndPos = LONG_MAX; + p->pMemPos = 0; + p->nSprmsLen = 0; + p->bRealLineEnd = false; + + if (!pPLCF) + { + p->nStartPos = LONG_MAX; // Es gibt keine Felder + return; + } + + long n = pPLCF->GetIdx(); + + long nP; + void *pData; + if (!pPLCF->Get(nP, pData)) // Ende des PLCFspecial ? + { + p->nStartPos = LONG_MAX; // PLCF fertig abgearbeitet + return; + } + + p->nStartPos = nP; + + (*pPLCF)++; + if (!pPLCF->Get(nP, pData)) // Ende des PLCFspecial ? + { + p->nStartPos = LONG_MAX; // PLCF fertig abgearbeitet + return; + } + + p->nEndPos = nP; + + pPLCF->SetIdx(n); + + p->nCp2OrIdx = pPLCF->GetIdx(); +} + +WW8PLCFx& WW8PLCFx_FLD::operator ++( int ) +{ + (*pPLCF)++; + return *this; +} + +bool WW8PLCFx_FLD::GetPara(long nIdx, WW8FieldDesc& rF) +{ + ASSERT( pPLCF, "Aufruf ohne Feld PLCFspecial" ); + if( !pPLCF ) + return false; + + long n = pPLCF->GetIdx(); + pPLCF->SetIdx(nIdx); + + bool bOk = WW8GetFieldPara(*pPLCF, rF); + + pPLCF->SetIdx(n); + return bOk; +} + +//----------------------------------------- +// class WW8PLCF_Book +//----------------------------------------- + +/* to be optimized like this: */ +void WW8ReadSTTBF(bool bVer8, SvStream& rStrm, UINT32 nStart, INT32 nLen, + USHORT nExtraLen, rtl_TextEncoding eCS, std::vector<String> &rArray, + std::vector<String>* pExtraArray) +{ + ULONG nOldPos = rStrm.Tell(); + rStrm.Seek( nStart ); + + UINT16 nLen2; + rStrm >> nLen2; // bVer67: total length of structure + // bVer8 : count of strings + + if( bVer8 ) + { + UINT16 nStrings; + bool bUnicode = (0xFFFF == nLen2); + if( bUnicode ) + rStrm >> nStrings; + else + nStrings = nLen2; + + rStrm >> nExtraLen; + + for( USHORT i=0; i < nStrings; i++ ) + { + if( bUnicode ) + rArray.push_back(WW8Read_xstz(rStrm, 0, false)); + else + { + BYTE nBChar; + rStrm >> nBChar; + ByteString aTmp; + SafeReadString(aTmp,nBChar,rStrm); + rArray.push_back(String(aTmp, eCS)); + } + + // Skip the extra data + if( nExtraLen ) + { + if (pExtraArray) + { + ByteString aTmp; + SafeReadString(aTmp,nExtraLen,rStrm); + pExtraArray->push_back(String(aTmp, eCS)); + } + else + rStrm.SeekRel( nExtraLen ); + } + } + } + else + { + BYTE nBChar; + if( nLen2 != nLen ) + { + ASSERT( nLen2 == nLen, "Fib length and read length are different" ); + if (nLen > USHRT_MAX) + nLen = USHRT_MAX; + else if (nLen < 2 ) + nLen = 2; + nLen2 = static_cast<UINT16>(nLen); + } + ULONG nRead = 0; + for( nLen2 -= 2; nRead < nLen2; ) + { + rStrm >> nBChar; ++nRead; + if (nBChar) + { + ByteString aTmp; + nRead += SafeReadString(aTmp,nBChar,rStrm); + rArray.push_back(String(aTmp, eCS)); + } + else + rArray.push_back(aEmptyStr); + + // #89125# Skip the extra data (for bVer67 versions this must come + // from external knowledge) + if (nExtraLen) + { + if (pExtraArray) + { + ByteString aTmp; + SafeReadString(aTmp,nExtraLen,rStrm); + pExtraArray->push_back(String(aTmp, eCS)); + } + else + rStrm.SeekRel( nExtraLen ); + nRead+=nExtraLen; + } + } + } + rStrm.Seek( nOldPos ); +} + +WW8PLCFx_Book::WW8PLCFx_Book(SvStream* pTblSt, const WW8Fib& rFib) + : WW8PLCFx(rFib.nVersion, false), pStatus(0), nIsEnd(0) +{ + if( !rFib.fcPlcfbkf || !rFib.lcbPlcfbkf || !rFib.fcPlcfbkl || + !rFib.lcbPlcfbkl || !rFib.fcSttbfbkmk || !rFib.lcbSttbfbkmk ) + { + pBook[0] = pBook[1] = 0; + nIMax = 0; + } + else + { + pBook[0] = new WW8PLCFspecial(pTblSt,rFib.fcPlcfbkf,rFib.lcbPlcfbkf,4); + + pBook[1] = new WW8PLCFspecial( pTblSt, rFib.fcPlcfbkl, rFib.lcbPlcfbkl, + 0, -1, true); + + rtl_TextEncoding eStructChrSet = WW8Fib::GetFIBCharset(rFib.chseTables); + + WW8ReadSTTBF( (7 < rFib.nVersion), *pTblSt, rFib.fcSttbfbkmk, + rFib.lcbSttbfbkmk, 0, eStructChrSet, aBookNames ); + + nIMax = aBookNames.size(); + + if( pBook[0]->GetIMax() < nIMax ) // Count of Bookmarks + nIMax = pBook[0]->GetIMax(); + if( pBook[1]->GetIMax() < nIMax ) + nIMax = pBook[1]->GetIMax(); + pStatus = new eBookStatus[ nIMax ]; + memset( pStatus, 0, nIMax * sizeof( eBookStatus ) ); + } +} + +WW8PLCFx_Book::~WW8PLCFx_Book() +{ + delete[] pStatus; + delete pBook[1]; + delete pBook[0]; +} + +ULONG WW8PLCFx_Book::GetIdx() const +{ + return nIMax ? pBook[0]->GetIdx() : 0; +} + +void WW8PLCFx_Book::SetIdx( ULONG nI ) +{ + if( nIMax ) + pBook[0]->SetIdx( nI ); +} + +ULONG WW8PLCFx_Book::GetIdx2() const +{ + return nIMax ? ( pBook[1]->GetIdx() | ( ( nIsEnd ) ? 0x80000000 : 0 ) ) : 0; +} + +void WW8PLCFx_Book::SetIdx2( ULONG nI ) +{ + if( nIMax ) + { + pBook[1]->SetIdx( nI & 0x7fffffff ); + nIsEnd = (USHORT)( ( nI >> 31 ) & 1 ); // 0 oder 1 + } +} + +bool WW8PLCFx_Book::SeekPos(WW8_CP nCpPos) +{ + if( !pBook[0] ) + return false; + + bool bOk = pBook[0]->SeekPosExact( nCpPos ); + bOk &= pBook[1]->SeekPosExact( nCpPos ); + nIsEnd = 0; + + return bOk; +} + +WW8_CP WW8PLCFx_Book::Where() +{ + return pBook[nIsEnd]->Where(); +} + +long WW8PLCFx_Book::GetNoSprms( long& rStart, long& rEnd, long& rLen ) +{ + void* pData; + rEnd = LONG_MAX; + rLen = 0; + + if (!pBook[0] || !pBook[1] || !nIMax || (pBook[nIsEnd]->GetIdx()) >= nIMax) + { + rStart = rEnd = LONG_MAX; + return -1; + } + + pBook[nIsEnd]->Get( rStart, pData ); // Pos. abfragen + + return pBook[nIsEnd]->GetIdx(); +} + +// Der Operator ++ hat eine Tuecke: Wenn 2 Bookmarks aneinandergrenzen, dann +// sollte erst das Ende des ersten und dann der Anfang des 2. erreicht werden. +// Liegen jedoch 2 Bookmarks der Laenge 0 aufeinander, *muss* von jedem Bookmark +// erst der Anfang und dann das Ende gefunden werden. +// Der Fall: ][ +// [...] +// ][ +// ist noch nicht geloest, dabei muesste ich in den Anfangs- und Endindices +// vor- und zurueckspringen, wobei ein weiterer Index oder ein Bitfeld +// oder etwas aehnliches zum Merken der bereits abgearbeiteten Bookmarks +// noetig wird. +WW8PLCFx& WW8PLCFx_Book::operator ++( int ) +{ + if( pBook[0] && pBook[1] && nIMax ) + { + (*pBook[nIsEnd])++; + + ULONG l0 = pBook[0]->Where(); + ULONG l1 = pBook[1]->Where(); + if( l0 < l1 ) + nIsEnd = 0; + else if( l1 < l0 ) + nIsEnd = 1; + else + nIsEnd = ( nIsEnd ) ? 0 : 1; + } + return *this; +} + +long WW8PLCFx_Book::GetLen() const +{ + if( nIsEnd ) + { + ASSERT( !this, "Falscher Aufruf (1) von PLCF_Book::GetLen()" ); + return 0; + } + void * p; + WW8_CP nStartPos; + if( !pBook[0]->Get( nStartPos, p ) ) + { + ASSERT( !this, "Falscher Aufruf (2) von PLCF_Book::GetLen()" ); + return 0; + } + USHORT nEndIdx = SVBT16ToShort( *((SVBT16*)p) ); + long nNum = pBook[1]->GetPos( nEndIdx ); + nNum -= nStartPos; + return nNum; +} + +void WW8PLCFx_Book::SetStatus(USHORT nIndex, eBookStatus eStat ) +{ + ASSERT(nIndex < nIMax, "set status of non existing bookmark!"); + pStatus[nIndex] = (eBookStatus)( pStatus[nIndex] | eStat ); +} + +eBookStatus WW8PLCFx_Book::GetStatus() const +{ + if( !pStatus ) + return BOOK_NORMAL; + long nEndIdx = GetHandle(); + return ( nEndIdx < nIMax ) ? pStatus[nEndIdx] : BOOK_NORMAL; +} + +long WW8PLCFx_Book::GetHandle() const +{ + if( !pBook[0] || !pBook[1] ) + return LONG_MAX; + + if( nIsEnd ) + return pBook[1]->GetIdx(); + else + { + if (const void* p = pBook[0]->GetData(pBook[0]->GetIdx())) + return SVBT16ToShort( *((SVBT16*)p) ); + else + return LONG_MAX; + } +} + +String WW8PLCFx_Book::GetBookmark(long nStart,long nEnd, USHORT &nIndex) +{ + bool bFound = false; + USHORT i = 0; + if( pBook[0] && pBook[1] ) + { + WW8_CP nStartAkt, nEndAkt; + do + { + void* p; + USHORT nEndIdx; + + if( pBook[0]->GetData( i, nStartAkt, p ) && p ) + nEndIdx = SVBT16ToShort( *((SVBT16*)p) ); + else + { + ASSERT( !this, "Bookmark-EndIdx nicht lesbar" ); + nEndIdx = i; + } + + nEndAkt = pBook[1]->GetPos( nEndIdx ); + + if ((nStartAkt >= nStart) && (nEndAkt <= nEnd)) + { + nIndex = i; + bFound=true; + break; + } + ++i; + } + while (i < pBook[0]->GetIMax()); + } + return bFound ? aBookNames[i] : aEmptyStr; +} + +bool WW8PLCFx_Book::MapName(String& rName) +{ + if( !pBook[0] || !pBook[1] ) + return false; + + bool bFound = false; + USHORT i = 0; + WW8_CP nStartAkt, nEndAkt; + do + { + void* p; + USHORT nEndIdx; + + if( pBook[0]->GetData( i, nStartAkt, p ) && p ) + nEndIdx = SVBT16ToShort( *((SVBT16*)p) ); + else + { + ASSERT( !this, "Bookmark-EndIdx nicht lesbar" ); + nEndIdx = i; + } + nEndAkt = pBook[1]->GetPos( nEndIdx ); + if (COMPARE_EQUAL == rName.CompareIgnoreCaseToAscii(aBookNames[i])) + { + rName = aBookNames[i]; + bFound = true; + } + ++i; + } + while (!bFound && i < pBook[0]->GetIMax()); + return bFound; +} + +const String* WW8PLCFx_Book::GetName() const +{ + const String *pRet = 0; + if (!nIsEnd && (pBook[0]->GetIdx() < nIMax)) + pRet = &(aBookNames[pBook[0]->GetIdx()]); + return pRet; +} + +//----------------------------------------- +// WW8PLCFMan +//----------------------------------------- + +#ifndef DUMP + +// Am Ende eines Absatzes reichen bei WW6 die Attribute bis hinter das <CR>. +// Das wird fuer die Verwendung mit dem SW um 1 Zeichen zurueckgesetzt, wenn +// dadurch kein AErger zu erwarten ist. +void WW8PLCFMan::AdjustEnds( WW8PLCFxDesc& rDesc ) +{ + //Store old end position for supercool new property finder that uses + //cp instead of fc's as nature intended + rDesc.nOrigEndPos = rDesc.nEndPos; + rDesc.nOrigStartPos = rDesc.nStartPos; + + /* + Normally given ^XXX{para end}^ we don't actually insert a para end + character into the document, so we clip the para end property one to the + left to make the para properties end when the paragraph text does. In a + drawing textbox we actually do insert a para end character, so we don't + clip it. Making the para end properties end after the para end char. + */ + if (GetDoingDrawTextBox()) + return; + + if ( (&rDesc == pPap) && rDesc.bRealLineEnd ) + { + if ( pPap->nEndPos != LONG_MAX ) // Para adjust + { + nLineEnd = pPap->nEndPos;// nLineEnd zeigt *hinter* das <CR> + pPap->nEndPos--; // Absatzende um 1 Zeichen verkuerzen + + // gibt es bereits ein CharAttr-Ende das auf das jetzige + // Absatzende zeigt ? ... dann auch um 1 Zeichen verkuerzen + if (pChp->nEndPos == nLineEnd) + pChp->nEndPos--; + + // gibt es bereits ein Sep-Ende, das auf das jetzige Absatzende + // zeigt ? ... dann auch um 1 Zeichen verkuerzen + if( pSep->nEndPos == nLineEnd ) + pSep->nEndPos--; + } + } + else if ( (&rDesc == pChp) || (&rDesc == pSep) ) + { + // Char Adjust oder Sep Adjust Wenn Ende Char-Attr == Absatzende ... + if( (rDesc.nEndPos == nLineEnd) && (rDesc.nEndPos > rDesc.nStartPos) ) + rDesc.nEndPos--; // ... dann um 1 Zeichen verkuerzen + } +} + +void WW8PLCFxDesc::ReduceByOffset() +{ + ASSERT((LONG_MAX == nStartPos) || (nStartPos <= nEndPos), + "Attr-Anfang und -Ende ueber Kreuz" ); + + if( nStartPos != LONG_MAX ) + { + /* + ##516##,##517## + Force the property change to happen at the beginning of this + subdocument, same as in GetNewNoSprms, except that the target type is + attributes attached to a piece that might span subdocument boundaries + */ + if (nCpOfs > nStartPos) + nStartPos = 0; + else + nStartPos -= nCpOfs; + } + if( nEndPos != LONG_MAX ) + { + ASSERT(nCpOfs <= nEndPos, + "oh oh, so much for the subdocument piece theory"); + nEndPos -= nCpOfs; + } +} + +void WW8PLCFMan::GetNewSprms( WW8PLCFxDesc& rDesc ) +{ + rDesc.pPLCFx->GetSprms(&rDesc); + rDesc.ReduceByOffset(); + + rDesc.bFirstSprm = true; + AdjustEnds( rDesc ); + rDesc.nOrigSprmsLen = rDesc.nSprmsLen; +} + +void WW8PLCFMan::GetNewNoSprms( WW8PLCFxDesc& rDesc ) +{ + rDesc.nCp2OrIdx = rDesc.pPLCFx->GetNoSprms(rDesc.nStartPos, rDesc.nEndPos, + rDesc.nSprmsLen); + + ASSERT((LONG_MAX == rDesc.nStartPos) || (rDesc.nStartPos <= rDesc.nEndPos), + "Attr-Anfang und -Ende ueber Kreuz" ); + + rDesc.ReduceByOffset(); + + rDesc.bFirstSprm = true; + rDesc.nOrigSprmsLen = rDesc.nSprmsLen; +} + +USHORT WW8PLCFMan::GetId(const WW8PLCFxDesc* p) const +{ + USHORT nId; + + if (p == pFld) + nId = eFLD; + else if (p->nSprmsLen > 0) + nId = maSprmParser.GetSprmId(p->pMemPos); + else + nId = 0; // Id = 0 for empty attributes + + return nId; +} + +WW8PLCFMan::WW8PLCFMan(WW8ScannerBase* pBase, short nType, long nStartCp, + bool bDoingDrawTextBox) + : maSprmParser(pBase->pWw8Fib->nVersion), + mbDoingDrawTextBox(bDoingDrawTextBox) +{ + pWwFib = pBase->pWw8Fib; + + nLastWhereIdxCp = 0; + memset( aD, 0, sizeof( aD ) ); + nLineEnd = LONG_MAX; + nManType = nType; + USHORT i; + + if( MAN_MAINTEXT == nType ) + { + // Suchreihenfolge der Attribute + nPLCF = MAN_ANZ_PLCF; + pFld = &aD[0]; + pBkm = &aD[1]; + pEdn = &aD[2]; + pFtn = &aD[3]; + pAnd = &aD[4]; + + pPcd = ( pBase->pPLCFx_PCD ) ? &aD[5] : 0; + //pPcdA index == pPcd index + 1 + pPcdA = ( pBase->pPLCFx_PCDAttrs ) ? &aD[6] : 0; + + pChp = &aD[7]; + pPap = &aD[8]; + pSep = &aD[9]; + + pSep->pPLCFx = pBase->pSepPLCF; + pFtn->pPLCFx = pBase->pFtnPLCF; + pEdn->pPLCFx = pBase->pEdnPLCF; + pBkm->pPLCFx = pBase->pBook; + pAnd->pPLCFx = pBase->pAndPLCF; + + } + else + { + // Suchreihenfolge der Attribute + nPLCF = 7; + pFld = &aD[0]; + pBkm = ( pBase->pBook ) ? &aD[1] : 0; + + pPcd = ( pBase->pPLCFx_PCD ) ? &aD[2] : 0; + //pPcdA index == pPcd index + 1 + pPcdA= ( pBase->pPLCFx_PCDAttrs ) ? &aD[3] : 0; + + pChp = &aD[4]; + pPap = &aD[5]; + pSep = &aD[6]; // Dummy + + pAnd = pFtn = pEdn = 0; // unbenutzt bei SpezText + } + + pChp->pPLCFx = pBase->pChpPLCF; + pPap->pPLCFx = pBase->pPapPLCF; + if( pPcd ) + pPcd->pPLCFx = pBase->pPLCFx_PCD; + if( pPcdA ) + pPcdA->pPLCFx= pBase->pPLCFx_PCDAttrs; + if( pBkm ) + pBkm->pPLCFx = pBase->pBook; + + pMagicTables = pBase->pMagicTables; + + switch( nType ) // Feld-Initialisierung + { + case MAN_HDFT: + pFld->pPLCFx = pBase->pFldHdFtPLCF; + nCpO = pWwFib->ccpText + pWwFib->ccpFtn; + pFdoa = pBase->pHdFtFdoa; + pTxbx = pBase->pHdFtTxbx; + pTxbxBkd = pBase->pHdFtTxbxBkd; + break; + case MAN_FTN: + pFld->pPLCFx = pBase->pFldFtnPLCF; + nCpO = pWwFib->ccpText; + pFdoa = pTxbx = pTxbxBkd = 0; + break; + case MAN_EDN: + pFld->pPLCFx = pBase->pFldEdnPLCF; + nCpO = pWwFib->ccpText + pWwFib->ccpFtn + pWwFib->ccpHdr + + pWwFib->ccpAtn; + pFdoa = pTxbx = pTxbxBkd = 0; + break; + case MAN_AND: + pFld->pPLCFx = pBase->pFldAndPLCF; + nCpO = pWwFib->ccpText + pWwFib->ccpFtn + pWwFib->ccpHdr; + pFdoa = pTxbx = pTxbxBkd = 0; + break; + case MAN_TXBX: + pFld->pPLCFx = pBase->pFldTxbxPLCF; + nCpO = pWwFib->ccpText + pWwFib->ccpFtn + pWwFib->ccpHdr + + pWwFib->ccpMcr + pWwFib->ccpAtn + pWwFib->ccpEdn; + pTxbx = pBase->pMainTxbx; + pTxbxBkd = pBase->pMainTxbxBkd; + pFdoa = 0; + break; + case MAN_TXBX_HDFT: + pFld->pPLCFx = pBase->pFldTxbxHdFtPLCF; + nCpO = pWwFib->ccpText + pWwFib->ccpFtn + pWwFib->ccpHdr + + pWwFib->ccpMcr + pWwFib->ccpAtn + pWwFib->ccpEdn + + pWwFib->ccpTxbx; + pTxbx = pBase->pHdFtTxbx; + pTxbxBkd = pBase->pHdFtTxbxBkd; + pFdoa = 0; + break; + default: + pFld->pPLCFx = pBase->pFldPLCF; + nCpO = 0; + pFdoa = pBase->pMainFdoa; + pTxbx = pBase->pMainTxbx; + pTxbxBkd = pBase->pMainTxbxBkd; + break; + } + + if( nStartCp || nCpO ) + SeekPos( nStartCp ); // PLCFe auf Text-StartPos einstellen + + // initialisieren der Member-Vars Low-Level + GetChpPLCF()->ResetAttrStartEnd(); + GetPapPLCF()->ResetAttrStartEnd(); + for( i=0; i < nPLCF; i++) + { + WW8PLCFxDesc* p = &aD[i]; + + /* + ##516##,##517## + For subdocuments we modify the cp of properties to be relative to + the beginning of subdocuments, we should also do the same for + piecetable changes, and piecetable properties, otherwise a piece + change that happens in a subdocument is lost. + */ + p->nCpOfs = ( p == pChp || p == pPap || p == pBkm || p == pPcd || + p == pPcdA ) ? nCpO : 0; + + p->nCp2OrIdx = 0; + p->bFirstSprm = false; + p->pIdStk = 0; + + if ((p == pChp) || (p == pPap)) + p->nStartPos = p->nEndPos = nStartCp; + else + p->nStartPos = p->nEndPos = LONG_MAX; + } + + // initialisieren der Member-Vars High-Level + for( i=0; i<nPLCF; i++){ + WW8PLCFxDesc* p = &aD[i]; + + if( !p->pPLCFx ) + { + p->nStartPos = p->nEndPos = LONG_MAX; + continue; + } + + if( p->pPLCFx->IsSprm() ) + { + // Vorsicht: nEndPos muss bereits + p->pIdStk = new std::stack<USHORT>; + if ((p == pChp) || (p == pPap)) + { + WW8_CP nTemp = p->nEndPos+p->nCpOfs; + p->pMemPos = 0; + p->nSprmsLen = 0; + p->nStartPos = nTemp; + if (!(*p->pPLCFx).SeekPos(p->nStartPos)) + p->nEndPos = p->nStartPos = LONG_MAX; + else + GetNewSprms( *p ); + } + else + GetNewSprms( *p ); // bei allen PLCFen initialisiert sein + } + else if( p->pPLCFx ) + GetNewNoSprms( *p ); + } +} + +WW8PLCFMan::~WW8PLCFMan() +{ + for( USHORT i=0; i<nPLCF; i++) + delete aD[i].pIdStk; +} + +// 0. welche Attr.-Klasse, +// 1. ob ein Attr.-Start ist, +// 2. CP, wo ist naechste Attr.-Aenderung +USHORT WW8PLCFMan::WhereIdx(bool* pbStart, long* pPos) const +{ + ASSERT(nPLCF,"What the hell"); + long nNext = LONG_MAX; // SuchReihenfolge: + USHORT nNextIdx = nPLCF;// first ending found ( CHP, PAP, ( SEP ) ), + bool bStart = true; // dann Anfaenge finden ( ( SEP ), PAP, CHP ) + USHORT i; + const WW8PLCFxDesc* pD; + for (i=0; i < nPLCF; i++) + { + pD = &aD[i]; + if (pD != pPcdA) + { + if( (pD->nEndPos < nNext) && (pD->nStartPos == LONG_MAX) ) + { + // sonst ist Anfang = Ende + nNext = pD->nEndPos; + nNextIdx = i; + bStart = false; + } + } + } + for (i=nPLCF; i > 0; i--) + { + pD = &aD[i-1]; + if (pD != pPcdA) + { + if( pD->nStartPos < nNext ) + { + nNext = pD->nStartPos; + nNextIdx = i-1; + bStart = true; + } + } + } + if( pPos ) + *pPos = nNext; + if( pbStart ) + *pbStart = bStart; + return nNextIdx; +} + +// gibt die CP-Pos der naechsten Attribut-Aenderung zurueck +WW8_CP WW8PLCFMan::Where() const +{ + long l; + WhereIdx(0, &l); + return l; +} + +void WW8PLCFMan::SeekPos( long nNewCp ) +{ + pChp->pPLCFx->SeekPos( nNewCp + nCpO ); // Attribute neu + pPap->pPLCFx->SeekPos( nNewCp + nCpO ); // aufsetzen + pFld->pPLCFx->SeekPos( nNewCp ); + if( pPcd ) + pPcd->pPLCFx->SeekPos( nNewCp + nCpO ); + if( pBkm ) + pBkm->pPLCFx->SeekPos( nNewCp + nCpO ); +} + +void WW8PLCFMan::SaveAllPLCFx( WW8PLCFxSaveAll& rSave ) const +{ + USHORT i, n=0; + if( pPcd ) + pPcd->Save( rSave.aS[n++] ); + if( pPcdA ) + pPcdA->Save( rSave.aS[n++] ); + + for(i=0; i<nPLCF; ++i) + if( pPcd != &aD[i] && pPcdA != &aD[i] ) + aD[i].Save( rSave.aS[n++] ); +} + +void WW8PLCFMan::RestoreAllPLCFx( const WW8PLCFxSaveAll& rSave ) +{ + USHORT i, n=0; + if( pPcd ) + pPcd->Restore( rSave.aS[n++] ); + if( pPcdA ) + pPcdA->Restore( rSave.aS[n++] ); + + for(i=0; i<nPLCF; ++i) + if( pPcd != &aD[i] && pPcdA != &aD[i] ) + aD[i].Restore( rSave.aS[n++] ); +} + +void WW8PLCFMan::GetSprmStart( short nIdx, WW8PLCFManResult* pRes ) const +{ + memset( pRes, 0, sizeof( WW8PLCFManResult ) ); + + // Pruefen !!! + + pRes->nMemLen = 0; + + const WW8PLCFxDesc* p = &aD[nIdx]; + + // first Sprm in a Group + if( p->bFirstSprm ) + { + if( p == pPap ) + pRes->nFlags |= MAN_MASK_NEW_PAP; + else if( p == pSep ) + pRes->nFlags |= MAN_MASK_NEW_SEP; + } + pRes->pMemPos = p->pMemPos; + pRes->nSprmId = GetId(p); + pRes->nCp2OrIdx = p->nCp2OrIdx; + if (p->nSprmsLen) + { + // Length of actual sprm + pRes->nMemLen = maSprmParser.GetSprmSize(pRes->nSprmId, pRes->pMemPos); + } +} + +void WW8PLCFMan::GetSprmEnd( short nIdx, WW8PLCFManResult* pRes ) const +{ + memset( pRes, 0, sizeof( WW8PLCFManResult ) ); + + const WW8PLCFxDesc* p = &aD[nIdx]; + + if (!(p->pIdStk->empty())) + pRes->nSprmId = p->pIdStk->top(); // get end position + else + { + ASSERT( !this, "No Id on the Stack" ); + pRes->nSprmId = 0; + } +} + +void WW8PLCFMan::GetNoSprmStart( short nIdx, WW8PLCFManResult* pRes ) const +{ + const WW8PLCFxDesc* p = &aD[nIdx]; + + pRes->nCpPos = p->nStartPos; + pRes->nMemLen = p->nSprmsLen; + pRes->nCp2OrIdx = p->nCp2OrIdx; + + if( p == pFld ) + pRes->nSprmId = eFLD; + else if( p == pFtn ) + pRes->nSprmId = eFTN; + else if( p == pEdn ) + pRes->nSprmId = eEDN; + else if( p == pBkm ) + pRes->nSprmId = eBKN; + else if( p == pAnd ) + pRes->nSprmId = eAND; + else if( p == pPcd ) + { + //We slave the piece table attributes to the piece table, the piece + //table attribute iterator contains the sprms for this piece. + GetSprmStart( nIdx+1, pRes ); + } + else + pRes->nSprmId = 0; // default: not found +} + +void WW8PLCFMan::GetNoSprmEnd( short nIdx, WW8PLCFManResult* pRes ) const +{ + pRes->nMemLen = -1; // Ende-Kennzeichen + + if( &aD[nIdx] == pBkm ) + pRes->nSprmId = eBKN; + else if( &aD[nIdx] == pPcd ) + { + //We slave the piece table attributes to the piece table, the piece + //table attribute iterator contains the sprms for this piece. + GetSprmEnd( nIdx+1, pRes ); + } + else + pRes->nSprmId = 0; +} + +bool WW8PLCFMan::TransferOpenSprms(std::stack<USHORT> &rStack) +{ + for (int i = 0; i < nPLCF; ++i) + { + WW8PLCFxDesc* p = &aD[i]; + if (!p || !p->pIdStk) + continue; + while (!p->pIdStk->empty()) + { + rStack.push(p->pIdStk->top()); + p->pIdStk->pop(); + } + } + return rStack.empty(); +} + +void WW8PLCFMan::AdvSprm(short nIdx, bool bStart) +{ + WW8PLCFxDesc* p = &aD[nIdx]; // Sprm-Klasse(!) ermitteln + + p->bFirstSprm = false; + if( bStart ) + { + USHORT nLastId = GetId(p); + p->pIdStk->push(nLastId); // merke Id fuer Attribut-Ende + + if( p->nSprmsLen ) + { /* + Pruefe, ob noch Sprm(s) abzuarbeiten sind + */ + if( p->pMemPos ) + { + // Length of last sprm + USHORT nSprmL = maSprmParser.GetSprmSize(nLastId, p->pMemPos); + + // Gesamtlaenge Sprms um SprmLaenge verringern + p->nSprmsLen -= nSprmL; + + // Pos des evtl. naechsten Sprm + if (p->nSprmsLen < maSprmParser.MinSprmLen()) + { + // sicherheitshalber auf Null setzen, da Enden folgen! + p->pMemPos = 0; + p->nSprmsLen = 0; + } + else + p->pMemPos += nSprmL; + } + else + p->nSprmsLen = 0; + } + if (p->nSprmsLen < maSprmParser.MinSprmLen()) + p->nStartPos = LONG_MAX; // es folgen Enden + } + else + { + if (!(p->pIdStk->empty())) + p->pIdStk->pop(); + if (p->pIdStk->empty()) + { + if ( (p == pChp) || (p == pPap) ) + { + p->pMemPos = 0; + p->nSprmsLen = 0; + p->nStartPos = p->nOrigEndPos+p->nCpOfs; + + /* + #93702# + On failed seek we have run out of sprms, probably. But if its + a fastsaved file (has pPcd) then we may be just in a sprm free + gap between pieces that have them, so set dirty flag in sprm + finder to consider than. + */ + if (!(*p->pPLCFx).SeekPos(p->nStartPos)) + { + p->nEndPos = LONG_MAX; + p->pPLCFx->SetDirty(true); + } + if (!p->pPLCFx->GetDirty() || pPcd) + GetNewSprms( *p ); + p->pPLCFx->SetDirty(false); + + /* + #i2325# + To get the character and paragraph properties you first get + the pap and chp and then apply the fastsaved pPcd properties + to the range. If a pap or chp starts inside the pPcd range + then we must bring the current pPcd range to a halt so as to + end those sprms, then the pap/chp will be processed, and then + we must force a restart of the pPcd on that pap/chp starting + boundary. Doing that effectively means that the pPcd sprms will + be applied to the new range. Not doing it means that the pPcd + sprms will only be applied to the first pap/chp set of + properties contained in the pap/chp range. + + So we bring the pPcd to a halt on this location here, by + settings its end to the current start, then store the starting + position of the current range to clipstart. The pPcd sprms + will end as normal (albeit earlier than originally expected), + and the existance of a clipstart will force the pPcd iterater + to reread the current set of sprms instead of advancing to its + next set. Then the clipstart will be set as the starting + position which will force them to be applied directly after + the pap and chps. + */ + if (pPcd && ((p->nStartPos > pPcd->nStartPos) || + (pPcd->nStartPos == LONG_MAX)) && + (pPcd->nEndPos != p->nStartPos)) + { + pPcd->nEndPos = p->nStartPos; + ((WW8PLCFx_PCD *)(pPcd->pPLCFx))->SetClipStart( + p->nStartPos); + } + + } + else + { + (*p->pPLCFx)++; // next Group of Sprms + p->pMemPos = 0; // !!! + p->nSprmsLen = 0; + GetNewSprms( *p ); + } + ASSERT( p->nStartPos <= p->nEndPos, "Attribut ueber Kreuz" ); + } + } +} + +void WW8PLCFMan::AdvNoSprm(short nIdx, bool bStart) +{ + /* + For the case of a piece table we slave the piece table attribute iterator + to the piece table and access it through that only. They are two seperate + structures, but act together as one logical one. The attributes only go + to the next entry when the piece changes + */ + WW8PLCFxDesc* p = &aD[nIdx]; + + if( p == pPcd ) + { + AdvSprm(nIdx+1,bStart); + if( bStart ) + p->nStartPos = aD[nIdx+1].nStartPos; + else + { + if (aD[nIdx+1].pIdStk->empty()) + { + WW8PLCFx_PCD *pTemp = (WW8PLCFx_PCD*)(pPcd->pPLCFx); + /* + #i2325# + As per normal, go on to the next set of properties, i.e. we + have traversed over to the next piece. With a clipstart set + we are being told to reread the current piece sprms so as to + reapply them to a new chp or pap range. + */ + if (pTemp->GetClipStart() == -1) + (*p->pPLCFx)++; + p->pMemPos = 0; + p->nSprmsLen = 0; + GetNewSprms( aD[nIdx+1] ); + GetNewNoSprms( *p ); + if (pTemp->GetClipStart() != -1) + { + /* + #i2325#, now we will force our starting position to the + clipping start so as to force the application of these + sprms after the current pap/chp sprms so as to apply the + fastsave sprms to the current range. + */ + p->nStartPos = pTemp->GetClipStart(); + pTemp->SetClipStart(-1); + } + } + } + } + else + { // NoSprm ohne Ende + (*p->pPLCFx)++; + p->pMemPos = 0; // MemPos ungueltig + p->nSprmsLen = 0; + GetNewNoSprms( *p ); + } +} + +WW8PLCFMan& WW8PLCFMan::operator ++(int) +{ + bool bStart; + USHORT nIdx = WhereIdx(&bStart); + if (nIdx < nPLCF) + { + WW8PLCFxDesc* p = &aD[nIdx]; + + p->bFirstSprm = true; // Default + + if( p->pPLCFx->IsSprm() ) + AdvSprm( nIdx, bStart ); + else // NoSprm + AdvNoSprm( nIdx, bStart ); + } + return *this; +} + +// Rueckgabe true fuer Anfang eines Attributes oder Fehler, +// false fuer Ende d. Attr +// Restliche Rueckgabewerte werden in der vom Aufrufer zu stellenden Struktur +// WW8PclxManResults geliefert. +bool WW8PLCFMan::Get(WW8PLCFManResult* pRes) const +{ + memset( pRes, 0, sizeof( WW8PLCFManResult ) ); + bool bStart; + USHORT nIdx = WhereIdx(&bStart); + + if( nIdx >= nPLCF ) + { + ASSERT( !this, "Position not found" ); + return true; + } + + if( aD[nIdx].pPLCFx->IsSprm() ) + { + if( bStart ) + { + GetSprmStart( nIdx, pRes ); + return true; + } + else + { + GetSprmEnd( nIdx, pRes ); + return false; + } + } + else + { + if( bStart ) + { + GetNoSprmStart( nIdx, pRes ); + return true; + } + else + { + GetNoSprmEnd( nIdx, pRes ); + return false; + } + } +} + +USHORT WW8PLCFMan::GetColl() const +{ + if( pPap->pPLCFx ) + return pPap->pPLCFx->GetIstd(); + else + { + ASSERT( !this, "GetColl ohne PLCF_Pap" ); + return 0; + } +} + +WW8PLCFx_FLD* WW8PLCFMan::GetFld() const +{ + return (WW8PLCFx_FLD*)pFld->pPLCFx; +} + +const BYTE* WW8PLCFMan::HasParaSprm( USHORT nId ) const +{ + return ((WW8PLCFx_Cp_FKP*)pPap->pPLCFx)->HasSprm( nId ); +} + +const BYTE* WW8PLCFMan::HasCharSprm( USHORT nId ) const +{ + return ((WW8PLCFx_Cp_FKP*)pChp->pPLCFx)->HasSprm( nId ); +} + +bool WW8PLCFMan::HasCharSprm(USHORT nId, + std::vector<const BYTE *> &rResult) const +{ + return ((WW8PLCFx_Cp_FKP*)pChp->pPLCFx)->HasSprm(nId, rResult); +} + +#endif // !DUMP + +void WW8PLCFx::Save( WW8PLCFxSave1& rSave ) const +{ + rSave.nPLCFxPos = GetIdx(); + rSave.nPLCFxPos2 = GetIdx2(); + rSave.nPLCFxMemOfs = 0; + rSave.nStartFC = GetStartFc(); +} + +void WW8PLCFx::Restore( const WW8PLCFxSave1& rSave ) +{ + SetIdx( rSave.nPLCFxPos ); + SetIdx2( rSave.nPLCFxPos2 ); + SetStartFc( rSave.nStartFC ); +} + +ULONG WW8PLCFx_Cp_FKP::GetIdx2() const +{ + return GetPCDIdx(); +} + +void WW8PLCFx_Cp_FKP::SetIdx2( ULONG nIdx ) +{ + SetPCDIdx( nIdx ); +} + +void WW8PLCFx_Cp_FKP::Save( WW8PLCFxSave1& rSave ) const +{ + WW8PLCFx::Save( rSave ); + + rSave.nAttrStart = nAttrStart; + rSave.nAttrEnd = nAttrEnd; + rSave.bLineEnd = bLineEnd; +} + +void WW8PLCFx_Cp_FKP::Restore( const WW8PLCFxSave1& rSave ) +{ + WW8PLCFx::Restore( rSave ); + + nAttrStart = rSave.nAttrStart; + nAttrEnd = rSave.nAttrEnd; + bLineEnd = rSave.bLineEnd; +} + +void WW8PLCFxDesc::Save( WW8PLCFxSave1& rSave ) const +{ + if( pPLCFx ) + { + pPLCFx->Save( rSave ); + if( pPLCFx->IsSprm() ) + { + WW8PLCFxDesc aD; + aD.nStartPos = nOrigStartPos+nCpOfs; + aD.nCpOfs = rSave.nCpOfs = nCpOfs; + if (!(pPLCFx->SeekPos(aD.nStartPos))) + { + aD.nEndPos = LONG_MAX; + pPLCFx->SetDirty(true); + } + pPLCFx->GetSprms(&aD); + pPLCFx->SetDirty(false); + aD.ReduceByOffset(); + rSave.nStartCp = aD.nStartPos; + rSave.nPLCFxMemOfs = nOrigSprmsLen - nSprmsLen; + } + } +} + +void WW8PLCFxDesc::Restore( const WW8PLCFxSave1& rSave ) +{ + if( pPLCFx ) + { + pPLCFx->Restore( rSave ); + if( pPLCFx->IsSprm() ) + { + WW8PLCFxDesc aD; + aD.nStartPos = rSave.nStartCp+rSave.nCpOfs; + nCpOfs = aD.nCpOfs = rSave.nCpOfs; + if (!(pPLCFx->SeekPos(aD.nStartPos))) + { + aD.nEndPos = LONG_MAX; + pPLCFx->SetDirty(true); + } + pPLCFx->GetSprms(&aD); + pPLCFx->SetDirty(false); + aD.ReduceByOffset(); + pMemPos = aD.pMemPos + rSave.nPLCFxMemOfs; + } + } +} + +//----------------------------------------- + + +WW8Fib::WW8Fib( SvStream& rSt, BYTE nWantedVersion,UINT32 nOffset ) + : nFibError( 0 ) +{ + BYTE aBits1; + BYTE aBits2; + BYTE aVer8Bits1; // nur ab WinWord 8 benutzt + rSt.Seek( nOffset ); + /* + Wunsch-Nr vermerken, File-Versionsnummer ermitteln + und gegen Wunsch-Nr. checken ! + */ + nVersion = nWantedVersion; + rSt >> wIdent; + rSt >> nFib; + rSt >> nProduct; + if( 0 != rSt.GetError() ) + { + INT16 nFibMin; + INT16 nFibMax; + // note: 6 stands for "6 OR 7", 7 stands for "ONLY 7" + switch( nVersion ) + { + case 6: + nFibMin = 0x0065; // von 101 WinWord 6.0 + // 102 " + // und 103 WinWord 6.0 fuer Macintosh + // 104 " + nFibMax = 0x0069; // bis 105 WinWord 95 + break; + case 7: + nFibMin = 0x0069; // von 105 WinWord 95 + nFibMax = 0x0069; // bis 105 WinWord 95 + break; + case 8: + nFibMin = 0x006A; // von 106 WinWord 97 + nFibMax = 0x00c1; // bis 193 WinWord 97 (?) + break; + default: + nFibMin = 0; // Programm-Fehler! + nFibMax = 0; + nFib = 1; + ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" ); + break; + } + if ( (nFib < nFibMin) || (nFib > nFibMax) ) + { + nFibError = ERR_SWG_READ_ERROR; // Error melden + return; // und hopp raus! + } + } + + // praktische Hilfsvariablen: + bool bVer67 = ((6 == nVersion) || (7 == nVersion)); + bool bVer8 = (8 == nVersion); + + // Hilfs-Varis fuer Ver67: + INT16 pnChpFirst_Ver67=0; + INT16 pnPapFirst_Ver67=0; + INT16 cpnBteChp_Ver67=0; + INT16 cpnBtePap_Ver67=0; + + // und auf gehts: FIB einlesen + rSt >> lid; + rSt >> pnNext; + rSt >> aBits1; + rSt >> aBits2; + rSt >> nFibBack; + rSt >> lKey1; + rSt >> lKey2; + rSt >> envr; + rSt >> aVer8Bits1; // unter Ver67 nur leeres Reservefeld + // Inhalt von aVer8Bits1 + // + // BYTE fMac :1; + // BYTE fEmptySpecial :1; + // BYTE fLoadOverridePage :1; + // BYTE fFuturesavedUndo :1; + // BYTE fWord97Saved :1; + // BYTE :3; + rSt >> chse; + rSt >> chseTables; + rSt >> fcMin; + rSt >> fcMac; + +// Einschub fuer WW8 ***************************************************** + if( !bVer67 ) + { + rSt >> csw; + + // Marke: "rgsw" Beginning of the array of shorts + rSt >> wMagicCreated; + rSt >> wMagicRevised; + rSt >> wMagicCreatedPrivate; + rSt >> wMagicRevisedPrivate; + rSt.SeekRel( 9 * sizeof( INT16 ) ); + + /* + // dies sind die 9 unused Felder: + && (bVer67 || WW8ReadINT16( rSt, pnFbpChpFirst_W6 )) // 1 + && (bVer67 || WW8ReadINT16( rSt, pnChpFirst_W6 )) // 2 + && (bVer67 || WW8ReadINT16( rSt, cpnBteChp_W6 )) // 3 + && (bVer67 || WW8ReadINT16( rSt, pnFbpPapFirst_W6 )) // 4 + && (bVer67 || WW8ReadINT16( rSt, pnPapFirst_W6 )) // 5 + && (bVer67 || WW8ReadINT16( rSt, cpnBtePap_W6 )) // 6 + && (bVer67 || WW8ReadINT16( rSt, pnFbpLvcFirst_W6 )) // 7 + && (bVer67 || WW8ReadINT16( rSt, pnLvcFirst_W6 )) // 8 + && (bVer67 || WW8ReadINT16( rSt, cpnBteLvc_W6 )) // 9 + */ + rSt >> lidFE; + rSt >> clw; + } + +// Ende des Einschubs fuer WW8 ******************************************* + + // Marke: "rglw" Beginning of the array of longs + rSt >> cbMac; + + // 2 Longs uebergehen, da unwichtiger Quatsch + rSt.SeekRel( 2 * sizeof( INT32) ); + + // weitere 2 Longs nur bei Ver67 ueberspringen + if( bVer67 ) + rSt.SeekRel( 2 * sizeof( INT32) ); + + rSt >> ccpText; + rSt >> ccpFtn; + rSt >> ccpHdr; + rSt >> ccpMcr; + rSt >> ccpAtn; + rSt >> ccpEdn; + rSt >> ccpTxbx; + rSt >> ccpHdrTxbx; + + // weiteres Long nur bei Ver67 ueberspringen + if( bVer67 ) + rSt.SeekRel( 1 * sizeof( INT32) ); + else + { +// Einschub fuer WW8 ***************************************************** + rSt >> pnFbpChpFirst; + rSt >> pnChpFirst; + rSt >> cpnBteChp; + rSt >> pnFbpPapFirst; + rSt >> pnPapFirst; + rSt >> cpnBtePap; + rSt >> pnFbpLvcFirst; + rSt >> pnLvcFirst; + rSt >> cpnBteLvc; + rSt >> fcIslandFirst; + rSt >> fcIslandLim; + rSt >> cfclcb; + } + +// Ende des Einschubs fuer WW8 ******************************************* + + // Marke: "rgfclcb" Beginning of array of FC/LCB pairs. + rSt >> fcStshfOrig; + rSt >> lcbStshfOrig; + rSt >> fcStshf; + rSt >> lcbStshf; + rSt >> fcPlcffndRef; + rSt >> lcbPlcffndRef; + rSt >> fcPlcffndTxt; + rSt >> lcbPlcffndTxt; + rSt >> fcPlcfandRef; + rSt >> lcbPlcfandRef; + rSt >> fcPlcfandTxt; + rSt >> lcbPlcfandTxt; + rSt >> fcPlcfsed; + rSt >> lcbPlcfsed; + rSt >> fcPlcfpad; + rSt >> lcbPlcfpad; + rSt >> fcPlcfphe; + rSt >> lcbPlcfphe; + rSt >> fcSttbfglsy; + rSt >> lcbSttbfglsy; + rSt >> fcPlcfglsy; + rSt >> lcbPlcfglsy; + rSt >> fcPlcfhdd; + rSt >> lcbPlcfhdd; + rSt >> fcPlcfbteChpx; + rSt >> lcbPlcfbteChpx; + rSt >> fcPlcfbtePapx; + rSt >> lcbPlcfbtePapx; + rSt >> fcPlcfsea; + rSt >> lcbPlcfsea; + rSt >> fcSttbfffn; + rSt >> lcbSttbfffn; + rSt >> fcPlcffldMom; + rSt >> lcbPlcffldMom; + rSt >> fcPlcffldHdr; + rSt >> lcbPlcffldHdr; + rSt >> fcPlcffldFtn; + rSt >> lcbPlcffldFtn; + rSt >> fcPlcffldAtn; + rSt >> lcbPlcffldAtn; + rSt >> fcPlcffldMcr; + rSt >> lcbPlcffldMcr; + rSt >> fcSttbfbkmk; + rSt >> lcbSttbfbkmk; + rSt >> fcPlcfbkf; + rSt >> lcbPlcfbkf; + rSt >> fcPlcfbkl; + rSt >> lcbPlcfbkl; + rSt >> fcCmds; + rSt >> lcbCmds; + rSt >> fcPlcfmcr; + rSt >> lcbPlcfmcr; + rSt >> fcSttbfmcr; + rSt >> lcbSttbfmcr; + rSt >> fcPrDrvr; + rSt >> lcbPrDrvr; + rSt >> fcPrEnvPort; + rSt >> lcbPrEnvPort; + rSt >> fcPrEnvLand; + rSt >> lcbPrEnvLand; + rSt >> fcWss; + rSt >> lcbWss; + rSt >> fcDop; + rSt >> lcbDop; + rSt >> fcSttbfAssoc; + rSt >> cbSttbfAssoc; + rSt >> fcClx; + rSt >> lcbClx; + rSt >> fcPlcfpgdFtn; + rSt >> lcbPlcfpgdFtn; + rSt >> fcAutosaveSource; + rSt >> lcbAutosaveSource; + rSt >> fcGrpStAtnOwners; + rSt >> lcbGrpStAtnOwners; + rSt >> fcSttbfAtnbkmk; + rSt >> lcbSttbfAtnbkmk; + + // weiteres short nur bei Ver67 ueberspringen + if (bVer67) + { + rSt.SeekRel( 1*sizeof( INT16) ); + + // folgende 4 Shorts existieren nur bei Ver67; + rSt >> pnChpFirst_Ver67; + rSt >> pnPapFirst_Ver67; + rSt >> cpnBteChp_Ver67; + rSt >> cpnBtePap_Ver67; + } + + rSt >> fcPlcfdoaMom; + rSt >> lcbPlcfdoaMom; + rSt >> fcPlcfdoaHdr; + rSt >> lcbPlcfdoaHdr; + rSt >> fcPlcfspaMom; + rSt >> lcbPlcfspaMom; + rSt >> fcPlcfspaHdr; + rSt >> lcbPlcfspaHdr; + + rSt >> fcPlcfAtnbkf; + rSt >> lcbPlcfAtnbkf; + rSt >> fcPlcfAtnbkl; + rSt >> lcbPlcfAtnbkl; + rSt >> fcPms; + rSt >> lcbPMS; + rSt >> fcFormFldSttbf; + rSt >> lcbFormFldSttbf; + rSt >> fcPlcfendRef; + rSt >> lcbPlcfendRef; + rSt >> fcPlcfendTxt; + rSt >> lcbPlcfendTxt; + rSt >> fcPlcffldEdn; + rSt >> lcbPlcffldEdn; + rSt >> fcPlcfpgdEdn; + rSt >> lcbPlcfpgdEdn; + rSt >> fcDggInfo; + rSt >> lcbDggInfo; + rSt >> fcSttbfRMark; + rSt >> lcbSttbfRMark; + rSt >> fcSttbfCaption; + rSt >> lcbSttbfCaption; + rSt >> fcSttbAutoCaption; + rSt >> lcbSttbAutoCaption; + rSt >> fcPlcfwkb; + rSt >> lcbPlcfwkb; + rSt >> fcPlcfspl; + rSt >> lcbPlcfspl; + rSt >> fcPlcftxbxTxt; + rSt >> lcbPlcftxbxTxt; + rSt >> fcPlcffldTxbx; + rSt >> lcbPlcffldTxbx; + rSt >> fcPlcfHdrtxbxTxt; + rSt >> lcbPlcfHdrtxbxTxt; + rSt >> fcPlcffldHdrTxbx; + rSt >> lcbPlcffldHdrTxbx; + + if( 0 == rSt.GetError() ) + { + // Bit-Flags setzen + fDot = aBits1 & 0x01 ; + fGlsy = ( aBits1 & 0x02 ) >> 1; + fComplex = ( aBits1 & 0x04 ) >> 2; + fHasPic = ( aBits1 & 0x08 ) >> 3; + cQuickSaves = ( aBits1 & 0xf0 ) >> 4; + fEncrypted = aBits2 & 0x01 ; + fWhichTblStm= ( aBits2 & 0x02 ) >> 1; + // dummy = ( aBits2 & 0x0e ) >> 1; + fExtChar = ( aBits2 & 0x10 ) >> 4; + // dummy = ( aBits2 & 0xe0 ) >> 5; + + /* + ggfs. Ziel-Varaiblen, aus xxx_Ver67 fuellen + oder Flags setzen + */ + if (bVer67) + { + pnChpFirst = pnChpFirst_Ver67; + pnPapFirst = pnPapFirst_Ver67; + cpnBteChp = cpnBteChp_Ver67; + cpnBtePap = cpnBtePap_Ver67; + } + else if( bVer8 ) + { + fMac = aVer8Bits1 & 0x01 ; + fEmptySpecial = ( aVer8Bits1 & 0x02 ) >> 1; + fLoadOverridePage = ( aVer8Bits1 & 0x04 ) >> 2; + fFuturesavedUndo = ( aVer8Bits1 & 0x08 ) >> 3; + fWord97Saved = ( aVer8Bits1 & 0x10 ) >> 4; + fWord2000Saved = ( aVer8Bits1 & 0x20 ) >> 5; + + /* + speziell fuer WW8: + ermittle die Werte fuer PLCF LST und PLF LFO + und PLCF fuer TextBox-Break-Deskriptoren + */ + long nOldPos = rSt.Tell(); + rSt.Seek( 0x02e2 ); + rSt >> fcPlcfLst; + rSt >> lcbPlcfLst; + rSt >> fcPlfLfo; + rSt >> lcbPlfLfo; + rSt >> fcPlcftxbxBkd; + rSt >> lcbPlcftxbxBkd; + rSt >> fcPlcfHdrtxbxBkd; + rSt >> lcbPlcfHdrtxbxBkd; + if( 0 != rSt.GetError() ) + { + nFibError = ERR_SWG_READ_ERROR; + } + + rSt.Seek( 0x372 ); // fcSttbListNames + rSt >> fcSttbListNames; + rSt >> lcbSttbListNames; + rSt.Seek( 0x382 ); // MagicTables + rSt >> fcMagicTable; + rSt >> lcbMagicTable; + if( 0 != rSt.GetError() ) + nFibError = ERR_SWG_READ_ERROR; + + rSt.Seek( nOldPos ); + } + } + else + { + nFibError = ERR_SWG_READ_ERROR; // Error melden + } +} + + +WW8Fib::WW8Fib(BYTE nVer) +{ + memset(this, 0, sizeof(*this)); + nVersion = nVer; + if (8 == nVer) + { + fcMin = 0x400; + wIdent = 0xa5ec; + nFib = 0xc2; + nFibBack = 0xbf; + nProduct = 0x204D; + + csw = 0x0e; // muss das sein ??? + cfclcb = 0x6c; // -""- + clw = 0x16; // -""- + pnFbpChpFirst = pnFbpPapFirst = pnFbpLvcFirst = 0x000fffff; + fExtChar = true; + fWord97Saved = fWord2000Saved = true; + + // diese Flags muessen nicht gesetzt werden; koennen aber. + // wMagicCreated = wMagicRevised = 0x6a62; + // wMagicCreatedPrivate = wMagicRevisedPrivate = 0xb3b2; + // + + wMagicCreated = 0x6143; + wMagicRevised = 0x6C6F; + wMagicCreatedPrivate = 0x6E61; + wMagicRevisedPrivate = 0x3136; + } + else + { + fcMin = 0x300; + wIdent = 0xa5dc; + nFib = nFibBack = 0x65; + nProduct = 0xc02d; + } + + lid = lidFE = 0x407; +} + +bool WW8Fib::Write(SvStream& rStrm) +{ + BYTE *pDataPtr = new BYTE[ fcMin ]; + BYTE *pData = pDataPtr; + memset( pData, 0, fcMin ); + + bool bVer8 = 8 == nVersion; + + ULONG nPos = rStrm.Tell(); + cbMac = rStrm.Seek( STREAM_SEEK_TO_END ); + rStrm.Seek( nPos ); + + Set_UInt16( pData, wIdent ); + Set_UInt16( pData, nFib ); + Set_UInt16( pData, nProduct ); + Set_UInt16( pData, lid ); + Set_UInt16( pData, pnNext ); + + UINT16 nBits16 = 0; + if( fDot ) nBits16 |= 0x0001; + if( fGlsy) nBits16 |= 0x0002; + if( fComplex ) nBits16 |= 0x0004; + if( fHasPic ) nBits16 |= 0x0008; + nBits16 |= (0xf0 & ( cQuickSaves << 4 )); + if( fEncrypted ) nBits16 |= 0x0100; + if( fWhichTblStm ) nBits16 |= 0x0200; + if( fExtChar ) nBits16 |= 0x1000; + Set_UInt16( pData, nBits16 ); + + Set_UInt16( pData, nFibBack ); + Set_UInt16( pData, lKey1 ); + Set_UInt16( pData, lKey2 ); + Set_UInt8( pData, envr ); + + BYTE nBits8 = 0; + if( bVer8 ) + { + if( fMac ) nBits8 |= 0x0001; + if( fEmptySpecial ) nBits8 |= 0x0002; + if( fLoadOverridePage ) nBits8 |= 0x0004; + if( fFuturesavedUndo ) nBits8 |= 0x0008; + if( fWord97Saved ) nBits8 |= 0x0010; + if( fWord2000Saved ) nBits8 |= 0x0020; + } + // unter Ver67 these are only reserved + Set_UInt8( pData, nBits8 ); + + Set_UInt16( pData, chse ); + Set_UInt16( pData, chseTables ); + Set_UInt32( pData, fcMin ); + Set_UInt32( pData, fcMac ); + +// Einschub fuer WW8 ***************************************************** + + // Marke: "rgsw" Beginning of the array of shorts + if( bVer8 ) + { + Set_UInt16( pData, csw ); + Set_UInt16( pData, wMagicCreated ); + Set_UInt16( pData, wMagicRevised ); + Set_UInt16( pData, wMagicCreatedPrivate ); + Set_UInt16( pData, wMagicRevisedPrivate ); + pData += 9 * sizeof( INT16 ); + Set_UInt16( pData, lidFE ); + Set_UInt16( pData, clw ); + } + +// Ende des Einschubs fuer WW8 ******************************************* + + // Marke: "rglw" Beginning of the array of longs + Set_UInt32( pData, cbMac ); + + // 2 Longs uebergehen, da unwichtiger Quatsch + pData += 2 * sizeof( INT32); + + // weitere 2 Longs nur bei Ver67 ueberspringen + if( !bVer8 ) + pData += 2 * sizeof( INT32); + + Set_UInt32( pData, ccpText ); + Set_UInt32( pData, ccpFtn ); + Set_UInt32( pData, ccpHdr ); + Set_UInt32( pData, ccpMcr ); + Set_UInt32( pData, ccpAtn ); + Set_UInt32( pData, ccpEdn ); + Set_UInt32( pData, ccpTxbx ); + Set_UInt32( pData, ccpHdrTxbx ); + + // weiteres Long nur bei Ver67 ueberspringen + if( !bVer8 ) + pData += 1 * sizeof( INT32); + +// Einschub fuer WW8 ***************************************************** + if( bVer8 ) + { + Set_UInt32( pData, pnFbpChpFirst ); + Set_UInt32( pData, pnChpFirst ); + Set_UInt32( pData, cpnBteChp ); + Set_UInt32( pData, pnFbpPapFirst ); + Set_UInt32( pData, pnPapFirst ); + Set_UInt32( pData, cpnBtePap ); + Set_UInt32( pData, pnFbpLvcFirst ); + Set_UInt32( pData, pnLvcFirst ); + Set_UInt32( pData, cpnBteLvc ); + Set_UInt32( pData, fcIslandFirst ); + Set_UInt32( pData, fcIslandLim ); + Set_UInt16( pData, cfclcb ); + } +// Ende des Einschubs fuer WW8 ******************************************* + + // Marke: "rgfclcb" Beginning of array of FC/LCB pairs. + Set_UInt32( pData, fcStshfOrig ); + Set_UInt32( pData, lcbStshfOrig ); + Set_UInt32( pData, fcStshf ); + Set_UInt32( pData, lcbStshf ); + Set_UInt32( pData, fcPlcffndRef ); + Set_UInt32( pData, lcbPlcffndRef ); + Set_UInt32( pData, fcPlcffndTxt ); + Set_UInt32( pData, lcbPlcffndTxt ); + Set_UInt32( pData, fcPlcfandRef ); + Set_UInt32( pData, lcbPlcfandRef ); + Set_UInt32( pData, fcPlcfandTxt ); + Set_UInt32( pData, lcbPlcfandTxt ); + Set_UInt32( pData, fcPlcfsed ); + Set_UInt32( pData, lcbPlcfsed ); + Set_UInt32( pData, fcPlcfpad ); + Set_UInt32( pData, lcbPlcfpad ); + Set_UInt32( pData, fcPlcfphe ); + Set_UInt32( pData, lcbPlcfphe ); + Set_UInt32( pData, fcSttbfglsy ); + Set_UInt32( pData, lcbSttbfglsy ); + Set_UInt32( pData, fcPlcfglsy ); + Set_UInt32( pData, lcbPlcfglsy ); + Set_UInt32( pData, fcPlcfhdd ); + Set_UInt32( pData, lcbPlcfhdd ); + Set_UInt32( pData, fcPlcfbteChpx ); + Set_UInt32( pData, lcbPlcfbteChpx ); + Set_UInt32( pData, fcPlcfbtePapx ); + Set_UInt32( pData, lcbPlcfbtePapx ); + Set_UInt32( pData, fcPlcfsea ); + Set_UInt32( pData, lcbPlcfsea ); + Set_UInt32( pData, fcSttbfffn ); + Set_UInt32( pData, lcbSttbfffn ); + Set_UInt32( pData, fcPlcffldMom ); + Set_UInt32( pData, lcbPlcffldMom ); + Set_UInt32( pData, fcPlcffldHdr ); + Set_UInt32( pData, lcbPlcffldHdr ); + Set_UInt32( pData, fcPlcffldFtn ); + Set_UInt32( pData, lcbPlcffldFtn ); + Set_UInt32( pData, fcPlcffldAtn ); + Set_UInt32( pData, lcbPlcffldAtn ); + Set_UInt32( pData, fcPlcffldMcr ); + Set_UInt32( pData, lcbPlcffldMcr ); + Set_UInt32( pData, fcSttbfbkmk ); + Set_UInt32( pData, lcbSttbfbkmk ); + Set_UInt32( pData, fcPlcfbkf ); + Set_UInt32( pData, lcbPlcfbkf ); + Set_UInt32( pData, fcPlcfbkl ); + Set_UInt32( pData, lcbPlcfbkl ); + Set_UInt32( pData, fcCmds ); + Set_UInt32( pData, lcbCmds ); + Set_UInt32( pData, fcPlcfmcr ); + Set_UInt32( pData, lcbPlcfmcr ); + Set_UInt32( pData, fcSttbfmcr ); + Set_UInt32( pData, lcbSttbfmcr ); + Set_UInt32( pData, fcPrDrvr ); + Set_UInt32( pData, lcbPrDrvr ); + Set_UInt32( pData, fcPrEnvPort ); + Set_UInt32( pData, lcbPrEnvPort ); + Set_UInt32( pData, fcPrEnvLand ); + Set_UInt32( pData, lcbPrEnvLand ); + Set_UInt32( pData, fcWss ); + Set_UInt32( pData, lcbWss ); + Set_UInt32( pData, fcDop ); + Set_UInt32( pData, lcbDop ); + Set_UInt32( pData, fcSttbfAssoc ); + Set_UInt32( pData, cbSttbfAssoc ); + Set_UInt32( pData, fcClx ); + Set_UInt32( pData, lcbClx ); + Set_UInt32( pData, fcPlcfpgdFtn ); + Set_UInt32( pData, lcbPlcfpgdFtn ); + Set_UInt32( pData, fcAutosaveSource ); + Set_UInt32( pData, lcbAutosaveSource ); + Set_UInt32( pData, fcGrpStAtnOwners ); + Set_UInt32( pData, lcbGrpStAtnOwners ); + Set_UInt32( pData, fcSttbfAtnbkmk ); + Set_UInt32( pData, lcbSttbfAtnbkmk ); + + // weiteres short nur bei Ver67 ueberspringen + if( !bVer8 ) + { + pData += 1*sizeof( INT16); + Set_UInt16( pData, (UINT16)pnChpFirst ); + Set_UInt16( pData, (UINT16)pnPapFirst ); + Set_UInt16( pData, (UINT16)cpnBteChp ); + Set_UInt16( pData, (UINT16)cpnBtePap ); + } + + Set_UInt32( pData, fcPlcfdoaMom ); // nur bei Ver67, in Ver8 unused + Set_UInt32( pData, lcbPlcfdoaMom ); // nur bei Ver67, in Ver8 unused + Set_UInt32( pData, fcPlcfdoaHdr ); // nur bei Ver67, in Ver8 unused + Set_UInt32( pData, lcbPlcfdoaHdr ); // nur bei Ver67, in Ver8 unused + + Set_UInt32( pData, fcPlcfspaMom ); // in Ver67 leere Reserve + Set_UInt32( pData, lcbPlcfspaMom ); // in Ver67 leere Reserve + Set_UInt32( pData, fcPlcfspaHdr ); // in Ver67 leere Reserve + Set_UInt32( pData, lcbPlcfspaHdr ); // in Ver67 leere Reserve + + Set_UInt32( pData, fcPlcfAtnbkf ); + Set_UInt32( pData, lcbPlcfAtnbkf ); + Set_UInt32( pData, fcPlcfAtnbkl ); + Set_UInt32( pData, lcbPlcfAtnbkl ); + Set_UInt32( pData, fcPms ); + Set_UInt32( pData, lcbPMS ); + Set_UInt32( pData, fcFormFldSttbf ); + Set_UInt32( pData, lcbFormFldSttbf ); + Set_UInt32( pData, fcPlcfendRef ); + Set_UInt32( pData, lcbPlcfendRef ); + Set_UInt32( pData, fcPlcfendTxt ); + Set_UInt32( pData, lcbPlcfendTxt ); + Set_UInt32( pData, fcPlcffldEdn ); + Set_UInt32( pData, lcbPlcffldEdn ); + Set_UInt32( pData, fcPlcfpgdEdn ); + Set_UInt32( pData, lcbPlcfpgdEdn ); + Set_UInt32( pData, fcDggInfo ); // in Ver67 leere Reserve + Set_UInt32( pData, lcbDggInfo ); // in Ver67 leere Reserve + Set_UInt32( pData, fcSttbfRMark ); + Set_UInt32( pData, lcbSttbfRMark ); + Set_UInt32( pData, fcSttbfCaption ); + Set_UInt32( pData, lcbSttbfCaption ); + Set_UInt32( pData, fcSttbAutoCaption ); + Set_UInt32( pData, lcbSttbAutoCaption ); + Set_UInt32( pData, fcPlcfwkb ); + Set_UInt32( pData, lcbPlcfwkb ); + Set_UInt32( pData, fcPlcfspl ); // in Ver67 leere Reserve + Set_UInt32( pData, lcbPlcfspl ); // in Ver67 leere Reserve + Set_UInt32( pData, fcPlcftxbxTxt ); + Set_UInt32( pData, lcbPlcftxbxTxt ); + Set_UInt32( pData, fcPlcffldTxbx ); + Set_UInt32( pData, lcbPlcffldTxbx ); + Set_UInt32( pData, fcPlcfHdrtxbxTxt ); + Set_UInt32( pData, lcbPlcfHdrtxbxTxt ); + Set_UInt32( pData, fcPlcffldHdrTxbx ); + Set_UInt32( pData, lcbPlcffldHdrTxbx ); + + if( bVer8 ) + { + pData += 0x2e2 - 0x27a; // Pos + Offset (fcPlcfLst - fcStwUser) + Set_UInt32( pData, fcPlcfLst ); + Set_UInt32( pData, lcbPlcfLst ); + Set_UInt32( pData, fcPlfLfo ); + Set_UInt32( pData, lcbPlfLfo ); + Set_UInt32( pData, fcPlcftxbxBkd ); + Set_UInt32( pData, lcbPlcftxbxBkd ); + Set_UInt32( pData, fcPlcfHdrtxbxBkd ); + Set_UInt32( pData, lcbPlcfHdrtxbxBkd ); + + pData += 0x372 - 0x302; // Pos + Offset (fcSttbListNames - fcDocUndo) + Set_UInt32( pData, fcSttbListNames ); + Set_UInt32( pData, lcbSttbListNames ); + + pData += 0x382 - 0x37A; + Set_UInt32( pData, fcMagicTable ); + Set_UInt32( pData, lcbMagicTable ); + + pData += 0x3FA - 0x38A; + Set_UInt16( pData, (UINT16)0x0002); + Set_UInt16( pData, (UINT16)0x00D9); + } + + rStrm.Write( pDataPtr, fcMin ); + delete[] pDataPtr; + return 0 == rStrm.GetError(); +} + +rtl_TextEncoding WW8Fib::GetFIBCharset(UINT16 chs) +{ + ASSERT(chs <= 0x100, "overflowed winword charset set"); + rtl_TextEncoding eCharSet = + (0x0100 == chs) + ? RTL_TEXTENCODING_APPLE_ROMAN + : rtl_getTextEncodingFromWindowsCharset( static_cast<BYTE>(chs) ); + return eCharSet; +} + +WW8Style::WW8Style(SvStream& rStream, WW8Fib& rFibPara) + : rFib(rFibPara), rSt(rStream), cstd(0), cbSTDBaseInFile(0), + stiMaxWhenSaved(0), istdMaxFixedWhenSaved(0), nVerBuiltInNamesWhenSaved(0), + ftcStandardChpStsh(0), ftcStandardChpCJKStsh(0), ftcStandardChpCTLStsh(0) +{ + nStyleStart = rFib.fcStshf; + nStyleLen = rFib.lcbStshf; + + rSt.Seek(nStyleStart); + + USHORT cbStshi = 0; // 2 bytes size of the following STSHI structure + + // alte Version ? + if (rFib.nFib < 67) + cbStshi = 4; // -> Laengenfeld fehlt + else // neue Version: + // lies die Laenge der in der Datei gespeicherten Struktur + rSt >> cbStshi; + + UINT16 nRead = cbStshi; + do + { + UINT16 a16Bit; + + if( 2 > nRead ) break; + rSt >> cstd; + + if( 4 > nRead ) break; + rSt >> cbSTDBaseInFile; + + if( 6 > nRead ) break; + rSt >> a16Bit; + fStdStylenamesWritten = a16Bit & 0x0001; + + if( 8 > nRead ) break; + rSt >> stiMaxWhenSaved; + + if( 10 > nRead ) break; + rSt >> istdMaxFixedWhenSaved; + + if( 12 > nRead ) break; + rSt >> nVerBuiltInNamesWhenSaved; + + if( 14 > nRead ) break; + rSt >> ftcStandardChpStsh; + + if( 16 > nRead ) break; + rSt >> ftcStandardChpCJKStsh; + + if ( 18 > nRead ) break; + rSt >> ftcStandardChpCTLStsh; + + // ggfs. den Rest ueberlesen + if( 18 < nRead ) + rSt.SeekRel( nRead-18 ); + } + while( !this ); // Trick: obiger Block wird genau einmal durchlaufen + // und kann vorzeitig per "break" verlassen werden. + + if( 0 != rSt.GetError() ) + { + // wie denn nun den Error melden? + } +} + +// Read1STDFixed() liest ein Style ein. Wenn der Style vollstaendig vorhanden +// ist, d.h. kein leerer Slot, dann wird Speicher alloziert und ein Pointer auf +// die ( evtl. mit Nullen aufgefuellten ) STD geliefert. Ist es ein leerer +// Slot, dann wird ein Nullpointer zurueckgeliefert. +WW8_STD* WW8Style::Read1STDFixed( short& rSkip, short* pcbStd ) +{ + WW8_STD* pStd = 0; + + UINT16 cbStd; + rSt >> cbStd; // lies Laenge + + UINT16 nRead = cbSTDBaseInFile; + if( cbStd >= cbSTDBaseInFile ) + { + // Fixed part vollst. vorhanden + + // read fixed part of STD + pStd = new WW8_STD; + memset( pStd, 0, sizeof( *pStd ) ); + + do + { + UINT16 a16Bit; + + if( 2 > nRead ) break; + rSt >> a16Bit; + pStd->sti = a16Bit & 0x0fff ; + pStd->fScratch = 0 != ( a16Bit & 0x1000 ); + pStd->fInvalHeight = 0 != ( a16Bit & 0x2000 ); + pStd->fHasUpe = 0 != ( a16Bit & 0x4000 ); + pStd->fMassCopy = 0 != ( a16Bit & 0x8000 ); + + if( 4 > nRead ) break; + rSt >> a16Bit; + pStd->sgc = a16Bit & 0x000f ; + pStd->istdBase = ( a16Bit & 0xfff0 ) >> 4; + + if( 6 > nRead ) break; + rSt >> a16Bit; + pStd->cupx = a16Bit & 0x000f ; + pStd->istdNext = ( a16Bit & 0xfff0 ) >> 4; + + if( 8 > nRead ) break; + rSt >> pStd->bchUpe; + + // ab Ver8 sollten diese beiden Felder dazukommen: + if(10 > nRead ) break; + rSt >> a16Bit; + pStd->fAutoRedef = a16Bit & 0x0001 ; + pStd->fHidden = ( a16Bit & 0x0002 ) >> 2; + + // man kann nie wissen: vorsichtshalber ueberlesen + // wir eventuelle Fuellsel, die noch zum BASE-Part gehoeren... + if( 10 < nRead ) + rSt.SeekRel( nRead-10 ); + } + while( !this ); // Trick: obiger Block wird genau einmal durchlaufen + // und kann vorzeitig per "break" verlassen werden. + + if( (0 != rSt.GetError()) || !nRead ) + DELETEZ( pStd ); // per NULL den Error melden + + rSkip = cbStd - cbSTDBaseInFile; + } + else + { // Fixed part zu kurz + if( cbStd ) + rSt.SeekRel( cbStd ); // ueberlies Reste + rSkip = 0; + } + if( pcbStd ) + *pcbStd = cbStd; + return pStd; +} + +WW8_STD* WW8Style::Read1Style( short& rSkip, String* pString, short* pcbStd ) +{ + // Attention: MacWord-Documents have their Stylenames + // always in ANSI, even if eStructCharSet == CHARSET_MAC !! + + WW8_STD* pStd = Read1STDFixed( rSkip, pcbStd ); // lese STD + + // String gewuenscht ? + if( pString ) + { // echter Style ? + if ( pStd ) + { + switch( rFib.nVersion ) + { + case 6: + case 7: + // lies Pascal-String + *pString = WW8ReadPString( rSt, RTL_TEXTENCODING_MS_1252 ); + // leading len and trailing zero --> 2 + rSkip -= 2+ pString->Len(); + break; + case 8: + // handle Unicode-String with leading length short and + // trailing zero + if (ww8String::TestBeltAndBraces(rSt)) + { + *pString = WW8Read_xstz(rSt, 0, true); + rSkip -= (pString->Len() + 2) * 2; + } + else + { + /* + #i8114# + This is supposed to be impossible, its just supposed + to be 16 bit count followed by the string and ending + in a 0 short. But "Lotus SmartSuite Product: Word Pro" + is creating invalid style names in ww7- format. So we + use the belt and braces of the ms strings to see if + they are not corrupt. If they are then we try them as + 8bit ones + */ + *pString = WW8ReadPString(rSt,RTL_TEXTENCODING_MS_1252); + // leading len and trailing zero --> 2 + rSkip -= 2+ pString->Len(); + } + break; + default: + ASSERT(!this, "Es wurde vergessen, nVersion zu kodieren!"); + break; + } + } + else + *pString = aEmptyStr; // Kann keinen Namen liefern + } + return pStd; +} + + +//----------------------------------------- + + +struct WW8_FFN_Ver6 : public WW8_FFN_BASE +{ + // ab Ver6 + sal_Char szFfn[65]; // 0x6 bzw. 0x40 ab Ver8 zero terminated string that + // records name of font. + // Maximal size of szFfn is 65 characters. + // Vorsicht: Dieses Array kann auch kleiner sein!!! + // Possibly followed by a second sz which records the + // name of an alternate font to use if the first named + // font does not exist on this system. +}; +struct WW8_FFN_Ver8 : public WW8_FFN_BASE +{ + // ab Ver8 sind folgende beiden Felder eingeschoben, + // werden von uns ignoriert. + sal_Char panose[ 10 ]; // 0x6 PANOSE + sal_Char fs[ 24 ]; // 0x10 FONTSIGNATURE + + // ab Ver8 als Unicode + UINT16 szFfn[65]; // 0x6 bzw. 0x40 ab Ver8 zero terminated string that + // records name of font. + // Maximal size of szFfn is 65 characters. + // Vorsicht: Dieses Array kann auch kleiner sein!!! + // Possibly followed by a second sz which records the + // name of an alternate font to use if the first named + // font does not exist on this system. +}; + +WW8Fonts::WW8Fonts( SvStream& rSt, WW8Fib& rFib ) +{ + // Attention: MacWord-Documents have their Fontnames + // always in ANSI, even if eStructCharSet == CHARSET_MAC !! + if( rFib.lcbSttbfffn <= 2 ) + { + ASSERT( !this, "Fonttabelle kaputt! (rFib.lcbSttbfffn < 2)" ); + pFontA = 0; + nMax = 0; + return; + } + + bool bVer67 = (8 > rFib.nVersion); + + rSt.Seek( rFib.fcSttbfffn ); + + // allocate Font Array + BYTE* pA = new BYTE[ rFib.lcbSttbfffn - 2 ]; + WW8_FFN* p = (WW8_FFN*)pA; + + if( !bVer67 ) + { + // bVer8: read the count of strings in nMax + rSt >> nMax; + } + + // Ver8: skip undefined uint16 + // Ver67: skip the herein stored total byte of structure + // - we already got that information in rFib.lcbSttbfffn + rSt.SeekRel( 2 ); + + // read all font information + rSt.Read( pA, rFib.lcbSttbfffn - 2 ); + + if( bVer67 ) + { + // try to figure out how many fonts are defined here + nMax = 0; + long nLeft = rFib.lcbSttbfffn - 2; + for(;;) + { + short nNextSiz; + + nNextSiz = p->cbFfnM1 + 1; + if( nNextSiz > nLeft ) + break; + nMax++; + nLeft -= nNextSiz; + if( nLeft < 1 ) // can we read the given ammount of bytes ? + break; + // increase p by nNextSiz Bytes + p = (WW8_FFN *)( ( (BYTE*)p ) + nNextSiz ); + } + } + + if( nMax ) + { + // allocate Index Array + pFontA = new WW8_FFN[ nMax ]; + p = pFontA; + + if( bVer67 ) + { + WW8_FFN_Ver6* pVer6 = (WW8_FFN_Ver6*)pA; + BYTE c2; + for(USHORT i=0; i<nMax; ++i, ++p) + { + p->cbFfnM1 = pVer6->cbFfnM1; + c2 = *(((BYTE*)pVer6) + 1); + + p->prg = c2 & 0x02; + p->fTrueType = (c2 & 0x04) >> 2; + // ein Reserve-Bit ueberspringen + p->ff = (c2 & 0x70) >> 4; + + p->wWeight = SVBT16ToShort( *(SVBT16*)&pVer6->wWeight ); + p->chs = pVer6->chs; + p->ibszAlt = pVer6->ibszAlt; + /* + #i8726# 7- seems to encode the name in the same encoding as + the font, e.g load the doc in 97 and save to see the unicode + ver of the asian fontnames in that example to confirm. + */ + rtl_TextEncoding eEnc = WW8Fib::GetFIBCharset(p->chs); + if ((eEnc == RTL_TEXTENCODING_SYMBOL) || (eEnc == RTL_TEXTENCODING_DONTKNOW)) + eEnc = RTL_TEXTENCODING_MS_1252; + p->sFontname = String(pVer6->szFfn, eEnc); +// p->sFontname = String(pVer6->szFfn, RTL_TEXTENCODING_MS_1252); + if (p->ibszAlt) + { + p->sFontname.Append(';'); + p->sFontname += String(pVer6->szFfn+p->ibszAlt, eEnc); +// RTL_TEXTENCODING_MS_1252 ); + } + pVer6 = (WW8_FFN_Ver6*)( ((BYTE*)pVer6) + pVer6->cbFfnM1 + 1 ); + } + } + else + { + WW8_FFN_Ver8* pVer8 = (WW8_FFN_Ver8*)pA; + BYTE c2; + for(USHORT i=0; i<nMax; ++i, ++p) + { + p->cbFfnM1 = pVer8->cbFfnM1; + c2 = *(((BYTE*)pVer8) + 1); + + p->prg = c2 & 0x02; + p->fTrueType = (c2 & 0x04) >> 2; + // ein Reserve-Bit ueberspringen + p->ff = (c2 & 0x70) >> 4; + + p->wWeight = SVBT16ToShort( *(SVBT16*)&pVer8->wWeight ); + p->chs = pVer8->chs; + p->ibszAlt = pVer8->ibszAlt; + +#ifdef __WW8_NEEDS_COPY + { + BYTE nLen = 0x28; + for( UINT16* pTmp = pVer8->szFfn; + nLen < pVer8->cbFfnM1 + 1 ; ++pTmp, nLen+=2 ) + { + *pTmp = SVBT16ToShort( *(SVBT16*)pTmp ); + } + } +#endif // defined __WW8_NEEDS_COPY + + p->sFontname = pVer8->szFfn; + if (p->ibszAlt) + { + p->sFontname.Append(';'); + p->sFontname.Append(pVer8->szFfn+p->ibszAlt); + } + + // Zeiger auf Ursprungsarray einen Font nach hinten setzen + pVer8 = (WW8_FFN_Ver8*)( ((BYTE*)pVer8) + pVer8->cbFfnM1 + 1 ); + } + } + } + delete[] pA; +} + +const WW8_FFN* WW8Fonts::GetFont( USHORT nNum ) const +{ + if( !pFontA || nNum >= nMax ) + return 0; + + return &pFontA[ nNum ]; +} + + + +//----------------------------------------- + + +// Suche zu einem Header / Footer den Index in der WW-Liste von Headern / Footern +// +// Pferdefuesse bei WinWord6 und -7: +// 1) Am Anfang des Einlesens muss WWPLCF_HdFt mit Fib und Dop konstruiert werden +// 2) Der Haupttext muss sequentiell ueber alle Sections gelesen werden +// 3) Fuer jedes vorkommende Header / Footer - Attribut des Haupttextes +// ( Darf pro Section maximal eins sein ) muss UpdateIndex() genau einmal +// mit dem Parameter des Attributes gerufen werden. Dieser Aufruf muss *nach* +// dem letzten Aufruf von GetTextPos() passieren. +// 4) GetTextPos() darf mit genau einem der obenstehen WW_... aufgerufen werden +// ( nicht verodern ! ) +// -> dann liefert GetTextPos() vielleicht auch ein richtiges Ergebnis + +WW8PLCF_HdFt::WW8PLCF_HdFt( SvStream* pSt, WW8Fib& rFib, WW8Dop& rDop ) + : aPLCF( pSt, rFib.fcPlcfhdd , rFib.lcbPlcfhdd , 0 ) +{ + nIdxOffset = 0; + + /* + cmc 23/02/2000: This dop.grpfIhdt has a bit set for each special + footnote *and endnote!!* seperator,continuation seperator, and + continuation notice entry, the documentation does not mention the + endnote seperators, the documentation also gets the index numbers + backwards when specifiying which bits to test. The bottom six bits + of this value must be tested and skipped over. Each section's + grpfIhdt is then tested for the existence of the appropiate headers + and footers, at the end of each section the nIdxOffset must be updated + to point to the beginning of the next section's group of headers and + footers in this PLCF, UpdateIndex does that task. + */ + for( BYTE nI = 0x1; nI <= 0x20; nI <<= 1 ) + if( nI & rDop.grpfIhdt ) // Bit gesetzt ? + nIdxOffset++; + + nTextOfs = rFib.ccpText + rFib.ccpFtn; // Groesse des Haupttextes + // und der Fussnoten +} + +bool WW8PLCF_HdFt::GetTextPos(BYTE grpfIhdt, BYTE nWhich, WW8_CP& rStart, + long& rLen) +{ + BYTE nI = 0x01; + short nIdx = nIdxOffset; + while (true) + { + if( nI & nWhich ) + break; // found + if( grpfIhdt & nI ) + nIdx++; // uninteresting Header / Footer + nI <<= 1; // text next bit + if( nI > 0x20 ) + return false; // not found + } + // nIdx ist HdFt-Index + WW8_CP nEnd; + void* pData; + + aPLCF.SetIdx( nIdx ); // Lookup suitable CP + aPLCF.Get( rStart, nEnd, pData ); + rLen = nEnd - rStart; + aPLCF++; + + return true; +} + +bool WW8PLCF_HdFt::GetTextPosExact(short nIdx, WW8_CP& rStart, long& rLen) +{ + WW8_CP nEnd; + void* pData; + + aPLCF.SetIdx( nIdx ); // Lookup suitable CP + aPLCF.Get( rStart, nEnd, pData ); + rLen = nEnd - rStart; + return true; +} + +void WW8PLCF_HdFt::UpdateIndex( BYTE grpfIhdt ) +{ + // Caution: Description is not correct + for( BYTE nI = 0x01; nI <= 0x20; nI <<= 1 ) + if( nI & grpfIhdt ) + nIdxOffset++; +} + +//----------------------------------------- +// WW8Dop +//----------------------------------------- + +WW8Dop::WW8Dop( SvStream& rSt, INT16 nFib, INT32 nPos, INT32 nSize ) +{ + BYTE* pDataPtr = new BYTE[ 500 ]; + BYTE* pData = pDataPtr; + + UINT32 nRead = 500 < nSize ? 500 : nSize; + rSt.Seek( nPos ); + if( 2 > nSize || nRead != rSt.Read( pData, nRead )) + { + memset( &nDataStart, 0, (&nDataEnd - &nDataStart) ); + nDopError = ERR_SWG_READ_ERROR; // Error melden + } + else + { + if( 500 > nRead ) + memset( pData + nRead, 0, 500 - nRead ); + + // dann mal die Daten auswerten + UINT32 a32Bit; + UINT16 a16Bit; + BYTE a8Bit; + + a16Bit = Get_UShort( pData ); + fFacingPages = 0 != ( a16Bit & 0x0001 ) ; + fWidowControl = 0 != ( a16Bit & 0x0002 ) ; + fPMHMainDoc = 0 != ( a16Bit & 0x0004 ) ; + grfSuppression = ( a16Bit & 0x0018 ) >> 3; + fpc = ( a16Bit & 0x0060 ) >> 5; + grpfIhdt = ( a16Bit & 0xff00 ) >> 8; + + a16Bit = Get_UShort( pData ); + rncFtn = a16Bit & 0x0003 ; + nFtn = ( a16Bit & ~0x0003 ) >> 2 ; + + a8Bit = Get_Byte( pData ); + fOutlineDirtySave = 0 != ( a8Bit & 0x01 ); + + a8Bit = Get_Byte( pData ); + fOnlyMacPics = 0 != ( a8Bit & 0x01 ); + fOnlyWinPics = 0 != ( a8Bit & 0x02 ); + fLabelDoc = 0 != ( a8Bit & 0x04 ); + fHyphCapitals = 0 != ( a8Bit & 0x08 ); + fAutoHyphen = 0 != ( a8Bit & 0x10 ); + fFormNoFields = 0 != ( a8Bit & 0x20 ); + fLinkStyles = 0 != ( a8Bit & 0x40 ); + fRevMarking = 0 != ( a8Bit & 0x80 ); + + a8Bit = Get_Byte( pData ); + fBackup = 0 != ( a8Bit & 0x01 ); + fExactCWords = 0 != ( a8Bit & 0x02 ); + fPagHidden = 0 != ( a8Bit & 0x04 ); + fPagResults = 0 != ( a8Bit & 0x08 ); + fLockAtn = 0 != ( a8Bit & 0x10 ); + fMirrorMargins = 0 != ( a8Bit & 0x20 ); + fReadOnlyRecommended = 0 != ( a8Bit & 0x40 ); + fDfltTrueType = 0 != ( a8Bit & 0x80 ); + + a8Bit = Get_Byte( pData ); + fPagSuppressTopSpacing = 0 != ( a8Bit & 0x01 ); + fProtEnabled = 0 != ( a8Bit & 0x02 ); + fDispFormFldSel = 0 != ( a8Bit & 0x04 ); + fRMView = 0 != ( a8Bit & 0x08 ); + fRMPrint = 0 != ( a8Bit & 0x10 ); + fWriteReservation = 0 != ( a8Bit & 0x20 ); + fLockRev = 0 != ( a8Bit & 0x40 ); + fEmbedFonts = 0 != ( a8Bit & 0x80 ); + + + a8Bit = Get_Byte( pData ); + copts_fNoTabForInd = 0 != ( a8Bit & 0x01 ); + copts_fNoSpaceRaiseLower = 0 != ( a8Bit & 0x02 ); + copts_fSupressSpbfAfterPgBrk = 0 != ( a8Bit & 0x04 ); + copts_fWrapTrailSpaces = 0 != ( a8Bit & 0x08 ); + copts_fMapPrintTextColor = 0 != ( a8Bit & 0x10 ); + copts_fNoColumnBalance = 0 != ( a8Bit & 0x20 ); + copts_fConvMailMergeEsc = 0 != ( a8Bit & 0x40 ); + copts_fSupressTopSpacing = 0 != ( a8Bit & 0x80 ); + + a8Bit = Get_Byte( pData ); + copts_fOrigWordTableRules = 0 != ( a8Bit & 0x01 ); + copts_fTransparentMetafiles = 0 != ( a8Bit & 0x02 ); + copts_fShowBreaksInFrames = 0 != ( a8Bit & 0x04 ); + copts_fSwapBordersFacingPgs = 0 != ( a8Bit & 0x08 ); + + dxaTab = Get_Short( pData ); + wSpare = Get_UShort( pData ); + dxaHotZ = Get_UShort( pData ); + cConsecHypLim = Get_UShort( pData ); + wSpare2 = Get_UShort( pData ); + dttmCreated = Get_Long( pData ); + dttmRevised = Get_Long( pData ); + dttmLastPrint = Get_Long( pData ); + nRevision = Get_Short( pData ); + tmEdited = Get_Long( pData ); + cWords = Get_Long( pData ); + cCh = Get_Long( pData ); + cPg = Get_Short( pData ); + cParas = Get_Long( pData ); + + a16Bit = Get_UShort( pData ); + rncEdn = a16Bit & 0x0003 ; + nEdn = ( a16Bit & ~0x0003 ) >> 2; + + a16Bit = Get_UShort( pData ); + epc = a16Bit & 0x0003 ; + nfcFtnRef = ( a16Bit & 0x003c ) >> 2; + nfcEdnRef = ( a16Bit & 0x03c0 ) >> 6; + fPrintFormData = 0 != ( a16Bit & 0x0400 ); + fSaveFormData = 0 != ( a16Bit & 0x0800 ); + fShadeFormData = 0 != ( a16Bit & 0x1000 ); + fWCFtnEdn = 0 != ( a16Bit & 0x8000 ); + + cLines = Get_Long( pData ); + cWordsFtnEnd = Get_Long( pData ); + cChFtnEdn = Get_Long( pData ); + cPgFtnEdn = Get_Short( pData ); + cParasFtnEdn = Get_Long( pData ); + cLinesFtnEdn = Get_Long( pData ); + lKeyProtDoc = Get_Long( pData ); + + a16Bit = Get_UShort( pData ); + wvkSaved = a16Bit & 0x0007 ; + wScaleSaved = ( a16Bit & 0x0ff8 ) >> 3 ; + zkSaved = ( a16Bit & 0x3000 ) >> 12; + fRotateFontW6 = ( a16Bit & 0x4000 ) >> 14; + iGutterPos = ( a16Bit & 0x8000 ) >> 15; + /* + bei nFib >= 103 gehts weiter: + */ + if( nFib >= 103 ) + { + a32Bit = Get_ULong( pData ); + fNoTabForInd = ( a32Bit & 0x00000001 ) ; + fNoSpaceRaiseLower = ( a32Bit & 0x00000002 ) >> 1 ; + fSupressSpbfAfterPageBreak = ( a32Bit & 0x00000004 ) >> 2 ; + fWrapTrailSpaces = ( a32Bit & 0x00000008 ) >> 3 ; + fMapPrintTextColor = ( a32Bit & 0x00000010 ) >> 4 ; + fNoColumnBalance = ( a32Bit & 0x00000020 ) >> 5 ; + fConvMailMergeEsc = ( a32Bit & 0x00000040 ) >> 6 ; + fSupressTopSpacing = ( a32Bit & 0x00000080 ) >> 7 ; + fOrigWordTableRules = ( a32Bit & 0x00000100 ) >> 8 ; + fTransparentMetafiles = ( a32Bit & 0x00000200 ) >> 9 ; + fShowBreaksInFrames = ( a32Bit & 0x00000400 ) >> 10 ; + fSwapBordersFacingPgs = ( a32Bit & 0x00000800 ) >> 11 ; + fSuppressTopSpacingMac5 = ( a32Bit & 0x00010000 ) >> 16 ; + fTruncDxaExpand = ( a32Bit & 0x00020000 ) >> 17 ; + fPrintBodyBeforeHdr = ( a32Bit & 0x00040000 ) >> 18 ; + fNoLeading = ( a32Bit & 0x00080000 ) >> 19 ; + fMWSmallCaps = ( a32Bit & 0x00200000 ) >> 21 ; + + fUsePrinterMetrics = ( a32Bit & 0x80000000 ) >> 31 ; + } + + /* + bei nFib > 105 gehts weiter: + */ + if( nFib > 105 ) + { + adt = Get_Short( pData ); + + doptypography.ReadFromMem(pData); + + memcpy( &dogrid, pData, sizeof( WW8_DOGRID )); + pData += sizeof( WW8_DOGRID ); + + a16Bit = Get_UShort( pData ); + // die untersten 9 Bit sind uninteressant + fHtmlDoc = ( a16Bit & 0x0200 ) >> 9 ; + fSnapBorder = ( a16Bit & 0x0800 ) >> 11 ; + fIncludeHeader = ( a16Bit & 0x1000 ) >> 12 ; + fIncludeFooter = ( a16Bit & 0x2000 ) >> 13 ; + fForcePageSizePag = ( a16Bit & 0x4000 ) >> 14 ; + fMinFontSizePag = ( a16Bit & 0x8000 ) >> 15 ; + + a16Bit = Get_UShort( pData ); + fHaveVersions = 0 != ( a16Bit & 0x0001 ); + fAutoVersion = 0 != ( a16Bit & 0x0002 ); + + pData += 12; + + cChWS = Get_Long( pData ); + cChWSFtnEdn = Get_Long( pData ); + grfDocEvents = Get_Long( pData ); + + pData += 4+30+8; + + cDBC = Get_Long( pData ); + cDBCFtnEdn = Get_Long( pData ); + + pData += 1 * sizeof( long ); + + nfcFtnRef = Get_Short( pData ); + nfcEdnRef = Get_Short( pData ); + hpsZoonFontPag = Get_Short( pData ); + dywDispPag = Get_Short( pData ); + } + } + delete[] pDataPtr; +} + +WW8Dop::WW8Dop() +{ + // first set everything to a default of 0 + memset( &nDataStart, 0, (&nDataEnd - &nDataStart) ); + + fWidowControl = 1; + fpc = 1; + nFtn = 1; + fOutlineDirtySave = 1; + fHyphCapitals = 1; + fBackup = 1; + fPagHidden = 1; + fPagResults = 1; + fDfltTrueType = 1; + + /* + Writer acts like this all the time at the moment, ideally we need an + option for these two as well to import word docs that are not like + this by default + */ + fNoLeading = 1; + fUsePrinterMetrics = 1; + + fRMView = 1; + fRMPrint = 1; + dxaTab = 0x2d0; + dxaHotZ = 0x168; + dttmCreated = 0x45FBAC69; + dttmRevised = 0x45FBAC69; + nRevision = 1; + nEdn = 1; + + epc = 3; + nfcEdnRef = 2; + fShadeFormData = 1; + + wvkSaved = 2; + wScaleSaved = 100; + zkSaved = 0; + + lvl = 9; + fIncludeHeader = 1; + fIncludeFooter = 1; + + cChWS = /**!!**/ 0; + cChWSFtnEdn = /**!!**/ 0; + + cDBC = /**!!**/ 0; + cDBCFtnEdn = /**!!**/ 0; +} + +UINT32 WW8Dop::GetCompatabilityOptions() const +{ + UINT32 a32Bit = 0; + if (fNoTabForInd) a32Bit |= 0x00000001; + if (fNoSpaceRaiseLower) a32Bit |= 0x00000002; + if (fSupressSpbfAfterPageBreak) a32Bit |= 0x00000004; + if (fWrapTrailSpaces) a32Bit |= 0x00000008; + if (fMapPrintTextColor) a32Bit |= 0x00000010; + if (fNoColumnBalance) a32Bit |= 0x00000020; + if (fConvMailMergeEsc) a32Bit |= 0x00000040; + if (fSupressTopSpacing) a32Bit |= 0x00000080; + if (fOrigWordTableRules) a32Bit |= 0x00000100; + if (fTransparentMetafiles) a32Bit |= 0x00000200; + if (fShowBreaksInFrames) a32Bit |= 0x00000400; + if (fSwapBordersFacingPgs) a32Bit |= 0x00000800; + if (fSuppressTopSpacingMac5) a32Bit |= 0x00010000; + if (fTruncDxaExpand) a32Bit |= 0x00020000; + if (fPrintBodyBeforeHdr) a32Bit |= 0x00040000; + if (fNoLeading) a32Bit |= 0x00080000; + if (fMWSmallCaps) a32Bit |= 0x00200000; + if (fUsePrinterMetrics) a32Bit |= 0x80000000; + return a32Bit; +} + +bool WW8Dop::Write(SvStream& rStrm, WW8Fib& rFib) const +{ + INT32 nLen = 8 == rFib.nVersion ? 0x220 : 84; + rFib.fcDop = rStrm.Tell(); + rFib.lcbDop = nLen; + + BYTE aData[ 0x220 ]; + memset( aData, 0, 0x220 ); + BYTE* pData = aData; + + // dann mal die Daten auswerten + UINT16 a16Bit; + BYTE a8Bit; + + a16Bit = 0; + if (fFacingPages) + a16Bit |= 0x0001; + if (fWidowControl) + a16Bit |= 0x0002; + if (fPMHMainDoc) + a16Bit |= 0x0004; + a16Bit |= ( 0x0018 & (grfSuppression << 3)); + a16Bit |= ( 0x0060 & (fpc << 5)); + a16Bit |= ( 0xff00 & (grpfIhdt << 8)); + Set_UInt16( pData, a16Bit ); + + a16Bit = 0; + a16Bit |= ( 0x0003 & rncFtn ); + a16Bit |= ( ~0x0003 & (nFtn << 2)); + Set_UInt16( pData, a16Bit ); + + a8Bit = 0; + if( fOutlineDirtySave ) a8Bit |= 0x01; + Set_UInt8( pData, a8Bit ); + + a8Bit = 0; + if( fOnlyMacPics ) a8Bit |= 0x01; + if( fOnlyWinPics ) a8Bit |= 0x02; + if( fLabelDoc ) a8Bit |= 0x04; + if( fHyphCapitals ) a8Bit |= 0x08; + if( fAutoHyphen ) a8Bit |= 0x10; + if( fFormNoFields ) a8Bit |= 0x20; + if( fLinkStyles ) a8Bit |= 0x40; + if( fRevMarking ) a8Bit |= 0x80; + Set_UInt8( pData, a8Bit ); + + a8Bit = 0; + if( fBackup ) a8Bit |= 0x01; + if( fExactCWords ) a8Bit |= 0x02; + if( fPagHidden ) a8Bit |= 0x04; + if( fPagResults ) a8Bit |= 0x08; + if( fLockAtn ) a8Bit |= 0x10; + if( fMirrorMargins ) a8Bit |= 0x20; + if( fReadOnlyRecommended ) a8Bit |= 0x40; + if( fDfltTrueType ) a8Bit |= 0x80; + Set_UInt8( pData, a8Bit ); + + a8Bit = 0; + if( fPagSuppressTopSpacing ) a8Bit |= 0x01; + if( fProtEnabled ) a8Bit |= 0x02; + if( fDispFormFldSel ) a8Bit |= 0x04; + if( fRMView ) a8Bit |= 0x08; + if( fRMPrint ) a8Bit |= 0x10; + if( fWriteReservation ) a8Bit |= 0x20; + if( fLockRev ) a8Bit |= 0x40; + if( fEmbedFonts ) a8Bit |= 0x80; + Set_UInt8( pData, a8Bit ); + + + a8Bit = 0; + if( copts_fNoTabForInd ) a8Bit |= 0x01; + if( copts_fNoSpaceRaiseLower ) a8Bit |= 0x02; + if( copts_fSupressSpbfAfterPgBrk ) a8Bit |= 0x04; + if( copts_fWrapTrailSpaces ) a8Bit |= 0x08; + if( copts_fMapPrintTextColor ) a8Bit |= 0x10; + if( copts_fNoColumnBalance ) a8Bit |= 0x20; + if( copts_fConvMailMergeEsc ) a8Bit |= 0x40; + if( copts_fSupressTopSpacing ) a8Bit |= 0x80; + Set_UInt8( pData, a8Bit ); + + a8Bit = 0; + if( copts_fOrigWordTableRules ) a8Bit |= 0x01; + if( copts_fTransparentMetafiles ) a8Bit |= 0x02; + if( copts_fShowBreaksInFrames ) a8Bit |= 0x04; + if( copts_fSwapBordersFacingPgs ) a8Bit |= 0x08; + Set_UInt8( pData, a8Bit ); + + Set_UInt16( pData, dxaTab ); + Set_UInt16( pData, wSpare ); + Set_UInt16( pData, dxaHotZ ); + Set_UInt16( pData, cConsecHypLim ); + Set_UInt16( pData, wSpare2 ); + Set_UInt32( pData, dttmCreated ); + Set_UInt32( pData, dttmRevised ); + Set_UInt32( pData, dttmLastPrint ); + Set_UInt16( pData, nRevision ); + Set_UInt32( pData, tmEdited ); + Set_UInt32( pData, cWords ); + Set_UInt32( pData, cCh ); + Set_UInt16( pData, cPg ); + Set_UInt32( pData, cParas ); + + a16Bit = 0; + a16Bit |= ( 0x0003 & rncEdn ); + a16Bit |= (~0x0003 & ( nEdn << 2)); + Set_UInt16( pData, a16Bit ); + + a16Bit = 0; + a16Bit |= (0x0003 & epc ); + a16Bit |= (0x003c & (nfcFtnRef << 2)); + a16Bit |= (0x03c0 & (nfcEdnRef << 6)); + if( fPrintFormData ) a16Bit |= 0x0400; + if( fSaveFormData ) a16Bit |= 0x0800; + if( fShadeFormData ) a16Bit |= 0x1000; + if( fWCFtnEdn ) a16Bit |= 0x8000; + Set_UInt16( pData, a16Bit ); + + Set_UInt32( pData, cLines ); + Set_UInt32( pData, cWordsFtnEnd ); + Set_UInt32( pData, cChFtnEdn ); + Set_UInt16( pData, cPgFtnEdn ); + Set_UInt32( pData, cParasFtnEdn ); + Set_UInt32( pData, cLinesFtnEdn ); + Set_UInt32( pData, lKeyProtDoc ); + + a16Bit = 0; + if (wvkSaved) + a16Bit |= 0x0007; + a16Bit |= (0x0ff8 & (wScaleSaved << 3)); + a16Bit |= (0x3000 & (zkSaved << 12)); + Set_UInt16( pData, a16Bit ); + + if( 8 == rFib.nVersion ) + { + Set_UInt32(pData, GetCompatabilityOptions()); + + Set_UInt16( pData, adt ); + + doptypography.WriteToMem(pData); + + memcpy( pData, &dogrid, sizeof( WW8_DOGRID )); + pData += sizeof( WW8_DOGRID ); + + a16Bit = 0x12; // lvl auf 9 setzen + if( fHtmlDoc ) a16Bit |= 0x0200; + if( fSnapBorder ) a16Bit |= 0x0800; + if( fIncludeHeader ) a16Bit |= 0x1000; + if( fIncludeFooter ) a16Bit |= 0x2000; + if( fForcePageSizePag ) a16Bit |= 0x4000; + if( fMinFontSizePag ) a16Bit |= 0x8000; + Set_UInt16( pData, a16Bit ); + + a16Bit = 0; + if( fHaveVersions ) a16Bit |= 0x0001; + if( fAutoVersion ) a16Bit |= 0x0002; + Set_UInt16( pData, a16Bit ); + + pData += 12; + + Set_UInt32( pData, cChWS ); + Set_UInt32( pData, cChWSFtnEdn ); + Set_UInt32( pData, grfDocEvents ); + + pData += 4+30+8; + + Set_UInt32( pData, cDBC ); + Set_UInt32( pData, cDBCFtnEdn ); + + pData += 1 * sizeof( long ); + + Set_UInt16( pData, nfcFtnRef ); + Set_UInt16( pData, nfcEdnRef ); + Set_UInt16( pData, hpsZoonFontPag ); + Set_UInt16( pData, dywDispPag ); + + //500 -> 508, Appear to be repeated here in 2000+ + pData += 8; + Set_UInt32(pData, GetCompatabilityOptions()); + } + rStrm.Write( aData, nLen ); + return 0 == rStrm.GetError(); +} + +void WW8DopTypography::ReadFromMem(BYTE *&pData) +{ + USHORT a16Bit = Get_UShort(pData); + fKerningPunct = (a16Bit & 0x0001); + iJustification = (a16Bit & 0x0006) >> 1; + iLevelOfKinsoku = (a16Bit & 0x0018) >> 3; + f2on1 = (a16Bit & 0x0020) >> 5; + reserved1 = (a16Bit & 0x03C0) >> 6; + reserved2 = (a16Bit & 0xFC00) >> 10; + + cchFollowingPunct = Get_Short(pData); + cchLeadingPunct = Get_Short(pData); + + INT16 i; + for (i=0; i < nMaxFollowing; ++i) + rgxchFPunct[i] = Get_Short(pData); + for (i=0; i < nMaxLeading; ++i) + rgxchLPunct[i] = Get_Short(pData); + + rgxchFPunct[cchFollowingPunct]=0; + rgxchLPunct[cchLeadingPunct]=0; +} + +void WW8DopTypography::WriteToMem(BYTE *&pData) const +{ + USHORT a16Bit = fKerningPunct; + a16Bit |= (iJustification << 1) & 0x0006; + a16Bit |= (iLevelOfKinsoku << 3) & 0x0018; + a16Bit |= (f2on1 << 5) & 0x002; + a16Bit |= (reserved1 << 6) & 0x03C0; + a16Bit |= (reserved2 << 10) & 0xFC00; + Set_UInt16(pData,a16Bit); + + Set_UInt16(pData,cchFollowingPunct); + Set_UInt16(pData,cchLeadingPunct); + + INT16 i; + for (i=0; i < nMaxFollowing; ++i) + Set_UInt16(pData,rgxchFPunct[i]); + for (i=0; i < nMaxLeading; ++i) + Set_UInt16(pData,rgxchLPunct[i]); +} + +USHORT WW8DopTypography::GetConvertedLang() const +{ + USHORT nLang; + //I have assumed peoples republic/taiwan == simplified/traditional + + //This isn't a documented issue, so we might have it all wrong, + //i.e. i.e. whats with the powers of two ? + + /* + #84082# + One example of 3 for reserved1 which was really Japanese, perhaps last bit + is for some other use ?, or redundant. If more examples trigger the assert + we might be able to figure it out. + */ + switch(reserved1 & 0xE) + { + case 2: //Japan + nLang = LANGUAGE_JAPANESE; + break; + case 4: //Chinese (Peoples Republic) + nLang = LANGUAGE_CHINESE_SIMPLIFIED; + break; + case 6: //Korean + nLang = LANGUAGE_KOREAN; + break; + case 8: //Chinese (Taiwan) + nLang = LANGUAGE_CHINESE_TRADITIONAL; + break; + default: + ASSERT(!this, "Unknown MS Asian Typography language, report"); + nLang = LANGUAGE_CHINESE; + break; + case 0: + //And here we have the possibility that it says 2, but its really + //a bug and only japanese level 2 has been selected after a custom + //version was chosen on last save! + nLang = LANGUAGE_JAPANESE; + break; + } + return nLang; +} + +//----------------------------------------- +// Sprms +//----------------------------------------- +USHORT wwSprmParser::GetSprmTailLen(sal_uInt16 nId, const sal_uInt8* pSprm) + const +{ + SprmInfo aSprm = GetSprmInfo(nId); + USHORT nL = 0; // number of Bytes to read + + //sprmPChgTabs + switch( nId ) + { + case 23: + case 0xC615: + if( pSprm[1 + mnDelta] != 255 ) + nL = pSprm[1 + mnDelta] + aSprm.nLen; + else + { + BYTE nDel = pSprm[2 + mnDelta]; + BYTE nIns = pSprm[3 + mnDelta + 4 * nDel]; + + nL = 2 + 4 * nDel + 3 * nIns; + } + break; + case 0xD608: + nL = SVBT16ToShort( &pSprm[1 + mnDelta] ); + break; + default: + switch (aSprm.nVari) + { + case L_FIX: + nL = aSprm.nLen; // Excl. Token + break; + case L_VAR: + // Variable 1-Byte Length? + // Excl. Token + Var-Lengthbyte + nL = pSprm[1 + mnDelta] + aSprm.nLen; + break; + case L_VAR2: + // Variable 2-Byte Length? + // Excl. Token + Var-Lengthbyte + nL = SVBT16ToShort( &pSprm[1 + mnDelta] ) + aSprm.nLen - 1; + break; + default: + ASSERT(!this, "Unknown sprm varient"); + break; + } + break; + } + return nL; +} + +int wwSprmParser::CountSprms(const sal_uInt8* pSp, long nSprmSiz, + const wwSprmSequence* pIgnoreSprms) const +{ + USHORT nMySprms = 0; + USHORT i=0; + while (i+1+mnDelta < nSprmSiz) + { + USHORT nSpId = GetSprmId(pSp); + + if( !nSpId ) + break; + + USHORT nSpLen = GetSprmSize(nSpId, pSp); + // increase pointers so to point to next sprm + i += nSpLen; + pSp += nSpLen; + + if (!pIgnoreSprms || !pIgnoreSprms->search(nSpId)) + ++nMySprms; + } + return nMySprms; +} + +// one or two bytes at the beginning at the sprm id +USHORT wwSprmParser::GetSprmId(const sal_uInt8* pSp) const +{ + ASSERT_RET_ON_FAIL(pSp, "Why GetSprmId with pSp of 0", 0); + + USHORT nId = 0; + switch (mnVersion) // 6 stands for "6 OR 7", 7 stands for "ONLY 7" + { + case 6: + case 7: + nId = *pSp; + if (0x0100 < nId) + nId = 0; + break; + default: + case 8: + nId = SVBT16ToShort(pSp); + if (0x0800 > nId) + nId = 0; + break; + } + return nId; +} + +// with tokens and length byte +USHORT wwSprmParser::GetSprmSize(sal_uInt16 nId, const sal_uInt8* pSprm) const +{ + return GetSprmTailLen(nId, pSprm) + 1 + mnDelta + SprmDataOfs(nId); +} + +BYTE wwSprmParser::SprmDataOfs(USHORT nId) const +{ + return GetSprmInfo(nId).nVari; +} + +USHORT wwSprmParser::DistanceToData(USHORT nId) const +{ + return 1 + mnDelta + SprmDataOfs(nId); +} + +SEPr::SEPr() : + bkc(2), fTitlePage(0), fAutoPgn(0), nfcPgn(0), fUnlocked(0), cnsPgn(0), + fPgnRestart(0), fEndNote(1), lnc(0), grpfIhdt(0), nLnnMod(0), dxaLnn(0), + dxaPgn(720), dyaPgn(720), fLBetween(0), vjc(0), dmBinFirst(0), + dmBinOther(0), dmPaperReq(0), fPropRMark(0), ibstPropRMark(0), + dttmPropRMark(0), dxtCharSpace(0), dyaLinePitch(0), clm(0), reserved1(0), + dmOrientPage(0), iHeadingPgn(0), pgnStart(1), lnnMin(0), wTextFlow(0), + reserved2(0), pgbApplyTo(0), pgbPageDepth(0), pgbOffsetFrom(0), + xaPage(12242), yaPage(15842), xaPageNUp(12242), yaPageNUp(15842), + dxaLeft(1800), dxaRight(1800), dyaTop(1440), dyaBottom(1440), dzaGutter(0), + dyaHdrTop(720), dyaHdrBottom(720), ccolM1(0), fEvenlySpaced(1), + reserved3(0), fBiDi(0), fFacingCol(0), fRTLGutter(0), fRTLAlignment(0), + dxaColumns(720), dxaColumnWidth(0), dmOrientFirst(0), fLayout(0), + reserved4(0) +{ + memset(rgdxaColumnWidthSpacing, 0, sizeof(rgdxaColumnWidthSpacing)); +} + +/* vi:set tabstop=4 shiftwidth=4 expandtab: */ |