xref: /trunk/main/sw/source/filter/ww8/dump/ww8scan.cxx (revision 152e651ef53ab2fae14bf93407606b2c7fcbd35b)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 
29 #include <algorithm>
30 #include <functional>
31 
32 #include <string.h>         // memset()
33 #include <osl/endian.h>
34 #include <rtl/tencinfo.h>
35 
36 #ifdef DUMP
37 
38 #define ERR_SWG_READ_ERROR 1234
39 #define ASSERT( a, b )
40 
41 #else                       // dump
42 #include <swerror.h>        // ERR_WW6_...
43 #include <errhdl.hxx>       // ASSERT()
44 #include <swtypes.hxx>      // DELETEZ
45 
46 #endif                      // dump
47 #include <tools/debug.hxx>
48 #include "ww8scan.hxx"
49 
50 #define ASSERT_RET_ON_FAIL( aCon, aError, aRet ) \
51     ASSERT(aCon, aError); \
52     if (!(aCon)) \
53         return aRet;
54 
55 //-begin
56 namespace SL
57 {
58 #   define IMPLCONSTSTRINGARRAY(X) const char a##X[] = "" #X ""
59     IMPLCONSTSTRINGARRAY(ObjectPool);
60     IMPLCONSTSTRINGARRAY(1Table);
61     IMPLCONSTSTRINGARRAY(0Table);
62     IMPLCONSTSTRINGARRAY(Data);
63     IMPLCONSTSTRINGARRAY(CheckBox);
64     IMPLCONSTSTRINGARRAY(TextBox);
65     IMPLCONSTSTRINGARRAY(TextField);
66     IMPLCONSTSTRINGARRAY(MSMacroCmds);
67 }
68 
TestBeltAndBraces(const SvStream & rStrm)69 template<class C> bool wwString<C>::TestBeltAndBraces(const SvStream& rStrm)
70 {
71     bool bRet = false;
72     sal_uInt32 nOldPos = rStrm.Tell();
73     SvStream &rMutableStrm = const_cast<SvStream &>(rStrm);
74     sal_uInt32 nLen = rMutableStrm.Seek(STREAM_SEEK_TO_END);
75     rMutableStrm.Seek(nOldPos);
76     C nBelt;
77     rMutableStrm >> nBelt;
78     nBelt *= sizeof(C);
79     if (nOldPos + sizeof(C) + nBelt + sizeof(C) <= nLen &&
80         !rStrm.GetError() && !rStrm.IsEof())
81     {
82         rMutableStrm.SeekRel(nBelt);
83         if (!rStrm.GetError())
84         {
85             C cBraces;
86             rMutableStrm >> cBraces;
87             if (!rMutableStrm.GetError() && cBraces == 0)
88                 bRet = true;
89         }
90     }
91     rMutableStrm.Seek(nOldPos);
92     return bRet;
93 }
94 
95 template<class C> class wwSortedArray
96 {
97 private:
98     //The array e.g. of sprms.
99     C *mpWwSprmTab;
100     size_t mnNoElems;
101 public:
wwSortedArray(C * pWwSprmTab,size_t nNoElems)102     wwSortedArray(C *pWwSprmTab, size_t nNoElems)
103         : mpWwSprmTab(pWwSprmTab), mnNoElems(nNoElems)
104     {
105         ASSERT(mnNoElems && pWwSprmTab, "WW8: empty Array: Don't do that");
106         std::sort(mpWwSprmTab, mpWwSprmTab + mnNoElems);
107 #ifdef DEBUG
108         bool bBroken=false;
109         rtl::OUString sError;
110         const C *pIter = mpWwSprmTab;
111         const C *pBeforeEnd = mpWwSprmTab + mnNoElems - 1;
112         while (pIter < pBeforeEnd)
113         {
114             if (*pIter == *(pIter+1))
115             {
116                 if (!bBroken)
117                 {
118                     sError = rtl::OUString::createFromAscii(
119                         "WW8: Duplicate in list, almost certainly don't want that!\n"
120                         "(You will not see this message again unless you restart)\n"
121                         "Extra entries are...\n");
122                     bBroken=true;
123                 }
124 
125                 size_t nSize = sizeof(C);
126                 const sal_uInt8 *pHack =
127                     reinterpret_cast<const sal_uInt8 *>(&(*pIter));
128                 for (size_t i=0; i < nSize; ++i)
129                 {
130                     sError += rtl::OUString::valueOf(
131                         static_cast<sal_Int32>(pHack[i]), 16);
132                     sError += rtl::OUString::valueOf(sal_Unicode(' '));
133                 }
134                 sError += rtl::OUString::valueOf(sal_Unicode('\n'));
135                 while (*pIter == *(pIter+1) && pIter < pBeforeEnd)
136                     ++pIter;
137             }
138             else
139                 ++pIter;
140         }
141         if (bBroken)
142             DbgError(rtl::OUStringToOString(sError, RTL_TEXTENCODING_ASCII_US));
143 #endif
144     }
145 
146     //Find an entry, return its address if found and 0 if not
147     const C *search(C aSrch) const;
148 };
149 
search(C aSrch) const150 template<class C> const C *wwSortedArray<C>::search(C aSrch) const
151 {
152     std::pair<C *, C *> aPair =
153         std::equal_range(mpWwSprmTab, mpWwSprmTab + mnNoElems, aSrch);
154     if (aPair.first != aPair.second)
155         return aPair.first;
156     else
157         return 0;
158 }
159 
operator ==(const SprmInfo & rFirst,const SprmInfo & rSecond)160 bool operator==(const SprmInfo &rFirst, const SprmInfo &rSecond)
161 {
162     return (rFirst.nId == rSecond.nId);
163 }
164 
operator <(const SprmInfo & rFirst,const SprmInfo & rSecond)165 bool operator<(const SprmInfo &rFirst, const SprmInfo &rSecond)
166 {
167     return (rFirst.nId < rSecond.nId);
168 }
169 
GetWW6SprmSearcher()170 const wwSprmSearcher *wwSprmParser::GetWW6SprmSearcher()
171 {
172     //double lock me
173     // WW7- Sprms
174     static SprmInfo aSprms[] =
175     {
176         {  0, 0, L_FIX}, // "Default-sprm",  wird uebersprungen
177         {  2, 2, L_FIX}, // "sprmPIstd",  pap.istd (style code)
178         {  3, 3, L_VAR}, // "sprmPIstdPermute pap.istd permutation
179         {  4, 1, L_FIX}, // "sprmPIncLv1" pap.istddifference
180         {  5, 1, L_FIX}, // "sprmPJc" pap.jc (justification)
181         {  6, 1, L_FIX}, // "sprmPFSideBySide" pap.fSideBySide
182         {  7, 1, L_FIX}, // "sprmPFKeep" pap.fKeep
183         {  8, 1, L_FIX}, // "sprmPFKeepFollow " pap.fKeepFollow
184         {  9, 1, L_FIX}, // "sprmPPageBreakBefore" pap.fPageBreakBefore
185         { 10, 1, L_FIX}, // "sprmPBrcl" pap.brcl
186         { 11, 1, L_FIX}, // "sprmPBrcp" pap.brcp
187         { 12, 0, L_VAR}, // "sprmPAnld" pap.anld (ANLD structure)
188         { 13, 1, L_FIX}, // "sprmPNLvlAnm" pap.nLvlAnm nn
189         { 14, 1, L_FIX}, // "sprmPFNoLineNumb" pap.fNoLnn
190         { 15, 0, L_VAR}, // "?sprmPChgTabsPapx" pap.itbdMac, ...
191         { 16, 2, L_FIX}, // "sprmPDxaRight" pap.dxaRight
192         { 17, 2, L_FIX}, // "sprmPDxaLeft" pap.dxaLeft
193         { 18, 2, L_FIX}, // "sprmPNest" pap.dxaLeft
194         { 19, 2, L_FIX}, // "sprmPDxaLeft1" pap.dxaLeft1
195         { 20, 4, L_FIX}, // "sprmPDyaLine" pap.lspd an LSPD
196         { 21, 2, L_FIX}, // "sprmPDyaBefore" pap.dyaBefore
197         { 22, 2, L_FIX}, // "sprmPDyaAfter" pap.dyaAfter
198         { 23, 0, L_VAR}, // "?sprmPChgTabs" pap.itbdMac, pap.rgdxaTab, ...
199         { 24, 1, L_FIX}, // "sprmPFInTable" pap.fInTable
200         { 25, 1, L_FIX}, // "sprmPTtp" pap.fTtp
201         { 26, 2, L_FIX}, // "sprmPDxaAbs" pap.dxaAbs
202         { 27, 2, L_FIX}, // "sprmPDyaAbs" pap.dyaAbs
203         { 28, 2, L_FIX}, // "sprmPDxaWidth" pap.dxaWidth
204         { 29, 1, L_FIX}, // "sprmPPc" pap.pcHorz, pap.pcVert
205         { 30, 2, L_FIX}, // "sprmPBrcTop10" pap.brcTop BRC10
206         { 31, 2, L_FIX}, // "sprmPBrcLeft10" pap.brcLeft BRC10
207         { 32, 2, L_FIX}, // "sprmPBrcBottom10" pap.brcBottom BRC10
208         { 33, 2, L_FIX}, // "sprmPBrcRight10" pap.brcRight BRC10
209         { 34, 2, L_FIX}, // "sprmPBrcBetween10" pap.brcBetween BRC10
210         { 35, 2, L_FIX}, // "sprmPBrcBar10" pap.brcBar BRC10
211         { 36, 2, L_FIX}, // "sprmPFromText10" pap.dxaFromText dxa
212         { 37, 1, L_FIX}, // "sprmPWr" pap.wr wr
213         { 38, 2, L_FIX}, // "sprmPBrcTop" pap.brcTop BRC
214         { 39, 2, L_FIX}, // "sprmPBrcLeft" pap.brcLeft BRC
215         { 40, 2, L_FIX}, // "sprmPBrcBottom" pap.brcBottom BRC
216         { 41, 2, L_FIX}, // "sprmPBrcRight" pap.brcRight BRC
217         { 42, 2, L_FIX}, // "sprmPBrcBetween" pap.brcBetween BRC
218         { 43, 2, L_FIX}, // "sprmPBrcBar" pap.brcBar BRC word
219         { 44, 1, L_FIX}, // "sprmPFNoAutoHyph" pap.fNoAutoHyph
220         { 45, 2, L_FIX}, // "sprmPWHeightAbs" pap.wHeightAbs w
221         { 46, 2, L_FIX}, // "sprmPDcs" pap.dcs DCS
222         { 47, 2, L_FIX}, // "sprmPShd" pap.shd SHD
223         { 48, 2, L_FIX}, // "sprmPDyaFromText" pap.dyaFromText dya
224         { 49, 2, L_FIX}, // "sprmPDxaFromText" pap.dxaFromText dxa
225         { 50, 1, L_FIX}, // "sprmPFLocked" pap.fLocked 0 or 1 byte
226         { 51, 1, L_FIX}, // "sprmPFWidowControl" pap.fWidowControl 0 or 1 byte
227         { 52, 0, L_FIX}, // "?sprmPRuler 52"
228         { 64, 0, L_VAR}, // rtl property ?
229         { 65, 1, L_FIX}, // "sprmCFStrikeRM" chp.fRMarkDel 1 or 0 bit
230         { 66, 1, L_FIX}, // "sprmCFRMark" chp.fRMark 1 or 0 bit
231         { 67, 1, L_FIX}, // "sprmCFFldVanish" chp.fFldVanish 1 or 0 bit
232         { 68, 0, L_VAR}, // "sprmCPicLocation" chp.fcPic and chp.fSpec
233         { 69, 2, L_FIX}, // "sprmCIbstRMark" chp.ibstRMark index into sttbRMark
234         { 70, 4, L_FIX}, // "sprmCDttmRMark" chp.dttm DTTM long
235         { 71, 1, L_FIX}, // "sprmCFData" chp.fData 1 or 0 bit
236         { 72, 2, L_FIX}, // "sprmCRMReason" chp.idslRMReason an index to a table
237         { 73, 3, L_FIX}, // "sprmCChse" chp.fChsDiff and chp.chse
238         { 74, 0, L_VAR}, // "sprmCSymbol" chp.fSpec, chp.chSym and chp.ftcSym
239         { 75, 1, L_FIX}, // "sprmCFOle2" chp.fOle2 1 or 0   bit
240         { 79, 0, L_VAR}, // unknown
241         { 80, 2, L_FIX}, // "sprmCIstd" chp.istd istd, see stylesheet definition
242         { 81, 0, L_VAR}, // "sprmCIstdPermute" chp.istd permutation vector
243         { 82, 0, L_VAR}, // "sprmCDefault" whole CHP
244         { 83, 0, L_FIX}, // "sprmCPlain" whole CHP
245         { 85, 1, L_FIX}, // "sprmCFBold" chp.fBold 0,1, 128, or 129
246         { 86, 1, L_FIX}, // "sprmCFItalic" chp.fItalic 0,1, 128, or 129
247         { 87, 1, L_FIX}, // "sprmCFStrike" chp.fStrike 0,1, 128, or 129
248         { 88, 1, L_FIX}, // "sprmCFOutline" chp.fOutline 0,1, 128, or 129
249         { 89, 1, L_FIX}, // "sprmCFShadow" chp.fShadow 0,1, 128, or 129
250         { 90, 1, L_FIX}, // "sprmCFSmallCaps" chp.fSmallCaps 0,1, 128, or 129
251         { 91, 1, L_FIX}, // "sprmCFCaps" chp.fCaps 0,1, 128, or 129
252         { 92, 1, L_FIX}, // "sprmCFVanish" chp.fVanish 0,1, 128, or 129
253         { 93, 2, L_FIX}, // "sprmCFtc" chp.ftc ftc word
254         { 94, 1, L_FIX}, // "sprmCKul" chp.kul kul byte
255         { 95, 3, L_FIX}, // "sprmCSizePos" chp.hps, chp.hpsPos
256         { 96, 2, L_FIX}, // "sprmCDxaSpace" chp.dxaSpace dxa
257         { 97, 2, L_FIX}, // "sprmCLid" chp.lid LID
258         { 98, 1, L_FIX}, // "sprmCIco" chp.ico ico byte
259         { 99, 2, L_FIX}, // "sprmCHps" chp.hps hps !word!
260         {100, 1, L_FIX}, // "sprmCHpsInc" chp.hps
261         {101, 2, L_FIX}, // "sprmCHpsPos" chp.hpsPos hps !word!
262         {102, 1, L_FIX}, // "sprmCHpsPosAdj" chp.hpsPos hps
263         {103, 0, L_VAR}, // "?sprmCMajority" chp.fBold, chp.fItalic, ...
264         {104, 1, L_FIX}, // "sprmCIss" chp.iss iss
265         {105, 0, L_VAR}, // "sprmCHpsNew50" chp.hps hps variable width
266         {106, 0, L_VAR}, // "sprmCHpsInc1" chp.hps complex
267         {107, 2, L_FIX}, // "sprmCHpsKern" chp.hpsKern hps
268         {108, 0, L_VAR}, // "sprmCMajority50" chp.fBold, chp.fItalic, ...
269         {109, 2, L_FIX}, // "sprmCHpsMul" chp.hps percentage to grow hps
270         {110, 2, L_FIX}, // "sprmCCondHyhen" chp.ysri ysri
271         {111, 2, L_FIX}, // unknown
272         {112, 2, L_FIX}, // unknown
273         {113, 0, L_VAR}, // rtl property ?
274         {115, 0, L_VAR}, // rtl property ?
275         {116, 0, L_VAR}, // unknown
276         {117, 1, L_FIX}, // "sprmCFSpec" chp.fSpec  1 or 0 bit
277         {118, 1, L_FIX}, // "sprmCFObj" chp.fObj 1 or 0 bit
278         {119, 1, L_FIX}, // "sprmPicBrcl" pic.brcl brcl (see PIC definition)
279         {120,12, L_VAR}, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
280         {121, 2, L_FIX}, // "sprmPicBrcTop" pic.brcTop BRC word
281         {122, 2, L_FIX}, // "sprmPicBrcLeft" pic.brcLeft BRC word
282         {123, 2, L_FIX}, // "sprmPicBrcBottom" pic.brcBottom BRC word
283         {124, 2, L_FIX}, // "sprmPicBrcRight" pic.brcRight BRC word
284         {131, 1, L_FIX}, // "sprmSScnsPgn" sep.cnsPgn cns byte
285         {132, 1, L_FIX}, // "sprmSiHeadingPgn" sep.iHeadingPgn
286         {133, 0, L_VAR}, // "sprmSOlstAnm" sep.olstAnm OLST variable length
287         {136, 3, L_FIX}, // "sprmSDxaColWidth" sep.rgdxaColWidthSpacing complex
288         {137, 3, L_FIX}, // "sprmSDxaColSpacing" sep.rgdxaColWidthSpacing
289         {138, 1, L_FIX}, // "sprmSFEvenlySpaced" sep.fEvenlySpaced 1 or 0
290         {139, 1, L_FIX}, // "sprmSFProtected" sep.fUnlocked 1 or 0 byte
291         {140, 2, L_FIX}, // "sprmSDmBinFirst" sep.dmBinFirst  word
292         {141, 2, L_FIX}, // "sprmSDmBinOther" sep.dmBinOther  word
293         {142, 1, L_FIX}, // "sprmSBkc" sep.bkc bkc byte
294         {143, 1, L_FIX}, // "sprmSFTitlePage" sep.fTitlePage 0 or 1 byte
295         {144, 2, L_FIX}, // "sprmSCcolumns" sep.ccolM1 # of cols - 1 word
296         {145, 2, L_FIX}, // "sprmSDxaColumns" sep.dxaColumns dxa word
297         {146, 1, L_FIX}, // "sprmSFAutoPgn" sep.fAutoPgn obsolete byte
298         {147, 1, L_FIX}, // "sprmSNfcPgn" sep.nfcPgn nfc byte
299         {148, 2, L_FIX}, // "sprmSDyaPgn" sep.dyaPgn dya short
300         {149, 2, L_FIX}, // "sprmSDxaPgn" sep.dxaPgn dya short
301         {150, 1, L_FIX}, // "sprmSFPgnRestart" sep.fPgnRestart 0 or 1 byte
302         {151, 1, L_FIX}, // "sprmSFEndnote" sep.fEndnote 0 or 1 byte
303         {152, 1, L_FIX}, // "sprmSLnc" sep.lnc lnc byte
304         {153, 1, L_FIX}, // "sprmSGprfIhdt" sep.grpfIhdt grpfihdt
305         {154, 2, L_FIX}, // "sprmSNLnnMod" sep.nLnnMod non-neg int. word
306         {155, 2, L_FIX}, // "sprmSDxaLnn" sep.dxaLnn dxa word
307         {156, 2, L_FIX}, // "sprmSDyaHdrTop" sep.dyaHdrTop dya word
308         {157, 2, L_FIX}, // "sprmSDyaHdrBottom" sep.dyaHdrBottom dya word
309         {158, 1, L_FIX}, // "sprmSLBetween" sep.fLBetween 0 or 1 byte
310         {159, 1, L_FIX}, // "sprmSVjc" sep.vjc vjc byte
311         {160, 2, L_FIX}, // "sprmSLnnMin" sep.lnnMin lnn word
312         {161, 2, L_FIX}, // "sprmSPgnStart" sep.pgnStart pgn word
313         {162, 1, L_FIX}, // "sprmSBOrientation" sep.dmOrientPage dm byte
314         {163, 0, L_FIX}, // "?SprmSBCustomize 163"
315         {164, 2, L_FIX}, // "sprmSXaPage" sep.xaPage xa word
316         {165, 2, L_FIX}, // "sprmSYaPage" sep.yaPage ya word
317         {166, 2, L_FIX}, // "sprmSDxaLeft" sep.dxaLeft dxa word
318         {167, 2, L_FIX}, // "sprmSDxaRight" sep.dxaRight dxa word
319         {168, 2, L_FIX}, // "sprmSDyaTop" sep.dyaTop dya word
320         {169, 2, L_FIX}, // "sprmSDyaBottom" sep.dyaBottom dya word
321         {170, 2, L_FIX}, // "sprmSDzaGutter" sep.dzaGutter dza word
322         {171, 2, L_FIX}, // "sprmSDMPaperReq" sep.dmPaperReq dm word
323         {179, 0, L_VAR}, // rtl property ?
324         {181, 0, L_VAR}, // rtl property ?
325         {182, 2, L_FIX}, // "sprmTJc" tap.jc jc (low order byte is significant)
326         {183, 2, L_FIX}, // "sprmTDxaLeft" tap.rgdxaCenter dxa word
327         {184, 2, L_FIX}, // "sprmTDxaGapHalf" tap.dxaGapHalf, tap.rgdxaCenter
328         {185, 1, L_FIX}, // "sprmTFCantSplit" tap.fCantSplit 1 or 0 byte
329         {186, 1, L_FIX}, // "sprmTTableHeader" tap.fTableHeader 1 or 0 byte
330         {187,12, L_FIX}, // "sprmTTableBorders" tap.rgbrcTable complex 12 bytes
331         {188, 0, L_VAR}, // "sprmTDefTable10" tap.rgdxaCenter, tap.rgtc complex
332         {189, 2, L_FIX}, // "sprmTDyaRowHeight" tap.dyaRowHeight dya word
333         {190, 0, L_VAR2},// "sprmTDefTable" tap.rgtc complex
334         {191, 1, L_VAR}, // "sprmTDefTableShd" tap.rgshd complex
335         {192, 4, L_FIX}, // "sprmTTlp" tap.tlp TLP 4 bytes
336         {193, 5, L_FIX}, // "sprmTSetBrc" tap.rgtc[].rgbrc complex 5 bytes
337         {194, 4, L_FIX}, // "sprmTInsert" tap.rgdxaCenter,tap.rgtc complex
338         {195, 2, L_FIX}, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc complex
339         {196, 4, L_FIX}, // "sprmTDxaCol" tap.rgdxaCenter complex
340         {197, 2, L_FIX}, // "sprmTMerge" tap.fFirstMerged, tap.fMerged complex
341         {198, 2, L_FIX}, // "sprmTSplit" tap.fFirstMerged, tap.fMerged complex
342         {199, 5, L_FIX}, // "sprmTSetBrc10" tap.rgtc[].rgbrc complex 5 bytes
343         {200, 4, L_FIX}  // "sprmTSetShd", tap.rgshd complex 4 bytes
344     };
345 
346     static wwSprmSearcher aSprmSrch(aSprms, sizeof(aSprms) / sizeof(aSprms[0]));
347     return &aSprmSrch;
348 };
349 
GetWW8SprmSearcher()350 const wwSprmSearcher *wwSprmParser::GetWW8SprmSearcher()
351 {
352     //double lock me
353     //WW8+ Sprms
354     static SprmInfo aSprms[] =
355     {
356         {     0, 0, L_FIX}, // "Default-sprm"/ wird uebersprungen
357         {0x4600, 2, L_FIX}, // "sprmPIstd" pap.istd;istd (style code);short;
358         {0xC601, 0, L_VAR}, // "sprmPIstdPermute" pap.istd;permutation vector
359         {0x2602, 1, L_FIX}, // "sprmPIncLvl" pap.istd, pap.lvl;difference
360                             // between istd of base PAP and istd of PAP to be
361                             // produced
362         {0x2403, 1, L_FIX}, // "sprmPJc" pap.jc;jc (justification);byte;
363         {0x2404, 1, L_FIX}, // "sprmPFSideBySide" pap.fSideBySide;0 or 1;byte;
364         {0x2405, 1, L_FIX}, // "sprmPFKeep" pap.fKeep;0 or 1;byte;
365         {0x2406, 1, L_FIX}, // "sprmPFKeepFollow" pap.fKeepFollow;0 or 1;byte;
366         {0x2407, 1, L_FIX}, // "sprmPFPageBreakBefore" pap.fPageBreakBefore;
367                             // 0 or 1
368         {0x2408, 1, L_FIX}, // "sprmPBrcl" pap.brcl;brcl;byte;
369         {0x2409, 1, L_FIX}, // "sprmPBrcp" pap.brcp;brcp;byte;
370         {0x260A, 1, L_FIX}, // "sprmPIlvl" pap.ilvl;ilvl;byte;
371         {0x460B, 2, L_FIX}, // "sprmPIlfo" pap.ilfo;ilfo (list index) ;short;
372         {0x240C, 1, L_FIX}, // "sprmPFNoLineNumb" pap.fNoLnn;0 or 1;byte;
373         {0xC60D, 0, L_VAR}, // "sprmPChgTabsPapx" pap.itbdMac, pap.rgdxaTab,
374                             // pap.rgtbd;complex
375         {0x840E, 2, L_FIX}, // "sprmPDxaRight" pap.dxaRight;dxa;word;
376         {0x840F, 2, L_FIX}, // "sprmPDxaLeft" pap.dxaLeft;dxa;word;
377         {0x4610, 2, L_FIX}, // "sprmPNest" pap.dxaLeft;dxa
378         {0x8411, 2, L_FIX}, // "sprmPDxaLeft1" pap.dxaLeft1;dxa;word;
379         {0x6412, 4, L_FIX}, // "sprmPDyaLine" pap.lspd;an LSPD, a long word
380                             // structure consisting of a short of dyaLine
381                             // followed by a short of fMultLinespace
382         {0xA413, 2, L_FIX}, // "sprmPDyaBefore" pap.dyaBefore;dya;word;
383         {0xA414, 2, L_FIX}, // "sprmPDyaAfter" pap.dyaAfter;dya;word;
384         {0xC615, 0, L_VAR}, // "sprmPChgTabs" pap.itbdMac, pap.rgdxaTab,
385                             // pap.rgtbd;complex
386         {0x2416, 1, L_FIX}, // "sprmPFInTable" pap.fInTable;0 or 1;byte;
387         {0x2417, 1, L_FIX}, // "sprmPFTtp" pap.fTtp;0 or 1;byte;
388         {0x8418, 2, L_FIX}, // "sprmPDxaAbs" pap.dxaAbs;dxa;word;
389         {0x8419, 2, L_FIX}, // "sprmPDyaAbs" pap.dyaAbs;dya;word;
390         {0x841A, 2, L_FIX}, // "sprmPDxaWidth" pap.dxaWidth;dxa;word;
391         {0x261B, 1, L_FIX}, // "sprmPPc" pap.pcHorz, pap.pcVert;complex
392         {0x461C, 2, L_FIX}, // "sprmPBrcTop10" pap.brcTop;BRC10;word;
393         {0x461D, 2, L_FIX}, // "sprmPBrcLeft10" pap.brcLeft;BRC10;word;
394         {0x461E, 2, L_FIX}, // "sprmPBrcBottom10" pap.brcBottom;BRC10;word;
395         {0x461F, 2, L_FIX}, // "sprmPBrcRight10" pap.brcRight;BRC10;word;
396         {0x4620, 2, L_FIX}, // "sprmPBrcBetween10" pap.brcBetween;BRC10;word;
397         {0x4621, 2, L_FIX}, // "sprmPBrcBar10" pap.brcBar;BRC10;word;
398         {0x4622, 2, L_FIX}, // "sprmPDxaFromText10" pap.dxaFromText;dxa;word;
399         {0x2423, 1, L_FIX}, // "sprmPWr" pap.wr;wr
400         {0x6424, 4, L_FIX}, // "sprmPBrcTop" pap.brcTop;BRC;long;
401         {0x6425, 4, L_FIX}, // "sprmPBrcLeft" pap.brcLeft;BRC;long;
402         {0x6426, 4, L_FIX}, // "sprmPBrcBottom" pap.brcBottom;BRC;long;
403         {0x6427, 4, L_FIX}, // "sprmPBrcRight" pap.brcRight;BRC;long;
404         {0x6428, 4, L_FIX}, // "sprmPBrcBetween" pap.brcBetween;BRC;long;
405         {0x6629, 4, L_FIX}, // "sprmPBrcBar" pap.brcBar;BRC;long;
406         {0x242A, 1, L_FIX}, // "sprmPFNoAutoHyph" pap.fNoAutoHyph;0 or 1;byte;
407         {0x442B, 2, L_FIX}, // "sprmPWHeightAbs" pap.wHeightAbs;w;word;
408         {0x442C, 2, L_FIX}, // "sprmPDcs" pap.dcs;DCS;short;
409         {0x442D, 2, L_FIX}, // "sprmPShd" pap.shd;SHD;word;
410         {0x842E, 2, L_FIX}, // "sprmPDyaFromText" pap.dyaFromText;dya;word;
411         {0x842F, 2, L_FIX}, // "sprmPDxaFromText" pap.dxaFromText;dxa;word;
412         {0x2430, 1, L_FIX}, // "sprmPFLocked" pap.fLocked;0 or 1;byte;
413         {0x2431, 1, L_FIX}, // "sprmPFWidowControl" pap.fWidowControl;0 or 1
414         {0xC632, 0, L_VAR}, // "sprmPRuler" ;;variable length;
415         {0x2433, 1, L_FIX}, // "sprmPFKinsoku" pap.fKinsoku;0 or 1;byte;
416         {0x2434, 1, L_FIX}, // "sprmPFWordWrap" pap.fWordWrap;0 or 1;byte;
417         {0x2435, 1, L_FIX}, // "sprmPFOverflowPunct" pap.fOverflowPunct;0 or 1
418         {0x2436, 1, L_FIX}, // "sprmPFTopLinePunct" pap.fTopLinePunct;0 or 1
419         {0x2437, 1, L_FIX}, // "sprmPFAutoSpaceDE" pap.fAutoSpaceDE;0 or 1
420         {0x2438, 1, L_FIX}, // "sprmPFAutoSpaceDN" pap.fAutoSpaceDN;0 or 1
421         {0x4439, 2, L_FIX}, // "sprmPWAlignFont" pap.wAlignFont;iFa
422         {0x443A, 2, L_FIX}, // "sprmPFrameTextFlow" pap.fVertical pap.fBackward
423                             // pap.fRotateFont;complex
424         {0x243B, 1, L_FIX}, // "sprmPISnapBaseLine" obsolete: not applicable in
425                             // Word97 and later versions;
426         {0xC63E, 0, L_VAR}, // "sprmPAnld" pap.anld;;variable length;
427         {0xC63F, 0, L_VAR}, // "sprmPPropRMark" pap.fPropRMark;complex
428         {0x2640, 1, L_FIX}, // "sprmPOutLvl" pap.lvl;has no effect if pap.istd
429                             // is < 1 or is > 9
430         {0x2441, 1, L_FIX}, // "sprmPFBiDi" ;;byte;
431         {0x2443, 1, L_FIX}, // "sprmPFNumRMIns" pap.fNumRMIns;1 or 0;bit;
432         {0x2444, 1, L_FIX}, // "sprmPCrLf" ;;byte;
433         {0xC645, 0, L_VAR}, // "sprmPNumRM" pap.numrm;;variable length;
434         {0x6645, 4, L_FIX}, // "sprmPHugePapx" fc in the data stream to locate
435                             // the huge grpprl
436         {0x6646, 4, L_FIX}, // "sprmPHugePapx" fc in the data stream to locate
437                             // the huge grpprl
438         {0x2447, 1, L_FIX}, // "sprmPFUsePgsuSettings" pap.fUsePgsuSettings;
439                             // 1 or 0
440         {0x2448, 1, L_FIX}, // "sprmPFAdjustRight" pap.fAdjustRight;1 or 0;byte;
441         {0x0800, 1, L_FIX}, // "sprmCFRMarkDel" chp.fRMarkDel;1 or 0;bit;
442         {0x0801, 1, L_FIX}, // "sprmCFRMark" chp.fRMark;1 or 0;bit;
443         {0x0802, 1, L_FIX}, // "sprmCFFldVanish" chp.fFldVanish;1 or 0;bit;
444         {0x6A03, 4, L_FIX}, // "sprmCPicLocation" chp.fcPic and chp.fSpec;
445         {0x4804, 2, L_FIX}, // "sprmCIbstRMark" chp.ibstRMark;index into
446                             // sttbRMark
447         {0x6805, 4, L_FIX}, // "sprmCDttmRMark" chp.dttmRMark;DTTM;long;
448         {0x0806, 1, L_FIX}, // "sprmCFData" chp.fData;1 or 0;bit;
449         {0x4807, 2, L_FIX}, // "sprmCIdslRMark" chp.idslRMReason;an index to a
450                             // table of strings defined in Word 6.0
451                             // executables;short;
452         {0xEA08, 1, L_FIX}, // "sprmCChs" chp.fChsDiff and chp.chse;
453         {0x6A09, 4, L_FIX}, // "sprmCSymbol" chp.fSpec, chp.xchSym and
454                             // chp.ftcSym
455         {0x080A, 1, L_FIX}, // "sprmCFOle2" chp.fOle2;1 or 0;bit;
456         {0x480B, 0, L_FIX}, // "sprmCIdCharType" obsolete: not applicable in
457                             // Word97 and later versions;;;
458         {0x2A0C, 1, L_FIX}, // "sprmCHighlight" chp.fHighlight,
459                             // chp.icoHighlight;ico (fHighlight is set to 1 iff
460                             // ico is not 0)
461         {0x680E, 4, L_FIX}, // "sprmCObjLocation" chp.fcObj;FC;long;
462         {0x2A10, 0, L_FIX}, // "sprmCFFtcAsciSymb" ;;;
463         {0x4A30, 2, L_FIX}, // "sprmCIstd" chp.istd;istd, see stylesheet def
464         {0xCA31, 0, L_VAR}, // "sprmCIstdPermute" chp.istd;permutation vector
465         {0x2A32, 0, L_VAR}, // "sprmCDefault" whole CHP;none;variable length;
466         {0x2A33, 0, L_FIX}, // "sprmCPlain" whole CHP;none;0;
467         {0x2A34, 1, L_FIX}, // "sprmCKcd" ;;;
468         {0x0835, 1, L_FIX}, // "sprmCFBold" chp.fBold;0,1, 128, or 129
469         {0x0836, 1, L_FIX}, // "sprmCFItalic" chp.fItalic;0,1, 128, or 129
470         {0x0837, 1, L_FIX}, // "sprmCFStrike" chp.fStrike;0,1, 128, or 129
471         {0x0838, 1, L_FIX}, // "sprmCFOutline" chp.fOutline;0,1, 128, or 129
472         {0x0839, 1, L_FIX}, // "sprmCFShadow" chp.fShadow;0,1, 128, or 129
473         {0x083A, 1, L_FIX}, // "sprmCFSmallCaps" chp.fSmallCaps;0,1, 128, or 129
474         {0x083B, 1, L_FIX}, // "sprmCFCaps" chp.fCaps;0,1, 128, or 129
475         {0x083C, 1, L_FIX}, // "sprmCFVanish" chp.fVanish;0,1, 128, or 129
476         {0x4A3D, 2, L_FIX}, // "sprmCFtcDefault" ;ftc, only used internally
477         {0x2A3E, 1, L_FIX}, // "sprmCKul" chp.kul;kul;byte;
478         {0xEA3F, 3, L_FIX}, // "sprmCSizePos" chp.hps, chp.hpsPos;3 bytes;
479         {0x8840, 2, L_FIX}, // "sprmCDxaSpace" chp.dxaSpace;dxa;word;
480         {0x4A41, 2, L_FIX}, // "sprmCLid" ;only used internally never stored
481         {0x2A42, 1, L_FIX}, // "sprmCIco" chp.ico;ico;byte;
482         {0x4A43, 2, L_FIX}, // "sprmCHps" chp.hps;hps
483         {0x2A44, 1, L_FIX}, // "sprmCHpsInc" chp.hps;
484         {0x4845, 2, L_FIX}, // "sprmCHpsPos" chp.hpsPos;hps;short; (doc wrong)
485         {0x2A46, 1, L_FIX}, // "sprmCHpsPosAdj" chp.hpsPos;hps
486         {0xCA47, 0, L_VAR}, // "sprmCMajority" chp.fBold, chp.fItalic,
487                             // chp.fSmallCaps, chp.fVanish, chp.fStrike,
488                             // chp.fCaps, chp.rgftc, chp.hps, chp.hpsPos,
489                             // chp.kul, chp.dxaSpace, chp.ico,
490                             // chp.rglid;complex;variable length, length byte
491                             // plus size of following grpprl;
492         {0x2A48, 1, L_FIX}, // "sprmCIss" chp.iss;iss;byte;
493         {0xCA49, 0, L_VAR}, // "sprmCHpsNew50" chp.hps;hps;variable width
494         {0xCA4A, 0, L_VAR}, // "sprmCHpsInc1" chp.hps;complex
495         {0x484B, 2, L_FIX}, // "sprmCHpsKern" chp.hpsKern;hps;short;
496         {0xCA4C, 2, L_FIX}, // "sprmCMajority50" chp.fBold, chp.fItalic,
497                             // chp.fSmallCaps, chp.fVanish, chp.fStrike,
498                             // chp.fCaps, chp.ftc, chp.hps, chp.hpsPos, chp.kul,
499                             // chp.dxaSpace, chp.ico,;complex
500         {0x4A4D, 2, L_FIX}, // "sprmCHpsMul" chp.hps;percentage to grow hps
501         {0x484E, 2, L_FIX}, // "sprmCYsri" chp.ysri;ysri;short;
502         {0x4A4F, 2, L_FIX}, // "sprmCRgFtc0" chp.rgftc[0];ftc for ASCII text
503         {0x4A50, 2, L_FIX}, // "sprmCRgFtc1" chp.rgftc[1];ftc for Far East text
504         {0x4A51, 2, L_FIX}, // "sprmCRgFtc2" chp.rgftc[2];ftc for non-FE text
505         {0x4852, 2, L_FIX}, // "sprmCCharScale"
506         {0x2A53, 1, L_FIX}, // "sprmCFDStrike" chp.fDStrike;;byte;
507         {0x0854, 1, L_FIX}, // "sprmCFImprint" chp.fImprint;1 or 0;bit;
508         {0x0855, 1, L_FIX}, // "sprmCFSpec" chp.fSpec ;1 or 0;bit;
509         {0x0856, 1, L_FIX}, // "sprmCFObj" chp.fObj;1 or 0;bit;
510         {0xCA57, 0, L_VAR}, // "sprmCPropRMark" chp.fPropRMark,
511                             // chp.ibstPropRMark, chp.dttmPropRMark;Complex
512         {0x0858, 1, L_FIX}, // "sprmCFEmboss" chp.fEmboss;1 or 0;bit;
513         {0x2859, 1, L_FIX}, // "sprmCSfxText" chp.sfxtText;text animation;byte;
514         {0x085A, 1, L_FIX}, // "sprmCFBiDi" ;;;
515         {0x085B, 1, L_FIX}, // "sprmCFDiacColor" ;;;
516         {0x085C, 1, L_FIX}, // "sprmCFBoldBi" ;;;
517         {0x085D, 1, L_FIX}, // "sprmCFItalicBi" ;;;
518         {0x4A5E, 2, L_FIX},
519         {0x485F, 2, L_FIX}, // "sprmCLidBi" ;;;
520         {0x4A60, 1, L_FIX}, // "sprmCIcoBi" ;;;
521         {0x4A61, 2, L_FIX}, // "sprmCHpsBi" ;;;
522         {0xCA62, 0, L_VAR}, // "sprmCDispFldRMark" chp.fDispFldRMark,
523                             // chp.ibstDispFldRMark, chp.dttmDispFldRMark ;
524         {0x4863, 2, L_FIX}, // "sprmCIbstRMarkDel" chp.ibstRMarkDel;index into
525                             // sttbRMark;short;
526         {0x6864, 4, L_FIX}, // "sprmCDttmRMarkDel" chp.dttmRMarkDel;DTTM;long;
527         {0x6865, 4, L_FIX}, // "sprmCBrc" chp.brc;BRC;long;
528         {0x4866, 2, L_FIX}, // "sprmCShd" chp.shd;SHD;short;
529         {0x4867, 2, L_FIX}, // "sprmCIdslRMarkDel" chp.idslRMReasonDel;an index
530                             // to a table of strings defined in Word 6.0
531                             // executables;short;
532         {0x0868, 1, L_FIX}, // "sprmCFUsePgsuSettings"
533                             // chp.fUsePgsuSettings;1 or 0
534         {0x486B, 2, L_FIX}, // "sprmCCpg" ;;word;
535         {0x486D, 2, L_FIX}, // "sprmCRgLid0" chp.rglid[0];LID: for non-FE text
536         {0x486E, 2, L_FIX}, // "sprmCRgLid1" chp.rglid[1];LID: for Far East text
537         {0x286F, 1, L_FIX}, // "sprmCIdctHint" chp.idctHint;IDCT:
538         {0x2E00, 1, L_FIX}, // "sprmPicBrcl" pic.brcl;brcl (see PIC definition)
539         {0xCE01, 0, L_VAR}, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
540                             // pic.dyaCropTop pic.dxaCropRight,
541                             // pic.dyaCropBottom;Complex
542         {0x6C02, 4, L_FIX}, // "sprmPicBrcTop" pic.brcTop;BRC;long;
543         {0x6C03, 4, L_FIX}, // "sprmPicBrcLeft" pic.brcLeft;BRC;long;
544         {0x6C04, 4, L_FIX}, // "sprmPicBrcBottom" pic.brcBottom;BRC;long;
545         {0x6C05, 4, L_FIX}, // "sprmPicBrcRight" pic.brcRight;BRC;long;
546         {0x3000, 1, L_FIX}, // "sprmScnsPgn" sep.cnsPgn;cns;byte;
547         {0x3001, 1, L_FIX}, // "sprmSiHeadingPgn" sep.iHeadingPgn;heading number
548                             // level;byte;
549         {0xD202, 0, L_VAR}, // "sprmSOlstAnm" sep.olstAnm;OLST;variable length;
550         {0xF203, 3, L_FIX}, // "sprmSDxaColWidth" sep.rgdxaColWidthSpacing;
551         {0xF204, 3, L_FIX}, // "sprmSDxaColSpacing" sep.rgdxaColWidthSpacing;
552                             // complex
553         {0x3005, 1, L_FIX}, // "sprmSFEvenlySpaced" sep.fEvenlySpaced;1 or 0
554         {0x3006, 1, L_FIX}, // "sprmSFProtected" sep.fUnlocked;1 or 0;byte;
555         {0x5007, 2, L_FIX}, // "sprmSDmBinFirst" sep.dmBinFirst;;word;
556         {0x5008, 2, L_FIX}, // "sprmSDmBinOther" sep.dmBinOther;;word;
557         {0x3009, 1, L_FIX}, // "sprmSBkc" sep.bkc;bkc;byte;
558         {0x300A, 1, L_FIX}, // "sprmSFTitlePage" sep.fTitlePage;0 or 1;byte;
559         {0x500B, 2, L_FIX}, // "sprmSCcolumns" sep.ccolM1;# of cols - 1;word;
560         {0x900C, 2, L_FIX}, // "sprmSDxaColumns" sep.dxaColumns;dxa;word;
561         {0x300D, 1, L_FIX}, // "sprmSFAutoPgn" sep.fAutoPgn;obsolete;byte;
562         {0x300E, 1, L_FIX}, // "sprmSNfcPgn" sep.nfcPgn;nfc;byte;
563         {0xB00F, 2, L_FIX}, // "sprmSDyaPgn" sep.dyaPgn;dya;short;
564         {0xB010, 2, L_FIX}, // "sprmSDxaPgn" sep.dxaPgn;dya;short;
565         {0x3011, 1, L_FIX}, // "sprmSFPgnRestart" sep.fPgnRestart;0 or 1;byte;
566         {0x3012, 1, L_FIX}, // "sprmSFEndnote" sep.fEndnote;0 or 1;byte;
567         {0x3013, 1, L_FIX}, // "sprmSLnc" sep.lnc;lnc;byte;
568         {0x3014, 1, L_FIX}, // "sprmSGprfIhdt" sep.grpfIhdt;grpfihdt
569         {0x5015, 2, L_FIX}, // "sprmSNLnnMod" sep.nLnnMod;non-neg int.;word;
570         {0x9016, 2, L_FIX}, // "sprmSDxaLnn" sep.dxaLnn;dxa;word;
571         {0xB017, 2, L_FIX}, // "sprmSDyaHdrTop" sep.dyaHdrTop;dya;word;
572         {0xB018, 2, L_FIX}, // "sprmSDyaHdrBottom" sep.dyaHdrBottom;dya;word;
573         {0x3019, 1, L_FIX}, // "sprmSLBetween" sep.fLBetween;0 or 1;byte;
574         {0x301A, 1, L_FIX}, // "sprmSVjc" sep.vjc;vjc;byte;
575         {0x501B, 2, L_FIX}, // "sprmSLnnMin" sep.lnnMin;lnn;word;
576         {0x501C, 2, L_FIX}, // "sprmSPgnStart" sep.pgnStart;pgn;word;
577         {0x301D, 1, L_FIX}, // "sprmSBOrientation" sep.dmOrientPage;dm;byte;
578         {0x301E, 1, L_FIX}, // "sprmSBCustomize" ;;;
579         {0xB01F, 2, L_FIX}, // "sprmSXaPage" sep.xaPage;xa;word;
580         {0xB020, 2, L_FIX}, // "sprmSYaPage" sep.yaPage;ya;word;
581         {0xB021, 2, L_FIX}, // "sprmSDxaLeft" sep.dxaLeft;dxa;word;
582         {0xB022, 2, L_FIX}, // "sprmSDxaRight" sep.dxaRight;dxa;word;
583         {0x9023, 2, L_FIX}, // "sprmSDyaTop" sep.dyaTop;dya;word;
584         {0x9024, 2, L_FIX}, // "sprmSDyaBottom" sep.dyaBottom;dya;word;
585         {0xB025, 2, L_FIX}, // "sprmSDzaGutter" sep.dzaGutter;dza;word;
586         {0x5026, 2, L_FIX}, // "sprmSDmPaperReq" sep.dmPaperReq;dm;word;
587         {0xD227, 0, L_VAR}, // "sprmSPropRMark" sep.fPropRMark,
588                             // sep.ibstPropRMark, sep.dttmPropRMark ;complex
589         {0x3228, 1, L_FIX}, // "sprmSFBiDi" ;;;
590         {0x3229, 1, L_FIX}, // "sprmSFFacingCol" ;;;
591         {0x322A, 1, L_FIX}, // "sprmSFRTLGutter", set to one if gutter is on
592                             // right
593         {0x702B, 4, L_FIX}, // "sprmSBrcTop" sep.brcTop;BRC;long;
594         {0x702C, 4, L_FIX}, // "sprmSBrcLeft" sep.brcLeft;BRC;long;
595         {0x702D, 4, L_FIX}, // "sprmSBrcBottom" sep.brcBottom;BRC;long;
596         {0x702E, 4, L_FIX}, // "sprmSBrcRight" sep.brcRight;BRC;long;
597         {0x522F, 2, L_FIX}, // "sprmSPgbProp" sep.pgbProp;;word;
598         {0x7030, 4, L_FIX}, // "sprmSDxtCharSpace" sep.dxtCharSpace;dxt;long;
599         {0x9031, 2, L_FIX}, // "sprmSDyaLinePitch"
600                             // sep.dyaLinePitch;dya; WRONG:long; RIGHT:short; !
601         {0x5032, 2, L_FIX}, // "sprmSClm" ;;;
602         {0x5033, 2, L_FIX}, // "sprmSTextFlow" sep.wTextFlow;complex
603         {0x5400, 2, L_FIX}, // "sprmTJc" tap.jc;jc;word (low order byte is
604                             // significant);
605         {0x9601, 2, L_FIX}, // "sprmTDxaLeft" tap.rgdxaCenter
606         {0x9602, 2, L_FIX}, // "sprmTDxaGapHalf" tap.dxaGapHalf,
607                             // tap.rgdxaCenter
608         {0x3403, 1, L_FIX}, // "sprmTFCantSplit" tap.fCantSplit;1 or 0;byte;
609         {0x3404, 1, L_FIX}, // "sprmTTableHeader" tap.fTableHeader;1 or 0;byte;
610         {0xD605, 0, L_VAR}, // "sprmTTableBorders" tap.rgbrcTable;complex
611         {0xD606, 0, L_VAR}, // "sprmTDefTable10" tap.rgdxaCenter,
612                             // tap.rgtc;complex
613         {0x9407, 2, L_FIX}, // "sprmTDyaRowHeight" tap.dyaRowHeight;dya;word;
614         {0xD608, 0, L_VAR}, // "sprmTDefTable" tap.rgtc;complex
615         {0xD609, 0, L_VAR}, // "sprmTDefTableShd" tap.rgshd;complex
616         {0x740A, 4, L_FIX}, // "sprmTTlp" tap.tlp;TLP;4 bytes;
617         {0x560B, 1, L_FIX}, // "sprmTFBiDi" ;;;
618         {0x740C, 1, L_FIX}, // "sprmTHTMLProps" ;;;
619         {0xD620, 0, L_VAR}, // "sprmTSetBrc" tap.rgtc[].rgbrc;complex
620         {0x7621, 4, L_FIX}, // "sprmTInsert" tap.rgdxaCenter, tap.rgtc;complex
621         {0x5622, 2, L_FIX}, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc;complex
622         {0x7623, 4, L_FIX}, // "sprmTDxaCol" tap.rgdxaCenter;complex
623         {0x5624, 0, L_VAR}, // "sprmTMerge" tap.fFirstMerged, tap.fMerged;
624         {0x5625, 0, L_VAR}, // "sprmTSplit" tap.fFirstMerged, tap.fMerged;
625         {0xD626, 0, L_VAR}, // "sprmTSetBrc10" tap.rgtc[].rgbrc;complex
626         {0x7627, 0, L_VAR}, // "sprmTSetShd" tap.rgshd;complex
627         {0x7628, 0, L_VAR}, // "sprmTSetShdOdd" tap.rgshd;complex
628         {0x7629, 0, L_VAR}, // "sprmTTextFlow" tap.rgtc[].fVerticaltap,
629                             // rgtc[].fBackwardtap, rgtc[].fRotateFont;0 or 10
630                             // or 10 or 1;word;
631         {0xD62A, 1, L_FIX}, // "sprmTDiagLine" ;;;
632         {0xD62B, 0, L_VAR}, // "sprmTVertMerge" tap.rgtc[].vertMerge
633         {0xD62C, 0, L_VAR}, // "sprmTVertAlign" tap.rgtc[].vertAlign
634         {0xCA78, 0, L_VAR}, // undocumented "sprmCDoubleLine ?"
635         {0x6649, 4, L_FIX}, // undocumented
636         {0xF614, 3, L_FIX}, // undocumented
637         {0xD612, 0, L_VAR}, // undocumented, new background colours.
638         {0xD613, 0, L_VAR}, // undocumented
639         {0xD61A, 0, L_VAR}, // undocumented
640         {0xD61B, 0, L_VAR}, // undocumented
641         {0xD61C, 0, L_VAR}, // undocumented
642         {0xD61D, 0, L_VAR}, // undocumented
643         {0xD632, 0, L_VAR}, // undocumented
644         {0xD634, 0, L_VAR}, // undocumented
645         {0xD238, 0, L_VAR}, // undocumented sep
646         {0xC64E, 0, L_VAR}, // undocumented
647         {0xC64F, 0, L_VAR}, // undocumented
648         {0xC650, 0, L_VAR}, // undocumented
649         {0xC651, 0, L_VAR}, // undocumented
650         {0xF661, 3, L_FIX}, // undocumented
651         {0x4873, 2, L_FIX}, // undocumented
652         {0x4874, 2, L_FIX}, // undocumented
653         {0x6463, 4, L_FIX}, // undocumented
654         {0x2461, 1, L_FIX}, // undoc, must be asian version of "sprmPJc"
655         {0x845D, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaRight"
656         {0x845E, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaLeft"
657         {0x8460, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaLeft1"
658         {0x3615, 1, L_FIX}, // undocumented
659         {0x360D, 1, L_FIX}, // undocumented
660         {0x703A, 4, L_FIX}, // undocumented, sep, perhaps related to textgrids ?
661         {0x303B, 1, L_FIX}, // undocumented, sep
662         {0x244B, 1, L_FIX}, // undocumented, subtable "sprmPFInTable" equiv ?
663         {0x244C, 1, L_FIX}, // undocumented, subtable "sprmPFTtp" equiv ?
664         {0x940E, 2, L_FIX}, // undocumented
665         {0x940F, 2, L_FIX}, // undocumented
666         {0x9410, 2, L_FIX}, // undocumented
667         {0x6815, 4, L_FIX}, // undocumented
668         {0x6816, 4, L_FIX}, // undocumented
669         {0x6870, 4, L_FIX}, // undocumented, text colour
670         {0xC64D, 0, L_VAR}, // undocumented, para back colour
671         {0x6467, 4, L_FIX}, // undocumented
672         {0x646B, 4, L_FIX}, // undocumented
673         {0xF617, 3, L_FIX}, // undocumented
674         {0xD660, 0, L_VAR}, // undocumented, something to do with colour.
675         {0xD670, 0, L_VAR}, // undocumented, something to do with colour.
676         {0xCA71, 0, L_VAR}, // undocumented, text backcolour
677         {0x303C, 1, L_FIX}, // undocumented, sep
678         {0x245B, 1, L_FIX}, // undocumented, para autobefore
679         {0x245C, 1, L_FIX}  // undocumented, para autoafter
680     };
681 
682     static wwSprmSearcher aSprmSrch(aSprms, sizeof(aSprms) / sizeof(aSprms[0]));
683     return &aSprmSrch;
684 };
685 
wwSprmParser(int nVersion)686 wwSprmParser::wwSprmParser(int nVersion) : mnVersion(nVersion)
687 {
688     ASSERT((mnVersion >= 6 && mnVersion <= 8), "Impossible value for version");
689 
690     mnDelta = (8 > mnVersion) ? 0 : 1;
691 
692     if (mnVersion < 8)
693         mpKnownSprms = GetWW6SprmSearcher();
694     else
695         mpKnownSprms = GetWW8SprmSearcher();
696 }
697 
GetSprmInfo(sal_uInt16 nId) const698 SprmInfo wwSprmParser::GetSprmInfo(sal_uInt16 nId) const
699 {
700     // Find sprm
701     SprmInfo aSrch;
702     aSrch.nId = nId;
703     const SprmInfo* pFound = mpKnownSprms->search(aSrch);
704     if (pFound == 0)
705     {
706         ASSERT(mnVersion >= 8,
707            "Unknown ww6 sprm, dangerous, report to development");
708 
709         aSrch.nId = 0;
710         aSrch.nLen = 0;
711         //All the unknown ww7 sprms appear to be variable (which makes sense)
712         aSrch.nVari = L_VAR;
713 
714         if (mnVersion == 8) //We can recover perfectly in this case
715         {
716             aSrch.nVari = L_FIX;
717             switch (nId >> 13)
718             {
719                 case 0:
720                 case 1:
721                     aSrch.nLen = 1;
722                     break;
723                 case 2:
724                     aSrch.nLen = 2;
725                     break;
726                 case 3:
727                     aSrch.nLen = 4;
728                     break;
729                 case 4:
730                 case 5:
731                     aSrch.nLen = 2;
732                     break;
733                 case 6:
734                     aSrch.nLen = 0;
735                     aSrch.nVari =  L_VAR;
736                     break;
737                 case 7:
738                 default:
739                     aSrch.nLen = 3;
740                     break;
741             }
742         }
743 
744         pFound = &aSrch;
745     }
746     return *pFound;
747 }
748 
749 //-end
750 
Get_Byte(sal_uInt8 * & p)751 inline sal_uInt8 Get_Byte( sal_uInt8 *& p )
752 {
753     sal_uInt8 n = SVBT8ToByte( *(SVBT8*)p );
754     p += 1;
755     return n;
756 }
757 
Get_UShort(sal_uInt8 * & p)758 inline sal_uInt16 Get_UShort( sal_uInt8 *& p )
759 {
760     sal_uInt16 n = SVBT16ToShort( *(SVBT16*)p );
761     p += 2;
762     return n;
763 }
764 
Get_Short(sal_uInt8 * & p)765 inline short Get_Short( sal_uInt8 *& p )
766 {
767     return Get_UShort(p);
768 }
769 
Get_ULong(sal_uInt8 * & p)770 inline sal_uLong Get_ULong( sal_uInt8 *& p )
771 {
772     sal_uLong n = SVBT32ToUInt32( *(SVBT32*)p );
773     p += 4;
774     return n;
775 }
776 
Get_Long(sal_uInt8 * & p)777 inline long Get_Long( sal_uInt8 *& p )
778 {
779     return Get_ULong(p);
780 }
781 
WW8SprmIter(const sal_uInt8 * pSprms_,long nLen_,const wwSprmParser & rParser)782 WW8SprmIter::WW8SprmIter(const sal_uInt8* pSprms_, long nLen_,
783     const wwSprmParser &rParser)
784     :  mrSprmParser(rParser), pSprms( pSprms_), nRemLen( nLen_)
785 {
786     UpdateMyMembers();
787 }
788 
SetSprms(const sal_uInt8 * pSprms_,long nLen_)789 void WW8SprmIter::SetSprms(const sal_uInt8* pSprms_, long nLen_)
790 {
791     pSprms = pSprms_;
792     nRemLen = nLen_;
793     UpdateMyMembers();
794 }
795 
operator ++(int)796 const sal_uInt8* WW8SprmIter::operator ++( int )
797 {
798     if (nRemLen > 0)
799     {
800         pSprms += nAktSize;
801         nRemLen -= nAktSize;
802         UpdateMyMembers();
803     }
804     return pSprms;
805 }
806 
UpdateMyMembers()807 void WW8SprmIter::UpdateMyMembers()
808 {
809     if (pSprms && nRemLen > 0)
810     {
811         nAktId = mrSprmParser.GetSprmId(pSprms);
812         pAktParams = pSprms + mrSprmParser.DistanceToData(nAktId);
813         nAktSize = mrSprmParser.GetSprmSize(nAktId, pSprms);
814     }
815     else
816     {
817         nAktId = 0;
818         pAktParams = 0;
819         nAktSize = 0;
820         nRemLen = 0;
821     }
822 }
823 
FindSprm(sal_uInt16 nId)824 const sal_uInt8* WW8SprmIter::FindSprm(sal_uInt16 nId)
825 {
826     while(GetSprms())
827     {
828         if( GetAktId() == nId )
829             return GetAktParams();              // SPRM found!
830         operator ++(0);
831     }
832 
833     return 0;                                   // SPRM _not_ found
834 }
835 
836 //-----------------------------------------
837 //      temporaerer Test
838 //-----------------------------------------
839 // WW8PLCFx_PCDAttrs halten sich an WW8PLCF_Pcd fest und besitzen deshalb keine
840 // eigenen Iteratoren. Alle sich auf Iteratoren beziehenden Methoden
841 // sind deshalb Dummies.
842 
WW8PLCFx_PCDAttrs(sal_uInt8 nVersion,WW8PLCFx_PCD * pPLCFx_PCD,const WW8ScannerBase * pBase)843 WW8PLCFx_PCDAttrs::WW8PLCFx_PCDAttrs(sal_uInt8 nVersion, WW8PLCFx_PCD* pPLCFx_PCD,
844     const WW8ScannerBase* pBase)
845     : WW8PLCFx(nVersion, true), pPcdI(pPLCFx_PCD->GetPLCFIter()),
846     pPcd(pPLCFx_PCD), pGrpprls(pBase->pPieceGrpprls),
847     nGrpprls(pBase->nPieceGrpprls)
848 {
849 }
850 
GetIdx() const851 sal_uLong WW8PLCFx_PCDAttrs::GetIdx() const
852 {
853     return 0;
854 }
855 
SetIdx(sal_uLong)856 void WW8PLCFx_PCDAttrs::SetIdx( sal_uLong )
857 {
858 }
859 
SeekPos(WW8_CP)860 bool WW8PLCFx_PCDAttrs::SeekPos(WW8_CP )
861 {
862     return true;
863 }
864 
operator ++(int)865 WW8PLCFx& WW8PLCFx_PCDAttrs::operator ++( int )
866 {
867     return *this;
868 }
869 
Where()870 WW8_CP WW8PLCFx_PCDAttrs::Where()
871 {
872     return ( pPcd ) ? pPcd->Where() : LONG_MAX;
873 }
874 
GetSprms(WW8PLCFxDesc * p)875 void WW8PLCFx_PCDAttrs::GetSprms(WW8PLCFxDesc* p)
876 {
877     void* pData;
878 
879     p->bRealLineEnd = false;
880     if ( !pPcdI || !pPcdI->Get(p->nStartPos, p->nEndPos, pData) )
881     {
882         // PLCF fully processed
883         p->nStartPos = p->nEndPos = LONG_MAX;
884         p->pMemPos = 0;
885         p->nSprmsLen = 0;
886         return;
887     }
888 
889     sal_uInt16 nPrm = SVBT16ToShort( ( (WW8_PCD*)pData )->prm );
890     if ( nPrm & 1 )
891     {
892         // PRM Variant 2
893         sal_uInt16 nSprmIdx = nPrm >> 1;
894 
895         if( nSprmIdx >= nGrpprls )
896         {
897             // Invalid Index
898             p->nStartPos = p->nEndPos = LONG_MAX;
899             p->pMemPos = 0;
900             p->nSprmsLen = 0;
901             return;
902         }
903         const sal_uInt8* pSprms = pGrpprls[ nSprmIdx ];
904 
905         p->nSprmsLen = SVBT16ToShort( pSprms ); // Length
906         pSprms += 2;
907         p->pMemPos = pSprms;                    // Position
908     }
909     else
910     {
911         // PRM Variante 1:  Sprm wird direkt in Member-Var abgelegt
912         /*
913             Dies sind die Attr, die in der Piece-Table stehen, statt im Text !
914         */
915 
916         if(8 > GetVersion())
917         {
918             aShortSprm[0] = (sal_uInt8)( ( nPrm & 0xfe) >> 1 );
919             aShortSprm[1] = (sal_uInt8)(   nPrm         >> 8 );
920             p->nSprmsLen = ( nPrm ) ? 2 : 0;        // Laenge
921 
922             // store Postion of internal mini storage in Data Pointer
923             p->pMemPos = aShortSprm;
924         }
925         else
926         {
927             p->pMemPos = 0;
928             p->nSprmsLen = 0;
929             sal_uInt8 nSprmListIdx = (sal_uInt8)((nPrm & 0xfe) >> 1);
930             if( nSprmListIdx )
931             {
932                 // process Sprm Id Matching as explained in MS Doku
933                 //
934                 // ''Property Modifier(variant 1) (PRM)''
935                 // see file: s62f39.htm
936                 //
937                 // Since isprm is 7 bits, rgsprmPrm can hold 0x80 entries.
938                 static const sal_uInt16 aSprmId[0x80] =
939                 {
940                     // sprmNoop, sprmNoop, sprmNoop, sprmNoop
941                     0x0000,0x0000,0x0000,0x0000,
942                     // sprmPIncLvl, sprmPJc, sprmPFSideBySide, sprmPFKeep
943                     0x2402,0x2403,0x2404,0x2405,
944                     // sprmPFKeepFollow, sprmPFPageBreakBefore, sprmPBrcl,
945                     // sprmPBrcp
946                     0x2406,0x2407,0x2408,0x2409,
947                     // sprmPIlvl, sprmNoop, sprmPFNoLineNumb, sprmNoop
948                     0x260A,0x0000,0x240C,0x0000,
949                     // sprmNoop, sprmNoop, sprmNoop, sprmNoop
950                     0x0000,0x0000,0x0000,0x0000,
951                     // sprmNoop, sprmNoop, sprmNoop, sprmNoop
952                     0x0000,0x0000,0x0000,0x0000,
953                     // sprmPFInTable, sprmPFTtp, sprmNoop, sprmNoop
954                     0x2416,0x2417,0x0000,0x0000,
955                     // sprmNoop, sprmPPc,  sprmNoop, sprmNoop
956                     0x0000,0x261B,0x0000,0x0000,
957                     // sprmNoop, sprmNoop, sprmNoop, sprmNoop
958                     0x0000,0x0000,0x0000,0x0000,
959                     // sprmNoop, sprmPWr,  sprmNoop, sprmNoop
960                     0x0000,0x2423,0x0000,0x0000,
961                     // sprmNoop, sprmNoop, sprmNoop, sprmNoop
962                     0x0000,0x0000,0x0000,0x0000,
963                     // sprmPFNoAutoHyph, sprmNoop, sprmNoop, sprmNoop
964                     0x242A,0x0000,0x0000,0x0000,
965                     // sprmNoop, sprmNoop, sprmPFLocked, sprmPFWidowControl
966                     0x0000,0x0000,0x2430,0x2431,
967                     // sprmNoop, sprmPFKinsoku, sprmPFWordWrap,
968                     // sprmPFOverflowPunct
969                     0x0000,0x2433,0x2434,0x2435,
970                     // sprmPFTopLinePunct, sprmPFAutoSpaceDE,
971                     // sprmPFAutoSpaceDN, sprmNoop
972                     0x2436,0x2437,0x2438,0x0000,
973                     // sprmNoop, sprmPISnapBaseLine, sprmNoop, sprmNoop
974                     0x0000,0x243B,0x000,0x0000,
975                     // sprmNoop, sprmCFStrikeRM, sprmCFRMark, sprmCFFldVanish
976                     0x0000,0x0800,0x0801,0x0802,
977                     // sprmNoop, sprmNoop, sprmNoop, sprmCFData
978                     0x0000,0x0000,0x0000,0x0806,
979                     // sprmNoop, sprmNoop, sprmNoop, sprmCFOle2
980                     0x0000,0x0000,0x0000,0x080A,
981                     // sprmNoop, sprmCHighlight, sprmCFEmboss, sprmCSfxText
982                     0x0000,0x2A0C,0x0858,0x2859,
983                     // sprmNoop, sprmNoop, sprmNoop, sprmCPlain
984                     0x0000,0x0000,0x0000,0x2A33,
985                     // sprmNoop, sprmCFBold, sprmCFItalic, sprmCFStrike
986                     0x0000,0x0835,0x0836,0x0837,
987                     // sprmCFOutline, sprmCFShadow, sprmCFSmallCaps, sprmCFCaps,
988                     0x0838,0x0839,0x083a,0x083b,
989                     // sprmCFVanish, sprmNoop, sprmCKul, sprmNoop,
990                     0x083C,0x0000,0x2A3E,0x0000,
991                     // sprmNoop, sprmNoop, sprmCIco, sprmNoop,
992                     0x0000,0x0000,0x2A42,0x0000,
993                     // sprmCHpsInc, sprmNoop, sprmCHpsPosAdj, sprmNoop,
994                     0x2A44,0x0000,0x2A46,0x0000,
995                     // sprmCIss, sprmNoop, sprmNoop, sprmNoop,
996                     0x2A48,0x0000,0x0000,0x0000,
997                     // sprmNoop, sprmNoop, sprmNoop, sprmNoop,
998                     0x0000,0x0000,0x0000,0x0000,
999                     // sprmNoop, sprmNoop, sprmNoop, sprmCFDStrike,
1000                     0x0000,0x0000,0x0000,0x2A53,
1001                     // sprmCFImprint, sprmCFSpec, sprmCFObj, sprmPicBrcl,
1002                     0x0854,0x0855,0x0856,0x2E00,
1003                     // sprmPOutLvl, sprmPFBiDi, sprmNoop, sprmNoop,
1004                     0x2640,0x2441,0x0000,0x0000,
1005                     // sprmNoop, sprmNoop, sprmPPnbrRMarkNot
1006                     0x0000,0x0000,0x0000,0x0000
1007                 };
1008 
1009                 // find real Sprm Id:
1010                 sal_uInt16 nSprmId = aSprmId[ nSprmListIdx ];
1011 
1012                 if( nSprmId )
1013                 {
1014                     // move Sprm Id and Sprm Param to internal mini storage:
1015                     aShortSprm[0] = (sal_uInt8)( ( nSprmId & 0x00ff)      );
1016                     aShortSprm[1] = (sal_uInt8)( ( nSprmId & 0xff00) >> 8 );
1017                     aShortSprm[2] = (sal_uInt8)( nPrm >> 8 );
1018 
1019                     // store Sprm Length in member:
1020                     p->nSprmsLen = ( nPrm ) ? 3 : 0;
1021 
1022                     // store Postion of internal mini storage in Data Pointer
1023                     p->pMemPos = aShortSprm;
1024                 }
1025             }
1026         }
1027     }
1028 }
1029 
1030 //------------------------------------------------------------------------
1031 
WW8PLCFx_PCD(sal_uInt8 nVersion,WW8PLCFpcd * pPLCFpcd,WW8_CP nStartCp,bool bVer67P)1032 WW8PLCFx_PCD::WW8PLCFx_PCD(sal_uInt8 nVersion, WW8PLCFpcd* pPLCFpcd,
1033     WW8_CP nStartCp, bool bVer67P)
1034     : WW8PLCFx(nVersion, false), nClipStart(-1)
1035 {
1036     // eigenen Iterator konstruieren
1037     pPcdI = new WW8PLCFpcd_Iter(*pPLCFpcd, nStartCp);
1038     bVer67= bVer67P;
1039 }
1040 
~WW8PLCFx_PCD()1041 WW8PLCFx_PCD::~WW8PLCFx_PCD()
1042 {
1043     // pPcd-Dtor which in called from WW8ScannerBase
1044     delete pPcdI;
1045 }
1046 
GetIMax() const1047 sal_uLong WW8PLCFx_PCD::GetIMax() const
1048 {
1049     return pPcdI ? pPcdI->GetIMax() : 0;
1050 }
1051 
GetIdx() const1052 sal_uLong WW8PLCFx_PCD::GetIdx() const
1053 {
1054     return pPcdI ? pPcdI->GetIdx() : 0;
1055 }
1056 
SetIdx(sal_uLong nIdx)1057 void WW8PLCFx_PCD::SetIdx( sal_uLong nIdx )
1058 {
1059     if (pPcdI)
1060         pPcdI->SetIdx( nIdx );
1061 }
1062 
SeekPos(WW8_CP nCpPos)1063 bool WW8PLCFx_PCD::SeekPos(WW8_CP nCpPos)
1064 {
1065     return pPcdI ? pPcdI->SeekPos( nCpPos ) : false;
1066 }
1067 
Where()1068 WW8_CP WW8PLCFx_PCD::Where()
1069 {
1070     return pPcdI ? pPcdI->Where() : LONG_MAX;
1071 }
1072 
GetNoSprms(long & rStart,long & rEnd,long & rLen)1073 long WW8PLCFx_PCD::GetNoSprms( long& rStart, long& rEnd, long& rLen )
1074 {
1075     void* pData;
1076     rLen = 0;
1077 
1078     if ( !pPcdI || !pPcdI->Get(rStart, rEnd, pData) )
1079     {
1080         rStart = rEnd = LONG_MAX;
1081         return -1;
1082     }
1083     return pPcdI->GetIdx();
1084 }
1085 
operator ++(int)1086 WW8PLCFx& WW8PLCFx_PCD::operator ++( int )
1087 {
1088     if (pPcdI)
1089         (*pPcdI)++;
1090     else
1091         ASSERT( !this, "pPcdI fehlt");
1092     return *this;
1093 }
1094 
AktPieceStartCp2Fc(WW8_CP nCp)1095 WW8_FC WW8PLCFx_PCD::AktPieceStartCp2Fc( WW8_CP nCp )
1096 {
1097     WW8_CP nCpStart, nCpEnd;
1098     void* pData;
1099 
1100     if ( !pPcdI->Get(nCpStart, nCpEnd, pData) )
1101     {
1102         ASSERT( !this, "AktPieceStartCp2Fc() with false Cp found (1)" );
1103         return LONG_MAX;
1104     }
1105 
1106     ASSERT( nCp >= nCpStart && nCp < nCpEnd,
1107         "AktPieceCp2Fc() with false Cp found (2)" );
1108 
1109     if( nCp < nCpStart )
1110         nCp = nCpStart;
1111     if( nCp >= nCpEnd )
1112         nCp = nCpEnd - 1;
1113 
1114     bool bIsUnicode = false;
1115     WW8_FC nFC = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
1116     if( !bVer67 )
1117         nFC = WW8PLCFx_PCD::TransformPieceAddress( nFC, bIsUnicode );
1118 
1119     return nFC + (nCp - nCpStart) * (bIsUnicode ? 2 : 1);
1120 }
1121 
1122 
AktPieceFc2Cp(long & rStartPos,long & rEndPos,const WW8ScannerBase * pSBase)1123 void WW8PLCFx_PCD::AktPieceFc2Cp( long& rStartPos, long& rEndPos,
1124     const WW8ScannerBase *pSBase )
1125 {
1126     //No point going anywhere with this
1127     if ((rStartPos == LONG_MAX) && (rEndPos == LONG_MAX))
1128         return;
1129 
1130     rStartPos = pSBase->WW8Fc2Cp( rStartPos );
1131     rEndPos = pSBase->WW8Fc2Cp( rEndPos );
1132 }
1133 
AktPieceStartFc2Cp(WW8_FC nStartPos)1134 WW8_CP WW8PLCFx_PCD::AktPieceStartFc2Cp( WW8_FC nStartPos )
1135 {
1136     WW8_CP nCpStart, nCpEnd;
1137     void* pData;
1138     if ( !pPcdI->Get( nCpStart, nCpEnd, pData ) )
1139     {
1140         ASSERT( !this, "AktPieceStartFc2Cp() - Fehler" );
1141         return LONG_MAX;
1142     }
1143     bool bIsUnicode = false;
1144     sal_Int32 nFcStart  = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
1145     if( !bVer67 )
1146         nFcStart = WW8PLCFx_PCD::TransformPieceAddress( nFcStart, bIsUnicode );
1147 
1148     sal_Int32 nUnicodeFactor = bIsUnicode ? 2 : 1;
1149 
1150     if( nStartPos < nFcStart )
1151         nStartPos = nFcStart;
1152 
1153     if( nStartPos >= nFcStart + (nCpEnd - nCpStart)     * nUnicodeFactor )
1154         nStartPos  = nFcStart + (nCpEnd - nCpStart - 1) * nUnicodeFactor;
1155 
1156     return nCpStart + (nStartPos - nFcStart) / nUnicodeFactor;
1157 }
1158 
1159 //-----------------------------------------
1160 //      Hilfsroutinen fuer alle
1161 //-----------------------------------------
1162 
WW8DTTM2DateTime(long lDTTM)1163 DateTime WW8ScannerBase::WW8DTTM2DateTime(long lDTTM)
1164 {
1165     /*
1166     mint    short   :6  0000003F    minutes (0-59)
1167     hr      short   :5  000007C0    hours (0-23)
1168     dom     short   :5  0000F800    days of month (1-31)
1169     mon     short   :4  000F0000    months (1-12)
1170     yr      short   :9  1FF00000    years (1900-2411)-1900
1171     wdy     short   :3  E0000000    weekday(Sunday=0
1172                                             Monday=1
1173     ( wdy can be ignored )                  Tuesday=2
1174                                             Wednesday=3
1175                                             Thursday=4
1176                                             Friday=5
1177                                             Saturday=6)
1178     */
1179     DateTime aDateTime(Date( 0 ), Time( 0 ));
1180     if( lDTTM )
1181     {
1182         sal_uInt16 lMin = (sal_uInt16)(lDTTM & 0x0000003F);
1183         lDTTM >>= 6;
1184         sal_uInt16 lHour= (sal_uInt16)(lDTTM & 0x0000001F);
1185         lDTTM >>= 5;
1186         sal_uInt16 lDay = (sal_uInt16)(lDTTM & 0x0000001F);
1187         lDTTM >>= 5;
1188         sal_uInt16 lMon = (sal_uInt16)(lDTTM & 0x0000000F);
1189         lDTTM >>= 4;
1190         sal_uInt16 lYear= (sal_uInt16)(lDTTM & 0x000001FF) + 1900;
1191         aDateTime = DateTime(Date(lDay, lMon, lYear), Time(lHour, lMin));
1192     }
1193     return aDateTime;
1194 }
1195 
DetermineBorderProperties(bool bVer67,short * pSpace,sal_uInt8 * pCol,short * pIdx) const1196 short WW8_BRC::DetermineBorderProperties(bool bVer67, short *pSpace,
1197     sal_uInt8 *pCol, short *pIdx) const
1198 {
1199     /*
1200         Word does not factor the width of the border into the width/height
1201         stored in the information for graphic/table/object widths, so we need
1202         to figure out this extra width here and utilize the returned size in
1203         our calculations
1204     */
1205     short nMSTotalWidth;
1206     sal_uInt8 nCol;
1207     short nIdx,nSpace;
1208     if( bVer67 )
1209     {
1210         sal_uInt16 aBrc1 = SVBT16ToShort(aBits1);
1211         nCol = ((aBrc1 >> 6) & 0x1f);   // aBor.ico
1212         nSpace = (aBrc1 & 0xF800) >> 11;
1213 
1214         nMSTotalWidth = aBrc1 & 0x07;
1215         nIdx = (aBrc1 & 0x18) >> 3;
1216         //Dashed/Dotted unsets double/thick
1217         if (nMSTotalWidth > 5)
1218         {
1219             nMSTotalWidth=1;
1220             nIdx = 1;
1221         }
1222         nMSTotalWidth *= nIdx;
1223         nMSTotalWidth *= 15;
1224     }
1225     else
1226     {
1227         nIdx = aBits1[1];
1228         nCol = aBits2[0];   // aBor.ico
1229         nSpace = aBits2[1] & 0x1F; //space between line and object
1230 
1231         //Specification in 8ths of a point, 1 Point = 20 Twips, so by 2.5
1232         nMSTotalWidth  = aBits1[ 0 ] * 20 / 8;
1233 
1234         //Figure out the real size of the border according to word
1235         switch (nIdx)
1236         {
1237             //Note that codes over 25 are undocumented, and I can't create
1238             //these 4 here in the wild.
1239             default:
1240             case 2:
1241             case 4:
1242             case 5:
1243             case 22:
1244                 DBG_WARNING("Can't create these from the menus, please report");
1245             case 1:
1246             case 6:
1247             case 7:
1248             case 8:
1249             case 9:
1250             case 23:    //Only 3pt in the menus, but honours the size setting.
1251                 break;
1252             case 3:
1253                 /*
1254                 double line is three times the width of an ordinary line,
1255                 except for the smallest 1/4 point size which appears to have
1256                 exactly the same total border width as a 1/2 point size
1257                 ordinary line, i.e. twice the nominal line width
1258                 */
1259                 nMSTotalWidth = (nMSTotalWidth == 5) ?
1260                     nMSTotalWidth*2 : nMSTotalWidth*3;
1261                 break;
1262             case 10:
1263                 /*
1264                 triple line is five times the width of an ordinary line,
1265                 except that the smallest 1/4 point size appears to have
1266                 exactly the same total border width as a 3/4 point size
1267                 ordinary line, i.e. three times the nominal line width.  The
1268                 second smallest 1/2 point size appears to have exactly the
1269                 total border width as a 2 1/4 border, i.e 4.5 times the size.
1270                 */
1271                 if (nMSTotalWidth == 5)
1272                     nMSTotalWidth*=3;
1273                 else if (nMSTotalWidth == 10)
1274                     nMSTotalWidth = nMSTotalWidth*9/2;
1275                 else
1276                     nMSTotalWidth*=5;
1277                 break;
1278             case 11:
1279             case 12:
1280                 /*
1281                 small gap thin thick and thick thin appears to have a 3/4
1282                 point line, a 3/4 point gap and a thick line of the specified
1283                 width
1284                 */
1285                 nMSTotalWidth = nMSTotalWidth + 15*2;
1286                 break;
1287             case 13:
1288                 /*
1289                 thin thick thin appears to have two outside 3/4 point lines,
1290                 two 3/4 point gaps and a thick line of the specified width
1291                 */
1292                 nMSTotalWidth = nMSTotalWidth + 15*4;
1293                 break;
1294             case 14:
1295             case 15:
1296                 /*
1297                 medium gap thin thick and thick thin appears to have a line
1298                 50% of the thick line, and an equal sized gap and then the
1299                 thick line of the specified width. But it appears to only
1300                 use one of the existing predefined widths for the thin line,
1301                 so the closest smallest existing border to the halved thick
1302                 line is used.
1303                 */
1304                 switch (nMSTotalWidth)
1305                 {
1306                     case 45:    //2 1/4, closest to half is 1
1307                         nMSTotalWidth += 20 + (nMSTotalWidth-1)/2;
1308                         break;
1309                     case 5:
1310                     case 10:
1311                         nMSTotalWidth += 5;
1312                         break;
1313                     case 15:    //3/4, closest to half is 1/4
1314                         nMSTotalWidth += 5 + (nMSTotalWidth-1)/2;
1315                         break;
1316                     default:
1317                         nMSTotalWidth*=2;
1318                         break;
1319                 }
1320                 break;
1321             case 16:
1322                 /*
1323                 medium gap thin thick thin appears to have a line
1324                 50% of the thick line, and an equal sized gap and then the
1325                 thick line of the specified width. But it appears to only
1326                 use one of the existing predefined widths for the thin
1327                 line, so the closest smallest existing border to the halved
1328                 thick line is used. Though some fudging at smaller sizes is
1329                 still required.
1330                 */
1331                 switch (nMSTotalWidth)
1332                 {
1333                     case 45:    //2 1/4, closest to half is 1
1334                         nMSTotalWidth += nMSTotalWidth + 20 * 2;
1335                         break;
1336                     case 20:
1337                     case 15:
1338                         nMSTotalWidth += nMSTotalWidth + 7 * 2;
1339                         break;
1340                     case 10:
1341                     case 5:
1342                         nMSTotalWidth += 5 + 4;
1343                         break;
1344                     default:
1345                         nMSTotalWidth*=3;
1346                         break;
1347                 }
1348                 break;
1349             case 17:
1350             case 18:
1351                 /*
1352                 large gap thin thick and thick thin appears to have a thick
1353                 line of 1 1/2 pt and a narrow of 3/4 point, with a distance
1354                 between the two of the explicitly set line width
1355                 */
1356                 nMSTotalWidth+=15+30;
1357                 break;
1358             case 19:
1359                 /*
1360                 large gap thin thick thin appears to have a thick line of 1
1361                 1/2 pt and two narrows of 3/4 point, with a distance between
1362                 the two of the explicitly set line width, though the narrowest
1363                 line appears to behave as if it was even smaller
1364                 */
1365                 if (nMSTotalWidth == 5)
1366                     nMSTotalWidth = 3;
1367                 nMSTotalWidth = nMSTotalWidth*2 + 15*2 + 30;
1368                 break;
1369             case 20:
1370                 /*
1371                 wave, the dimensions appear to be created by the drawing of
1372                 the wave, so we have only two possibilities in the menus, 3/4
1373                 point is equal to solid 3 point. This calculation seems to
1374                 match well to results.
1375                 */
1376                 nMSTotalWidth +=45;
1377                 break;
1378             case 21:
1379                 /*
1380                 double wave, the dimensions appear to be created by the
1381                 drawing of the wave, so we have only one possibilities in the
1382                 menus, that of 3/4 point is equal to solid 3 point. This
1383                 calculation seems to match well to results.
1384                 */
1385                 nMSTotalWidth += 45*2;
1386                 break;
1387             case 24:
1388             case 25:
1389                 /*
1390                 emboss and engrave consist of a three lines, the central is of
1391                 the explicit point width, the other two (of equal size to each
1392                 other are the shadows and are either 3/4 pt of 1 1/2 depending
1393                 on if the central line is greater of less than 2 1/4 pt
1394                 */
1395                 if (nMSTotalWidth <= 45)
1396                     nMSTotalWidth += 2*15;
1397                 else
1398                     nMSTotalWidth += 2*30;
1399                 break;
1400         }
1401     }
1402 
1403     if (pIdx)
1404         *pIdx = nIdx;
1405     if (pSpace)
1406         *pSpace = nSpace*20;
1407     if (pCol)
1408         *pCol = nCol;
1409     return nMSTotalWidth;
1410 }
1411 
WW8Fc2Cp(WW8_FC nFcPos) const1412 WW8_CP WW8ScannerBase::WW8Fc2Cp( WW8_FC nFcPos ) const
1413 {
1414     WW8_CP nFallBackCpEnd = LONG_MAX;
1415     if( nFcPos == LONG_MAX )
1416         return nFallBackCpEnd;
1417 
1418     bool bIsUnicode = false;
1419     if( pPieceIter )    // Complex File ?
1420     {
1421         sal_uLong nOldPos = pPieceIter->GetIdx();
1422 
1423         for (pPieceIter->SetIdx(0);
1424             pPieceIter->GetIdx() < pPieceIter->GetIMax();(*pPieceIter)++)
1425         {
1426             long nCpStart, nCpEnd;
1427             void* pData;
1428             if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) )
1429             {   // ausserhalb PLCFfpcd ?
1430                 ASSERT( !this, "PLCFpcd-WW8Fc2Cp() ging schief" );
1431                 break;
1432             }
1433             sal_Int32 nFcStart  = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
1434             if( 8 <= pWw8Fib->nVersion )
1435                 nFcStart = WW8PLCFx_PCD::TransformPieceAddress( nFcStart,
1436                                                                 bIsUnicode );
1437             sal_Int32 nLen = (nCpEnd - nCpStart) * (bIsUnicode ? 2 : 1);
1438 
1439             /*
1440             If this cp is inside this piece, or its the last piece and we are
1441             on the very last cp of that piece
1442             */
1443             if (nFcPos >= nFcStart)
1444             {
1445                 // found
1446                 WW8_CP nTempCp =
1447                     nCpStart + ((nFcPos - nFcStart) / (bIsUnicode ? 2 : 1));
1448                 if (nFcPos < nFcStart + nLen)
1449                 {
1450                     pPieceIter->SetIdx( nOldPos );
1451                     return nTempCp;
1452                 }
1453                 else if (nFcPos == nFcStart + nLen)
1454                 {
1455                     //Keep this cp as its on a piece boundary because we might
1456                     //need it if tests fail
1457                     nFallBackCpEnd = nTempCp;
1458                 }
1459             }
1460         }
1461         // not found
1462         pPieceIter->SetIdx( nOldPos );      // not found
1463         /*
1464         If it was not found, then this is because it has fallen between two
1465         stools, i.e. either it is the last cp/fc of the last piece, or it is
1466         the last cp/fc of a disjoint piece.
1467         */
1468         return nFallBackCpEnd;
1469     }
1470     // No complex file
1471     if (pWw8Fib->fExtChar)
1472         bIsUnicode=true;
1473     return ((nFcPos - pWw8Fib->fcMin) / (bIsUnicode ? 2 : 1));
1474 }
1475 
WW8Cp2Fc(WW8_CP nCpPos,bool * pIsUnicode,WW8_CP * pNextPieceCp,bool * pTestFlag) const1476 WW8_FC WW8ScannerBase::WW8Cp2Fc(WW8_CP nCpPos, bool* pIsUnicode,
1477     WW8_CP* pNextPieceCp, bool* pTestFlag) const
1478 {
1479     if( pTestFlag )
1480         *pTestFlag = true;
1481     if( LONG_MAX == nCpPos )
1482         return LONG_MAX;
1483 
1484     bool bIsUnicode;
1485     if( !pIsUnicode )
1486         pIsUnicode = &bIsUnicode;
1487 
1488     if( pPieceIter )
1489     {   // Complex File
1490         if( pNextPieceCp )
1491             *pNextPieceCp = LONG_MAX;
1492 
1493         if( !pPieceIter->SeekPos( nCpPos ) )
1494         {
1495             if( pTestFlag )
1496                 *pTestFlag = false;
1497             else
1498                 ASSERT( !this, "Falscher CP an WW8Cp2Fc() uebergeben" );
1499             return LONG_MAX;
1500         }
1501         long nCpStart, nCpEnd;
1502         void* pData;
1503         if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) )
1504         {
1505             if( pTestFlag )
1506                 *pTestFlag = false;
1507             else
1508                 ASSERT( !this, "PLCFfpcd-Get ging schief" );
1509             return LONG_MAX;
1510         }
1511         if( pNextPieceCp )
1512             *pNextPieceCp = nCpEnd;
1513 
1514         WW8_FC nRet = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
1515         if (8 > pWw8Fib->nVersion)
1516             *pIsUnicode = false;
1517         else
1518             nRet = WW8PLCFx_PCD::TransformPieceAddress( nRet, *pIsUnicode );
1519 
1520 
1521         nRet += (nCpPos - nCpStart) * (*pIsUnicode ? 2 : 1);
1522 
1523         return nRet;
1524     }
1525 
1526     // No complex file
1527     if (pWw8Fib->fExtChar)
1528         *pIsUnicode = true;
1529     else
1530         *pIsUnicode = false;
1531     return pWw8Fib->fcMin + nCpPos * (*pIsUnicode ? 2 : 1);
1532 }
1533 
1534 //-----------------------------------------
1535 //      class WW8ScannerBase
1536 //-----------------------------------------
1537 
OpenPieceTable(SvStream * pStr,const WW8Fib * pWwF)1538 WW8PLCFpcd* WW8ScannerBase::OpenPieceTable( SvStream* pStr, const WW8Fib* pWwF )
1539 {
1540     if ( ((8 > pWw8Fib->nVersion) && !pWwF->fComplex) || !pWwF->lcbClx )
1541         return 0;
1542 
1543     WW8_FC nClxPos = pWwF->fcClx;
1544     sal_Int32 nClxLen = pWwF->lcbClx;
1545     sal_Int32 nLeft = nClxLen;
1546     sal_Int16 nGrpprl = 0;
1547     sal_uInt8 clxt;
1548 
1549     pStr->Seek( nClxPos );
1550     while( nGrpprl < SAL_MAX_INT16 ) // Zaehle Zahl der Grpprls
1551     {
1552         *pStr >> clxt;
1553         nLeft--;
1554         if( 2 == clxt )                         // PLCFfpcd ?
1555             break;                              // PLCFfpcd gefunden
1556         if( 1 == clxt )                         // clxtGrpprl ?
1557             nGrpprl++;
1558         sal_uInt16 nLen;
1559         *pStr >> nLen;
1560         nLeft -= 2 + nLen;
1561         if( nLeft < 0 )
1562             return 0;                           // schiefgegangen
1563         pStr->SeekRel( nLen );                  // ueberlies grpprl
1564     }
1565     if ( nGrpprl == SAL_MAX_INT16 )
1566         return 0;
1567     pStr->Seek( nClxPos );
1568     nLeft = nClxLen;
1569     pPieceGrpprls = new sal_uInt8*[nGrpprl + 1];
1570     memset( pPieceGrpprls, 0, ( nGrpprl + 1 ) * 4 );
1571     nPieceGrpprls = nGrpprl;
1572     sal_Int16 nAktGrpprl = 0;                       // lies Grpprls ein
1573     while( 1 )
1574     {
1575         *pStr >> clxt;
1576         nLeft--;
1577         if( 2 == clxt)                          // PLCFfpcd ?
1578             break;                              // PLCFfpcd gefunden
1579         sal_uInt16 nLen;
1580         *pStr >> nLen;
1581         nLeft -= 2 + nLen;
1582         if( nLeft < 0 )
1583             return 0;                           // schiefgegangen
1584         if( 1 == clxt )                         // clxtGrpprl ?
1585         {
1586             sal_uInt8* p = new sal_uInt8[nLen+2];           // alloziere
1587             ShortToSVBT16(nLen, p);             // trage Laenge ein
1588             pStr->Read( p+2, nLen );            // lies grpprl
1589             pPieceGrpprls[nAktGrpprl++] = p;    // trage in Array ein
1590         }
1591         else
1592             pStr->SeekRel( nLen );              // ueberlies nicht-Grpprl
1593     }
1594     // lies Piece Table PLCF ein
1595     sal_Int32 nPLCFfLen;
1596     *pStr >> nPLCFfLen;
1597     ASSERT( 65536 > nPLCFfLen, "PLCFfpcd ueber 64 k" );
1598     return new WW8PLCFpcd( pStr, pStr->Tell(), nPLCFfLen, 8 );
1599 }
1600 
DeletePieceTable()1601 void WW8ScannerBase::DeletePieceTable()
1602 {
1603     if( pPieceGrpprls )
1604     {
1605         for( sal_uInt8** p = pPieceGrpprls; *p; p++ )
1606             delete[] (*p);
1607         delete[] pPieceGrpprls;
1608         pPieceGrpprls = 0;
1609     }
1610 }
1611 
WW8ScannerBase(SvStream * pSt,SvStream * pTblSt,SvStream * pDataSt,const WW8Fib * pWwFib)1612 WW8ScannerBase::WW8ScannerBase( SvStream* pSt, SvStream* pTblSt,
1613     SvStream* pDataSt, const WW8Fib* pWwFib )
1614     : pWw8Fib(pWwFib), pMainFdoa(0), pHdFtFdoa(0), pMainTxbx(0),
1615     pMainTxbxBkd(0), pHdFtTxbx(0), pHdFtTxbxBkd(0), pMagicTables(0),
1616     pPieceGrpprls(0)
1617 {
1618     pPiecePLCF = OpenPieceTable( pTblSt, pWw8Fib );             // Complex
1619     if( pPiecePLCF )
1620     {
1621         pPieceIter = new WW8PLCFpcd_Iter( *pPiecePLCF );
1622         pPLCFx_PCD = new WW8PLCFx_PCD( pWwFib->nVersion, pPiecePLCF, 0,
1623             8 > pWw8Fib->nVersion );
1624         pPLCFx_PCDAttrs = new WW8PLCFx_PCDAttrs( pWwFib->nVersion, pPLCFx_PCD,
1625             this);
1626     }
1627     else
1628     {
1629         pPieceIter = 0;
1630         pPLCFx_PCD = 0;
1631         pPLCFx_PCDAttrs = 0;
1632     }
1633 
1634     // pChpPLCF and pPapPLCF may NOT be created before pPLCFx_PCD !!
1635     pChpPLCF = new WW8PLCFx_Cp_FKP( pSt, pTblSt, pDataSt, *this, CHP ); // CHPX
1636     pPapPLCF = new WW8PLCFx_Cp_FKP( pSt, pTblSt, pDataSt, *this, PAP ); // PAPX
1637 
1638     pSepPLCF = new WW8PLCFx_SEPX(   pSt, pTblSt, *pWwFib, 0 );          // SEPX
1639 
1640     // Footnotes
1641     pFtnPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->nVersion, 0,
1642         pWwFib->fcPlcffndRef, pWwFib->lcbPlcffndRef, pWwFib->fcPlcffndTxt,
1643         pWwFib->lcbPlcffndTxt, 2 );
1644     // Endnotes
1645     pEdnPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->nVersion, 0,
1646         pWwFib->fcPlcfendRef, pWwFib->lcbPlcfendRef, pWwFib->fcPlcfendTxt,
1647         pWwFib->lcbPlcfendTxt, 2 );
1648     // Anmerkungen
1649     pAndPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->nVersion, 0,
1650         pWwFib->fcPlcfandRef, pWwFib->lcbPlcfandRef, pWwFib->fcPlcfandTxt,
1651         pWwFib->lcbPlcfandTxt, (8 > pWwFib->nVersion) ? 20 : 30 );
1652 
1653     // Fields Main Text
1654     pFldPLCF    = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_MAINTEXT);
1655     // Fields Header / Footer
1656     pFldHdFtPLCF= new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_HDFT);
1657     // Fields Footnote
1658     pFldFtnPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_FTN);
1659     // Fields Endnote
1660     pFldEdnPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_EDN);
1661     // Fields Anmerkungen
1662     pFldAndPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_AND);
1663     // Fields in Textboxes in Main Text
1664     pFldTxbxPLCF= new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_TXBX);
1665     // Fields in Textboxes in Header / Footer
1666     pFldTxbxHdFtPLCF = new WW8PLCFx_FLD(pTblSt,*pWwFib,MAN_TXBX_HDFT);
1667 
1668     // Note: 6 stands for "6 OR 7",  7 stands for "ONLY 7"
1669     switch( pWw8Fib->nVersion )
1670     {
1671         case 6:
1672         case 7:
1673             if( pWwFib->fcPlcfdoaMom && pWwFib->lcbPlcfdoaMom )
1674             {
1675                 pMainFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfdoaMom,
1676                     pWwFib->lcbPlcfdoaMom, 6 );
1677             }
1678             if( pWwFib->fcPlcfdoaHdr && pWwFib->lcbPlcfdoaHdr )
1679             {
1680                 pHdFtFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfdoaHdr,
1681                 pWwFib->lcbPlcfdoaHdr, 6 );
1682             }
1683             break;
1684         case 8:
1685             if( pWwFib->fcPlcfspaMom && pWwFib->lcbPlcfspaMom )
1686             {
1687                 pMainFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfspaMom,
1688                     pWwFib->lcbPlcfspaMom, 26 );
1689             }
1690             if( pWwFib->fcPlcfspaHdr && pWwFib->lcbPlcfspaHdr )
1691             {
1692                 pHdFtFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfspaHdr,
1693                     pWwFib->lcbPlcfspaHdr, 26 );
1694             }
1695             // PLCF fuer TextBox-Break-Deskriptoren im Maintext
1696             if( pWwFib->fcPlcftxbxBkd && pWwFib->lcbPlcftxbxBkd )
1697             {
1698                 pMainTxbxBkd = new WW8PLCFspecial( pTblSt,
1699                     pWwFib->fcPlcftxbxBkd, pWwFib->lcbPlcftxbxBkd, 0);
1700             }
1701             // PLCF fuer TextBox-Break-Deskriptoren im Header-/Footer-Bereich
1702             if( pWwFib->fcPlcfHdrtxbxBkd && pWwFib->lcbPlcfHdrtxbxBkd )
1703             {
1704                 pHdFtTxbxBkd = new WW8PLCFspecial( pTblSt,
1705                     pWwFib->fcPlcfHdrtxbxBkd, pWwFib->lcbPlcfHdrtxbxBkd, 0);
1706             }
1707             // Sub table cp positions
1708             if (pWwFib->fcMagicTable && pWwFib->lcbMagicTable)
1709             {
1710                 pMagicTables = new WW8PLCFspecial( pTblSt,
1711                     pWwFib->fcMagicTable, pWwFib->lcbMagicTable, 4);
1712             }
1713             break;
1714         default:
1715             ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" );
1716             break;
1717     }
1718 
1719     // PLCF fuer TextBox-Stories im Maintext
1720     long nLenTxBxS = (8 > pWw8Fib->nVersion) ? 0 : 22;
1721     if( pWwFib->fcPlcftxbxTxt && pWwFib->lcbPlcftxbxTxt )
1722     {
1723         pMainTxbx = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcftxbxTxt,
1724             pWwFib->lcbPlcftxbxTxt, nLenTxBxS );
1725     }
1726 
1727     // PLCF fuer TextBox-Stories im Header-/Footer-Bereich
1728     if( pWwFib->fcPlcfHdrtxbxTxt && pWwFib->lcbPlcfHdrtxbxTxt )
1729     {
1730         pHdFtTxbx = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfHdrtxbxTxt,
1731             pWwFib->lcbPlcfHdrtxbxTxt, nLenTxBxS );
1732     }
1733 
1734     pBook = new WW8PLCFx_Book(pTblSt, *pWwFib);
1735 }
1736 
~WW8ScannerBase()1737 WW8ScannerBase::~WW8ScannerBase()
1738 {
1739     DeletePieceTable();
1740     delete pPLCFx_PCDAttrs;
1741     delete pPLCFx_PCD;
1742     delete pPieceIter;
1743     delete pPiecePLCF;
1744     delete pBook;
1745     delete pFldEdnPLCF;
1746     delete pFldFtnPLCF;
1747     delete pFldAndPLCF;
1748     delete pFldHdFtPLCF;
1749     delete pFldPLCF;
1750     delete pFldTxbxPLCF;
1751     delete pFldTxbxHdFtPLCF;
1752     delete pEdnPLCF;
1753     delete pFtnPLCF;
1754     delete pAndPLCF;
1755     delete pSepPLCF;
1756     delete pPapPLCF;
1757     delete pChpPLCF;
1758     // vergessene Schaeflein
1759     delete pMainFdoa;
1760     delete pHdFtFdoa;
1761     delete pMainTxbx;
1762     delete pMainTxbxBkd;
1763     delete pHdFtTxbx;
1764     delete pHdFtTxbxBkd;
1765     delete pMagicTables;
1766 }
1767 
1768 //-----------------------------------------
1769 //          Fields
1770 //-----------------------------------------
WW8SkipField(WW8PLCFspecial & rPLCF)1771 static bool WW8SkipField(WW8PLCFspecial& rPLCF)
1772 {
1773     void* pData;
1774     long nP;
1775 
1776     if (!rPLCF.Get(nP, pData))              // Ende des PLCFspecial ?
1777         return false;
1778 
1779     rPLCF++;
1780 
1781     if((((sal_uInt8*)pData)[0] & 0x1f ) != 0x13 )   // Kein Anfang ?
1782         return true;                            // Bei Fehler nicht abbrechen
1783 
1784     if( !rPLCF.Get( nP, pData ) )
1785         return false;
1786 
1787 
1788     while((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13 )
1789     {
1790         // immer noch neue (nested) Anfaenge ?
1791         WW8SkipField( rPLCF );              // nested Field im Beschreibungsteil
1792         if( !rPLCF.Get( nP, pData ) )
1793             return false;
1794     }
1795 
1796     if((((sal_uInt8*)pData)[0] & 0x1f ) == 0x14 )
1797     {
1798 
1799         // Field Separator ?
1800         rPLCF++;
1801 
1802         if( !rPLCF.Get( nP, pData ) )
1803             return false;
1804 
1805         while ((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13)
1806         {
1807             // immer noch neue (nested) Anfaenge ?
1808             WW8SkipField( rPLCF );          // nested Field im Resultatteil
1809             if( !rPLCF.Get( nP, pData ) )
1810                 return false;
1811         }
1812     }
1813     rPLCF++;
1814 
1815     return true;
1816 }
1817 
WW8GetFieldPara(WW8PLCFspecial & rPLCF,WW8FieldDesc & rF)1818 static bool WW8GetFieldPara(WW8PLCFspecial& rPLCF, WW8FieldDesc& rF)
1819 {
1820     void* pData;
1821     sal_uLong nOldIdx = rPLCF.GetIdx();
1822 
1823     rF.nLen = rF.nId = rF.nOpt = rF.bCodeNest = rF.bResNest = 0;
1824 
1825     if( !rPLCF.Get( rF.nSCode, pData ) )             // Ende des PLCFspecial ?
1826         goto Err;
1827 
1828     rPLCF++;
1829 
1830     if((((sal_uInt8*)pData)[0] & 0x1f ) != 0x13 )       // Kein Anfang ?
1831         goto Err;
1832 
1833     rF.nId = ((sal_uInt8*)pData)[1];
1834 
1835     if( !rPLCF.Get( rF.nLCode, pData ) )
1836         goto Err;
1837 
1838     rF.nSRes = rF.nLCode;                           // Default
1839     rF.nSCode++;                                    // ohne Marken
1840     rF.nLCode -= rF.nSCode;                         // Pos zu Laenge
1841 
1842     while((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13 )
1843     {
1844         // immer noch neue (nested) Anfaenge ?
1845         WW8SkipField( rPLCF );              // nested Field im Beschreibungsteil
1846         rF.bCodeNest = true;
1847         if( !rPLCF.Get( rF.nSRes, pData ) )
1848             goto Err;
1849     }
1850 
1851     if((((sal_uInt8*)pData)[0] & 0x1f ) == 0x14 ){      // Field Separator ?
1852         rPLCF++;
1853 
1854         if( !rPLCF.Get( rF.nLRes, pData ) )
1855             goto Err;
1856 
1857         while((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13 )
1858         {
1859             // immer noch neue (nested) Anfaenge ?
1860             WW8SkipField( rPLCF );              // nested Field im Resultatteil
1861             rF.bResNest = true;
1862             if( !rPLCF.Get( rF.nLRes, pData ) )
1863                 goto Err;
1864         }
1865         rF.nLen = rF.nLRes - rF.nSCode + 2; // nLRes ist noch die Endposition
1866         rF.nLRes -= rF.nSRes;                       // nun: nLRes = Laenge
1867         rF.nSRes++;                                 // Endpos encl. Marken
1868         rF.nLRes--;
1869 
1870     }else{
1871         rF.nLRes = 0;                               // Kein Result vorhanden
1872         rF.nLen = rF.nSRes - rF.nSCode + 2;         // Gesamtlaenge
1873     }
1874 
1875     rPLCF++;
1876     if((((sal_uInt8*)pData)[0] & 0x1f ) == 0x15 )
1877     {
1878         // Field Ende ?
1879         // INDEX-Fld hat Bit7 gesetzt!?!
1880         rF.nOpt = ((sal_uInt8*)pData)[1];               // Ja -> Flags uebernehmen
1881     }else{
1882         rF.nId = 0;                                 // Nein -> Feld ungueltig
1883     }
1884 
1885     rPLCF.SetIdx( nOldIdx );
1886     return true;
1887 Err:
1888     rPLCF.SetIdx( nOldIdx );
1889     return false;
1890 }
1891 
1892 
1893 //-----------------------------------------
1894 
1895 
1896 // WW8ReadPString liest einen Pascal-String ein und gibt ihn zurueck. Der
1897 // Pascal- String hat am Ende ein \0, der aber im Laengenbyte nicht
1898 // mitgezaehlt wird.  Der Speicher fuer den Pascalstring wird alloziert.
WW8ReadPString(SvStream & rStrm,rtl_TextEncoding eEnc,bool bAtEndSeekRel1)1899 String WW8ReadPString(SvStream& rStrm, rtl_TextEncoding eEnc,
1900     bool bAtEndSeekRel1)
1901 {
1902     ByteString aByteStr;
1903     sal_uInt8 b;
1904     rStrm >> b;
1905 
1906     if (b)
1907     {
1908         // Alloc methode automatically sets Zero at the end
1909         sal_Char*  pByteData = aByteStr.AllocBuffer( b );
1910 
1911         sal_uLong nWasRead = rStrm.Read( pByteData, b );
1912         if( nWasRead != b )
1913             aByteStr.ReleaseBufferAccess(static_cast<xub_StrLen>(nWasRead));
1914     }
1915 
1916     if( bAtEndSeekRel1 )
1917         rStrm.SeekRel( 1 ); // ueberspringe das Null-Byte am Ende.
1918 
1919 
1920     return String( aByteStr, eEnc );
1921 }
1922 
WW8Read_xstz(SvStream & rStrm,sal_uInt16 nChars,bool bAtEndSeekRel1)1923 String WW8Read_xstz(SvStream& rStrm, sal_uInt16 nChars, bool bAtEndSeekRel1)
1924 {
1925     sal_uInt16 b;
1926 
1927     if( nChars )
1928         b = nChars;
1929     else
1930         rStrm >> b;
1931 
1932     String aStr;
1933     if (b)
1934     {
1935         // Alloc methode automatically sets Zero at the end
1936         sal_Unicode* pData = aStr.AllocBuffer( b );
1937 
1938         sal_uLong nWasRead = rStrm.Read( (sal_Char*)pData, b * 2 );
1939         if( nWasRead != static_cast<sal_uLong>(b*2) )
1940         {
1941             b = static_cast<sal_uInt16>(nWasRead / 2);
1942             aStr.ReleaseBufferAccess( b );
1943             pData = aStr.GetBufferAccess();
1944         }
1945 
1946 #ifdef OSL_BIGENDIAN
1947         sal_uLong n;
1948         sal_Unicode *pWork;
1949         for( n = 0, pWork = pData; n < b; ++n, ++pWork )
1950             *pWork = SWAPSHORT( *pWork );
1951 #endif // ifdef OSL_BIGENDIAN
1952     }
1953 
1954     if( bAtEndSeekRel1 )
1955         rStrm.SeekRel( 2 ); // ueberspringe das Null-Character am Ende.
1956 
1957     return aStr;
1958 }
1959 
SafeReadString(ByteString & rStr,sal_uInt16 nLen,SvStream & rStrm)1960 static sal_uLong SafeReadString(ByteString &rStr,sal_uInt16 nLen,SvStream &rStrm)
1961 {
1962     sal_uLong nWasRead=0;
1963     if (nLen)
1964     {
1965         nWasRead = rStrm.Read( rStr.AllocBuffer( nLen ), nLen);
1966         if( nWasRead != nLen )
1967             rStr.ReleaseBufferAccess(static_cast<xub_StrLen>(nWasRead));
1968     }
1969     return nWasRead;
1970 }
1971 
WW8ReadString(SvStream & rStrm,String & rStr,WW8_CP nAktStartCp,long nTotalLen,rtl_TextEncoding eEnc) const1972 sal_uInt16 WW8ScannerBase::WW8ReadString( SvStream& rStrm, String& rStr,
1973     WW8_CP nAktStartCp, long nTotalLen, rtl_TextEncoding eEnc ) const
1974 {
1975     // Klartext einlesen, der sich ueber mehrere Pieces erstrecken kann
1976     rStr.Erase();
1977 
1978     long nTotalRead = 0;
1979     WW8_CP nBehindTextCp = nAktStartCp + nTotalLen;
1980     WW8_CP nNextPieceCp  = nBehindTextCp; // Initialisierung wichtig fuer Ver6
1981     do
1982     {
1983         bool bIsUnicode, bPosOk;
1984         WW8_FC fcAct = WW8Cp2Fc(nAktStartCp,&bIsUnicode,&nNextPieceCp,&bPosOk);
1985 
1986         // vermutlich uebers Dateiende hinaus gezielt, macht nix!
1987         if( !bPosOk )
1988             break;
1989 
1990         rStrm.Seek( fcAct );
1991 
1992         long nLen = ( (nNextPieceCp < nBehindTextCp) ? nNextPieceCp
1993             : nBehindTextCp ) - nAktStartCp;
1994 
1995         if( 0 >= nLen )
1996             break;
1997 
1998         if( nLen > USHRT_MAX - 1 )
1999             nLen = USHRT_MAX - 1;
2000 
2001         if( bIsUnicode )
2002             rStr.Append(WW8Read_xstz(rStrm, (sal_uInt16)nLen, false));
2003         else
2004         {
2005             // Alloc method automatically sets Zero at the end
2006             ByteString aByteStr;
2007             SafeReadString(aByteStr,(sal_uInt16)nLen,rStrm);
2008             rStr += String( aByteStr, eEnc );
2009         }
2010         nTotalRead  += nLen;
2011         nAktStartCp += nLen;
2012         if ( nTotalRead != rStr.Len() )
2013             break;
2014     }
2015     while( nTotalRead < nTotalLen );
2016 
2017     return rStr.Len();
2018 }
2019 
2020 //-----------------------------------------
2021 //              WW8PLCFspecial
2022 //-----------------------------------------
2023 
2024 // Bei nStartPos < 0 wird das erste Element des PLCFs genommen
WW8PLCFspecial(SvStream * pSt,long nFilePos,long nPLCF,long nStruct,long nStartPos,bool bNoEnd)2025 WW8PLCFspecial::WW8PLCFspecial(SvStream* pSt, long nFilePos, long nPLCF,
2026     long nStruct, long nStartPos, bool bNoEnd)
2027     : nIdx(0), nStru(nStruct)
2028 {
2029     nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
2030     // Pointer auf Pos- u. Struct-Array
2031     pPLCF_PosArray = new sal_Int32[ ( nPLCF + 3 ) / 4 ];
2032 
2033     long nOldPos = pSt->Tell();
2034 
2035     pSt->Seek( nFilePos );
2036     pSt->Read( pPLCF_PosArray, nPLCF );
2037 #ifdef OSL_BIGENDIAN
2038     for( nIdx = 0; nIdx <= nIMax; nIdx++ )
2039         pPLCF_PosArray[nIdx] = SWAPLONG( pPLCF_PosArray[nIdx] );
2040     nIdx = 0;
2041 #endif // OSL_BIGENDIAN
2042     if( bNoEnd )
2043         nIMax++;
2044     if( nStruct ) // Pointer auf Inhalts-Array
2045         pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
2046     else
2047         pPLCF_Contents = 0;                         // kein Inhalt
2048     if( nStartPos >= 0 )
2049         SeekPos( nStartPos );
2050 
2051     pSt->Seek( nOldPos );
2052 }
2053 
2054 // WW8PLCFspecial::SeekPos() stellt den WW8PLCFspecial auf die Stelle nPos, wobei auch noch der
2055 // Eintrag benutzt wird, der vor nPos beginnt und bis hinter nPos reicht.
2056 // geeignet fuer normale Attribute. Allerdings wird der Attributanfang nicht
2057 // auf die Position nPos korrigiert.
SeekPos(long nP)2058 bool WW8PLCFspecial::SeekPos(long nP)
2059 {
2060     if( nP < pPLCF_PosArray[0] )
2061     {
2062         nIdx = 0;
2063         return false;   // Not found: nP unterhalb kleinstem Eintrag
2064     }
2065 
2066     // Search from beginning?
2067     if( (1 > nIdx) || (nP < pPLCF_PosArray[ nIdx-1 ]) )
2068         nIdx = 1;
2069 
2070     long nI   = nIdx ? nIdx : 1;
2071     long nEnd = nIMax;
2072 
2073     for(int n = (1==nIdx ? 1 : 2); n; --n )
2074     {
2075         for( ; nI <=nEnd; ++nI)
2076         {                                   // Suchen mit um 1 erhoehtem Index
2077             if( nP < pPLCF_PosArray[nI] )
2078             {                               // Position gefunden
2079                 nIdx = nI - 1;              // nI - 1 ist der richtige Index
2080                 return true;                // ... und fertig
2081             }
2082         }
2083         nI   = 1;
2084         nEnd = nIdx-1;
2085     }
2086     nIdx = nIMax;               // Nicht gefunden, groesser als alle Eintraege
2087     return false;
2088 }
2089 
2090 // WW8PLCFspecial::SeekPosExact() wie SeekPos(), aber es wird sichergestellt,
2091 // dass kein Attribut angeschnitten wird, d.h. das naechste gelieferte
2092 // Attribut beginnt auf oder hinter nPos. Wird benutzt fuer Felder +
2093 // Bookmarks.
SeekPosExact(long nP)2094 bool WW8PLCFspecial::SeekPosExact(long nP)
2095 {
2096     if( nP < pPLCF_PosArray[0] )
2097     {
2098         nIdx = 0;
2099         return false;       // Not found: nP unterhalb kleinstem Eintrag
2100     }
2101     // Search from beginning?
2102     if( nP <=pPLCF_PosArray[nIdx] )
2103         nIdx = 0;
2104 
2105     long nI   = nIdx ? nIdx-1 : 0;
2106     long nEnd = nIMax;
2107 
2108     for(int n = (0==nIdx ? 1 : 2); n; --n )
2109     {
2110         for( ; nI < nEnd; ++nI)
2111         {
2112             if( nP <=pPLCF_PosArray[nI] )
2113             {                           // Position gefunden
2114                 nIdx = nI;              // nI     ist der richtige Index
2115                 return true;            // ... und fertig
2116             }
2117         }
2118         nI   = 0;
2119         nEnd = nIdx;
2120     }
2121     nIdx = nIMax;               // Not found, groesser als alle Eintraege
2122     return false;
2123 }
2124 
Get(long & rPos,void * & rpValue) const2125 bool WW8PLCFspecial::Get(long& rPos, void*& rpValue) const
2126 {
2127     return GetData( nIdx, rPos, rpValue );
2128 }
2129 
GetData(long nInIdx,long & rPos,void * & rpValue) const2130 bool WW8PLCFspecial::GetData(long nInIdx, long& rPos, void*& rpValue) const
2131 {
2132     if ( nInIdx >= nIMax )
2133     {
2134         rPos = LONG_MAX;
2135         return false;
2136     }
2137     rPos = pPLCF_PosArray[nInIdx];
2138     rpValue = pPLCF_Contents ? (void*)&pPLCF_Contents[nInIdx * nStru] : 0;
2139     return true;
2140 }
2141 
2142 //-----------------------------------------
2143 //              WW8PLCF z.B. fuer SEPX
2144 //-----------------------------------------
2145 
2146 // Ctor fuer *andere* als Fkps
2147 // Bei nStartPos < 0 wird das erste Element des PLCFs genommen
WW8PLCF(SvStream * pSt,long nFilePos,long nPLCF,long nStruct,long nStartPos)2148 WW8PLCF::WW8PLCF( SvStream* pSt, long nFilePos, long nPLCF, long nStruct,
2149     long nStartPos ) :nIdx( 0 ), nStru( nStruct )
2150 {
2151     ASSERT( nPLCF, "WW8PLCF: nPLCF ist Null!" );
2152 
2153     nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
2154 
2155     ReadPLCF( pSt, nFilePos, nPLCF );
2156 
2157     if( nStartPos >= 0 )
2158         SeekPos( nStartPos );
2159 }
2160 
2161 // Ctor *nur* fuer Fkps
2162 // Die letzten 2 Parameter sind fuer PLCF.Chpx und PLCF.Papx noetig.  ist ncpN
2163 // != 0, dann wird ein unvollstaendiger PLCF vervollstaendigt.  Das ist bei
2164 // WW6 bei Resourcenmangel und bei WordPad (W95) immer noetig.  Bei nStartPos
2165 // < 0 wird das erste Element des PLCFs genommen
WW8PLCF(SvStream * pSt,long nFilePos,long nPLCF,long nStruct,long nStartPos,long nPN,long ncpN)2166 WW8PLCF::WW8PLCF( SvStream* pSt, long nFilePos, long nPLCF, long nStruct,
2167     long nStartPos, long nPN, long ncpN ) :nIdx( 0 ), nStru( nStruct )
2168 {
2169     nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
2170 
2171     if( nIMax >= (long) ncpN )
2172         ReadPLCF( pSt, nFilePos, nPLCF );
2173     else
2174         GeneratePLCF( pSt, nPN, ncpN );
2175 
2176     if( nStartPos >= 0 )
2177         SeekPos( nStartPos );
2178 }
2179 
ReadPLCF(SvStream * pSt,long nFilePos,long nPLCF)2180 void WW8PLCF::ReadPLCF( SvStream* pSt, long nFilePos, long nPLCF )
2181 {
2182     // Pointer auf Pos-Array
2183     pPLCF_PosArray = new sal_Int32[ ( nPLCF + 3 ) / 4 ];
2184 
2185     long nOldPos = pSt->Tell();
2186 
2187     pSt->Seek( nFilePos );
2188     pSt->Read( pPLCF_PosArray, nPLCF );
2189 #ifdef OSL_BIGENDIAN
2190     for( nIdx = 0; nIdx <= nIMax; nIdx++ )
2191         pPLCF_PosArray[nIdx] = SWAPLONG( pPLCF_PosArray[nIdx] );
2192     nIdx = 0;
2193 #endif // OSL_BIGENDIAN
2194     // Pointer auf Inhalts-Array
2195     pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
2196 
2197     pSt->Seek( nOldPos );
2198 }
2199 
GeneratePLCF(SvStream * pSt,long nPN,long ncpN)2200 void WW8PLCF::GeneratePLCF( SvStream* pSt, long nPN, long ncpN )
2201 {
2202     ASSERT( nIMax < (long)ncpN, "Pcl.Fkp: Warum ist PLCF zu gross ?" );
2203     nIMax = ncpN;
2204     long nSiz = 6 * nIMax + 4;
2205     pPLCF_PosArray = new sal_Int32[ ( nSiz + 3 ) / 4 ]; // Pointer auf Pos-Array
2206     memset( pPLCF_PosArray, 0, (size_t)nSiz );
2207 
2208     sal_Int32 nFc;
2209     sal_uInt16 i;
2210 
2211     for( i = 0; i < ncpN; i++ ){        // Baue FC-Eintraege
2212         pSt->Seek( ( nPN + i ) << 9 );  // erster FC-Eintrag jedes Fkp
2213         *pSt >> nFc;
2214         pPLCF_PosArray[i] = nFc;
2215     }
2216     sal_uLong nLastFkpPos = ( ( nPN + nIMax - 1 ) << 9 );
2217     pSt->Seek( nLastFkpPos + 511 );     // Anz. Fkp-Eintraege des letzten Fkp
2218     sal_uInt8 nb;
2219     *pSt >> nb;
2220     pSt->Seek( nLastFkpPos + nb * 4 );  // letzer FC-Eintrag des letzten Fkp
2221     *pSt >> nFc;
2222     pPLCF_PosArray[nIMax] = nFc;        // Ende des letzten Fkp
2223 
2224     // Pointer auf Inhalts-Array
2225     pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
2226     sal_uInt8* p = pPLCF_Contents;
2227 
2228     for( i = 0; i < ncpN; i++ )         // Baue PNs
2229     {
2230         ShortToSVBT16(nPN + i, p);
2231         p+=2;
2232     }
2233 }
2234 
SeekPos(long nPos)2235 bool WW8PLCF::SeekPos(long nPos)
2236 {
2237     long nP = nPos;
2238 
2239     if( nP < pPLCF_PosArray[0] )
2240     {
2241         nIdx = 0;
2242         // Nicht gefunden: nPos unterhalb kleinstem Eintrag
2243         return false;
2244     }
2245 
2246     // Search from beginning?
2247     if( (1 > nIdx) || (nP < pPLCF_PosArray[ nIdx-1 ]) )
2248         nIdx = 1;
2249 
2250     long nI   = nIdx ? nIdx : 1;
2251     long nEnd = nIMax;
2252 
2253     for(int n = (1==nIdx ? 1 : 2); n; --n )
2254     {
2255         for( ; nI <=nEnd; ++nI)             // Suchen mit um 1 erhoehtem Index
2256         {
2257             if( nP < pPLCF_PosArray[nI] )   // Position gefunden
2258             {
2259                 nIdx = nI - 1;              // nI - 1 ist der richtige Index
2260                 return true;                // ... und fertig
2261             }
2262         }
2263         nI   = 1;
2264         nEnd = nIdx-1;
2265     }
2266 
2267     nIdx = nIMax;               // Nicht gefunden, groesser als alle Eintraege
2268     return false;
2269 }
2270 
Get(long & rStart,long & rEnd,void * & rpValue) const2271 bool WW8PLCF::Get(long& rStart, long& rEnd, void*& rpValue) const
2272 {
2273     if ( nIdx >= nIMax )
2274     {
2275         rStart = rEnd = LONG_MAX;
2276         return false;
2277     }
2278     rStart = pPLCF_PosArray[ nIdx ];
2279     rEnd   = pPLCF_PosArray[ nIdx + 1 ];
2280     rpValue = (void*)&pPLCF_Contents[nIdx * nStru];
2281     return true;
2282 }
2283 
Where() const2284 long WW8PLCF::Where() const
2285 {
2286     if ( nIdx >= nIMax )
2287         return LONG_MAX;
2288 
2289     return pPLCF_PosArray[nIdx];
2290 }
2291 
2292 //-----------------------------------------
2293 //              WW8PLCFpcd
2294 //-----------------------------------------
2295 
WW8PLCFpcd(SvStream * pSt,long nFilePos,long nPLCF,long nStruct)2296 WW8PLCFpcd::WW8PLCFpcd( SvStream* pSt, long nFilePos, long nPLCF, long nStruct )
2297     :nStru( nStruct )
2298 {
2299     nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
2300     pPLCF_PosArray = new sal_Int32[ ( nPLCF + 3 ) / 4 ];    // Pointer auf Pos-Array
2301 
2302     long nOldPos = pSt->Tell();
2303 
2304     pSt->Seek( nFilePos );
2305     pSt->Read( pPLCF_PosArray, nPLCF );
2306 #ifdef OSL_BIGENDIAN
2307     for( long nI = 0; nI <= nIMax; nI++ )
2308       pPLCF_PosArray[nI] = SWAPLONG( pPLCF_PosArray[nI] );
2309 #endif // OSL_BIGENDIAN
2310 
2311     // Pointer auf Inhalts-Array
2312     pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
2313 
2314     pSt->Seek( nOldPos );
2315 }
2316 
2317 // Bei nStartPos < 0 wird das erste Element des PLCFs genommen
WW8PLCFpcd_Iter(WW8PLCFpcd & rPLCFpcd,long nStartPos)2318 WW8PLCFpcd_Iter::WW8PLCFpcd_Iter( WW8PLCFpcd& rPLCFpcd, long nStartPos )
2319     :rPLCF( rPLCFpcd ), nIdx( 0 )
2320 {
2321     if( nStartPos >= 0 )
2322         SeekPos( nStartPos );
2323 }
2324 
SeekPos(long nPos)2325 bool WW8PLCFpcd_Iter::SeekPos(long nPos)
2326 {
2327     long nP = nPos;
2328 
2329     if( nP < rPLCF.pPLCF_PosArray[0] )
2330     {
2331         nIdx = 0;
2332         return false;       // Nicht gefunden: nPos unterhalb kleinstem Eintrag
2333     }
2334     // Search from beginning?
2335     if( (1 > nIdx) || (nP < rPLCF.pPLCF_PosArray[ nIdx-1 ]) )
2336         nIdx = 1;
2337 
2338     long nI   = nIdx ? nIdx : 1;
2339     long nEnd = rPLCF.nIMax;
2340 
2341     for(int n = (1==nIdx ? 1 : 2); n; --n )
2342     {
2343         for( ; nI <=nEnd; ++nI)
2344         {                               // Suchen mit um 1 erhoehtem Index
2345             if( nP < rPLCF.pPLCF_PosArray[nI] )
2346             {                           // Position gefunden
2347                 nIdx = nI - 1;          // nI - 1 ist der richtige Index
2348                 return true;            // ... und fertig
2349             }
2350         }
2351         nI   = 1;
2352         nEnd = nIdx-1;
2353     }
2354     nIdx = rPLCF.nIMax;         // Nicht gefunden, groesser als alle Eintraege
2355     return false;
2356 }
2357 
Get(long & rStart,long & rEnd,void * & rpValue) const2358 bool WW8PLCFpcd_Iter::Get(long& rStart, long& rEnd, void*& rpValue) const
2359 {
2360     if( nIdx >= rPLCF.nIMax )
2361     {
2362         rStart = rEnd = LONG_MAX;
2363         return false;
2364     }
2365     rStart = rPLCF.pPLCF_PosArray[nIdx];
2366     rEnd = rPLCF.pPLCF_PosArray[nIdx + 1];
2367     rpValue = (void*)&rPLCF.pPLCF_Contents[nIdx * rPLCF.nStru];
2368     return true;
2369 }
2370 
Where() const2371 long WW8PLCFpcd_Iter::Where() const
2372 {
2373     if ( nIdx >= rPLCF.nIMax )
2374         return LONG_MAX;
2375 
2376     return rPLCF.pPLCF_PosArray[nIdx];
2377 }
2378 
2379 //-----------------------------------------
operator <(const WW8PLCFx_Fc_FKP::WW8Fkp::Entry & rSecond) const2380 bool WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator<
2381     (const WW8PLCFx_Fc_FKP::WW8Fkp::Entry& rSecond) const
2382 {
2383     return (mnFC < rSecond.mnFC);
2384 }
2385 
WW8Fkp(sal_uInt8 nFibVer,SvStream * pSt,SvStream * pDataSt,long _nFilePos,long nItemSiz,ePLCFT ePl,WW8_FC nStartFc)2386 WW8PLCFx_Fc_FKP::WW8Fkp::WW8Fkp(sal_uInt8 nFibVer, SvStream* pSt, SvStream* pDataSt,
2387     long _nFilePos, long nItemSiz, ePLCFT ePl, WW8_FC nStartFc)
2388     : nItemSize(nItemSiz), nFilePos(_nFilePos),  nIdx(0), ePLCF(ePl),
2389     maSprmParser(nFibVer)
2390 {
2391     long nOldPos = pSt->Tell();
2392 
2393     pSt->Seek(nFilePos);
2394     pSt->Read(maRawData, 512);
2395     nIMax = maRawData[511];
2396 
2397     sal_uInt8 *pStart = maRawData;
2398     // Pointer to Offset-Location in maRawData
2399     sal_uInt8* pOfs = maRawData + (nIMax + 1) * 4;
2400 
2401     for (nIdx = 0; nIdx < nIMax; ++nIdx)
2402     {
2403         sal_uInt16 nOfs = (*(pOfs + nIdx * nItemSize)) * 2;
2404         Entry aEntry(Get_Long(pStart));
2405 
2406         if (nOfs)
2407         {
2408             switch (ePLCF)
2409             {
2410                 case CHP:
2411                     aEntry.mnLen  = maRawData[nOfs];
2412                     aEntry.mpData = maRawData + nOfs + 1;
2413                     break;
2414                 case PAP:
2415                     sal_uInt8 nDelta = 0;
2416 
2417                     aEntry.mnLen = maRawData[nOfs];
2418                     if (8 <= nFibVer && !aEntry.mnLen)
2419                     {
2420                         aEntry.mnLen = maRawData[ nOfs+1 ];
2421                         nDelta++;
2422                     }
2423 
2424                     aEntry.mnIStd = SVBT16ToShort(maRawData+nOfs+1+nDelta);
2425 
2426                     aEntry.mpData = maRawData + nOfs + 3+ nDelta;
2427 
2428                     sal_uInt16 nSpId = maSprmParser.GetSprmId(aEntry.mpData);
2429 
2430                     if (0x6645 == nSpId || 0x6646 == nSpId)
2431                     {
2432                         sal_uInt32 nCurr = pDataSt->Tell();
2433 
2434                         sal_uInt32 nPos = SVBT32ToUInt32(aEntry.mpData + 2);
2435                         pDataSt->Seek(nPos);
2436                         *pDataSt >> aEntry.mnLen;
2437                         aEntry.mpData = new sal_uInt8[aEntry.mnLen];
2438                         aEntry.mbMustDelete = true;
2439                         pDataSt->Read(aEntry.mpData, aEntry.mnLen);
2440 
2441                         pDataSt->Seek( nCurr );
2442                     }
2443                     else
2444                     {
2445                         aEntry.mnLen *= 2;
2446                         aEntry.mnLen -= 2;
2447                     }
2448                     break;
2449             }
2450         }
2451 
2452         maEntries.push_back(aEntry);
2453     }
2454 
2455     //one more FC than grrpl entries
2456     maEntries.push_back(Entry(Get_Long(pStart)));
2457 
2458     //#104773#, we expect them sorted, but it appears possible
2459     //for them to arrive unsorted
2460     std::sort(maEntries.begin(), maEntries.end());
2461 
2462     nIdx = 0;
2463 
2464     if (nStartFc >= 0)
2465         SeekPos(nStartFc);
2466 
2467     pSt->Seek(nOldPos);
2468 }
2469 
Entry(const Entry & rEntry)2470 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::Entry(const Entry &rEntry)
2471     : mnFC(rEntry.mnFC), mnLen(rEntry.mnLen), mnIStd(rEntry.mnIStd),
2472     mbMustDelete(rEntry.mbMustDelete)
2473 {
2474     if (mbMustDelete)
2475     {
2476         mpData = new sal_uInt8[mnLen];
2477         memcpy(mpData, rEntry.mpData, mnLen);
2478     }
2479     else
2480         mpData = rEntry.mpData;
2481 }
2482 
2483 WW8PLCFx_Fc_FKP::WW8Fkp::Entry&
operator =(const Entry & rEntry)2484     WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator=(const Entry &rEntry)
2485 {
2486     if (mbMustDelete)
2487         delete[] mpData;
2488 
2489     mnFC = rEntry.mnFC;
2490     mnLen = rEntry.mnLen;
2491     mnIStd = rEntry.mnIStd;
2492     mbMustDelete = rEntry.mbMustDelete;
2493 
2494     if (mbMustDelete)
2495     {
2496         mpData = new sal_uInt8[mnLen];
2497         memcpy(mpData, rEntry.mpData, mnLen);
2498     }
2499     else
2500         mpData = rEntry.mpData;
2501     return *this;
2502 }
2503 
~Entry()2504 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::~Entry()
2505 {
2506     if (mbMustDelete)
2507         delete[] mpData;
2508 }
2509 
Reset(WW8_FC nFc)2510 void WW8PLCFx_Fc_FKP::WW8Fkp::Reset(WW8_FC nFc)
2511 {
2512     SetIdx(0);
2513     if (nFc >= 0)
2514         SeekPos(nFc);
2515 }
2516 
SeekPos(WW8_FC nFc)2517 bool WW8PLCFx_Fc_FKP::WW8Fkp::SeekPos(WW8_FC nFc)
2518 {
2519     if (nFc < maEntries[0].mnFC)
2520     {
2521         nIdx = 0;
2522         return false;       // Nicht gefunden: nPos unterhalb kleinstem Eintrag
2523     }
2524     // Search from beginning?
2525     if( (1 > nIdx) || (nFc < maEntries[nIdx-1].mnFC) )
2526         nIdx = 1;
2527 
2528     long nI   = nIdx ? nIdx : 1;
2529     long nEnd = nIMax;
2530 
2531     for(int n = (1==nIdx ? 1 : 2); n; --n )
2532     {
2533         for( ; nI <=nEnd; ++nI)
2534         {                               // Suchen mit um 1 erhoehtem Index
2535             if (nFc < maEntries[nI].mnFC)
2536             {                           // Position gefunden
2537                 nIdx = nI - 1;          // nI - 1 ist der richtige Index
2538                 return true;            // ... und fertig
2539             }
2540         }
2541         nI   = 1;
2542         nEnd = nIdx-1;
2543     }
2544     nIdx = nIMax;               // Nicht gefunden, groesser als alle Eintraege
2545     return false;
2546 }
2547 
Get(WW8_FC & rStart,WW8_FC & rEnd,long & rLen) const2548 sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::Get( WW8_FC& rStart, WW8_FC& rEnd, long& rLen )
2549     const
2550 {
2551     rLen = 0;
2552 
2553     if( nIdx >= nIMax )
2554     {
2555         rStart = LONG_MAX;
2556         return 0;
2557     }
2558 
2559     rStart = maEntries[nIdx].mnFC;
2560     rEnd   = maEntries[nIdx + 1].mnFC;
2561 
2562     sal_uInt8* pSprms = GetLenAndIStdAndSprms( rLen );
2563     return pSprms;
2564 }
2565 
SetIdx(sal_uLong nI)2566 void WW8PLCFx_Fc_FKP::WW8Fkp::SetIdx( sal_uLong nI )
2567 {
2568     if( nI < nIMax)
2569         nIdx = (short)nI;
2570 }
2571 
GetLenAndIStdAndSprms(long & rLen) const2572 sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::GetLenAndIStdAndSprms(long& rLen) const
2573 {
2574     rLen = maEntries[nIdx].mnLen;
2575     return maEntries[nIdx].mpData;
2576 }
2577 
HasSprm(sal_uInt16 nId)2578 const sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm( sal_uInt16 nId )
2579 {
2580     if( nIdx >= nIMax )
2581         return 0;
2582 
2583     long nLen;
2584     sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
2585 
2586     WW8SprmIter aIter(pSprms, nLen, maSprmParser);
2587     return aIter.FindSprm(nId);
2588 }
2589 
HasSprm(sal_uInt16 nId,std::vector<const sal_uInt8 * > & rResult)2590 bool WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm(sal_uInt16 nId,
2591     std::vector<const sal_uInt8 *> &rResult)
2592 {
2593     if (nIdx >= nIMax)
2594        return false;
2595 
2596     long nLen;
2597     sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
2598 
2599     WW8SprmIter aIter(pSprms, nLen, maSprmParser);
2600 
2601     while(aIter.GetSprms())
2602     {
2603         if (aIter.GetAktId() == nId)
2604             rResult.push_back(aIter.GetAktParams());
2605         aIter++;
2606     };
2607     return !rResult.empty();
2608 }
2609 
2610 //-----------------------------------------
GetSprms(WW8PLCFxDesc * p)2611 void WW8PLCFx::GetSprms( WW8PLCFxDesc* p )
2612 {
2613     ASSERT( !this, "Falsches GetSprms gerufen" );
2614     p->nStartPos = p->nEndPos = LONG_MAX;
2615     p->pMemPos = 0;
2616     p->nSprmsLen = 0;
2617     p->bRealLineEnd = false;
2618     return;
2619 }
2620 
GetNoSprms(long & rStart,long & rEnd,long & rLen)2621 long WW8PLCFx::GetNoSprms( long& rStart, long& rEnd, long& rLen )
2622 {
2623     ASSERT( !this, "Falsches GetNoSprms gerufen" );
2624     rStart = rEnd = LONG_MAX;
2625     rLen = 0;
2626     return 0;
2627 }
2628 
2629 // ...Idx2: Default: ignorieren
GetIdx2() const2630 sal_uLong WW8PLCFx::GetIdx2() const
2631 {
2632     return 0;
2633 }
2634 
SetIdx2(sal_uLong)2635 void WW8PLCFx::SetIdx2(sal_uLong )
2636 {
2637 }
2638 
2639 class SamePos :
2640     public std::unary_function<const WW8PLCFx_Fc_FKP::WW8Fkp *, bool>
2641 {
2642 private:
2643     long mnPo;
2644 public:
SamePos(long nPo)2645     SamePos(long nPo) : mnPo(nPo) {};
operator ()(const WW8PLCFx_Fc_FKP::WW8Fkp * pFkp)2646     bool operator()(const WW8PLCFx_Fc_FKP::WW8Fkp *pFkp)
2647         {return mnPo == pFkp->GetFilePos();}
2648 };
2649 
2650 //-----------------------------------------
NewFkp()2651 bool WW8PLCFx_Fc_FKP::NewFkp()
2652 {
2653     long nPLCFStart, nPLCFEnd;
2654     void* pPage;
2655 
2656     static const int WW8FkpSizeTabVer6[ PLCF_END ] =
2657     {
2658         1,  7, 0 /*, 0, 0, 0*/
2659     };
2660     static const int WW8FkpSizeTabVer8[ PLCF_END ] =
2661     {
2662         1, 13, 0 /*, 0, 0, 0*/
2663     };
2664     const int* pFkpSizeTab;
2665     switch (GetVersion())
2666     {
2667         case 6:
2668         case 7:
2669             pFkpSizeTab = WW8FkpSizeTabVer6;
2670             break;
2671         case 8:
2672             pFkpSizeTab = WW8FkpSizeTabVer8;
2673             break;
2674         default:
2675             // Programm-Fehler!
2676             ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" );
2677             return false;
2678     }
2679 
2680     if (!pPLCF->Get( nPLCFStart, nPLCFEnd, pPage ))
2681     {
2682         pFkp = 0;
2683         return false;                           // PLCF fertig abgearbeitet
2684     }
2685     (*pPLCF)++;
2686     long nPo = SVBT16ToShort( (sal_uInt8 *)pPage );
2687     nPo <<= 9;                                  // shift als LONG
2688 
2689     long nAktFkpFilePos = pFkp ? pFkp->GetFilePos() : -1;
2690     if (nAktFkpFilePos == nPo)
2691         pFkp->Reset(GetStartFc()); // #79464# //
2692     else
2693     {
2694         myiter aIter =
2695             std::find_if(maFkpCache.begin(), maFkpCache.end(), SamePos(nPo));
2696         if (aIter != maFkpCache.end())
2697         {
2698             pFkp = *aIter;
2699             pFkp->Reset(GetStartFc());
2700         }
2701         else if ((pFkp = new WW8Fkp(GetVersion(), pFKPStrm, pDataStrm, nPo,
2702             pFkpSizeTab[ ePLCF ], ePLCF, GetStartFc())))
2703         {
2704             maFkpCache.push_back(pFkp);
2705 
2706             if (maFkpCache.size() > eMaxCache)
2707             {
2708                 delete maFkpCache.front();
2709                 maFkpCache.pop_front();
2710             }
2711         }
2712     }
2713 
2714     SetStartFc( -1 );                                   // Nur das erste Mal
2715     return true;
2716 }
2717 
WW8PLCFx_Fc_FKP(SvStream * pSt,SvStream * pTblSt,SvStream * pDataSt,const WW8Fib & rFib,ePLCFT ePl,WW8_FC nStartFcL)2718 WW8PLCFx_Fc_FKP::WW8PLCFx_Fc_FKP(SvStream* pSt, SvStream* pTblSt,
2719     SvStream* pDataSt, const WW8Fib& rFib, ePLCFT ePl, WW8_FC nStartFcL)
2720     : WW8PLCFx(rFib.nVersion, true), pFKPStrm(pSt), pDataStrm(pDataSt),
2721     pFkp(0), ePLCF(ePl), pPCDAttrs(0)
2722 {
2723     SetStartFc(nStartFcL);
2724     long nLenStruct = (8 > rFib.nVersion) ? 2 : 4;
2725     if (ePl == CHP)
2726     {
2727         pPLCF = new WW8PLCF(pTblSt, rFib.fcPlcfbteChpx, rFib.lcbPlcfbteChpx,
2728             nLenStruct, GetStartFc(), rFib.pnChpFirst, rFib.cpnBteChp);
2729     }
2730     else
2731     {
2732         pPLCF = new WW8PLCF(pTblSt, rFib.fcPlcfbtePapx, rFib.lcbPlcfbtePapx,
2733             nLenStruct, GetStartFc(), rFib.pnPapFirst, rFib.cpnBtePap);
2734     }
2735 }
2736 
~WW8PLCFx_Fc_FKP()2737 WW8PLCFx_Fc_FKP::~WW8PLCFx_Fc_FKP()
2738 {
2739     myiter aEnd = maFkpCache.end();
2740     for (myiter aIter = maFkpCache.begin(); aIter != aEnd; ++aIter)
2741         delete *aIter;
2742     delete pPLCF;
2743     delete pPCDAttrs;
2744 }
2745 
GetIdx() const2746 sal_uLong WW8PLCFx_Fc_FKP::GetIdx() const
2747 {
2748     sal_uLong u = pPLCF->GetIdx() << 8;
2749     if (pFkp)
2750         u |= pFkp->GetIdx();
2751     return u;
2752 }
2753 
SetIdx(sal_uLong nIdx)2754 void WW8PLCFx_Fc_FKP::SetIdx( sal_uLong nIdx )
2755 {
2756     if( !( nIdx & 0xffffff00L ) )
2757     {
2758         pPLCF->SetIdx( nIdx >> 8 );
2759         pFkp = 0;
2760     }
2761     else
2762     {                                   //Es gab einen Fkp
2763         //Lese PLCF um 1 Pos zurueck, um die Adresse des Fkp wiederzubekommen
2764         pPLCF->SetIdx( ( nIdx >> 8 ) - 1 );
2765         if ( NewFkp() )                     // und lese Fkp wieder ein
2766             pFkp->SetIdx( nIdx & 0xff );    // Dann stelle Fkp-Pos wieder ein
2767     }
2768 }
2769 
SeekPos(WW8_FC nFcPos)2770 bool WW8PLCFx_Fc_FKP::SeekPos(WW8_FC nFcPos)
2771 {
2772     // StartPos for next Where()
2773     SetStartFc( nFcPos );
2774 
2775     // find StartPos for next pPLCF->Get()
2776     bool bRet = pPLCF->SeekPos(nFcPos);
2777 
2778     // make FKP invalid?
2779     long nPLCFStart, nPLCFEnd;
2780     void* pPage;
2781     if( pFkp && pPLCF->Get( nPLCFStart, nPLCFEnd, pPage ) )
2782     {
2783         long nPo = SVBT16ToShort( (sal_uInt8 *)pPage );
2784         nPo <<= 9;                                          // shift als LONG
2785         if (nPo != pFkp->GetFilePos())
2786             pFkp = 0;
2787         else
2788             pFkp->SeekPos( nFcPos );
2789     }
2790     return bRet;
2791 }
2792 
Where()2793 WW8_FC WW8PLCFx_Fc_FKP::Where()
2794 {
2795     if( !pFkp )
2796     {
2797         if( !NewFkp() )
2798             return LONG_MAX;
2799     }
2800     WW8_FC nP = pFkp->Where();
2801     if( nP != LONG_MAX )
2802         return nP;
2803 
2804     pFkp = 0;                   // FKP beendet -> hole neuen
2805     return Where();                     // am einfachsten rekursiv
2806 }
2807 
GetSprmsAndPos(WW8_FC & rStart,WW8_FC & rEnd,long & rLen)2808 sal_uInt8* WW8PLCFx_Fc_FKP::GetSprmsAndPos(WW8_FC& rStart, WW8_FC& rEnd, long& rLen)
2809 {
2810     rLen = 0;                               // Default
2811     rStart = rEnd = LONG_MAX;
2812 
2813     if( !pFkp )     // Fkp not there ?
2814     {
2815         if( !NewFkp() )
2816             return 0;
2817     }
2818 
2819     sal_uInt8* pPos = pFkp->Get( rStart, rEnd, rLen );
2820     if( rStart == LONG_MAX )    //Not found
2821         return 0;
2822     return pPos;
2823 }
2824 
operator ++(int)2825 WW8PLCFx& WW8PLCFx_Fc_FKP::operator ++( int )
2826 {
2827     if( !pFkp )
2828     {
2829         if( !NewFkp() )
2830             return *this;
2831     }
2832 
2833     (*pFkp)++;
2834     if( pFkp->Where() == LONG_MAX )
2835         NewFkp();
2836 
2837     return *this;
2838 }
2839 
GetIstd() const2840 sal_uInt16 WW8PLCFx_Fc_FKP::GetIstd() const
2841 {
2842     return pFkp ? pFkp->GetIstd() : 0xFFFF;
2843 }
2844 
GetPCDSprms(WW8PLCFxDesc & rDesc)2845 void WW8PLCFx_Fc_FKP::GetPCDSprms( WW8PLCFxDesc& rDesc )
2846 {
2847     rDesc.pMemPos   = 0;
2848     rDesc.nSprmsLen = 0;
2849     if( pPCDAttrs )
2850     {
2851         if( !pFkp )
2852         {
2853             DBG_WARNING(
2854                 "+Problem: GetPCDSprms: NewFkp necessary (not possible!)" );
2855             if( !NewFkp() )
2856                 return;
2857         }
2858         pPCDAttrs->GetSprms(&rDesc);
2859     }
2860 }
2861 
HasSprm(sal_uInt16 nId)2862 const sal_uInt8* WW8PLCFx_Fc_FKP::HasSprm( sal_uInt16 nId )
2863 {
2864     // const waere schoener, aber dafuer muesste NewFkp() ersetzt werden oder
2865     // wegfallen
2866     if( !pFkp )
2867     {
2868         DBG_WARNING( "+Motz: HasSprm: NewFkp noetig ( kein const moeglich )" );
2869         // Passiert bei BugDoc 31722
2870         if( !NewFkp() )
2871             return 0;
2872     }
2873 
2874     const sal_uInt8* pRes = pFkp->HasSprm( nId );
2875 
2876     if( !pRes )
2877     {
2878         WW8PLCFxDesc aDesc;
2879         GetPCDSprms( aDesc );
2880 
2881         if (aDesc.pMemPos)
2882         {
2883             WW8SprmIter aIter(aDesc.pMemPos, aDesc.nSprmsLen,
2884                 pFkp->GetSprmParser());
2885             pRes = aIter.FindSprm(nId);
2886         }
2887     }
2888 
2889     return pRes;
2890 }
2891 
HasSprm(sal_uInt16 nId,std::vector<const sal_uInt8 * > & rResult)2892 bool WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId, std::vector<const sal_uInt8 *> &rResult)
2893 {
2894     // const waere schoener, aber dafuer muesste NewFkp() ersetzt werden oder
2895     // wegfallen
2896     if (!pFkp)
2897     {
2898        DBG_WARNING( "+Motz: HasSprm: NewFkp noetig ( kein const moeglich )" );
2899        // Passiert bei BugDoc 31722
2900        if( !NewFkp() )
2901            return 0;
2902     }
2903 
2904     pFkp->HasSprm(nId, rResult);
2905 
2906     WW8PLCFxDesc aDesc;
2907     GetPCDSprms( aDesc );
2908 
2909     if (aDesc.pMemPos)
2910     {
2911         WW8SprmIter aIter(aDesc.pMemPos, aDesc.nSprmsLen,
2912             pFkp->GetSprmParser());
2913         while(aIter.GetSprms())
2914         {
2915             if (aIter.GetAktId() == nId)
2916                 rResult.push_back(aIter.GetAktParams());
2917             aIter++;
2918         };
2919     }
2920     return !rResult.empty();
2921 }
2922 
2923 //-----------------------------------------
2924 
WW8PLCFx_Cp_FKP(SvStream * pSt,SvStream * pTblSt,SvStream * pDataSt,const WW8ScannerBase & rBase,ePLCFT ePl)2925 WW8PLCFx_Cp_FKP::WW8PLCFx_Cp_FKP( SvStream* pSt, SvStream* pTblSt,
2926     SvStream* pDataSt, const WW8ScannerBase& rBase, ePLCFT ePl )
2927     : WW8PLCFx_Fc_FKP(pSt, pTblSt, pDataSt, *rBase.pWw8Fib, ePl,
2928     rBase.WW8Cp2Fc(0)), rSBase(rBase), nAttrStart(-1), nAttrEnd(-1),
2929     bLineEnd(false),
2930     bComplex( (7 < rBase.pWw8Fib->nVersion) || (0 != rBase.pWw8Fib->fComplex) )
2931 {
2932     ResetAttrStartEnd();
2933 
2934     pPcd = rSBase.pPiecePLCF ? new WW8PLCFx_PCD( rBase.pWw8Fib->nVersion,
2935         rBase.pPiecePLCF, 0, ((6 == GetVersion()) || (7 == GetVersion())) )
2936         : 0;
2937 
2938     /*
2939     Make a copy of the piece attributes for so that the calls to HasSprm on a
2940     Fc_FKP will be able to take into account the current piece attributes,
2941     despite the fact that such attributes can only be found through a cp based
2942     mechanism.
2943     */
2944     if (pPcd)
2945     {
2946         pPCDAttrs = rSBase.pPLCFx_PCDAttrs ? new WW8PLCFx_PCDAttrs(
2947             rSBase.pWw8Fib->nVersion, pPcd, &rSBase) : 0;
2948     }
2949 
2950     pPieceIter = rSBase.pPieceIter;
2951 }
2952 
~WW8PLCFx_Cp_FKP()2953 WW8PLCFx_Cp_FKP::~WW8PLCFx_Cp_FKP()
2954 {
2955     delete pPcd;
2956 }
2957 
ResetAttrStartEnd()2958 void WW8PLCFx_Cp_FKP::ResetAttrStartEnd()
2959 {
2960     nAttrStart = -1;
2961     nAttrEnd   = -1;
2962     bLineEnd   = false;
2963 }
2964 
GetPCDIMax() const2965 sal_uLong WW8PLCFx_Cp_FKP::GetPCDIMax() const
2966 {
2967     return pPcd ? pPcd->GetIMax() : 0;
2968 }
2969 
GetPCDIdx() const2970 sal_uLong WW8PLCFx_Cp_FKP::GetPCDIdx() const
2971 {
2972     return pPcd ? pPcd->GetIdx() : 0;
2973 }
2974 
SetPCDIdx(sal_uLong nIdx)2975 void WW8PLCFx_Cp_FKP::SetPCDIdx( sal_uLong nIdx )
2976 {
2977     if( pPcd )
2978         pPcd->SetIdx( nIdx );
2979 }
2980 
SeekPos(WW8_CP nCpPos)2981 bool WW8PLCFx_Cp_FKP::SeekPos(WW8_CP nCpPos)
2982 {
2983     if( pPcd )  // Complex
2984     {
2985         if( !pPcd->SeekPos( nCpPos ) )  // Piece setzen
2986             return false;
2987         if (pPCDAttrs && !pPCDAttrs->GetIter()->SeekPos(nCpPos))
2988             return false;
2989         return WW8PLCFx_Fc_FKP::SeekPos(pPcd->AktPieceStartCp2Fc(nCpPos));
2990     }
2991                                     // KEINE Piece-Table !!!
2992     return WW8PLCFx_Fc_FKP::SeekPos( rSBase.WW8Cp2Fc(nCpPos) );
2993 }
2994 
Where()2995 WW8_CP WW8PLCFx_Cp_FKP::Where()
2996 {
2997     WW8_FC nFc = WW8PLCFx_Fc_FKP::Where();
2998     if( pPcd )
2999         return pPcd->AktPieceStartFc2Cp( nFc ); // Piece ermitteln
3000     return rSBase.WW8Fc2Cp( nFc );      // KEINE Piece-Table !!!
3001 }
3002 
GetSprms(WW8PLCFxDesc * p)3003 void WW8PLCFx_Cp_FKP::GetSprms(WW8PLCFxDesc* p)
3004 {
3005     WW8_CP nOrigCp = p->nStartPos;
3006 
3007     if (!GetDirty())        //Normal case
3008     {
3009         p->pMemPos = WW8PLCFx_Fc_FKP::GetSprmsAndPos(p->nStartPos, p->nEndPos,
3010             p->nSprmsLen);
3011     }
3012     else
3013     {
3014         /*
3015         #93702#
3016         For the odd case where we have a location in a fastsaved file which
3017         does not have an entry in the FKP, perhaps its para end is in the next
3018         piece, or perhaps the cp just doesn't exist at all in this document.
3019         AdvSprm doesn't know so it sets the PLCF as dirty and we figure out
3020         in this method what the situation is
3021 
3022         It doesn't exist then the piece iterator will not be able to find it.
3023         Otherwise our cool fastsave algorithm can be brought to bear on the
3024         problem.
3025         */
3026         sal_uLong nOldPos = pPieceIter->GetIdx();
3027         bool bOk = pPieceIter->SeekPos(nOrigCp);
3028         pPieceIter->SetIdx( nOldPos );
3029         if (!bOk)
3030             return;
3031     }
3032 
3033     if( pPcd )  // Piece-Table vorhanden !!!
3034     {
3035         // Init ( noch kein ++ gerufen )
3036         if( (nAttrStart >  nAttrEnd) || (nAttrStart == -1) )
3037         {
3038             p->bRealLineEnd = (ePLCF == PAP);
3039 
3040             if ( ((ePLCF == PAP ) || (ePLCF == CHP)) && (nOrigCp != LONG_MAX) )
3041             {
3042                 bool bIsUnicode=false;
3043                 /*
3044                 To find the end of a paragraph for a character in a
3045                 complex format file.
3046 
3047                 It is necessary to know the piece that contains the
3048                 character and the FC assigned to the character.
3049                 */
3050 
3051                 //We set the piece iterator to the piece that contains the
3052                 //character, now we have the correct piece for this character
3053                 sal_uLong nOldPos = pPieceIter->GetIdx();
3054                 p->nStartPos = nOrigCp;
3055                 pPieceIter->SeekPos( p->nStartPos);
3056 
3057                 //This is the FC assigned to the character, but we already
3058                 //have the result of the next stage, so we can skip this step
3059                 //WW8_FC nStartFc = rSBase.WW8Cp2Fc(p->nStartPos, &bIsUnicode);
3060 
3061                 /*
3062                 Using the FC of the character, first search the FKP that
3063                 describes the character to find the smallest FC in the rgfc
3064                 that is larger than the character FC.
3065                 */
3066                 //But the search has already been done, the next largest FC is
3067                 //p->nEndPos.
3068                 WW8_FC nOldEndPos = p->nEndPos;
3069 
3070                 /*
3071                 If the FC found in the FKP is less than or equal to the limit
3072                 FC of the piece, the end of the paragraph that contains the
3073                 character is at the FKP FC minus 1.
3074                 */
3075                 long nCpStart, nCpEnd;
3076                 void* pData;
3077                 pPieceIter->Get(nCpStart, nCpEnd, pData);
3078 
3079                 WW8_FC nLimitFC = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
3080                 WW8_FC nBeginLimitFC = nLimitFC;
3081                 if( 8 <= GetVersion() )
3082                 {
3083                     nBeginLimitFC =
3084                         WW8PLCFx_PCD::TransformPieceAddress(nLimitFC,
3085                         bIsUnicode);
3086                 }
3087                 nLimitFC = nBeginLimitFC +
3088                     (nCpEnd - nCpStart) * (bIsUnicode ? 2 : 1);
3089 
3090                 if (nOldEndPos <= nLimitFC)
3091                 {
3092                     p->nEndPos = nCpEnd -
3093                         (nLimitFC-nOldEndPos) / (bIsUnicode ? 2 : 1);
3094                 }
3095                 else
3096                 {
3097                     if (ePLCF == CHP)
3098                         p->nEndPos = nCpEnd;
3099                     else
3100                     {
3101                         /*
3102                         If the FKP FC that was found was greater than the FC
3103                         of the end of the piece, scan piece by piece toward
3104                         the end of the document until a piece is found that
3105                         contains a  paragraph end mark.
3106                         */
3107 
3108                         /*
3109                         It's possible to check if a piece contains a paragraph
3110                         mark by using the FC of the beginning of the piece to
3111                         search in the FKPs for the smallest FC in the FKP rgfc
3112                         that is greater than the FC of the beginning of the
3113                         piece. If the FC found is less than or equal to the
3114                         limit FC of the piece, then the character that ends
3115                         the paragraph is the character immediately before the
3116                         FKP fc
3117                         */
3118 
3119                         (*pPieceIter)++;
3120 
3121                         for (;pPieceIter->GetIdx() < pPieceIter->GetIMax();
3122                             (*pPieceIter)++)
3123                         {
3124                             if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) )
3125                             {
3126                                 ASSERT( !this, "piece iter broken!" );
3127                                 break;
3128                             }
3129                             bIsUnicode = false;
3130                             sal_Int32 nFcStart=SVBT32ToUInt32(((WW8_PCD*)pData)->fc);
3131 
3132                             if( 8 <= GetVersion() )
3133                             {
3134                                 nFcStart =
3135                                     WW8PLCFx_PCD::TransformPieceAddress(
3136                                     nFcStart,bIsUnicode );
3137                             }
3138                             nLimitFC = nFcStart + (nCpEnd - nCpStart) *
3139                                 (bIsUnicode ? 2 : 1);
3140 
3141                             //if it doesn't exist, skip it
3142                             if (!SeekPos(nCpStart))
3143                                 continue;
3144 
3145                             WW8_FC nOne,nSmallest;
3146                             p->pMemPos = WW8PLCFx_Fc_FKP::GetSprmsAndPos(nOne,
3147                                 nSmallest, p->nSprmsLen);
3148 
3149                             if (nSmallest <= nLimitFC)
3150                             {
3151                                 p->nEndPos = nCpEnd -
3152                                     (nLimitFC-nSmallest) / (bIsUnicode ? 2 : 1);
3153                                 break;
3154                             }
3155                         }
3156                     }
3157                 }
3158                 pPieceIter->SetIdx( nOldPos );
3159             }
3160             else
3161                 pPcd->AktPieceFc2Cp( p->nStartPos, p->nEndPos,&rSBase );
3162         }
3163         else
3164         {
3165             p->nStartPos = nAttrStart;
3166             p->nEndPos = nAttrEnd;
3167             p->bRealLineEnd = bLineEnd;
3168         }
3169     }
3170     else        // KEINE Piece-Table !!!
3171     {
3172         p->nStartPos = rSBase.WW8Fc2Cp( p->nStartPos );
3173         p->nEndPos   = rSBase.WW8Fc2Cp( p->nEndPos );
3174         p->bRealLineEnd = ePLCF == PAP;
3175     }
3176 }
3177 
operator ++(int)3178 WW8PLCFx& WW8PLCFx_Cp_FKP::operator ++( int )
3179 {
3180     WW8PLCFx_Fc_FKP::operator ++( 0 );
3181     // !pPcd: Notbremse
3182     if ( !bComplex || !pPcd )
3183         return *this;
3184 
3185     if( GetPCDIdx() >= GetPCDIMax() )           // End of PLCF
3186     {
3187         nAttrStart = nAttrEnd = LONG_MAX;
3188         return *this;
3189     }
3190 
3191     long nFkpLen;                               // Fkp-Eintrag
3192     // Fkp-Eintrag holen
3193     WW8PLCFx_Fc_FKP::GetSprmsAndPos(nAttrStart, nAttrEnd, nFkpLen);
3194 
3195     pPcd->AktPieceFc2Cp( nAttrStart, nAttrEnd, &rSBase );
3196     bLineEnd = (ePLCF == PAP);
3197     return *this;
3198 }
3199 
3200 //-----------------------------------------
3201 //-----------------------------------------
3202 
WW8PLCFx_SEPX(SvStream * pSt,SvStream * pTblSt,const WW8Fib & rFib,WW8_CP nStartCp)3203 WW8PLCFx_SEPX::WW8PLCFx_SEPX(SvStream* pSt, SvStream* pTblSt,
3204     const WW8Fib& rFib, WW8_CP nStartCp)
3205     : WW8PLCFx(rFib.nVersion, true), maSprmParser(rFib.nVersion), pStrm(pSt),
3206     nArrMax(256), nSprmSiz(0)
3207 {
3208     pPLCF =   rFib.lcbPlcfsed
3209             ? new WW8PLCF(pTblSt, rFib.fcPlcfsed, rFib.lcbPlcfsed, 12, nStartCp)
3210             : 0;
3211 
3212     pSprms = new sal_uInt8[nArrMax];        // maximum length
3213 }
3214 
~WW8PLCFx_SEPX()3215 WW8PLCFx_SEPX::~WW8PLCFx_SEPX()
3216 {
3217     delete pPLCF;
3218     delete[] pSprms;
3219 }
3220 
GetIdx() const3221 sal_uLong WW8PLCFx_SEPX::GetIdx() const
3222 {
3223     return pPLCF ? pPLCF->GetIdx() : 0;
3224 }
3225 
SetIdx(sal_uLong nIdx)3226 void WW8PLCFx_SEPX::SetIdx( sal_uLong nIdx )
3227 {
3228     if( pPLCF ) pPLCF->SetIdx( nIdx );
3229 }
3230 
SeekPos(WW8_CP nCpPos)3231 bool WW8PLCFx_SEPX::SeekPos(WW8_CP nCpPos)
3232 {
3233     return pPLCF ? pPLCF->SeekPos( nCpPos ) : 0;
3234 }
3235 
Where()3236 WW8_CP WW8PLCFx_SEPX::Where()
3237 {
3238     return pPLCF ? pPLCF->Where() : 0;
3239 }
3240 
GetSprms(WW8PLCFxDesc * p)3241 void WW8PLCFx_SEPX::GetSprms(WW8PLCFxDesc* p)
3242 {
3243     if( !pPLCF ) return;
3244 
3245     void* pData;
3246 
3247     p->bRealLineEnd = false;
3248     if (!pPLCF->Get( p->nStartPos, p->nEndPos, pData ))
3249     {
3250         p->nStartPos = p->nEndPos = LONG_MAX;       // PLCF fertig abgearbeitet
3251         p->pMemPos = 0;
3252         p->nSprmsLen = 0;
3253     }
3254     else
3255     {
3256         long nPo =  SVBT32ToUInt32( (sal_uInt8*)pData+2 );
3257         if (nPo == -1L)
3258         {
3259             p->nStartPos = p->nEndPos = LONG_MAX;       // Sepx empty
3260             p->pMemPos = 0;
3261             p->nSprmsLen = 0;
3262         }
3263         else
3264         {
3265             pStrm->Seek( nPo );
3266             *pStrm >> nSprmSiz; // read len
3267 
3268             if( nSprmSiz > nArrMax )
3269             {               // passt nicht
3270                 delete[] pSprms;
3271                 nArrMax = nSprmSiz;                 // Hole mehr Speicher
3272                 pSprms = new sal_uInt8[nArrMax];
3273             }
3274             pStrm->Read( pSprms, nSprmSiz );        // read Sprms
3275 
3276             p->nSprmsLen = nSprmSiz;
3277             p->pMemPos = pSprms;                    // return Position
3278         }
3279     }
3280 }
3281 
operator ++(int)3282 WW8PLCFx& WW8PLCFx_SEPX::operator ++( int )
3283 {
3284     if( pPLCF )
3285         (*pPLCF)++;
3286     return *this;
3287 }
3288 
HasSprm(sal_uInt16 nId) const3289 const sal_uInt8* WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId ) const
3290 {
3291     return HasSprm( nId, pSprms, nSprmSiz);
3292 }
3293 
HasSprm(sal_uInt16 nId,const sal_uInt8 * pOtherSprms,long nOtherSprmSiz) const3294 const sal_uInt8* WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId, const sal_uInt8*  pOtherSprms,
3295     long nOtherSprmSiz ) const
3296 {
3297     const sal_uInt8 *pRet = 0;
3298     if (pPLCF)
3299     {
3300         WW8SprmIter aIter(pOtherSprms, nOtherSprmSiz, maSprmParser);
3301         pRet = aIter.FindSprm(nId);
3302     }
3303     return pRet;
3304 }
3305 
Find4Sprms(sal_uInt16 nId1,sal_uInt16 nId2,sal_uInt16 nId3,sal_uInt16 nId4,sal_uInt8 * & p1,sal_uInt8 * & p2,sal_uInt8 * & p3,sal_uInt8 * & p4) const3306 bool WW8PLCFx_SEPX::Find4Sprms(sal_uInt16 nId1,sal_uInt16 nId2,sal_uInt16 nId3,sal_uInt16 nId4,
3307     sal_uInt8*& p1, sal_uInt8*& p2, sal_uInt8*& p3, sal_uInt8*& p4) const
3308 {
3309     if( !pPLCF )
3310         return 0;
3311 
3312     bool bFound = false;
3313     p1 = 0;
3314     p2 = 0;
3315     p3 = 0;
3316     p4 = 0;
3317 
3318     sal_uInt8* pSp = pSprms;
3319     sal_uInt16 i=0;
3320     while (i + maSprmParser.MinSprmLen() <= nSprmSiz)
3321     {
3322         // Sprm gefunden?
3323         sal_uInt16 nAktId = maSprmParser.GetSprmId(pSp);
3324         bool bOk = true;
3325         if( nAktId  == nId1 )
3326             p1 = pSp + maSprmParser.DistanceToData(nId1);
3327         else if( nAktId  == nId2 )
3328             p2 = pSp + maSprmParser.DistanceToData(nId2);
3329         else if( nAktId  == nId3 )
3330             p3 = pSp + maSprmParser.DistanceToData(nId3);
3331         else if( nAktId  == nId4 )
3332             p4 = pSp + maSprmParser.DistanceToData(nId4);
3333         else
3334             bOk = false;
3335         bFound |= bOk;
3336         // erhoehe Zeiger, so dass er auf naechsten Sprm zeigt
3337         sal_uInt16 x = maSprmParser.GetSprmSize(nAktId, pSp);
3338         i += x;
3339         pSp += x;
3340     }
3341     return bFound;
3342 }
3343 
HasSprm(sal_uInt16 nId,sal_uInt8 n2nd) const3344 const sal_uInt8* WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId, sal_uInt8 n2nd ) const
3345 {
3346     if( !pPLCF )
3347         return 0;
3348 
3349     sal_uInt8* pSp = pSprms;
3350 
3351     sal_uInt16 i=0;
3352     while (i + maSprmParser.MinSprmLen() <= nSprmSiz)
3353     {
3354         // Sprm gefunden?
3355         sal_uInt16 nAktId = maSprmParser.GetSprmId(pSp);
3356         if (nAktId == nId)
3357         {
3358             sal_uInt8 *pRet = pSp + maSprmParser.DistanceToData(nId);
3359             if (*pRet == n2nd)
3360                 return pRet;
3361         }
3362         // erhoehe Zeiger, so dass er auf naechsten Sprm zeigt
3363         sal_uInt16 x = maSprmParser.GetSprmSize(nAktId, pSp);
3364         i += x;
3365         pSp += x;
3366     }
3367 
3368     return 0;   // Sprm nicht gefunden
3369 }
3370 
3371 //-----------------------------------------
WW8PLCFx_SubDoc(SvStream * pSt,sal_uInt8 nVersion,WW8_CP nStartCp,long nFcRef,long nLenRef,long nFcTxt,long nLenTxt,long nStruct)3372 WW8PLCFx_SubDoc::WW8PLCFx_SubDoc(SvStream* pSt, sal_uInt8 nVersion,
3373     WW8_CP nStartCp, long nFcRef, long nLenRef, long nFcTxt, long nLenTxt,
3374     long nStruct)
3375     : WW8PLCFx(nVersion, false), pRef(0), pTxt(0)
3376 {
3377     if( nLenRef && nLenTxt )
3378     {
3379         pRef = new WW8PLCF( pSt, nFcRef, nLenRef, nStruct, nStartCp );
3380         pTxt = new WW8PLCF( pSt, nFcTxt, nLenTxt, 0, nStartCp );
3381     }
3382 }
3383 
~WW8PLCFx_SubDoc()3384 WW8PLCFx_SubDoc::~WW8PLCFx_SubDoc()
3385 {
3386     delete pRef;
3387     delete pTxt;
3388 }
3389 
GetIdx() const3390 sal_uLong WW8PLCFx_SubDoc::GetIdx() const
3391 {
3392     // Wahrscheinlich pTxt... nicht noetig
3393     if( pRef )
3394         return ( pRef->GetIdx() << 16 | pTxt->GetIdx() );
3395     return 0;
3396 }
3397 
SetIdx(sal_uLong nIdx)3398 void WW8PLCFx_SubDoc::SetIdx( sal_uLong nIdx )
3399 {
3400     if( pRef )
3401     {
3402         pRef->SetIdx( nIdx >> 16 );
3403         // Wahrscheinlich pTxt... nicht noetig
3404         pTxt->SetIdx( nIdx & 0xFFFF );
3405     }
3406 }
3407 
SeekPos(WW8_CP nCpPos)3408 bool WW8PLCFx_SubDoc::SeekPos( WW8_CP nCpPos )
3409 {
3410     return ( pRef ) ? pRef->SeekPos( nCpPos ) : false;
3411 }
3412 
Where()3413 WW8_CP WW8PLCFx_SubDoc::Where()
3414 {
3415     return ( pRef ) ? pRef->Where() : LONG_MAX;
3416 }
3417 
GetNoSprms(WW8_CP & rStart,long & rEnd,long & rLen)3418 long WW8PLCFx_SubDoc::GetNoSprms( WW8_CP& rStart, long& rEnd, long& rLen )
3419 {
3420     void* pData;
3421     long nSt, nE;
3422     rEnd = LONG_MAX;
3423 
3424     if ( !pRef )
3425     {
3426         rStart  = LONG_MAX;             // Es gibt keine Noten
3427         rLen = 0;
3428         return -1;
3429     }
3430 
3431     sal_uLong nNr = pRef->GetIdx();
3432 
3433     if (!pRef->Get( rStart, nE, pData ))
3434     {
3435         rStart = LONG_MAX;              // PLCF fertig abgearbeitet
3436         rLen = 0;
3437         return -1;
3438     }
3439     pTxt->SetIdx( nNr );
3440 
3441     if(!pTxt->Get( nSt, rLen, pData ))
3442     {
3443         rStart = LONG_MAX;              // PLCF fertig abgearbeitet
3444         rLen = 0;
3445         return -1;
3446     }
3447 
3448     rLen -= nSt;
3449     return nSt;
3450 }
3451 
operator ++(int)3452 WW8PLCFx& WW8PLCFx_SubDoc::operator ++( int )
3453 {
3454     if( pRef && pTxt )
3455     {
3456         (*pRef)++;
3457         (*pTxt)++;
3458     }
3459     return *this;
3460 }
3461 
3462 //-----------------------------------------
3463 //          Felder
3464 //-----------------------------------------
3465 
WW8PLCFx_FLD(SvStream * pSt,const WW8Fib & rMyFib,short nType)3466 WW8PLCFx_FLD::WW8PLCFx_FLD( SvStream* pSt, const WW8Fib& rMyFib, short nType)
3467     : WW8PLCFx(rMyFib.nVersion, true), pPLCF(0), rFib(rMyFib)
3468 {
3469     long nFc, nLen;
3470 
3471     switch( nType )
3472     {
3473     case MAN_HDFT:
3474         nFc = rFib.fcPlcffldHdr;
3475         nLen = rFib.lcbPlcffldHdr;
3476         break;
3477     case MAN_FTN:
3478         nFc = rFib.fcPlcffldFtn;
3479         nLen = rFib.lcbPlcffldFtn;
3480         break;
3481     case MAN_EDN:
3482         nFc = rFib.fcPlcffldEdn;
3483         nLen = rFib.lcbPlcffldEdn;
3484         break;
3485     case MAN_AND:
3486         nFc = rFib.fcPlcffldAtn;
3487         nLen = rFib.lcbPlcffldAtn;
3488         break;
3489     case MAN_TXBX:
3490         nFc = rFib.fcPlcffldTxbx;
3491         nLen = rFib.lcbPlcffldTxbx;
3492         break;
3493     case MAN_TXBX_HDFT:
3494         nFc = rFib.fcPlcffldHdrTxbx;
3495         nLen = rFib.lcbPlcffldHdrTxbx;
3496         break;
3497     default:
3498         nFc = rFib.fcPlcffldMom;
3499         nLen = rFib.lcbPlcffldMom;
3500         break;
3501     }
3502 
3503     if( nLen )
3504         pPLCF = new WW8PLCFspecial( pSt, nFc, nLen, 2 );
3505 }
3506 
~WW8PLCFx_FLD()3507 WW8PLCFx_FLD::~WW8PLCFx_FLD()
3508 {
3509     delete pPLCF;
3510 }
3511 
GetIdx() const3512 sal_uLong WW8PLCFx_FLD::GetIdx() const
3513 {
3514     return pPLCF ? pPLCF->GetIdx() : 0;
3515 }
3516 
SetIdx(sal_uLong nIdx)3517 void WW8PLCFx_FLD::SetIdx( sal_uLong nIdx )
3518 {
3519     if( pPLCF )
3520         pPLCF->SetIdx( nIdx );
3521 }
3522 
SeekPos(WW8_CP nCpPos)3523 bool WW8PLCFx_FLD::SeekPos(WW8_CP nCpPos)
3524 {
3525     return pPLCF ? pPLCF->SeekPosExact( nCpPos ) : false;
3526 }
3527 
Where()3528 WW8_CP WW8PLCFx_FLD::Where()
3529 {
3530     return pPLCF ? pPLCF->Where() : LONG_MAX;
3531 }
3532 
StartPosIsFieldStart()3533 bool WW8PLCFx_FLD::StartPosIsFieldStart()
3534 {
3535     void* pData;
3536     long nTest;
3537     if (
3538          (!pPLCF || !pPLCF->Get(nTest, pData) ||
3539          ((((sal_uInt8*)pData)[0] & 0x1f) != 0x13))
3540        )
3541         return false;
3542     return true;
3543 }
3544 
EndPosIsFieldEnd(WW8_CP & nCP)3545 bool WW8PLCFx_FLD::EndPosIsFieldEnd(WW8_CP& nCP)
3546 {
3547     bool bRet = false;
3548 
3549     if (pPLCF)
3550     {
3551         long n = pPLCF->GetIdx();
3552 
3553         (*pPLCF)++;
3554 
3555         void* pData;
3556         long nTest;
3557         if ( pPLCF->Get(nTest, pData) && ((((sal_uInt8*)pData)[0] & 0x1f) == 0x15) )
3558         {
3559             nCP = nTest;
3560             bRet = true;
3561         }
3562 
3563         pPLCF->SetIdx(n);
3564     }
3565 
3566     return bRet;
3567 }
3568 
GetSprms(WW8PLCFxDesc * p)3569 void WW8PLCFx_FLD::GetSprms(WW8PLCFxDesc* p)
3570 {
3571     p->nStartPos = p->nEndPos = LONG_MAX;
3572     p->pMemPos = 0;
3573     p->nSprmsLen = 0;
3574     p->bRealLineEnd = false;
3575 
3576     if (!pPLCF)
3577     {
3578         p->nStartPos = LONG_MAX;                    // Es gibt keine Felder
3579         return;
3580     }
3581 
3582     long n = pPLCF->GetIdx();
3583 
3584     long nP;
3585     void *pData;
3586     if (!pPLCF->Get(nP, pData))             // Ende des PLCFspecial ?
3587     {
3588         p->nStartPos = LONG_MAX;            // PLCF fertig abgearbeitet
3589         return;
3590     }
3591 
3592     p->nStartPos = nP;
3593 
3594     (*pPLCF)++;
3595     if (!pPLCF->Get(nP, pData))             // Ende des PLCFspecial ?
3596     {
3597         p->nStartPos = LONG_MAX;            // PLCF fertig abgearbeitet
3598         return;
3599     }
3600 
3601     p->nEndPos = nP;
3602 
3603     pPLCF->SetIdx(n);
3604 
3605     p->nCp2OrIdx = pPLCF->GetIdx();
3606 }
3607 
operator ++(int)3608 WW8PLCFx& WW8PLCFx_FLD::operator ++( int )
3609 {
3610     (*pPLCF)++;
3611     return *this;
3612 }
3613 
GetPara(long nIdx,WW8FieldDesc & rF)3614 bool WW8PLCFx_FLD::GetPara(long nIdx, WW8FieldDesc& rF)
3615 {
3616     ASSERT( pPLCF, "Aufruf ohne Feld PLCFspecial" );
3617     if( !pPLCF )
3618         return false;
3619 
3620     long n = pPLCF->GetIdx();
3621     pPLCF->SetIdx(nIdx);
3622 
3623     bool bOk = WW8GetFieldPara(*pPLCF, rF);
3624 
3625     pPLCF->SetIdx(n);
3626     return bOk;
3627 }
3628 
3629 //-----------------------------------------
3630 //      class WW8PLCF_Book
3631 //-----------------------------------------
3632 
3633 /*  to be optimized like this:    */
WW8ReadSTTBF(bool bVer8,SvStream & rStrm,sal_uInt32 nStart,sal_Int32 nLen,sal_uInt16 nExtraLen,rtl_TextEncoding eCS,std::vector<String> & rArray,std::vector<String> * pExtraArray)3634 void WW8ReadSTTBF(bool bVer8, SvStream& rStrm, sal_uInt32 nStart, sal_Int32 nLen,
3635     sal_uInt16 nExtraLen, rtl_TextEncoding eCS, std::vector<String> &rArray,
3636     std::vector<String>* pExtraArray)
3637 {
3638     sal_uLong nOldPos = rStrm.Tell();
3639     rStrm.Seek( nStart );
3640 
3641     sal_uInt16 nLen2;
3642     rStrm >> nLen2; // bVer67: total length of structure
3643                     // bVer8 : count of strings
3644 
3645     if( bVer8 )
3646     {
3647         sal_uInt16 nStrings;
3648         bool bUnicode = (0xFFFF == nLen2);
3649         if( bUnicode )
3650             rStrm >> nStrings;
3651         else
3652             nStrings = nLen2;
3653 
3654         rStrm >> nExtraLen;
3655 
3656         for( sal_uInt16 i=0; i < nStrings; i++ )
3657         {
3658             if( bUnicode )
3659                 rArray.push_back(WW8Read_xstz(rStrm, 0, false));
3660             else
3661             {
3662                 sal_uInt8 nBChar;
3663                 rStrm >> nBChar;
3664                 ByteString aTmp;
3665                 SafeReadString(aTmp,nBChar,rStrm);
3666                 rArray.push_back(String(aTmp, eCS));
3667             }
3668 
3669             // Skip the extra data
3670             if( nExtraLen )
3671             {
3672                 if (pExtraArray)
3673                 {
3674                     ByteString aTmp;
3675                     SafeReadString(aTmp,nExtraLen,rStrm);
3676                     pExtraArray->push_back(String(aTmp, eCS));
3677                 }
3678                 else
3679                     rStrm.SeekRel( nExtraLen );
3680             }
3681         }
3682     }
3683     else
3684     {
3685         sal_uInt8 nBChar;
3686         if( nLen2 != nLen )
3687         {
3688             ASSERT( nLen2 == nLen, "Fib length and read length are different" );
3689             if (nLen > USHRT_MAX)
3690                 nLen = USHRT_MAX;
3691             else if (nLen < 2 )
3692                 nLen = 2;
3693             nLen2 = static_cast<sal_uInt16>(nLen);
3694         }
3695         sal_uLong nRead = 0;
3696         for( nLen2 -= 2; nRead < nLen2;  )
3697         {
3698             rStrm >> nBChar; ++nRead;
3699             if (nBChar)
3700             {
3701                 ByteString aTmp;
3702                 nRead += SafeReadString(aTmp,nBChar,rStrm);
3703                 rArray.push_back(String(aTmp, eCS));
3704             }
3705             else
3706                 rArray.push_back(aEmptyStr);
3707 
3708             // #89125# Skip the extra data (for bVer67 versions this must come
3709             // from external knowledge)
3710             if (nExtraLen)
3711             {
3712                 if (pExtraArray)
3713                 {
3714                     ByteString aTmp;
3715                     SafeReadString(aTmp,nExtraLen,rStrm);
3716                     pExtraArray->push_back(String(aTmp, eCS));
3717                 }
3718                 else
3719                     rStrm.SeekRel( nExtraLen );
3720                 nRead+=nExtraLen;
3721             }
3722         }
3723     }
3724     rStrm.Seek( nOldPos );
3725 }
3726 
WW8PLCFx_Book(SvStream * pTblSt,const WW8Fib & rFib)3727 WW8PLCFx_Book::WW8PLCFx_Book(SvStream* pTblSt, const WW8Fib& rFib)
3728     : WW8PLCFx(rFib.nVersion, false), pStatus(0), nIsEnd(0)
3729 {
3730     if( !rFib.fcPlcfbkf || !rFib.lcbPlcfbkf || !rFib.fcPlcfbkl ||
3731         !rFib.lcbPlcfbkl || !rFib.fcSttbfbkmk || !rFib.lcbSttbfbkmk )
3732     {
3733         pBook[0] = pBook[1] = 0;
3734         nIMax = 0;
3735     }
3736     else
3737     {
3738         pBook[0] = new WW8PLCFspecial(pTblSt,rFib.fcPlcfbkf,rFib.lcbPlcfbkf,4);
3739 
3740         pBook[1] = new WW8PLCFspecial( pTblSt, rFib.fcPlcfbkl, rFib.lcbPlcfbkl,
3741             0, -1, true);
3742 
3743         rtl_TextEncoding eStructChrSet = WW8Fib::GetFIBCharset(rFib.chseTables);
3744 
3745         WW8ReadSTTBF( (7 < rFib.nVersion), *pTblSt, rFib.fcSttbfbkmk,
3746             rFib.lcbSttbfbkmk, 0, eStructChrSet, aBookNames );
3747 
3748         nIMax = aBookNames.size();
3749 
3750         if( pBook[0]->GetIMax() < nIMax )   // Count of Bookmarks
3751             nIMax = pBook[0]->GetIMax();
3752         pStatus = new eBookStatus[ nIMax ];
3753         memset( pStatus, 0, nIMax * sizeof( eBookStatus ) );
3754     }
3755 }
3756 
~WW8PLCFx_Book()3757 WW8PLCFx_Book::~WW8PLCFx_Book()
3758 {
3759     delete[] pStatus;
3760     delete pBook[1];
3761     delete pBook[0];
3762 }
3763 
GetIdx() const3764 sal_uLong WW8PLCFx_Book::GetIdx() const
3765 {
3766     return nIMax ? pBook[0]->GetIdx() : 0;
3767 }
3768 
SetIdx(sal_uLong nI)3769 void WW8PLCFx_Book::SetIdx( sal_uLong nI )
3770 {
3771     if( nIMax )
3772         pBook[0]->SetIdx( nI );
3773 }
3774 
GetIdx2() const3775 sal_uLong WW8PLCFx_Book::GetIdx2() const
3776 {
3777     return nIMax ? ( pBook[1]->GetIdx() | ( ( nIsEnd ) ? 0x80000000 : 0 ) ) : 0;
3778 }
3779 
SetIdx2(sal_uLong nI)3780 void WW8PLCFx_Book::SetIdx2( sal_uLong nI )
3781 {
3782     if( nIMax )
3783     {
3784         pBook[1]->SetIdx( nI & 0x7fffffff );
3785         nIsEnd = (sal_uInt16)( ( nI >> 31 ) & 1 );  // 0 oder 1
3786     }
3787 }
3788 
SeekPos(WW8_CP nCpPos)3789 bool WW8PLCFx_Book::SeekPos(WW8_CP nCpPos)
3790 {
3791     if( !pBook[0] )
3792         return false;
3793 
3794     bool bOk = pBook[0]->SeekPosExact( nCpPos );
3795     bOk &= pBook[1]->SeekPosExact( nCpPos );
3796     nIsEnd = 0;
3797 
3798     return bOk;
3799 }
3800 
Where()3801 WW8_CP WW8PLCFx_Book::Where()
3802 {
3803     return pBook[nIsEnd]->Where();
3804 }
3805 
GetNoSprms(long & rStart,long & rEnd,long & rLen)3806 long WW8PLCFx_Book::GetNoSprms( long& rStart, long& rEnd, long& rLen )
3807 {
3808     void* pData;
3809     rEnd = LONG_MAX;
3810     rLen = 0;
3811 
3812     if (!pBook[0] || !pBook[1] || !nIMax || (pBook[nIsEnd]->GetIdx()) >= nIMax)
3813     {
3814         rStart = rEnd = LONG_MAX;
3815         return -1;
3816     }
3817 
3818     pBook[nIsEnd]->Get( rStart, pData );    // Pos. abfragen
3819 
3820     return pBook[nIsEnd]->GetIdx();
3821 }
3822 
3823 // Der Operator ++ hat eine Tuecke: Wenn 2 Bookmarks aneinandergrenzen, dann
3824 // sollte erst das Ende des ersten und dann der Anfang des 2. erreicht werden.
3825 // Liegen jedoch 2 Bookmarks der Laenge 0 aufeinander, *muss* von jedem Bookmark
3826 // erst der Anfang und dann das Ende gefunden werden.
3827 // Der Fall: ][
3828 //            [...]
3829 //           ][
3830 // ist noch nicht geloest, dabei muesste ich in den Anfangs- und Endindices
3831 // vor- und zurueckspringen, wobei ein weiterer Index oder ein Bitfeld
3832 // oder etwas aehnliches zum Merken der bereits abgearbeiteten Bookmarks
3833 // noetig wird.
operator ++(int)3834 WW8PLCFx& WW8PLCFx_Book::operator ++( int )
3835 {
3836     if( pBook[0] && pBook[1] && nIMax )
3837     {
3838         (*pBook[nIsEnd])++;
3839 
3840         sal_uLong l0 = pBook[0]->Where();
3841         sal_uLong l1 = pBook[1]->Where();
3842         if( l0 < l1 )
3843             nIsEnd = 0;
3844         else if( l1 < l0 )
3845             nIsEnd = 1;
3846         else
3847             nIsEnd = ( nIsEnd ) ? 0 : 1;
3848     }
3849     return *this;
3850 }
3851 
GetLen() const3852 long WW8PLCFx_Book::GetLen() const
3853 {
3854     if( nIsEnd )
3855     {
3856         ASSERT( !this, "Falscher Aufruf (1) von PLCF_Book::GetLen()" );
3857         return 0;
3858     }
3859     void * p;
3860     WW8_CP nStartPos;
3861     if( !pBook[0]->Get( nStartPos, p ) )
3862     {
3863         ASSERT( !this, "Falscher Aufruf (2) von PLCF_Book::GetLen()" );
3864         return 0;
3865     }
3866     sal_uInt16 nEndIdx = SVBT16ToShort( *((SVBT16*)p) );
3867     long nNum = pBook[1]->GetPos( nEndIdx );
3868     nNum -= nStartPos;
3869     return nNum;
3870 }
3871 
SetStatus(sal_uInt16 nIndex,eBookStatus eStat)3872 void WW8PLCFx_Book::SetStatus(sal_uInt16 nIndex, eBookStatus eStat )
3873 {
3874     ASSERT(nIndex < nIMax, "set status of non existing bookmark!");
3875     if ( nIndex < nIMax )
3876         pStatus[nIndex] = (eBookStatus)( pStatus[nIndex] | eStat );
3877 }
3878 
GetStatus() const3879 eBookStatus WW8PLCFx_Book::GetStatus() const
3880 {
3881     if( !pStatus )
3882         return BOOK_NORMAL;
3883     long nEndIdx = GetHandle();
3884     return ( nEndIdx < nIMax ) ? pStatus[nEndIdx] : BOOK_NORMAL;
3885 }
3886 
GetHandle() const3887 long WW8PLCFx_Book::GetHandle() const
3888 {
3889     if( !pBook[0] || !pBook[1] )
3890         return LONG_MAX;
3891 
3892     if( nIsEnd )
3893         return pBook[1]->GetIdx();
3894     else
3895     {
3896         if (const void* p = pBook[0]->GetData(pBook[0]->GetIdx()))
3897             return SVBT16ToShort( *((SVBT16*)p) );
3898         else
3899             return LONG_MAX;
3900     }
3901 }
3902 
GetBookmark(long nStart,long nEnd,sal_uInt16 & nIndex)3903 String WW8PLCFx_Book::GetBookmark(long nStart,long nEnd, sal_uInt16 &nIndex)
3904 {
3905     bool bFound = false;
3906     sal_uInt16 i = 0;
3907     if( pBook[0] && pBook[1] )
3908     {
3909         WW8_CP nStartAkt, nEndAkt;
3910         do
3911         {
3912             void* p;
3913             sal_uInt16 nEndIdx;
3914 
3915             if( pBook[0]->GetData( i, nStartAkt, p ) && p )
3916                 nEndIdx = SVBT16ToShort( *((SVBT16*)p) );
3917             else
3918             {
3919                 ASSERT( !this, "Bookmark-EndIdx nicht lesbar" );
3920                 nEndIdx = i;
3921             }
3922 
3923             nEndAkt = pBook[1]->GetPos( nEndIdx );
3924 
3925             if ((nStartAkt >= nStart) && (nEndAkt <= nEnd))
3926             {
3927                 nIndex = i;
3928                 bFound=true;
3929                 break;
3930             }
3931             ++i;
3932         }
3933         while (i < pBook[0]->GetIMax());
3934     }
3935     return bFound ? aBookNames[i] : aEmptyStr;
3936 }
3937 
MapName(String & rName)3938 bool WW8PLCFx_Book::MapName(String& rName)
3939 {
3940     if( !pBook[0] || !pBook[1] )
3941         return false;
3942 
3943     bool bFound = false;
3944     sal_uInt16 i = 0;
3945     WW8_CP nStartAkt, nEndAkt;
3946     do
3947     {
3948         void* p;
3949         sal_uInt16 nEndIdx;
3950 
3951         if( pBook[0]->GetData( i, nStartAkt, p ) && p )
3952             nEndIdx = SVBT16ToShort( *((SVBT16*)p) );
3953         else
3954         {
3955             ASSERT( !this, "Bookmark-EndIdx nicht lesbar" );
3956             nEndIdx = i;
3957         }
3958         nEndAkt = pBook[1]->GetPos( nEndIdx );
3959         if (COMPARE_EQUAL == rName.CompareIgnoreCaseToAscii(aBookNames[i]))
3960         {
3961             rName = aBookNames[i];
3962             bFound = true;
3963         }
3964         ++i;
3965     }
3966     while (!bFound && i < pBook[0]->GetIMax());
3967     return bFound;
3968 }
3969 
GetName() const3970 const String* WW8PLCFx_Book::GetName() const
3971 {
3972     const String *pRet = 0;
3973     if (!nIsEnd && (pBook[0]->GetIdx() < nIMax))
3974         pRet = &(aBookNames[pBook[0]->GetIdx()]);
3975     return pRet;
3976 }
3977 
3978 //-----------------------------------------
3979 //          WW8PLCFMan
3980 //-----------------------------------------
3981 
3982 #ifndef DUMP
3983 
3984 // Am Ende eines Absatzes reichen bei WW6 die Attribute bis hinter das <CR>.
3985 // Das wird fuer die Verwendung mit dem SW um 1 Zeichen zurueckgesetzt, wenn
3986 // dadurch kein AErger zu erwarten ist.
AdjustEnds(WW8PLCFxDesc & rDesc)3987 void WW8PLCFMan::AdjustEnds( WW8PLCFxDesc& rDesc )
3988 {
3989     //Store old end position for supercool new property finder that uses
3990     //cp instead of fc's as nature intended
3991     rDesc.nOrigEndPos = rDesc.nEndPos;
3992     rDesc.nOrigStartPos = rDesc.nStartPos;
3993 
3994     /*
3995      Normally given ^XXX{para end}^ we don't actually insert a para end
3996      character into the document, so we clip the para end property one to the
3997      left to make the para properties end when the paragraph text does. In a
3998      drawing textbox we actually do insert a para end character, so we don't
3999      clip it. Making the para end properties end after the para end char.
4000     */
4001     if (GetDoingDrawTextBox())
4002         return;
4003 
4004     if ( (&rDesc == pPap) && rDesc.bRealLineEnd )
4005     {
4006         if ( pPap->nEndPos != LONG_MAX )    // Para adjust
4007         {
4008             nLineEnd = pPap->nEndPos;// nLineEnd zeigt *hinter* das <CR>
4009             pPap->nEndPos--;        // Absatzende um 1 Zeichen verkuerzen
4010 
4011             // gibt es bereits ein CharAttr-Ende das auf das jetzige
4012             // Absatzende zeigt ?  ... dann auch um 1 Zeichen verkuerzen
4013             if (pChp->nEndPos == nLineEnd)
4014                 pChp->nEndPos--;
4015 
4016             // gibt es bereits ein Sep-Ende, das auf das jetzige Absatzende
4017             // zeigt ?  ... dann auch um 1 Zeichen verkuerzen
4018             if( pSep->nEndPos == nLineEnd )
4019                 pSep->nEndPos--;
4020         }
4021     }
4022     else if ( (&rDesc == pChp) || (&rDesc == pSep) )
4023     {
4024         // Char Adjust oder Sep Adjust Wenn Ende Char-Attr == Absatzende ...
4025         if( (rDesc.nEndPos == nLineEnd) && (rDesc.nEndPos > rDesc.nStartPos) )
4026             rDesc.nEndPos--;            // ... dann um 1 Zeichen verkuerzen
4027     }
4028 }
4029 
ReduceByOffset()4030 void WW8PLCFxDesc::ReduceByOffset()
4031 {
4032     ASSERT((LONG_MAX == nStartPos) || (nStartPos <= nEndPos),
4033             "Attr-Anfang und -Ende ueber Kreuz" );
4034 
4035     if( nStartPos != LONG_MAX )
4036     {
4037         /*
4038         ##516##,##517##
4039         Force the property change to happen at the beginning of this
4040         subdocument, same as in GetNewNoSprms, except that the target type is
4041         attributes attached to a piece that might span subdocument boundaries
4042         */
4043         if (nCpOfs > nStartPos)
4044             nStartPos = 0;
4045         else
4046             nStartPos -= nCpOfs;
4047     }
4048     if( nEndPos   != LONG_MAX )
4049     {
4050         ASSERT(nCpOfs <= nEndPos,
4051             "oh oh, so much for the subdocument piece theory");
4052         nEndPos   -= nCpOfs;
4053     }
4054 }
4055 
GetNewSprms(WW8PLCFxDesc & rDesc)4056 void WW8PLCFMan::GetNewSprms( WW8PLCFxDesc& rDesc )
4057 {
4058     rDesc.pPLCFx->GetSprms(&rDesc);
4059     rDesc.ReduceByOffset();
4060 
4061     rDesc.bFirstSprm = true;
4062     AdjustEnds( rDesc );
4063     rDesc.nOrigSprmsLen = rDesc.nSprmsLen;
4064 }
4065 
GetNewNoSprms(WW8PLCFxDesc & rDesc)4066 void WW8PLCFMan::GetNewNoSprms( WW8PLCFxDesc& rDesc )
4067 {
4068     rDesc.nCp2OrIdx = rDesc.pPLCFx->GetNoSprms(rDesc.nStartPos, rDesc.nEndPos,
4069         rDesc.nSprmsLen);
4070 
4071     ASSERT((LONG_MAX == rDesc.nStartPos) || (rDesc.nStartPos <= rDesc.nEndPos),
4072             "Attr-Anfang und -Ende ueber Kreuz" );
4073 
4074     rDesc.ReduceByOffset();
4075 
4076     rDesc.bFirstSprm = true;
4077     rDesc.nOrigSprmsLen = rDesc.nSprmsLen;
4078 }
4079 
GetId(const WW8PLCFxDesc * p) const4080 sal_uInt16 WW8PLCFMan::GetId(const WW8PLCFxDesc* p) const
4081 {
4082     sal_uInt16 nId;
4083 
4084     if (p == pFld)
4085         nId = eFLD;
4086     else if (p->nSprmsLen > 0)
4087         nId = maSprmParser.GetSprmId(p->pMemPos);
4088     else
4089         nId = 0;        // Id = 0 for empty attributes
4090 
4091     return nId;
4092 }
4093 
WW8PLCFMan(WW8ScannerBase * pBase,short nType,long nStartCp,bool bDoingDrawTextBox)4094 WW8PLCFMan::WW8PLCFMan(WW8ScannerBase* pBase, short nType, long nStartCp,
4095     bool bDoingDrawTextBox)
4096     : maSprmParser(pBase->pWw8Fib->nVersion),
4097     mbDoingDrawTextBox(bDoingDrawTextBox)
4098 {
4099     pWwFib = pBase->pWw8Fib;
4100 
4101     nLastWhereIdxCp = 0;
4102     memset( aD, 0, sizeof( aD ) );
4103     nLineEnd = LONG_MAX;
4104     nManType = nType;
4105     sal_uInt16 i;
4106 
4107     if( MAN_MAINTEXT == nType )
4108     {
4109         // Suchreihenfolge der Attribute
4110         nPLCF = MAN_ANZ_PLCF;
4111         pFld = &aD[0];
4112         pBkm = &aD[1];
4113         pEdn = &aD[2];
4114         pFtn = &aD[3];
4115         pAnd = &aD[4];
4116 
4117         pPcd = ( pBase->pPLCFx_PCD ) ? &aD[5] : 0;
4118         //pPcdA index == pPcd index + 1
4119         pPcdA = ( pBase->pPLCFx_PCDAttrs ) ? &aD[6] : 0;
4120 
4121         pChp = &aD[7];
4122         pPap = &aD[8];
4123         pSep = &aD[9];
4124 
4125         pSep->pPLCFx = pBase->pSepPLCF;
4126         pFtn->pPLCFx = pBase->pFtnPLCF;
4127         pEdn->pPLCFx = pBase->pEdnPLCF;
4128         pBkm->pPLCFx = pBase->pBook;
4129         pAnd->pPLCFx = pBase->pAndPLCF;
4130 
4131     }
4132     else
4133     {
4134         // Suchreihenfolge der Attribute
4135         nPLCF = 7;
4136         pFld = &aD[0];
4137         pBkm = ( pBase->pBook ) ? &aD[1] : 0;
4138 
4139         pPcd = ( pBase->pPLCFx_PCD ) ? &aD[2] : 0;
4140         //pPcdA index == pPcd index + 1
4141         pPcdA= ( pBase->pPLCFx_PCDAttrs ) ? &aD[3] : 0;
4142 
4143         pChp = &aD[4];
4144         pPap = &aD[5];
4145         pSep = &aD[6]; // Dummy
4146 
4147         pAnd = pFtn = pEdn = 0;     // unbenutzt bei SpezText
4148     }
4149 
4150     pChp->pPLCFx = pBase->pChpPLCF;
4151     pPap->pPLCFx = pBase->pPapPLCF;
4152     if( pPcd )
4153         pPcd->pPLCFx = pBase->pPLCFx_PCD;
4154     if( pPcdA )
4155         pPcdA->pPLCFx= pBase->pPLCFx_PCDAttrs;
4156     if( pBkm )
4157         pBkm->pPLCFx = pBase->pBook;
4158 
4159     pMagicTables = pBase->pMagicTables;
4160 
4161     switch( nType )                 // Feld-Initialisierung
4162     {
4163         case MAN_HDFT:
4164             pFld->pPLCFx = pBase->pFldHdFtPLCF;
4165             nCpO = pWwFib->ccpText + pWwFib->ccpFtn;
4166             pFdoa = pBase->pHdFtFdoa;
4167             pTxbx = pBase->pHdFtTxbx;
4168             pTxbxBkd = pBase->pHdFtTxbxBkd;
4169             break;
4170         case MAN_FTN:
4171             pFld->pPLCFx = pBase->pFldFtnPLCF;
4172             nCpO = pWwFib->ccpText;
4173             pFdoa = pTxbx = pTxbxBkd = 0;
4174             break;
4175         case MAN_EDN:
4176             pFld->pPLCFx = pBase->pFldEdnPLCF;
4177             nCpO = pWwFib->ccpText + pWwFib->ccpFtn + pWwFib->ccpHdr +
4178                 pWwFib->ccpAtn;
4179             pFdoa = pTxbx = pTxbxBkd = 0;
4180             break;
4181         case MAN_AND:
4182             pFld->pPLCFx = pBase->pFldAndPLCF;
4183             nCpO = pWwFib->ccpText + pWwFib->ccpFtn + pWwFib->ccpHdr;
4184             pFdoa = pTxbx = pTxbxBkd = 0;
4185             break;
4186         case MAN_TXBX:
4187             pFld->pPLCFx = pBase->pFldTxbxPLCF;
4188             nCpO = pWwFib->ccpText + pWwFib->ccpFtn + pWwFib->ccpHdr +
4189                 pWwFib->ccpMcr + pWwFib->ccpAtn + pWwFib->ccpEdn;
4190             pTxbx = pBase->pMainTxbx;
4191             pTxbxBkd = pBase->pMainTxbxBkd;
4192             pFdoa = 0;
4193             break;
4194         case MAN_TXBX_HDFT:
4195             pFld->pPLCFx = pBase->pFldTxbxHdFtPLCF;
4196             nCpO = pWwFib->ccpText + pWwFib->ccpFtn + pWwFib->ccpHdr +
4197                 pWwFib->ccpMcr + pWwFib->ccpAtn + pWwFib->ccpEdn +
4198                 pWwFib->ccpTxbx;
4199             pTxbx = pBase->pHdFtTxbx;
4200             pTxbxBkd = pBase->pHdFtTxbxBkd;
4201             pFdoa = 0;
4202             break;
4203         default:
4204             pFld->pPLCFx = pBase->pFldPLCF;
4205             nCpO = 0;
4206             pFdoa = pBase->pMainFdoa;
4207             pTxbx = pBase->pMainTxbx;
4208             pTxbxBkd = pBase->pMainTxbxBkd;
4209             break;
4210     }
4211 
4212     if( nStartCp || nCpO )
4213         SeekPos( nStartCp );    // PLCFe auf Text-StartPos einstellen
4214 
4215     // initialisieren der Member-Vars Low-Level
4216     GetChpPLCF()->ResetAttrStartEnd();
4217     GetPapPLCF()->ResetAttrStartEnd();
4218     for( i=0; i < nPLCF; i++)
4219     {
4220         WW8PLCFxDesc* p = &aD[i];
4221 
4222         /*
4223         ##516##,##517##
4224         For subdocuments we modify the cp of properties to be relative to
4225         the beginning of subdocuments, we should also do the same for
4226         piecetable changes, and piecetable properties, otherwise a piece
4227         change that happens in a subdocument is lost.
4228         */
4229         p->nCpOfs = ( p == pChp || p == pPap || p == pBkm || p == pPcd ||
4230             p == pPcdA ) ? nCpO : 0;
4231 
4232         p->nCp2OrIdx = 0;
4233         p->bFirstSprm = false;
4234         p->pIdStk = 0;
4235 
4236         if ((p == pChp) || (p == pPap))
4237             p->nStartPos = p->nEndPos = nStartCp;
4238         else
4239             p->nStartPos = p->nEndPos = LONG_MAX;
4240     }
4241 
4242     // initialisieren der Member-Vars High-Level
4243     for( i=0; i<nPLCF; i++){
4244         WW8PLCFxDesc* p = &aD[i];
4245 
4246         if( !p->pPLCFx )
4247         {
4248             p->nStartPos = p->nEndPos = LONG_MAX;
4249             continue;
4250         }
4251 
4252         if( p->pPLCFx->IsSprm() )
4253         {
4254             // Vorsicht: nEndPos muss bereits
4255             p->pIdStk = new std::stack<sal_uInt16>;
4256             if ((p == pChp) || (p == pPap))
4257             {
4258                 WW8_CP nTemp = p->nEndPos+p->nCpOfs;
4259                 p->pMemPos = 0;
4260                 p->nSprmsLen = 0;
4261                 p->nStartPos = nTemp;
4262                 if (!(*p->pPLCFx).SeekPos(p->nStartPos))
4263                     p->nEndPos = p->nStartPos = LONG_MAX;
4264                 else
4265                     GetNewSprms( *p );
4266             }
4267             else
4268                 GetNewSprms( *p );      // bei allen PLCFen initialisiert sein
4269         }
4270         else if( p->pPLCFx )
4271             GetNewNoSprms( *p );
4272     }
4273 }
4274 
~WW8PLCFMan()4275 WW8PLCFMan::~WW8PLCFMan()
4276 {
4277     for( sal_uInt16 i=0; i<nPLCF; i++)
4278         delete aD[i].pIdStk;
4279 }
4280 
4281 // 0. welche Attr.-Klasse,
4282 // 1. ob ein Attr.-Start ist,
4283 // 2. CP, wo ist naechste Attr.-Aenderung
WhereIdx(bool * pbStart,long * pPos) const4284 sal_uInt16 WW8PLCFMan::WhereIdx(bool* pbStart, long* pPos) const
4285 {
4286     ASSERT(nPLCF,"What the hell");
4287     long nNext = LONG_MAX;  // SuchReihenfolge:
4288     sal_uInt16 nNextIdx = nPLCF;// first ending found ( CHP, PAP, ( SEP ) ),
4289     bool bStart = true;     // dann Anfaenge finden ( ( SEP ), PAP, CHP )
4290     sal_uInt16 i;
4291     const WW8PLCFxDesc* pD;
4292     for (i=0; i < nPLCF; i++)
4293     {
4294         pD = &aD[i];
4295         if (pD != pPcdA)
4296         {
4297             if( (pD->nEndPos < nNext) && (pD->nStartPos == LONG_MAX) )
4298             {
4299                 // sonst ist Anfang = Ende
4300                 nNext = pD->nEndPos;
4301                 nNextIdx = i;
4302                 bStart = false;
4303             }
4304         }
4305     }
4306     for (i=nPLCF; i > 0; i--)
4307     {
4308         pD = &aD[i-1];
4309         if (pD != pPcdA)
4310         {
4311             if( pD->nStartPos < nNext )
4312             {
4313                 nNext = pD->nStartPos;
4314                 nNextIdx = i-1;
4315                 bStart = true;
4316             }
4317         }
4318     }
4319     if( pPos )
4320         *pPos = nNext;
4321     if( pbStart )
4322         *pbStart = bStart;
4323     return nNextIdx;
4324 }
4325 
4326 // gibt die CP-Pos der naechsten Attribut-Aenderung zurueck
Where() const4327 WW8_CP WW8PLCFMan::Where() const
4328 {
4329     long l;
4330     WhereIdx(0, &l);
4331     return l;
4332 }
4333 
SeekPos(long nNewCp)4334 void WW8PLCFMan::SeekPos( long nNewCp )
4335 {
4336     pChp->pPLCFx->SeekPos( nNewCp + nCpO ); // Attribute neu
4337     pPap->pPLCFx->SeekPos( nNewCp + nCpO ); // aufsetzen
4338     pFld->pPLCFx->SeekPos( nNewCp );
4339     if( pPcd )
4340         pPcd->pPLCFx->SeekPos( nNewCp + nCpO );
4341     if( pBkm )
4342         pBkm->pPLCFx->SeekPos( nNewCp + nCpO );
4343 }
4344 
SaveAllPLCFx(WW8PLCFxSaveAll & rSave) const4345 void WW8PLCFMan::SaveAllPLCFx( WW8PLCFxSaveAll& rSave ) const
4346 {
4347     sal_uInt16 i, n=0;
4348     if( pPcd )
4349         pPcd->Save(  rSave.aS[n++] );
4350     if( pPcdA )
4351         pPcdA->Save( rSave.aS[n++] );
4352 
4353     for(i=0; i<nPLCF; ++i)
4354         if( pPcd != &aD[i] && pPcdA != &aD[i] )
4355             aD[i].Save( rSave.aS[n++] );
4356 }
4357 
RestoreAllPLCFx(const WW8PLCFxSaveAll & rSave)4358 void WW8PLCFMan::RestoreAllPLCFx( const WW8PLCFxSaveAll& rSave )
4359 {
4360     sal_uInt16 i, n=0;
4361     if( pPcd )
4362         pPcd->Restore(  rSave.aS[n++] );
4363     if( pPcdA )
4364         pPcdA->Restore( rSave.aS[n++] );
4365 
4366     for(i=0; i<nPLCF; ++i)
4367         if( pPcd != &aD[i] && pPcdA != &aD[i] )
4368             aD[i].Restore( rSave.aS[n++] );
4369 }
4370 
GetSprmStart(short nIdx,WW8PLCFManResult * pRes) const4371 void WW8PLCFMan::GetSprmStart( short nIdx, WW8PLCFManResult* pRes ) const
4372 {
4373     memset( pRes, 0, sizeof( WW8PLCFManResult ) );
4374 
4375     // Pruefen !!!
4376 
4377     pRes->nMemLen = 0;
4378 
4379     const WW8PLCFxDesc* p = &aD[nIdx];
4380 
4381     // first Sprm in a Group
4382     if( p->bFirstSprm )
4383     {
4384         if( p == pPap )
4385             pRes->nFlags |= MAN_MASK_NEW_PAP;
4386         else if( p == pSep )
4387             pRes->nFlags |= MAN_MASK_NEW_SEP;
4388     }
4389     pRes->pMemPos = p->pMemPos;
4390     pRes->nSprmId = GetId(p);
4391     pRes->nCp2OrIdx = p->nCp2OrIdx;
4392     if (p->nSprmsLen)
4393     {
4394         // Length of actual sprm
4395         pRes->nMemLen = maSprmParser.GetSprmSize(pRes->nSprmId, pRes->pMemPos);
4396     }
4397 }
4398 
GetSprmEnd(short nIdx,WW8PLCFManResult * pRes) const4399 void WW8PLCFMan::GetSprmEnd( short nIdx, WW8PLCFManResult* pRes ) const
4400 {
4401     memset( pRes, 0, sizeof( WW8PLCFManResult ) );
4402 
4403     const WW8PLCFxDesc* p = &aD[nIdx];
4404 
4405     if (!(p->pIdStk->empty()))
4406         pRes->nSprmId = p->pIdStk->top();       // get end position
4407     else
4408     {
4409         ASSERT( !this, "No Id on the Stack" );
4410         pRes->nSprmId = 0;
4411     }
4412 }
4413 
GetNoSprmStart(short nIdx,WW8PLCFManResult * pRes) const4414 void WW8PLCFMan::GetNoSprmStart( short nIdx, WW8PLCFManResult* pRes ) const
4415 {
4416     const WW8PLCFxDesc* p = &aD[nIdx];
4417 
4418     pRes->nCpPos = p->nStartPos;
4419     pRes->nMemLen = p->nSprmsLen;
4420     pRes->nCp2OrIdx = p->nCp2OrIdx;
4421 
4422     if( p == pFld )
4423         pRes->nSprmId = eFLD;
4424     else if( p == pFtn )
4425         pRes->nSprmId = eFTN;
4426     else if( p == pEdn )
4427         pRes->nSprmId = eEDN;
4428     else if( p == pBkm )
4429         pRes->nSprmId = eBKN;
4430     else if( p == pAnd )
4431         pRes->nSprmId = eAND;
4432     else if( p == pPcd )
4433     {
4434         //We slave the piece table attributes to the piece table, the piece
4435         //table attribute iterator contains the sprms for this piece.
4436         GetSprmStart( nIdx+1, pRes );
4437     }
4438     else
4439         pRes->nSprmId = 0;          // default: not found
4440 }
4441 
GetNoSprmEnd(short nIdx,WW8PLCFManResult * pRes) const4442 void WW8PLCFMan::GetNoSprmEnd( short nIdx, WW8PLCFManResult* pRes ) const
4443 {
4444     pRes->nMemLen = -1;     // Ende-Kennzeichen
4445 
4446     if( &aD[nIdx] == pBkm )
4447         pRes->nSprmId = eBKN;
4448     else if( &aD[nIdx] == pPcd )
4449     {
4450         //We slave the piece table attributes to the piece table, the piece
4451         //table attribute iterator contains the sprms for this piece.
4452         GetSprmEnd( nIdx+1, pRes );
4453     }
4454     else
4455         pRes->nSprmId = 0;
4456 }
4457 
TransferOpenSprms(std::stack<sal_uInt16> & rStack)4458 bool WW8PLCFMan::TransferOpenSprms(std::stack<sal_uInt16> &rStack)
4459 {
4460     for (int i = 0; i < nPLCF; ++i)
4461     {
4462         WW8PLCFxDesc* p = &aD[i];
4463         if (!p || !p->pIdStk)
4464             continue;
4465         while (!p->pIdStk->empty())
4466         {
4467             rStack.push(p->pIdStk->top());
4468             p->pIdStk->pop();
4469         }
4470     }
4471     return rStack.empty();
4472 }
4473 
AdvSprm(short nIdx,bool bStart)4474 void WW8PLCFMan::AdvSprm(short nIdx, bool bStart)
4475 {
4476     WW8PLCFxDesc* p = &aD[nIdx];    // Sprm-Klasse(!) ermitteln
4477 
4478     p->bFirstSprm = false;
4479     if( bStart )
4480     {
4481         sal_uInt16 nLastId = GetId(p);
4482         p->pIdStk->push(nLastId);   // merke Id fuer Attribut-Ende
4483 
4484         if( p->nSprmsLen )
4485         {   /*
4486                 Pruefe, ob noch Sprm(s) abzuarbeiten sind
4487             */
4488             if( p->pMemPos )
4489             {
4490                 // Length of last sprm
4491                 sal_uInt16 nSprmL = maSprmParser.GetSprmSize(nLastId, p->pMemPos);
4492 
4493                 // Gesamtlaenge Sprms um SprmLaenge verringern
4494                 p->nSprmsLen -= nSprmL;
4495 
4496                 // Pos des evtl. naechsten Sprm
4497                 if (p->nSprmsLen < maSprmParser.MinSprmLen())
4498                 {
4499                     // sicherheitshalber auf Null setzen, da Enden folgen!
4500                     p->pMemPos = 0;
4501                     p->nSprmsLen = 0;
4502                 }
4503                 else
4504                     p->pMemPos += nSprmL;
4505             }
4506             else
4507                 p->nSprmsLen = 0;
4508         }
4509         if (p->nSprmsLen < maSprmParser.MinSprmLen())
4510             p->nStartPos = LONG_MAX;    // es folgen Enden
4511     }
4512     else
4513     {
4514         if (!(p->pIdStk->empty()))
4515             p->pIdStk->pop();
4516         if (p->pIdStk->empty())
4517         {
4518             if ( (p == pChp) || (p == pPap) )
4519             {
4520                 p->pMemPos = 0;
4521                 p->nSprmsLen = 0;
4522                 p->nStartPos = p->nOrigEndPos+p->nCpOfs;
4523 
4524                 /*
4525                 #93702#
4526                 On failed seek we have run out of sprms, probably.  But if its
4527                 a fastsaved file (has pPcd) then we may be just in a sprm free
4528                 gap between pieces that have them, so set dirty flag in sprm
4529                 finder to consider than.
4530                 */
4531                 if (!(*p->pPLCFx).SeekPos(p->nStartPos))
4532                 {
4533                     p->nEndPos = LONG_MAX;
4534                     p->pPLCFx->SetDirty(true);
4535                 }
4536                 if (!p->pPLCFx->GetDirty() || pPcd)
4537                     GetNewSprms( *p );
4538                 p->pPLCFx->SetDirty(false);
4539 
4540                 /*
4541                 #i2325#
4542                 To get the character and paragraph properties you first get
4543                 the pap and chp and then apply the fastsaved pPcd properties
4544                 to the range. If a pap or chp starts inside the pPcd range
4545                 then we must bring the current pPcd range to a halt so as to
4546                 end those sprms, then the pap/chp will be processed, and then
4547                 we must force a restart of the pPcd on that pap/chp starting
4548                 boundary. Doing that effectively means that the pPcd sprms will
4549                 be applied to the new range. Not doing it means that the pPcd
4550                 sprms will only be applied to the first pap/chp set of
4551                 properties contained in the pap/chp range.
4552 
4553                 So we bring the pPcd to a halt on this location here, by
4554                 settings its end to the current start, then store the starting
4555                 position of the current range to clipstart. The pPcd sprms
4556                 will end as normal (albeit earlier than originally expected),
4557                 and the existence of a clipstart will force the pPcd iterater
4558                 to reread the current set of sprms instead of advancing to its
4559                 next set. Then the clipstart will be set as the starting
4560                 position which will force them to be applied directly after
4561                 the pap and chps.
4562                 */
4563                 if (pPcd && ((p->nStartPos > pPcd->nStartPos) ||
4564                     (pPcd->nStartPos == LONG_MAX)) &&
4565                     (pPcd->nEndPos != p->nStartPos))
4566                 {
4567                     pPcd->nEndPos = p->nStartPos;
4568                     ((WW8PLCFx_PCD *)(pPcd->pPLCFx))->SetClipStart(
4569                         p->nStartPos);
4570                 }
4571 
4572             }
4573             else
4574             {
4575                 (*p->pPLCFx)++;     // next Group of Sprms
4576                 p->pMemPos = 0;     // !!!
4577                 p->nSprmsLen = 0;
4578                 GetNewSprms( *p );
4579             }
4580             ASSERT( p->nStartPos <= p->nEndPos, "Attribut ueber Kreuz" );
4581         }
4582     }
4583 }
4584 
AdvNoSprm(short nIdx,bool bStart)4585 void WW8PLCFMan::AdvNoSprm(short nIdx, bool bStart)
4586 {
4587     /*
4588     For the case of a piece table we slave the piece table attribute iterator
4589     to the piece table and access it through that only. They are two separate
4590     structures, but act together as one logical one. The attributes only go
4591     to the next entry when the piece changes
4592     */
4593     WW8PLCFxDesc* p = &aD[nIdx];
4594 
4595     if( p == pPcd )
4596     {
4597         AdvSprm(nIdx+1,bStart);
4598         if( bStart )
4599             p->nStartPos = aD[nIdx+1].nStartPos;
4600         else
4601         {
4602             if (aD[nIdx+1].pIdStk->empty())
4603             {
4604                 WW8PLCFx_PCD *pTemp = (WW8PLCFx_PCD*)(pPcd->pPLCFx);
4605                 /*
4606                 #i2325#
4607                 As per normal, go on to the next set of properties, i.e. we
4608                 have traversed over to the next piece.  With a clipstart set
4609                 we are being told to reread the current piece sprms so as to
4610                 reapply them to a new chp or pap range.
4611                 */
4612                 if (pTemp->GetClipStart() == -1)
4613                     (*p->pPLCFx)++;
4614                 p->pMemPos = 0;
4615                 p->nSprmsLen = 0;
4616                 GetNewSprms( aD[nIdx+1] );
4617                 GetNewNoSprms( *p );
4618                 if (pTemp->GetClipStart() != -1)
4619                 {
4620                     /*
4621                     #i2325#, now we will force our starting position to the
4622                     clipping start so as to force the application of these
4623                     sprms after the current pap/chp sprms so as to apply the
4624                     fastsave sprms to the current range.
4625                     */
4626                     p->nStartPos = pTemp->GetClipStart();
4627                     pTemp->SetClipStart(-1);
4628                 }
4629             }
4630         }
4631     }
4632     else
4633     {                                  // NoSprm ohne Ende
4634         (*p->pPLCFx)++;
4635         p->pMemPos = 0;                     // MemPos ungueltig
4636         p->nSprmsLen = 0;
4637         GetNewNoSprms( *p );
4638     }
4639 }
4640 
operator ++(int)4641 WW8PLCFMan& WW8PLCFMan::operator ++(int)
4642 {
4643     bool bStart;
4644     sal_uInt16 nIdx = WhereIdx(&bStart);
4645     if (nIdx < nPLCF)
4646     {
4647         WW8PLCFxDesc* p = &aD[nIdx];
4648 
4649         p->bFirstSprm = true;                       // Default
4650 
4651         if( p->pPLCFx->IsSprm() )
4652             AdvSprm( nIdx, bStart );
4653         else                                        // NoSprm
4654             AdvNoSprm( nIdx, bStart );
4655     }
4656     return *this;
4657 }
4658 
4659 // Rueckgabe true fuer Anfang eines Attributes oder Fehler,
4660 //           false fuer Ende d. Attr
4661 // Restliche Rueckgabewerte werden in der vom Aufrufer zu stellenden Struktur
4662 // WW8PclxManResults geliefert.
Get(WW8PLCFManResult * pRes) const4663 bool WW8PLCFMan::Get(WW8PLCFManResult* pRes) const
4664 {
4665     memset( pRes, 0, sizeof( WW8PLCFManResult ) );
4666     bool bStart;
4667     sal_uInt16 nIdx = WhereIdx(&bStart);
4668 
4669     if( nIdx >= nPLCF )
4670     {
4671         ASSERT( !this, "Position not found" );
4672         return true;
4673     }
4674 
4675     if( aD[nIdx].pPLCFx->IsSprm() )
4676     {
4677         if( bStart )
4678         {
4679             GetSprmStart( nIdx, pRes );
4680             return true;
4681         }
4682         else
4683         {
4684             GetSprmEnd( nIdx, pRes );
4685             return false;
4686         }
4687     }
4688     else
4689     {
4690         if( bStart )
4691         {
4692             GetNoSprmStart( nIdx, pRes );
4693             return true;
4694         }
4695         else
4696         {
4697             GetNoSprmEnd( nIdx, pRes );
4698             return false;
4699         }
4700     }
4701 }
4702 
GetColl() const4703 sal_uInt16 WW8PLCFMan::GetColl() const
4704 {
4705     if( pPap->pPLCFx )
4706         return  pPap->pPLCFx->GetIstd();
4707     else
4708     {
4709         ASSERT( !this, "GetColl ohne PLCF_Pap" );
4710         return 0;
4711     }
4712 }
4713 
GetFld() const4714 WW8PLCFx_FLD* WW8PLCFMan::GetFld() const
4715 {
4716     return (WW8PLCFx_FLD*)pFld->pPLCFx;
4717 }
4718 
HasParaSprm(sal_uInt16 nId) const4719 const sal_uInt8* WW8PLCFMan::HasParaSprm( sal_uInt16 nId ) const
4720 {
4721     return ((WW8PLCFx_Cp_FKP*)pPap->pPLCFx)->HasSprm( nId );
4722 }
4723 
HasCharSprm(sal_uInt16 nId) const4724 const sal_uInt8* WW8PLCFMan::HasCharSprm( sal_uInt16 nId ) const
4725 {
4726     return ((WW8PLCFx_Cp_FKP*)pChp->pPLCFx)->HasSprm( nId );
4727 }
4728 
HasCharSprm(sal_uInt16 nId,std::vector<const sal_uInt8 * > & rResult) const4729 bool WW8PLCFMan::HasCharSprm(sal_uInt16 nId,
4730     std::vector<const sal_uInt8 *> &rResult) const
4731 {
4732     return ((WW8PLCFx_Cp_FKP*)pChp->pPLCFx)->HasSprm(nId, rResult);
4733 }
4734 
4735 #endif // !DUMP
4736 
Save(WW8PLCFxSave1 & rSave) const4737 void WW8PLCFx::Save( WW8PLCFxSave1& rSave ) const
4738 {
4739     rSave.nPLCFxPos    = GetIdx();
4740     rSave.nPLCFxPos2   = GetIdx2();
4741     rSave.nPLCFxMemOfs = 0;
4742     rSave.nStartFC     = GetStartFc();
4743 }
4744 
Restore(const WW8PLCFxSave1 & rSave)4745 void WW8PLCFx::Restore( const WW8PLCFxSave1& rSave )
4746 {
4747     SetIdx(     rSave.nPLCFxPos  );
4748     SetIdx2(    rSave.nPLCFxPos2 );
4749     SetStartFc( rSave.nStartFC   );
4750 }
4751 
GetIdx2() const4752 sal_uLong WW8PLCFx_Cp_FKP::GetIdx2() const
4753 {
4754     return GetPCDIdx();
4755 }
4756 
SetIdx2(sal_uLong nIdx)4757 void WW8PLCFx_Cp_FKP::SetIdx2( sal_uLong nIdx )
4758 {
4759     SetPCDIdx( nIdx );
4760 }
4761 
Save(WW8PLCFxSave1 & rSave) const4762 void WW8PLCFx_Cp_FKP::Save( WW8PLCFxSave1& rSave ) const
4763 {
4764     WW8PLCFx::Save( rSave );
4765 
4766     rSave.nAttrStart = nAttrStart;
4767     rSave.nAttrEnd   = nAttrEnd;
4768     rSave.bLineEnd   = bLineEnd;
4769 }
4770 
Restore(const WW8PLCFxSave1 & rSave)4771 void WW8PLCFx_Cp_FKP::Restore( const WW8PLCFxSave1& rSave )
4772 {
4773     WW8PLCFx::Restore( rSave );
4774 
4775     nAttrStart = rSave.nAttrStart;
4776     nAttrEnd   = rSave.nAttrEnd;
4777     bLineEnd   = rSave.bLineEnd;
4778 }
4779 
Save(WW8PLCFxSave1 & rSave) const4780 void WW8PLCFxDesc::Save( WW8PLCFxSave1& rSave ) const
4781 {
4782     if( pPLCFx )
4783     {
4784         pPLCFx->Save( rSave );
4785         if( pPLCFx->IsSprm() )
4786         {
4787             WW8PLCFxDesc aD;
4788             aD.nStartPos = nOrigStartPos+nCpOfs;
4789             aD.nCpOfs = rSave.nCpOfs = nCpOfs;
4790             if (!(pPLCFx->SeekPos(aD.nStartPos)))
4791             {
4792                 aD.nEndPos = LONG_MAX;
4793                 pPLCFx->SetDirty(true);
4794             }
4795             pPLCFx->GetSprms(&aD);
4796             pPLCFx->SetDirty(false);
4797             aD.ReduceByOffset();
4798             rSave.nStartCp = aD.nStartPos;
4799             rSave.nPLCFxMemOfs = nOrigSprmsLen - nSprmsLen;
4800         }
4801     }
4802 }
4803 
Restore(const WW8PLCFxSave1 & rSave)4804 void WW8PLCFxDesc::Restore( const WW8PLCFxSave1& rSave )
4805 {
4806     if( pPLCFx )
4807     {
4808         pPLCFx->Restore( rSave );
4809         if( pPLCFx->IsSprm() )
4810         {
4811             WW8PLCFxDesc aD;
4812             aD.nStartPos = rSave.nStartCp+rSave.nCpOfs;
4813             nCpOfs = aD.nCpOfs = rSave.nCpOfs;
4814             if (!(pPLCFx->SeekPos(aD.nStartPos)))
4815             {
4816                 aD.nEndPos = LONG_MAX;
4817                 pPLCFx->SetDirty(true);
4818             }
4819             pPLCFx->GetSprms(&aD);
4820             pPLCFx->SetDirty(false);
4821             aD.ReduceByOffset();
4822             pMemPos = aD.pMemPos + rSave.nPLCFxMemOfs;
4823         }
4824     }
4825 }
4826 
4827 //-----------------------------------------
4828 
4829 
WW8Fib(SvStream & rSt,sal_uInt8 nWantedVersion,sal_uInt32 nOffset)4830 WW8Fib::WW8Fib( SvStream& rSt, sal_uInt8 nWantedVersion,sal_uInt32 nOffset )
4831     : nFibError( 0 )
4832 {
4833     sal_uInt8 aBits1;
4834     sal_uInt8 aBits2;
4835     sal_uInt8 aVer8Bits1;   // nur ab WinWord 8 benutzt
4836     rSt.Seek( nOffset );
4837     /*
4838         Wunsch-Nr vermerken, File-Versionsnummer ermitteln
4839         und gegen Wunsch-Nr. checken !
4840     */
4841     nVersion = nWantedVersion;
4842     rSt >> wIdent;
4843     rSt >> nFib;
4844     rSt >> nProduct;
4845     if( 0 != rSt.GetError() )
4846     {
4847         sal_Int16 nFibMin;
4848         sal_Int16 nFibMax;
4849         // note: 6 stands for "6 OR 7",  7 stands for "ONLY 7"
4850         switch( nVersion )
4851         {
4852             case 6:
4853                 nFibMin = 0x0065;   // von 101 WinWord 6.0
4854                                     //     102    "
4855                                     // und 103 WinWord 6.0 fuer Macintosh
4856                                     //     104    "
4857                 nFibMax = 0x0069;   // bis 105 WinWord 95
4858                 break;
4859             case 7:
4860                 nFibMin = 0x0069;   // von 105 WinWord 95
4861                 nFibMax = 0x0069;   // bis 105 WinWord 95
4862                 break;
4863             case 8:
4864                 nFibMin = 0x006A;   // von 106 WinWord 97
4865                 nFibMax = 0x00c1;   // bis 193 WinWord 97 (?)
4866                 break;
4867             default:
4868                 nFibMin = 0;            // Programm-Fehler!
4869                 nFibMax = 0;
4870                 nFib    = 1;
4871                 ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" );
4872                 break;
4873         }
4874         if ( (nFib < nFibMin) || (nFib > nFibMax) )
4875         {
4876             nFibError = ERR_SWG_READ_ERROR; // Error melden
4877             return;                         // und hopp raus!
4878         }
4879     }
4880 
4881     // praktische Hilfsvariablen:
4882     bool bVer67 = ((6 == nVersion) || (7 == nVersion));
4883     bool bVer8  =  (8 == nVersion);
4884 
4885     // Hilfs-Varis fuer Ver67:
4886     sal_Int16 pnChpFirst_Ver67=0;
4887     sal_Int16 pnPapFirst_Ver67=0;
4888     sal_Int16 cpnBteChp_Ver67=0;
4889     sal_Int16 cpnBtePap_Ver67=0;
4890 
4891     // und auf gehts: FIB einlesen
4892     rSt >> lid;
4893     rSt >> pnNext;
4894     rSt >> aBits1;
4895     rSt >> aBits2;
4896     rSt >> nFibBack;
4897     rSt >> lKey1;
4898     rSt >> lKey2;
4899     rSt >> envr;
4900     rSt >> aVer8Bits1;      // unter Ver67  nur leeres Reservefeld
4901                             // Inhalt von aVer8Bits1
4902                             //
4903                             // sal_uInt8 fMac              :1;
4904                             // sal_uInt8 fEmptySpecial     :1;
4905                             // sal_uInt8 fLoadOverridePage :1;
4906                             // sal_uInt8 fFuturesavedUndo  :1;
4907                             // sal_uInt8 fWord97Saved      :1;
4908                             // sal_uInt8 :3;
4909     rSt >> chse;
4910     rSt >> chseTables;
4911     rSt >> fcMin;
4912     rSt >> fcMac;
4913 
4914 // Einschub fuer WW8 *****************************************************
4915     if( !bVer67 )
4916     {
4917         rSt >> csw;
4918 
4919         // Marke: "rgsw"  Beginning of the array of shorts
4920         rSt >> wMagicCreated;
4921         rSt >> wMagicRevised;
4922         rSt >> wMagicCreatedPrivate;
4923         rSt >> wMagicRevisedPrivate;
4924         rSt.SeekRel( 9 * sizeof( sal_Int16 ) );
4925 
4926         /*
4927         // dies sind die 9 unused Felder:
4928         && (bVer67 || WW8ReadINT16(  rSt, pnFbpChpFirst_W6          ))  // 1
4929         && (bVer67 || WW8ReadINT16(  rSt, pnChpFirst_W6                 ))  // 2
4930         && (bVer67 || WW8ReadINT16(  rSt, cpnBteChp_W6                  ))  // 3
4931         && (bVer67 || WW8ReadINT16(  rSt, pnFbpPapFirst_W6          ))  // 4
4932         && (bVer67 || WW8ReadINT16(  rSt, pnPapFirst_W6                 ))  // 5
4933         && (bVer67 || WW8ReadINT16(  rSt, cpnBtePap_W6                  ))  // 6
4934         && (bVer67 || WW8ReadINT16(  rSt, pnFbpLvcFirst_W6          ))  // 7
4935         && (bVer67 || WW8ReadINT16(  rSt, pnLvcFirst_W6                 ))  // 8
4936         && (bVer67 || WW8ReadINT16(  rSt, cpnBteLvc_W6                  ))  // 9
4937         */
4938         rSt >> lidFE;
4939         rSt >> clw;
4940     }
4941 
4942 // Ende des Einschubs fuer WW8 *******************************************
4943 
4944         // Marke: "rglw"  Beginning of the array of longs
4945     rSt >> cbMac;
4946 
4947         // 2 Longs uebergehen, da unwichtiger Quatsch
4948     rSt.SeekRel( 2 * sizeof( sal_Int32) );
4949 
4950         // weitere 2 Longs nur bei Ver67 ueberspringen
4951     if( bVer67 )
4952         rSt.SeekRel( 2 * sizeof( sal_Int32) );
4953 
4954     rSt >> ccpText;
4955     rSt >> ccpFtn;
4956     rSt >> ccpHdr;
4957     rSt >> ccpMcr;
4958     rSt >> ccpAtn;
4959     rSt >> ccpEdn;
4960     rSt >> ccpTxbx;
4961     rSt >> ccpHdrTxbx;
4962 
4963         // weiteres Long nur bei Ver67 ueberspringen
4964     if( bVer67 )
4965         rSt.SeekRel( 1 * sizeof( sal_Int32) );
4966     else
4967     {
4968 // Einschub fuer WW8 *****************************************************
4969         rSt >> pnFbpChpFirst;
4970         rSt >> pnChpFirst;
4971         rSt >> cpnBteChp;
4972         rSt >> pnFbpPapFirst;
4973         rSt >> pnPapFirst;
4974         rSt >> cpnBtePap;
4975         rSt >> pnFbpLvcFirst;
4976         rSt >> pnLvcFirst;
4977         rSt >> cpnBteLvc;
4978         rSt >> fcIslandFirst;
4979         rSt >> fcIslandLim;
4980         rSt >> cfclcb;
4981     }
4982 
4983 // Ende des Einschubs fuer WW8 *******************************************
4984 
4985         // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
4986     rSt >> fcStshfOrig;
4987     rSt >> lcbStshfOrig;
4988     rSt >> fcStshf;
4989     rSt >> lcbStshf;
4990     rSt >> fcPlcffndRef;
4991     rSt >> lcbPlcffndRef;
4992     rSt >> fcPlcffndTxt;
4993     rSt >> lcbPlcffndTxt;
4994     rSt >> fcPlcfandRef;
4995     rSt >> lcbPlcfandRef;
4996     rSt >> fcPlcfandTxt;
4997     rSt >> lcbPlcfandTxt;
4998     rSt >> fcPlcfsed;
4999     rSt >> lcbPlcfsed;
5000     rSt >> fcPlcfpad;
5001     rSt >> lcbPlcfpad;
5002     rSt >> fcPlcfphe;
5003     rSt >> lcbPlcfphe;
5004     rSt >> fcSttbfglsy;
5005     rSt >> lcbSttbfglsy;
5006     rSt >> fcPlcfglsy;
5007     rSt >> lcbPlcfglsy;
5008     rSt >> fcPlcfhdd;
5009     rSt >> lcbPlcfhdd;
5010     rSt >> fcPlcfbteChpx;
5011     rSt >> lcbPlcfbteChpx;
5012     rSt >> fcPlcfbtePapx;
5013     rSt >> lcbPlcfbtePapx;
5014     rSt >> fcPlcfsea;
5015     rSt >> lcbPlcfsea;
5016     rSt >> fcSttbfffn;
5017     rSt >> lcbSttbfffn;
5018     rSt >> fcPlcffldMom;
5019     rSt >> lcbPlcffldMom;
5020     rSt >> fcPlcffldHdr;
5021     rSt >> lcbPlcffldHdr;
5022     rSt >> fcPlcffldFtn;
5023     rSt >> lcbPlcffldFtn;
5024     rSt >> fcPlcffldAtn;
5025     rSt >> lcbPlcffldAtn;
5026     rSt >> fcPlcffldMcr;
5027     rSt >> lcbPlcffldMcr;
5028     rSt >> fcSttbfbkmk;
5029     rSt >> lcbSttbfbkmk;
5030     rSt >> fcPlcfbkf;
5031     rSt >> lcbPlcfbkf;
5032     rSt >> fcPlcfbkl;
5033     rSt >> lcbPlcfbkl;
5034     rSt >> fcCmds;
5035     rSt >> lcbCmds;
5036     rSt >> fcPlcfmcr;
5037     rSt >> lcbPlcfmcr;
5038     rSt >> fcSttbfmcr;
5039     rSt >> lcbSttbfmcr;
5040     rSt >> fcPrDrvr;
5041     rSt >> lcbPrDrvr;
5042     rSt >> fcPrEnvPort;
5043     rSt >> lcbPrEnvPort;
5044     rSt >> fcPrEnvLand;
5045     rSt >> lcbPrEnvLand;
5046     rSt >> fcWss;
5047     rSt >> lcbWss;
5048     rSt >> fcDop;
5049     rSt >> lcbDop;
5050     rSt >> fcSttbfAssoc;
5051     rSt >> cbSttbfAssoc;
5052     rSt >> fcClx;
5053     rSt >> lcbClx;
5054     rSt >> fcPlcfpgdFtn;
5055     rSt >> lcbPlcfpgdFtn;
5056     rSt >> fcAutosaveSource;
5057     rSt >> lcbAutosaveSource;
5058     rSt >> fcGrpStAtnOwners;
5059     rSt >> lcbGrpStAtnOwners;
5060     rSt >> fcSttbfAtnbkmk;
5061     rSt >> lcbSttbfAtnbkmk;
5062 
5063         // weiteres short nur bei Ver67 ueberspringen
5064     if (bVer67)
5065     {
5066         rSt.SeekRel( 1*sizeof( sal_Int16) );
5067 
5068         // folgende 4 Shorts existieren nur bei Ver67;
5069         rSt >> pnChpFirst_Ver67;
5070         rSt >> pnPapFirst_Ver67;
5071         rSt >> cpnBteChp_Ver67;
5072         rSt >> cpnBtePap_Ver67;
5073     }
5074 
5075     rSt >> fcPlcfdoaMom;
5076     rSt >> lcbPlcfdoaMom;
5077     rSt >> fcPlcfdoaHdr;
5078     rSt >> lcbPlcfdoaHdr;
5079     rSt >> fcPlcfspaMom;
5080     rSt >> lcbPlcfspaMom;
5081     rSt >> fcPlcfspaHdr;
5082     rSt >> lcbPlcfspaHdr;
5083 
5084     rSt >> fcPlcfAtnbkf;
5085     rSt >> lcbPlcfAtnbkf;
5086     rSt >> fcPlcfAtnbkl;
5087     rSt >> lcbPlcfAtnbkl;
5088     rSt >> fcPms;
5089     rSt >> lcbPMS;
5090     rSt >> fcFormFldSttbf;
5091     rSt >> lcbFormFldSttbf;
5092     rSt >> fcPlcfendRef;
5093     rSt >> lcbPlcfendRef;
5094     rSt >> fcPlcfendTxt;
5095     rSt >> lcbPlcfendTxt;
5096     rSt >> fcPlcffldEdn;
5097     rSt >> lcbPlcffldEdn;
5098     rSt >> fcPlcfpgdEdn;
5099     rSt >> lcbPlcfpgdEdn;
5100     rSt >> fcDggInfo;
5101     rSt >> lcbDggInfo;
5102     rSt >> fcSttbfRMark;
5103     rSt >> lcbSttbfRMark;
5104     rSt >> fcSttbfCaption;
5105     rSt >> lcbSttbfCaption;
5106     rSt >> fcSttbAutoCaption;
5107     rSt >> lcbSttbAutoCaption;
5108     rSt >> fcPlcfwkb;
5109     rSt >> lcbPlcfwkb;
5110     rSt >> fcPlcfspl;
5111     rSt >> lcbPlcfspl;
5112     rSt >> fcPlcftxbxTxt;
5113     rSt >> lcbPlcftxbxTxt;
5114     rSt >> fcPlcffldTxbx;
5115     rSt >> lcbPlcffldTxbx;
5116     rSt >> fcPlcfHdrtxbxTxt;
5117     rSt >> lcbPlcfHdrtxbxTxt;
5118     rSt >> fcPlcffldHdrTxbx;
5119     rSt >> lcbPlcffldHdrTxbx;
5120 
5121     if( 0 == rSt.GetError() )
5122     {
5123         // Bit-Flags setzen
5124         fDot        =   aBits1 & 0x01       ;
5125         fGlsy       = ( aBits1 & 0x02 ) >> 1;
5126         fComplex    = ( aBits1 & 0x04 ) >> 2;
5127         fHasPic     = ( aBits1 & 0x08 ) >> 3;
5128         cQuickSaves = ( aBits1 & 0xf0 ) >> 4;
5129         fEncrypted  =   aBits2 & 0x01       ;
5130         fWhichTblStm= ( aBits2 & 0x02 ) >> 1;
5131         // dummy    = ( aBits2 & 0x0e ) >> 1;
5132         fExtChar    = ( aBits2 & 0x10 ) >> 4;
5133         // dummy    = ( aBits2 & 0xe0 ) >> 5;
5134 
5135         /*
5136             ggfs. Ziel-Varaiblen, aus xxx_Ver67 fuellen
5137             oder Flags setzen
5138         */
5139         if (bVer67)
5140         {
5141             pnChpFirst = pnChpFirst_Ver67;
5142             pnPapFirst = pnPapFirst_Ver67;
5143             cpnBteChp = cpnBteChp_Ver67;
5144             cpnBtePap = cpnBtePap_Ver67;
5145         }
5146         else if( bVer8 )
5147         {
5148           fMac              =   aVer8Bits1  & 0x01           ;
5149           fEmptySpecial     = ( aVer8Bits1  & 0x02 ) >> 1;
5150           fLoadOverridePage = ( aVer8Bits1  & 0x04 ) >> 2;
5151           fFuturesavedUndo  = ( aVer8Bits1  & 0x08 ) >> 3;
5152           fWord97Saved      = ( aVer8Bits1  & 0x10 ) >> 4;
5153           fWord2000Saved    = ( aVer8Bits1  & 0x20 ) >> 5;
5154 
5155             /*
5156                 speziell fuer WW8:
5157                 ermittle die Werte fuer PLCF LST und PLF LFO
5158                 und PLCF fuer TextBox-Break-Deskriptoren
5159             */
5160             long nOldPos = rSt.Tell();
5161             rSt.Seek( 0x02e2 );
5162             rSt >> fcPlcfLst;
5163             rSt >> lcbPlcfLst;
5164             rSt >> fcPlfLfo;
5165             rSt >> lcbPlfLfo;
5166             rSt >> fcPlcftxbxBkd;
5167             rSt >> lcbPlcftxbxBkd;
5168             rSt >> fcPlcfHdrtxbxBkd;
5169             rSt >> lcbPlcfHdrtxbxBkd;
5170             if( 0 != rSt.GetError() )
5171             {
5172                 nFibError = ERR_SWG_READ_ERROR;
5173             }
5174 
5175             rSt.Seek( 0x372 );          // fcSttbListNames
5176             rSt >> fcSttbListNames;
5177             rSt >> lcbSttbListNames;
5178             rSt.Seek( 0x382 );          // MagicTables
5179             rSt >> fcMagicTable;
5180             rSt >> lcbMagicTable;
5181             if( 0 != rSt.GetError() )
5182                 nFibError = ERR_SWG_READ_ERROR;
5183 
5184             rSt.Seek( nOldPos );
5185         }
5186     }
5187     else
5188     {
5189         nFibError = ERR_SWG_READ_ERROR;     // Error melden
5190     }
5191 }
5192 
5193 
WW8Fib(sal_uInt8 nVer)5194 WW8Fib::WW8Fib(sal_uInt8 nVer)
5195 {
5196     memset(this, 0, sizeof(*this));
5197     nVersion = nVer;
5198     if (8 == nVer)
5199     {
5200         fcMin = 0x400;
5201         wIdent = 0xa5ec;
5202         nFib = 0xc2;
5203         nFibBack = 0xbf;
5204         nProduct = 0x204D;
5205 
5206         csw = 0x0e;     // muss das sein ???
5207         cfclcb = 0x6c;  //      -""-
5208         clw = 0x16;     //      -""-
5209         pnFbpChpFirst = pnFbpPapFirst = pnFbpLvcFirst = 0x000fffff;
5210         fExtChar = true;
5211         fWord97Saved = fWord2000Saved = true;
5212 
5213         // diese Flags muessen nicht gesetzt werden; koennen aber.
5214         //  wMagicCreated = wMagicRevised = 0x6a62;
5215         //  wMagicCreatedPrivate = wMagicRevisedPrivate = 0xb3b2;
5216         //
5217 
5218         wMagicCreated = 0x6143;
5219         wMagicRevised = 0x6C6F;
5220         wMagicCreatedPrivate = 0x6E61;
5221         wMagicRevisedPrivate = 0x3136;
5222     }
5223     else
5224     {
5225         fcMin = 0x300;
5226         wIdent = 0xa5dc;
5227         nFib = nFibBack = 0x65;
5228         nProduct = 0xc02d;
5229     }
5230 
5231     lid = lidFE = 0x407;
5232 }
5233 
Write(SvStream & rStrm)5234 bool WW8Fib::Write(SvStream& rStrm)
5235 {
5236     sal_uInt8 *pDataPtr = new sal_uInt8[ fcMin ];
5237     sal_uInt8 *pData = pDataPtr;
5238     memset( pData, 0, fcMin );
5239 
5240     bool bVer8 = 8 == nVersion;
5241 
5242     sal_uLong nPos = rStrm.Tell();
5243     cbMac = rStrm.Seek( STREAM_SEEK_TO_END );
5244     rStrm.Seek( nPos );
5245 
5246     Set_UInt16( pData, wIdent );
5247     Set_UInt16( pData, nFib );
5248     Set_UInt16( pData, nProduct );
5249     Set_UInt16( pData, lid );
5250     Set_UInt16( pData, pnNext );
5251 
5252     sal_uInt16 nBits16 = 0;
5253     if( fDot )          nBits16 |= 0x0001;
5254     if( fGlsy)          nBits16 |= 0x0002;
5255     if( fComplex )      nBits16 |= 0x0004;
5256     if( fHasPic )       nBits16 |= 0x0008;
5257     nBits16 |= (0xf0 & ( cQuickSaves << 4 ));
5258     if( fEncrypted )    nBits16 |= 0x0100;
5259     if( fWhichTblStm )  nBits16 |= 0x0200;
5260     if( fExtChar )      nBits16 |= 0x1000;
5261     Set_UInt16( pData, nBits16 );
5262 
5263     Set_UInt16( pData, nFibBack );
5264     Set_UInt16( pData, lKey1 );
5265     Set_UInt16( pData, lKey2 );
5266     Set_UInt8( pData, envr );
5267 
5268     sal_uInt8 nBits8 = 0;
5269     if( bVer8 )
5270     {
5271         if( fMac )                  nBits8 |= 0x0001;
5272         if( fEmptySpecial )         nBits8 |= 0x0002;
5273         if( fLoadOverridePage )     nBits8 |= 0x0004;
5274         if( fFuturesavedUndo )      nBits8 |= 0x0008;
5275         if( fWord97Saved )          nBits8 |= 0x0010;
5276         if( fWord2000Saved )        nBits8 |= 0x0020;
5277     }
5278     // unter Ver67 these are only reserved
5279     Set_UInt8( pData, nBits8  );
5280 
5281     Set_UInt16( pData, chse );
5282     Set_UInt16( pData, chseTables );
5283     Set_UInt32( pData, fcMin );
5284     Set_UInt32( pData, fcMac );
5285 
5286 // Einschub fuer WW8 *****************************************************
5287 
5288     // Marke: "rgsw"  Beginning of the array of shorts
5289     if( bVer8 )
5290     {
5291         Set_UInt16( pData, csw );
5292         Set_UInt16( pData, wMagicCreated );
5293         Set_UInt16( pData, wMagicRevised );
5294         Set_UInt16( pData, wMagicCreatedPrivate );
5295         Set_UInt16( pData, wMagicRevisedPrivate );
5296         pData += 9 * sizeof( sal_Int16 );
5297         Set_UInt16( pData, lidFE );
5298         Set_UInt16( pData, clw );
5299     }
5300 
5301 // Ende des Einschubs fuer WW8 *******************************************
5302 
5303     // Marke: "rglw"  Beginning of the array of longs
5304     Set_UInt32( pData, cbMac );
5305 
5306     // 2 Longs uebergehen, da unwichtiger Quatsch
5307     pData += 2 * sizeof( sal_Int32);
5308 
5309     // weitere 2 Longs nur bei Ver67 ueberspringen
5310     if( !bVer8 )
5311         pData += 2 * sizeof( sal_Int32);
5312 
5313     Set_UInt32( pData, ccpText );
5314     Set_UInt32( pData, ccpFtn );
5315     Set_UInt32( pData, ccpHdr );
5316     Set_UInt32( pData, ccpMcr );
5317     Set_UInt32( pData, ccpAtn );
5318     Set_UInt32( pData, ccpEdn );
5319     Set_UInt32( pData, ccpTxbx );
5320     Set_UInt32( pData, ccpHdrTxbx );
5321 
5322         // weiteres Long nur bei Ver67 ueberspringen
5323     if( !bVer8 )
5324         pData += 1 * sizeof( sal_Int32);
5325 
5326 // Einschub fuer WW8 *****************************************************
5327     if( bVer8 )
5328     {
5329         Set_UInt32( pData, pnFbpChpFirst );
5330         Set_UInt32( pData, pnChpFirst );
5331         Set_UInt32( pData, cpnBteChp );
5332         Set_UInt32( pData, pnFbpPapFirst );
5333         Set_UInt32( pData, pnPapFirst );
5334         Set_UInt32( pData, cpnBtePap );
5335         Set_UInt32( pData, pnFbpLvcFirst );
5336         Set_UInt32( pData, pnLvcFirst );
5337         Set_UInt32( pData, cpnBteLvc );
5338         Set_UInt32( pData, fcIslandFirst );
5339         Set_UInt32( pData, fcIslandLim );
5340         Set_UInt16( pData, cfclcb );
5341     }
5342 // Ende des Einschubs fuer WW8 *******************************************
5343 
5344     // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
5345     Set_UInt32( pData, fcStshfOrig );
5346     Set_UInt32( pData, lcbStshfOrig );
5347     Set_UInt32( pData, fcStshf );
5348     Set_UInt32( pData, lcbStshf );
5349     Set_UInt32( pData, fcPlcffndRef );
5350     Set_UInt32( pData, lcbPlcffndRef );
5351     Set_UInt32( pData, fcPlcffndTxt );
5352     Set_UInt32( pData, lcbPlcffndTxt );
5353     Set_UInt32( pData, fcPlcfandRef );
5354     Set_UInt32( pData, lcbPlcfandRef );
5355     Set_UInt32( pData, fcPlcfandTxt );
5356     Set_UInt32( pData, lcbPlcfandTxt );
5357     Set_UInt32( pData, fcPlcfsed );
5358     Set_UInt32( pData, lcbPlcfsed );
5359     Set_UInt32( pData, fcPlcfpad );
5360     Set_UInt32( pData, lcbPlcfpad );
5361     Set_UInt32( pData, fcPlcfphe );
5362     Set_UInt32( pData, lcbPlcfphe );
5363     Set_UInt32( pData, fcSttbfglsy );
5364     Set_UInt32( pData, lcbSttbfglsy );
5365     Set_UInt32( pData, fcPlcfglsy );
5366     Set_UInt32( pData, lcbPlcfglsy );
5367     Set_UInt32( pData, fcPlcfhdd );
5368     Set_UInt32( pData, lcbPlcfhdd );
5369     Set_UInt32( pData, fcPlcfbteChpx );
5370     Set_UInt32( pData, lcbPlcfbteChpx );
5371     Set_UInt32( pData, fcPlcfbtePapx );
5372     Set_UInt32( pData, lcbPlcfbtePapx );
5373     Set_UInt32( pData, fcPlcfsea );
5374     Set_UInt32( pData, lcbPlcfsea );
5375     Set_UInt32( pData, fcSttbfffn );
5376     Set_UInt32( pData, lcbSttbfffn );
5377     Set_UInt32( pData, fcPlcffldMom );
5378     Set_UInt32( pData, lcbPlcffldMom );
5379     Set_UInt32( pData, fcPlcffldHdr );
5380     Set_UInt32( pData, lcbPlcffldHdr );
5381     Set_UInt32( pData, fcPlcffldFtn );
5382     Set_UInt32( pData, lcbPlcffldFtn );
5383     Set_UInt32( pData, fcPlcffldAtn );
5384     Set_UInt32( pData, lcbPlcffldAtn );
5385     Set_UInt32( pData, fcPlcffldMcr );
5386     Set_UInt32( pData, lcbPlcffldMcr );
5387     Set_UInt32( pData, fcSttbfbkmk );
5388     Set_UInt32( pData, lcbSttbfbkmk );
5389     Set_UInt32( pData, fcPlcfbkf );
5390     Set_UInt32( pData, lcbPlcfbkf );
5391     Set_UInt32( pData, fcPlcfbkl );
5392     Set_UInt32( pData, lcbPlcfbkl );
5393     Set_UInt32( pData, fcCmds );
5394     Set_UInt32( pData, lcbCmds );
5395     Set_UInt32( pData, fcPlcfmcr );
5396     Set_UInt32( pData, lcbPlcfmcr );
5397     Set_UInt32( pData, fcSttbfmcr );
5398     Set_UInt32( pData, lcbSttbfmcr );
5399     Set_UInt32( pData, fcPrDrvr );
5400     Set_UInt32( pData, lcbPrDrvr );
5401     Set_UInt32( pData, fcPrEnvPort );
5402     Set_UInt32( pData, lcbPrEnvPort );
5403     Set_UInt32( pData, fcPrEnvLand );
5404     Set_UInt32( pData, lcbPrEnvLand );
5405     Set_UInt32( pData, fcWss );
5406     Set_UInt32( pData, lcbWss );
5407     Set_UInt32( pData, fcDop );
5408     Set_UInt32( pData, lcbDop );
5409     Set_UInt32( pData, fcSttbfAssoc );
5410     Set_UInt32( pData, cbSttbfAssoc );
5411     Set_UInt32( pData, fcClx );
5412     Set_UInt32( pData, lcbClx );
5413     Set_UInt32( pData, fcPlcfpgdFtn );
5414     Set_UInt32( pData, lcbPlcfpgdFtn );
5415     Set_UInt32( pData, fcAutosaveSource );
5416     Set_UInt32( pData, lcbAutosaveSource );
5417     Set_UInt32( pData, fcGrpStAtnOwners );
5418     Set_UInt32( pData, lcbGrpStAtnOwners );
5419     Set_UInt32( pData, fcSttbfAtnbkmk );
5420     Set_UInt32( pData, lcbSttbfAtnbkmk );
5421 
5422     // weiteres short nur bei Ver67 ueberspringen
5423     if( !bVer8 )
5424     {
5425         pData += 1*sizeof( sal_Int16);
5426         Set_UInt16( pData, (sal_uInt16)pnChpFirst );
5427         Set_UInt16( pData, (sal_uInt16)pnPapFirst );
5428         Set_UInt16( pData, (sal_uInt16)cpnBteChp );
5429         Set_UInt16( pData, (sal_uInt16)cpnBtePap );
5430     }
5431 
5432     Set_UInt32( pData, fcPlcfdoaMom ); // nur bei Ver67, in Ver8 unused
5433     Set_UInt32( pData, lcbPlcfdoaMom ); // nur bei Ver67, in Ver8 unused
5434     Set_UInt32( pData, fcPlcfdoaHdr ); // nur bei Ver67, in Ver8 unused
5435     Set_UInt32( pData, lcbPlcfdoaHdr ); // nur bei Ver67, in Ver8 unused
5436 
5437     Set_UInt32( pData, fcPlcfspaMom ); // in Ver67 leere Reserve
5438     Set_UInt32( pData, lcbPlcfspaMom ); // in Ver67 leere Reserve
5439     Set_UInt32( pData, fcPlcfspaHdr ); // in Ver67 leere Reserve
5440     Set_UInt32( pData, lcbPlcfspaHdr ); // in Ver67 leere Reserve
5441 
5442     Set_UInt32( pData, fcPlcfAtnbkf );
5443     Set_UInt32( pData, lcbPlcfAtnbkf );
5444     Set_UInt32( pData, fcPlcfAtnbkl );
5445     Set_UInt32( pData, lcbPlcfAtnbkl );
5446     Set_UInt32( pData, fcPms );
5447     Set_UInt32( pData, lcbPMS );
5448     Set_UInt32( pData, fcFormFldSttbf );
5449     Set_UInt32( pData, lcbFormFldSttbf );
5450     Set_UInt32( pData, fcPlcfendRef );
5451     Set_UInt32( pData, lcbPlcfendRef );
5452     Set_UInt32( pData, fcPlcfendTxt );
5453     Set_UInt32( pData, lcbPlcfendTxt );
5454     Set_UInt32( pData, fcPlcffldEdn );
5455     Set_UInt32( pData, lcbPlcffldEdn );
5456     Set_UInt32( pData, fcPlcfpgdEdn );
5457     Set_UInt32( pData, lcbPlcfpgdEdn );
5458     Set_UInt32( pData, fcDggInfo ); // in Ver67 leere Reserve
5459     Set_UInt32( pData, lcbDggInfo ); // in Ver67 leere Reserve
5460     Set_UInt32( pData, fcSttbfRMark );
5461     Set_UInt32( pData, lcbSttbfRMark );
5462     Set_UInt32( pData, fcSttbfCaption );
5463     Set_UInt32( pData, lcbSttbfCaption );
5464     Set_UInt32( pData, fcSttbAutoCaption );
5465     Set_UInt32( pData, lcbSttbAutoCaption );
5466     Set_UInt32( pData, fcPlcfwkb );
5467     Set_UInt32( pData, lcbPlcfwkb );
5468     Set_UInt32( pData, fcPlcfspl ); // in Ver67 leere Reserve
5469     Set_UInt32( pData, lcbPlcfspl ); // in Ver67 leere Reserve
5470     Set_UInt32( pData, fcPlcftxbxTxt );
5471     Set_UInt32( pData, lcbPlcftxbxTxt );
5472     Set_UInt32( pData, fcPlcffldTxbx );
5473     Set_UInt32( pData, lcbPlcffldTxbx );
5474     Set_UInt32( pData, fcPlcfHdrtxbxTxt );
5475     Set_UInt32( pData, lcbPlcfHdrtxbxTxt );
5476     Set_UInt32( pData, fcPlcffldHdrTxbx );
5477     Set_UInt32( pData, lcbPlcffldHdrTxbx );
5478 
5479     if( bVer8 )
5480     {
5481         pData += 0x2e2 - 0x27a;         // Pos + Offset (fcPlcfLst - fcStwUser)
5482         Set_UInt32( pData, fcPlcfLst );
5483         Set_UInt32( pData, lcbPlcfLst );
5484         Set_UInt32( pData, fcPlfLfo );
5485         Set_UInt32( pData, lcbPlfLfo );
5486         Set_UInt32( pData, fcPlcftxbxBkd );
5487         Set_UInt32( pData, lcbPlcftxbxBkd );
5488         Set_UInt32( pData, fcPlcfHdrtxbxBkd );
5489         Set_UInt32( pData, lcbPlcfHdrtxbxBkd );
5490 
5491         pData += 0x372 - 0x302; // Pos + Offset (fcSttbListNames - fcDocUndo)
5492         Set_UInt32( pData, fcSttbListNames );
5493         Set_UInt32( pData, lcbSttbListNames );
5494 
5495         pData += 0x382 - 0x37A;
5496         Set_UInt32( pData, fcMagicTable );
5497         Set_UInt32( pData, lcbMagicTable );
5498 
5499         pData += 0x3FA - 0x38A;
5500         Set_UInt16( pData, (sal_uInt16)0x0002);
5501         Set_UInt16( pData, (sal_uInt16)0x00D9);
5502     }
5503 
5504     rStrm.Write( pDataPtr, fcMin );
5505     delete[] pDataPtr;
5506     return 0 == rStrm.GetError();
5507 }
5508 
GetFIBCharset(sal_uInt16 chs)5509 rtl_TextEncoding WW8Fib::GetFIBCharset(sal_uInt16 chs)
5510 {
5511     ASSERT(chs <= 0x100, "overflowed winword charset set");
5512     rtl_TextEncoding eCharSet =
5513         (0x0100 == chs)
5514         ? RTL_TEXTENCODING_APPLE_ROMAN
5515         : rtl_getTextEncodingFromWindowsCharset( static_cast<sal_uInt8>(chs) );
5516     return eCharSet;
5517 }
5518 
WW8Style(SvStream & rStream,WW8Fib & rFibPara)5519 WW8Style::WW8Style(SvStream& rStream, WW8Fib& rFibPara)
5520     : rFib(rFibPara), rSt(rStream), cstd(0), cbSTDBaseInFile(0),
5521     stiMaxWhenSaved(0), istdMaxFixedWhenSaved(0), nVerBuiltInNamesWhenSaved(0),
5522     ftcStandardChpStsh(0), ftcStandardChpCJKStsh(0), ftcStandardChpCTLStsh(0)
5523 {
5524     nStyleStart = rFib.fcStshf;
5525     nStyleLen = rFib.lcbStshf;
5526 
5527     rSt.Seek(nStyleStart);
5528 
5529     sal_uInt16 cbStshi = 0; //  2 bytes size of the following STSHI structure
5530 
5531     // alte Version ?
5532     if (rFib.nFib < 67)
5533         cbStshi = 4;    // -> Laengenfeld fehlt
5534     else    // neue Version:
5535         // lies die Laenge der in der Datei gespeicherten Struktur
5536         rSt >> cbStshi;
5537 
5538     sal_uInt16 nRead = cbStshi;
5539     do
5540     {
5541         sal_uInt16 a16Bit;
5542 
5543         if(  2 > nRead ) break;
5544         rSt >> cstd;
5545 
5546         if(  4 > nRead ) break;
5547         rSt >> cbSTDBaseInFile;
5548 
5549         if(  6 > nRead ) break;
5550         rSt >> a16Bit;
5551         fStdStylenamesWritten = a16Bit & 0x0001;
5552 
5553         if(  8 > nRead ) break;
5554         rSt >> stiMaxWhenSaved;
5555 
5556         if( 10 > nRead ) break;
5557         rSt >> istdMaxFixedWhenSaved;
5558 
5559         if( 12 > nRead ) break;
5560         rSt >> nVerBuiltInNamesWhenSaved;
5561 
5562         if( 14 > nRead ) break;
5563         rSt >> ftcStandardChpStsh;
5564 
5565         if( 16 > nRead ) break;
5566         rSt >> ftcStandardChpCJKStsh;
5567 
5568         if ( 18 > nRead ) break;
5569         rSt >> ftcStandardChpCTLStsh;
5570 
5571         // ggfs. den Rest ueberlesen
5572         if( 18 < nRead )
5573             rSt.SeekRel( nRead-18 );
5574     }
5575     while( !this ); // Trick: obiger Block wird genau einmal durchlaufen
5576                     //   und kann vorzeitig per "break" verlassen werden.
5577 
5578     if( 0 != rSt.GetError() )
5579     {
5580         // wie denn nun den Error melden?
5581     }
5582 }
5583 
5584 // Read1STDFixed() liest ein Style ein. Wenn der Style vollstaendig vorhanden
5585 // ist, d.h. kein leerer Slot, dann wird Speicher alloziert und ein Pointer auf
5586 // die ( evtl. mit Nullen aufgefuellten ) STD geliefert. Ist es ein leerer
5587 // Slot, dann wird ein Nullpointer zurueckgeliefert.
Read1STDFixed(short & rSkip,short * pcbStd)5588 WW8_STD* WW8Style::Read1STDFixed( short& rSkip, short* pcbStd )
5589 {
5590     WW8_STD* pStd = 0;
5591 
5592     sal_uInt16 cbStd;
5593     rSt >> cbStd;   // lies Laenge
5594 
5595     sal_uInt16 nRead = cbSTDBaseInFile;
5596     if( cbStd >= cbSTDBaseInFile )
5597     {
5598         // Fixed part vollst. vorhanden
5599 
5600         // read fixed part of STD
5601         pStd = new WW8_STD;
5602         memset( pStd, 0, sizeof( *pStd ) );
5603 
5604         do
5605         {
5606             sal_uInt16 a16Bit;
5607 
5608             if( 2 > nRead ) break;
5609             rSt >> a16Bit;
5610             pStd->sti          =        a16Bit & 0x0fff  ;
5611             pStd->fScratch     = 0 != ( a16Bit & 0x1000 );
5612             pStd->fInvalHeight = 0 != ( a16Bit & 0x2000 );
5613             pStd->fHasUpe      = 0 != ( a16Bit & 0x4000 );
5614             pStd->fMassCopy    = 0 != ( a16Bit & 0x8000 );
5615 
5616             if( 4 > nRead ) break;
5617             rSt >> a16Bit;
5618             pStd->sgc      =   a16Bit & 0x000f       ;
5619             pStd->istdBase = ( a16Bit & 0xfff0 ) >> 4;
5620 
5621             if( 6 > nRead ) break;
5622             rSt >> a16Bit;
5623             pStd->cupx     =   a16Bit & 0x000f       ;
5624             pStd->istdNext = ( a16Bit & 0xfff0 ) >> 4;
5625 
5626             if( 8 > nRead ) break;
5627             rSt >> pStd->bchUpe;
5628 
5629             // ab Ver8 sollten diese beiden Felder dazukommen:
5630             if(10 > nRead ) break;
5631             rSt >> a16Bit;
5632             pStd->fAutoRedef =   a16Bit & 0x0001       ;
5633             pStd->fHidden    = ( a16Bit & 0x0002 ) >> 2;
5634 
5635             // man kann nie wissen: vorsichtshalber ueberlesen
5636             // wir eventuelle Fuellsel, die noch zum BASE-Part gehoeren...
5637             if( 10 < nRead )
5638                 rSt.SeekRel( nRead-10 );
5639         }
5640         while( !this ); // Trick: obiger Block wird genau einmal durchlaufen
5641                         //   und kann vorzeitig per "break" verlassen werden.
5642 
5643         if( (0 != rSt.GetError()) || !nRead )
5644             DELETEZ( pStd );        // per NULL den Error melden
5645 
5646       rSkip = cbStd - cbSTDBaseInFile;
5647     }
5648     else
5649     {           // Fixed part zu kurz
5650         if( cbStd )
5651             rSt.SeekRel( cbStd );           // ueberlies Reste
5652         rSkip = 0;
5653     }
5654     if( pcbStd )
5655         *pcbStd = cbStd;
5656     return pStd;
5657 }
5658 
Read1Style(short & rSkip,String * pString,short * pcbStd)5659 WW8_STD* WW8Style::Read1Style( short& rSkip, String* pString, short* pcbStd )
5660 {
5661     // Attention: MacWord-Documents have their Stylenames
5662     // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
5663 
5664     WW8_STD* pStd = Read1STDFixed( rSkip, pcbStd );         // lese STD
5665 
5666     // String gewuenscht ?
5667     if( pString )
5668     {   // echter Style ?
5669         if ( pStd )
5670         {
5671             switch( rFib.nVersion )
5672             {
5673                 case 6:
5674                 case 7:
5675                     // lies Pascal-String
5676                     *pString = WW8ReadPString( rSt, RTL_TEXTENCODING_MS_1252 );
5677                     // leading len and trailing zero --> 2
5678                     rSkip -= 2+ pString->Len();
5679                     break;
5680                 case 8:
5681                     // handle Unicode-String with leading length short and
5682                     // trailing zero
5683                     if (ww8String::TestBeltAndBraces(rSt))
5684                     {
5685                         *pString = WW8Read_xstz(rSt, 0, true);
5686                         rSkip -= (pString->Len() + 2) * 2;
5687                     }
5688                     else
5689                     {
5690                         /*
5691                         #i8114#
5692                         This is supposed to be impossible, its just supposed
5693                         to be 16 bit count followed by the string and ending
5694                         in a 0 short. But "Lotus SmartSuite Product: Word Pro"
5695                         is creating invalid style names in ww7- format. So we
5696                         use the belt and braces of the ms strings to see if
5697                         they are not corrupt. If they are then we try them as
5698                         8bit ones
5699                         */
5700                         *pString = WW8ReadPString(rSt,RTL_TEXTENCODING_MS_1252);
5701                         // leading len and trailing zero --> 2
5702                         rSkip -= 2+ pString->Len();
5703                     }
5704                     break;
5705                 default:
5706                     ASSERT(!this, "Es wurde vergessen, nVersion zu kodieren!");
5707                     break;
5708             }
5709         }
5710         else
5711             *pString = aEmptyStr;   // Kann keinen Namen liefern
5712     }
5713     return pStd;
5714 }
5715 
5716 
5717 //-----------------------------------------
5718 
5719 
5720 struct WW8_FFN_Ver6 : public WW8_FFN_BASE
5721 {
5722     // ab Ver6
5723     sal_Char szFfn[65]; // 0x6 bzw. 0x40 ab Ver8 zero terminated string that
5724                         // records name of font.
5725                         // Maximal size of szFfn is 65 characters.
5726                         // Vorsicht: Dieses Array kann auch kleiner sein!!!
5727                         // Possibly followed by a second sz which records the
5728                         // name of an alternate font to use if the first named
5729                         // font does not exist on this system.
5730 };
5731 struct WW8_FFN_Ver8 : public WW8_FFN_BASE
5732 {
5733     // ab Ver8 sind folgende beiden Felder eingeschoben,
5734     // werden von uns ignoriert.
5735     sal_Char panose[ 10 ];  //  0x6   PANOSE
5736     sal_Char fs[ 24     ];  //  0x10  FONTSIGNATURE
5737 
5738     // ab Ver8 als Unicode
5739     sal_uInt16 szFfn[65];   // 0x6 bzw. 0x40 ab Ver8 zero terminated string that
5740                         // records name of font.
5741                         // Maximal size of szFfn is 65 characters.
5742                         // Vorsicht: Dieses Array kann auch kleiner sein!!!
5743                         // Possibly followed by a second sz which records the
5744                         // name of an alternate font to use if the first named
5745                         // font does not exist on this system.
5746 };
5747 
WW8Fonts(SvStream & rSt,WW8Fib & rFib)5748 WW8Fonts::WW8Fonts( SvStream& rSt, WW8Fib& rFib )
5749 {
5750     // Attention: MacWord-Documents have their Fontnames
5751     // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
5752     if( rFib.lcbSttbfffn <= 2 )
5753     {
5754         ASSERT( !this, "Fonttabelle kaputt! (rFib.lcbSttbfffn < 2)" );
5755         pFontA = 0;
5756         nMax = 0;
5757         return;
5758     }
5759 
5760     bool bVer67 = (8 > rFib.nVersion);
5761 
5762     rSt.Seek( rFib.fcSttbfffn );
5763 
5764     // allocate Font Array
5765     sal_uInt8* pA   = new sal_uInt8[ rFib.lcbSttbfffn - 2 ];
5766     WW8_FFN* p = (WW8_FFN*)pA;
5767 
5768     if( !bVer67 )
5769     {
5770         // bVer8: read the count of strings in nMax
5771         rSt >> nMax;
5772     }
5773 
5774     // Ver8:  skip undefined uint16
5775     // Ver67: skip the herein stored total byte of structure
5776     //        - we already got that information in rFib.lcbSttbfffn
5777     rSt.SeekRel( 2 );
5778 
5779     // read all font information
5780     rSt.Read( pA, rFib.lcbSttbfffn - 2 );
5781 
5782     if( bVer67 )
5783     {
5784         // try to figure out how many fonts are defined here
5785         nMax = 0;
5786         long nLeft = rFib.lcbSttbfffn - 2;
5787         for(;;)
5788         {
5789             short nNextSiz;
5790 
5791             nNextSiz = p->cbFfnM1 + 1;
5792             if( nNextSiz > nLeft )
5793                 break;
5794             nMax++;
5795             nLeft -= nNextSiz;
5796             if( nLeft < 1 )     // can we read the given amount of bytes ?
5797                 break;
5798             // increase p by nNextSiz Bytes
5799             p = (WW8_FFN *)( ( (sal_uInt8*)p ) + nNextSiz );
5800         }
5801     }
5802 
5803     if( nMax )
5804     {
5805         // allocate Index Array
5806         pFontA = new WW8_FFN[ nMax ];
5807         p = pFontA;
5808 
5809         if( bVer67 )
5810         {
5811             WW8_FFN_Ver6* pVer6 = (WW8_FFN_Ver6*)pA;
5812             sal_uInt8 c2;
5813             for(sal_uInt16 i=0; i<nMax; ++i, ++p)
5814             {
5815                 p->cbFfnM1   = pVer6->cbFfnM1;
5816                 c2           = *(((sal_uInt8*)pVer6) + 1);
5817 
5818                 p->prg       =  c2 & 0x02;
5819                 p->fTrueType = (c2 & 0x04) >> 2;
5820                 // ein Reserve-Bit ueberspringen
5821                 p->ff        = (c2 & 0x70) >> 4;
5822 
5823                 p->wWeight   = SVBT16ToShort( *(SVBT16*)&pVer6->wWeight );
5824                 p->chs       = pVer6->chs;
5825                 p->ibszAlt   = pVer6->ibszAlt;
5826                 /*
5827                  #i8726# 7- seems to encode the name in the same encoding as
5828                  the font, e.g load the doc in 97 and save to see the unicode
5829                  ver of the asian fontnames in that example to confirm.
5830                  */
5831                 rtl_TextEncoding eEnc = WW8Fib::GetFIBCharset(p->chs);
5832                 if ((eEnc == RTL_TEXTENCODING_SYMBOL) || (eEnc == RTL_TEXTENCODING_DONTKNOW))
5833                     eEnc = RTL_TEXTENCODING_MS_1252;
5834                 p->sFontname = String(pVer6->szFfn, eEnc);
5835 //              p->sFontname = String(pVer6->szFfn, RTL_TEXTENCODING_MS_1252);
5836                 if (p->ibszAlt)
5837                 {
5838                     p->sFontname.Append(';');
5839                     p->sFontname += String(pVer6->szFfn+p->ibszAlt, eEnc);
5840 //                      RTL_TEXTENCODING_MS_1252 );
5841                 }
5842                 pVer6 = (WW8_FFN_Ver6*)( ((sal_uInt8*)pVer6) + pVer6->cbFfnM1 + 1 );
5843             }
5844         }
5845         else
5846         {
5847             WW8_FFN_Ver8* pVer8 = (WW8_FFN_Ver8*)pA;
5848             sal_uInt8 c2;
5849             for(sal_uInt16 i=0; i<nMax; ++i, ++p)
5850             {
5851                 p->cbFfnM1   = pVer8->cbFfnM1;
5852                 c2           = *(((sal_uInt8*)pVer8) + 1);
5853 
5854                 p->prg       =  c2 & 0x02;
5855                 p->fTrueType = (c2 & 0x04) >> 2;
5856                 // ein Reserve-Bit ueberspringen
5857                 p->ff        = (c2 & 0x70) >> 4;
5858 
5859                 p->wWeight   = SVBT16ToShort( *(SVBT16*)&pVer8->wWeight );
5860                 p->chs       = pVer8->chs;
5861                 p->ibszAlt   = pVer8->ibszAlt;
5862 
5863 #ifdef __WW8_NEEDS_COPY
5864                 {
5865                     sal_uInt8 nLen = 0x28;
5866                     for( sal_uInt16* pTmp = pVer8->szFfn;
5867                         nLen < pVer8->cbFfnM1 + 1 ; ++pTmp, nLen+=2 )
5868                     {
5869                         *pTmp = SVBT16ToShort( *(SVBT16*)pTmp );
5870                     }
5871                 }
5872 #endif // defined __WW8_NEEDS_COPY
5873 
5874                 p->sFontname = pVer8->szFfn;
5875                 if (p->ibszAlt)
5876                 {
5877                     p->sFontname.Append(';');
5878                     p->sFontname.Append(pVer8->szFfn+p->ibszAlt);
5879                 }
5880 
5881                 // Zeiger auf Ursprungsarray einen Font nach hinten setzen
5882                 pVer8 = (WW8_FFN_Ver8*)( ((sal_uInt8*)pVer8) + pVer8->cbFfnM1 + 1 );
5883             }
5884         }
5885     }
5886     delete[] pA;
5887 }
5888 
GetFont(sal_uInt16 nNum) const5889 const WW8_FFN* WW8Fonts::GetFont( sal_uInt16 nNum ) const
5890 {
5891     if( !pFontA || nNum >= nMax )
5892         return 0;
5893 
5894     return &pFontA[ nNum ];
5895 }
5896 
5897 
5898 
5899 //-----------------------------------------
5900 
5901 
5902 // Suche zu einem Header / Footer den Index in der WW-Liste von Headern / Footern
5903 //
5904 // Pferdefuesse bei WinWord6 und -7:
5905 // 1) Am Anfang des Einlesens muss WWPLCF_HdFt mit Fib und Dop konstruiert werden
5906 // 2) Der Haupttext muss sequentiell ueber alle Sections gelesen werden
5907 // 3) Fuer jedes vorkommende Header / Footer - Attribut des Haupttextes
5908 //  ( Darf pro Section maximal eins sein ) muss UpdateIndex() genau einmal
5909 //  mit dem Parameter des Attributes gerufen werden. Dieser Aufruf muss *nach*
5910 //  dem letzten Aufruf von GetTextPos() passieren.
5911 // 4) GetTextPos() darf mit genau einem der obenstehen WW_... aufgerufen werden
5912 //   ( nicht verodern ! )
5913 // -> dann liefert GetTextPos() vielleicht auch ein richtiges Ergebnis
5914 
WW8PLCF_HdFt(SvStream * pSt,WW8Fib & rFib,WW8Dop & rDop)5915 WW8PLCF_HdFt::WW8PLCF_HdFt( SvStream* pSt, WW8Fib& rFib, WW8Dop& rDop )
5916     : aPLCF( pSt, rFib.fcPlcfhdd , rFib.lcbPlcfhdd , 0 )
5917 {
5918     nIdxOffset = 0;
5919 
5920      /*
5921       cmc 23/02/2000: This dop.grpfIhdt has a bit set for each special
5922       footnote *and endnote!!* seperator,continuation seperator, and
5923       continuation notice entry, the documentation does not mention the
5924       endnote seperators, the documentation also gets the index numbers
5925       backwards when specifying which bits to test. The bottom six bits
5926       of this value must be tested and skipped over. Each section's
5927       grpfIhdt is then tested for the existence of the appropriate headers
5928       and footers, at the end of each section the nIdxOffset must be updated
5929       to point to the beginning of the next section's group of headers and
5930       footers in this PLCF, UpdateIndex does that task.
5931       */
5932     for( sal_uInt8 nI = 0x1; nI <= 0x20; nI <<= 1 )
5933         if( nI & rDop.grpfIhdt )                // Bit gesetzt ?
5934             nIdxOffset++;
5935 
5936     nTextOfs = rFib.ccpText + rFib.ccpFtn;  // Groesse des Haupttextes
5937                                             // und der Fussnoten
5938 }
5939 
GetTextPos(sal_uInt8 grpfIhdt,sal_uInt8 nWhich,WW8_CP & rStart,long & rLen)5940 bool WW8PLCF_HdFt::GetTextPos(sal_uInt8 grpfIhdt, sal_uInt8 nWhich, WW8_CP& rStart,
5941     long& rLen)
5942 {
5943     sal_uInt8 nI = 0x01;
5944     short nIdx = nIdxOffset;
5945     while (true)
5946     {
5947         if( nI & nWhich )
5948             break;                      // found
5949         if( grpfIhdt & nI )
5950             nIdx++;                     // uninteresting Header / Footer
5951         nI <<= 1;                       // text next bit
5952         if( nI > 0x20 )
5953             return false;               // not found
5954     }
5955                                         // nIdx ist HdFt-Index
5956     WW8_CP nEnd;
5957     void* pData;
5958 
5959     aPLCF.SetIdx( nIdx );               // Lookup suitable CP
5960     aPLCF.Get( rStart, nEnd, pData );
5961     rLen = nEnd - rStart;
5962     aPLCF++;
5963 
5964     return true;
5965 }
5966 
GetTextPosExact(short nIdx,WW8_CP & rStart,long & rLen)5967 bool WW8PLCF_HdFt::GetTextPosExact(short nIdx, WW8_CP& rStart, long& rLen)
5968 {
5969     WW8_CP nEnd;
5970     void* pData;
5971 
5972     aPLCF.SetIdx( nIdx );               // Lookup suitable CP
5973     aPLCF.Get( rStart, nEnd, pData );
5974     rLen = nEnd - rStart;
5975     return true;
5976 }
5977 
UpdateIndex(sal_uInt8 grpfIhdt)5978 void WW8PLCF_HdFt::UpdateIndex( sal_uInt8 grpfIhdt )
5979 {
5980     // Caution: Description is not correct
5981     for( sal_uInt8 nI = 0x01; nI <= 0x20; nI <<= 1 )
5982         if( nI & grpfIhdt )
5983             nIdxOffset++;
5984 }
5985 
5986 //-----------------------------------------
5987 //          WW8Dop
5988 //-----------------------------------------
5989 
WW8Dop(SvStream & rSt,sal_Int16 nFib,sal_Int32 nPos,sal_Int32 nSize)5990 WW8Dop::WW8Dop( SvStream& rSt, sal_Int16 nFib, sal_Int32 nPos, sal_Int32 nSize )
5991 {
5992     sal_uInt8* pDataPtr = new sal_uInt8[ 500 ];
5993     sal_uInt8* pData = pDataPtr;
5994 
5995     sal_uInt32 nRead = 500 < nSize ? 500 : nSize;
5996     rSt.Seek( nPos );
5997     if( 2 > nSize || nRead != rSt.Read( pData, nRead ))
5998     {
5999         memset( &nDataStart, 0, (&nDataEnd - &nDataStart) );
6000         nDopError = ERR_SWG_READ_ERROR;     // Error melden
6001     }
6002     else
6003     {
6004         if( 500 > nRead )
6005             memset( pData + nRead, 0, 500 - nRead );
6006 
6007         // dann mal die Daten auswerten
6008         sal_uInt32 a32Bit;
6009         sal_uInt16 a16Bit;
6010         sal_uInt8   a8Bit;
6011 
6012         a16Bit = Get_UShort( pData );
6013         fFacingPages        = 0 != ( a16Bit  &  0x0001 )     ;
6014         fWidowControl       = 0 != ( a16Bit  &  0x0002 )     ;
6015         fPMHMainDoc         = 0 != ( a16Bit  &  0x0004 )     ;
6016         grfSuppression      =      ( a16Bit  &  0x0018 ) >> 3;
6017         fpc                 =      ( a16Bit  &  0x0060 ) >> 5;
6018         grpfIhdt            =      ( a16Bit  &  0xff00 ) >> 8;
6019 
6020         a16Bit = Get_UShort( pData );
6021         rncFtn              =   a16Bit  &  0x0003        ;
6022         nFtn                = ( a16Bit  & ~0x0003 ) >> 2 ;
6023 
6024         a8Bit = Get_Byte( pData );
6025         fOutlineDirtySave      = 0 != ( a8Bit  &  0x01   );
6026 
6027         a8Bit = Get_Byte( pData );
6028         fOnlyMacPics           = 0 != ( a8Bit  &  0x01   );
6029         fOnlyWinPics           = 0 != ( a8Bit  &  0x02   );
6030         fLabelDoc              = 0 != ( a8Bit  &  0x04   );
6031         fHyphCapitals          = 0 != ( a8Bit  &  0x08   );
6032         fAutoHyphen            = 0 != ( a8Bit  &  0x10   );
6033         fFormNoFields          = 0 != ( a8Bit  &  0x20   );
6034         fLinkStyles            = 0 != ( a8Bit  &  0x40   );
6035         fRevMarking            = 0 != ( a8Bit  &  0x80   );
6036 
6037         a8Bit = Get_Byte( pData );
6038         fBackup                = 0 != ( a8Bit  &  0x01   );
6039         fExactCWords           = 0 != ( a8Bit  &  0x02   );
6040         fPagHidden             = 0 != ( a8Bit  &  0x04   );
6041         fPagResults            = 0 != ( a8Bit  &  0x08   );
6042         fLockAtn               = 0 != ( a8Bit  &  0x10   );
6043         fMirrorMargins         = 0 != ( a8Bit  &  0x20   );
6044         fReadOnlyRecommended   = 0 != ( a8Bit  &  0x40   );
6045         fDfltTrueType          = 0 != ( a8Bit  &  0x80   );
6046 
6047         a8Bit = Get_Byte( pData );
6048         fPagSuppressTopSpacing = 0 != ( a8Bit  &  0x01   );
6049         fProtEnabled           = 0 != ( a8Bit  &  0x02   );
6050         fDispFormFldSel        = 0 != ( a8Bit  &  0x04   );
6051         fRMView                = 0 != ( a8Bit  &  0x08   );
6052         fRMPrint               = 0 != ( a8Bit  &  0x10   );
6053         fWriteReservation      = 0 != ( a8Bit  &  0x20   );
6054         fLockRev               = 0 != ( a8Bit  &  0x40   );
6055         fEmbedFonts            = 0 != ( a8Bit  &  0x80   );
6056 
6057 
6058         a8Bit = Get_Byte( pData );
6059         copts_fNoTabForInd           = 0 != ( a8Bit  &  0x01   );
6060         copts_fNoSpaceRaiseLower     = 0 != ( a8Bit  &  0x02   );
6061         copts_fSupressSpbfAfterPgBrk = 0 != ( a8Bit  &  0x04   );
6062         copts_fWrapTrailSpaces       = 0 != ( a8Bit  &  0x08   );
6063         copts_fMapPrintTextColor     = 0 != ( a8Bit  &  0x10   );
6064         copts_fNoColumnBalance       = 0 != ( a8Bit  &  0x20   );
6065         copts_fConvMailMergeEsc      = 0 != ( a8Bit  &  0x40   );
6066         copts_fSupressTopSpacing     = 0 != ( a8Bit  &  0x80   );
6067 
6068         a8Bit = Get_Byte( pData );
6069         copts_fOrigWordTableRules    = 0 != ( a8Bit  &  0x01   );
6070         copts_fTransparentMetafiles  = 0 != ( a8Bit  &  0x02   );
6071         copts_fShowBreaksInFrames    = 0 != ( a8Bit  &  0x04   );
6072         copts_fSwapBordersFacingPgs  = 0 != ( a8Bit  &  0x08   );
6073 
6074         dxaTab = Get_Short( pData );
6075         wSpare = Get_UShort( pData );
6076         dxaHotZ = Get_UShort( pData );
6077         cConsecHypLim = Get_UShort( pData );
6078         wSpare2 = Get_UShort( pData );
6079         dttmCreated = Get_Long( pData );
6080         dttmRevised = Get_Long( pData );
6081         dttmLastPrint = Get_Long( pData );
6082         nRevision = Get_Short( pData );
6083         tmEdited = Get_Long( pData );
6084         cWords = Get_Long( pData );
6085         cCh = Get_Long( pData );
6086         cPg = Get_Short( pData );
6087         cParas = Get_Long( pData );
6088 
6089         a16Bit = Get_UShort( pData );
6090         rncEdn =   a16Bit &  0x0003       ;
6091         nEdn   = ( a16Bit & ~0x0003 ) >> 2;
6092 
6093         a16Bit = Get_UShort( pData );
6094         epc            =   a16Bit &  0x0003       ;
6095         nfcFtnRef      = ( a16Bit &  0x003c ) >> 2;
6096         nfcEdnRef      = ( a16Bit &  0x03c0 ) >> 6;
6097         fPrintFormData = 0 != ( a16Bit &  0x0400 );
6098         fSaveFormData  = 0 != ( a16Bit &  0x0800 );
6099         fShadeFormData = 0 != ( a16Bit &  0x1000 );
6100         fWCFtnEdn      = 0 != ( a16Bit &  0x8000 );
6101 
6102         cLines = Get_Long( pData );
6103         cWordsFtnEnd = Get_Long( pData );
6104         cChFtnEdn = Get_Long( pData );
6105         cPgFtnEdn = Get_Short( pData );
6106         cParasFtnEdn = Get_Long( pData );
6107         cLinesFtnEdn = Get_Long( pData );
6108         lKeyProtDoc = Get_Long( pData );
6109 
6110         a16Bit = Get_UShort( pData );
6111         wvkSaved    =   a16Bit & 0x0007        ;
6112         wScaleSaved = ( a16Bit & 0x0ff8 ) >> 3 ;
6113         zkSaved     = ( a16Bit & 0x3000 ) >> 12;
6114         fRotateFontW6 = ( a16Bit & 0x4000 ) >> 14;
6115         iGutterPos = ( a16Bit &  0x8000 ) >> 15;
6116         /*
6117             bei nFib >= 103 gehts weiter:
6118         */
6119         if( nFib >= 103 )
6120         {
6121             a32Bit = Get_ULong( pData );
6122             fNoTabForInd                = ( a32Bit &  0x00000001 )       ;
6123             fNoSpaceRaiseLower          = ( a32Bit &  0x00000002 ) >>  1 ;
6124             fSupressSpbfAfterPageBreak  = ( a32Bit &  0x00000004 ) >>  2 ;
6125             fWrapTrailSpaces            = ( a32Bit &  0x00000008 ) >>  3 ;
6126             fMapPrintTextColor          = ( a32Bit &  0x00000010 ) >>  4 ;
6127             fNoColumnBalance            = ( a32Bit &  0x00000020 ) >>  5 ;
6128             fConvMailMergeEsc           = ( a32Bit &  0x00000040 ) >>  6 ;
6129             fSupressTopSpacing          = ( a32Bit &  0x00000080 ) >>  7 ;
6130             fOrigWordTableRules         = ( a32Bit &  0x00000100 ) >>  8 ;
6131             fTransparentMetafiles       = ( a32Bit &  0x00000200 ) >>  9 ;
6132             fShowBreaksInFrames         = ( a32Bit &  0x00000400 ) >> 10 ;
6133             fSwapBordersFacingPgs       = ( a32Bit &  0x00000800 ) >> 11 ;
6134             fSuppressTopSpacingMac5     = ( a32Bit &  0x00010000 ) >> 16 ;
6135             fTruncDxaExpand             = ( a32Bit &  0x00020000 ) >> 17 ;
6136             fPrintBodyBeforeHdr         = ( a32Bit &  0x00040000 ) >> 18 ;
6137             fNoLeading                  = ( a32Bit &  0x00080000 ) >> 19 ;
6138             fMWSmallCaps                = ( a32Bit &  0x00200000 ) >> 21 ;
6139 
6140             fUsePrinterMetrics          = ( a32Bit &  0x80000000 ) >> 31 ;
6141         }
6142 
6143         /*
6144             bei nFib > 105 gehts weiter:
6145         */
6146         if( nFib > 105 )
6147         {
6148             adt = Get_Short( pData );
6149 
6150             doptypography.ReadFromMem(pData);
6151 
6152             memcpy( &dogrid, pData, sizeof( WW8_DOGRID ));
6153             pData += sizeof( WW8_DOGRID );
6154 
6155             a16Bit = Get_UShort( pData );
6156             // die untersten 9 Bit sind uninteressant
6157             fHtmlDoc                = ( a16Bit &  0x0200 ) >>  9 ;
6158             fSnapBorder             = ( a16Bit &  0x0800 ) >> 11 ;
6159             fIncludeHeader          = ( a16Bit &  0x1000 ) >> 12 ;
6160             fIncludeFooter          = ( a16Bit &  0x2000 ) >> 13 ;
6161             fForcePageSizePag       = ( a16Bit &  0x4000 ) >> 14 ;
6162             fMinFontSizePag         = ( a16Bit &  0x8000 ) >> 15 ;
6163 
6164             a16Bit = Get_UShort( pData );
6165             fHaveVersions   = 0 != ( a16Bit  &  0x0001 );
6166             fAutoVersion    = 0 != ( a16Bit  &  0x0002 );
6167 
6168             pData += 12;
6169 
6170             cChWS = Get_Long( pData );
6171             cChWSFtnEdn = Get_Long( pData );
6172             grfDocEvents = Get_Long( pData );
6173 
6174             pData += 4+30+8;
6175 
6176             cDBC = Get_Long( pData );
6177             cDBCFtnEdn = Get_Long( pData );
6178 
6179             pData += 1 * sizeof( long );
6180 
6181             nfcFtnRef = Get_Short( pData );
6182             nfcEdnRef = Get_Short( pData );
6183             hpsZoonFontPag = Get_Short( pData );
6184             dywDispPag = Get_Short( pData );
6185         }
6186     }
6187     delete[] pDataPtr;
6188 }
6189 
WW8Dop()6190 WW8Dop::WW8Dop()
6191 {
6192     // first set everything to a default of 0
6193     memset( &nDataStart, 0, (&nDataEnd - &nDataStart) );
6194 
6195     fWidowControl = 1;
6196     fpc = 1;
6197     nFtn = 1;
6198     fOutlineDirtySave = 1;
6199     fHyphCapitals = 1;
6200     fBackup = 1;
6201     fPagHidden = 1;
6202     fPagResults = 1;
6203     fDfltTrueType = 1;
6204 
6205     /*
6206     Writer acts like this all the time at the moment, ideally we need an
6207     option for these two as well to import word docs that are not like
6208     this by default
6209     */
6210     fNoLeading = 1;
6211     fUsePrinterMetrics = 1;
6212 
6213     fRMView = 1;
6214     fRMPrint = 1;
6215     dxaTab = 0x2d0;
6216     dxaHotZ = 0x168;
6217     dttmCreated = 0x45FBAC69;
6218     dttmRevised = 0x45FBAC69;
6219     nRevision = 1;
6220     nEdn = 1;
6221 
6222     epc = 3;
6223     nfcEdnRef = 2;
6224     fShadeFormData = 1;
6225 
6226     wvkSaved = 2;
6227     wScaleSaved = 100;
6228     zkSaved = 0;
6229 
6230     lvl = 9;
6231     fIncludeHeader = 1;
6232     fIncludeFooter = 1;
6233 
6234     cChWS = /**!!**/ 0;
6235     cChWSFtnEdn = /**!!**/ 0;
6236 
6237     cDBC = /**!!**/ 0;
6238     cDBCFtnEdn = /**!!**/ 0;
6239 }
6240 
GetCompatabilityOptions() const6241 sal_uInt32 WW8Dop::GetCompatabilityOptions() const
6242 {
6243     sal_uInt32 a32Bit = 0;
6244     if (fNoTabForInd)                   a32Bit |= 0x00000001;
6245     if (fNoSpaceRaiseLower)             a32Bit |= 0x00000002;
6246     if (fSupressSpbfAfterPageBreak)     a32Bit |= 0x00000004;
6247     if (fWrapTrailSpaces)               a32Bit |= 0x00000008;
6248     if (fMapPrintTextColor)             a32Bit |= 0x00000010;
6249     if (fNoColumnBalance)               a32Bit |= 0x00000020;
6250     if (fConvMailMergeEsc)              a32Bit |= 0x00000040;
6251     if (fSupressTopSpacing)             a32Bit |= 0x00000080;
6252     if (fOrigWordTableRules)            a32Bit |= 0x00000100;
6253     if (fTransparentMetafiles)          a32Bit |= 0x00000200;
6254     if (fShowBreaksInFrames)            a32Bit |= 0x00000400;
6255     if (fSwapBordersFacingPgs)          a32Bit |= 0x00000800;
6256     if (fSuppressTopSpacingMac5)        a32Bit |= 0x00010000;
6257     if (fTruncDxaExpand)                a32Bit |= 0x00020000;
6258     if (fPrintBodyBeforeHdr)            a32Bit |= 0x00040000;
6259     if (fNoLeading)                     a32Bit |= 0x00080000;
6260     if (fMWSmallCaps)                   a32Bit |= 0x00200000;
6261     if (fUsePrinterMetrics)             a32Bit |= 0x80000000;
6262     return a32Bit;
6263 }
6264 
Write(SvStream & rStrm,WW8Fib & rFib) const6265 bool WW8Dop::Write(SvStream& rStrm, WW8Fib& rFib) const
6266 {
6267     sal_Int32 nLen = 8 == rFib.nVersion ? 0x220 : 84;
6268     rFib.fcDop =  rStrm.Tell();
6269     rFib.lcbDop = nLen;
6270 
6271     sal_uInt8 aData[ 0x220 ];
6272     memset( aData, 0, 0x220 );
6273     sal_uInt8* pData = aData;
6274 
6275     // dann mal die Daten auswerten
6276     sal_uInt16 a16Bit;
6277     sal_uInt8   a8Bit;
6278 
6279     a16Bit = 0;
6280     if (fFacingPages)
6281         a16Bit |= 0x0001;
6282     if (fWidowControl)
6283         a16Bit |= 0x0002;
6284     if (fPMHMainDoc)
6285         a16Bit |= 0x0004;
6286     a16Bit |= ( 0x0018 & (grfSuppression << 3));
6287     a16Bit |= ( 0x0060 & (fpc << 5));
6288     a16Bit |= ( 0xff00 & (grpfIhdt << 8));
6289     Set_UInt16( pData, a16Bit );
6290 
6291     a16Bit = 0;
6292     a16Bit |= ( 0x0003 & rncFtn );
6293     a16Bit |= ( ~0x0003 & (nFtn << 2));
6294     Set_UInt16( pData, a16Bit );
6295 
6296     a8Bit = 0;
6297     if( fOutlineDirtySave ) a8Bit |= 0x01;
6298     Set_UInt8( pData, a8Bit );
6299 
6300     a8Bit = 0;
6301     if( fOnlyMacPics )  a8Bit |= 0x01;
6302     if( fOnlyWinPics )  a8Bit |= 0x02;
6303     if( fLabelDoc )     a8Bit |= 0x04;
6304     if( fHyphCapitals ) a8Bit |= 0x08;
6305     if( fAutoHyphen )   a8Bit |= 0x10;
6306     if( fFormNoFields ) a8Bit |= 0x20;
6307     if( fLinkStyles )   a8Bit |= 0x40;
6308     if( fRevMarking )   a8Bit |= 0x80;
6309     Set_UInt8( pData, a8Bit );
6310 
6311     a8Bit = 0;
6312     if( fBackup )               a8Bit |= 0x01;
6313     if( fExactCWords )          a8Bit |= 0x02;
6314     if( fPagHidden )            a8Bit |= 0x04;
6315     if( fPagResults )           a8Bit |= 0x08;
6316     if( fLockAtn )              a8Bit |= 0x10;
6317     if( fMirrorMargins )        a8Bit |= 0x20;
6318     if( fReadOnlyRecommended )  a8Bit |= 0x40;
6319     if( fDfltTrueType )         a8Bit |= 0x80;
6320     Set_UInt8( pData, a8Bit );
6321 
6322     a8Bit = 0;
6323     if( fPagSuppressTopSpacing )    a8Bit |= 0x01;
6324     if( fProtEnabled )              a8Bit |= 0x02;
6325     if( fDispFormFldSel )           a8Bit |= 0x04;
6326     if( fRMView )                   a8Bit |= 0x08;
6327     if( fRMPrint )                  a8Bit |= 0x10;
6328     if( fWriteReservation )         a8Bit |= 0x20;
6329     if( fLockRev )                  a8Bit |= 0x40;
6330     if( fEmbedFonts )               a8Bit |= 0x80;
6331     Set_UInt8( pData, a8Bit );
6332 
6333 
6334     a8Bit = 0;
6335     if( copts_fNoTabForInd )            a8Bit |= 0x01;
6336     if( copts_fNoSpaceRaiseLower )      a8Bit |= 0x02;
6337     if( copts_fSupressSpbfAfterPgBrk )  a8Bit |= 0x04;
6338     if( copts_fWrapTrailSpaces )        a8Bit |= 0x08;
6339     if( copts_fMapPrintTextColor )      a8Bit |= 0x10;
6340     if( copts_fNoColumnBalance )        a8Bit |= 0x20;
6341     if( copts_fConvMailMergeEsc )       a8Bit |= 0x40;
6342     if( copts_fSupressTopSpacing )      a8Bit |= 0x80;
6343     Set_UInt8( pData, a8Bit );
6344 
6345     a8Bit = 0;
6346     if( copts_fOrigWordTableRules )     a8Bit |= 0x01;
6347     if( copts_fTransparentMetafiles )   a8Bit |= 0x02;
6348     if( copts_fShowBreaksInFrames )     a8Bit |= 0x04;
6349     if( copts_fSwapBordersFacingPgs )   a8Bit |= 0x08;
6350     Set_UInt8( pData, a8Bit );
6351 
6352     Set_UInt16( pData, dxaTab );
6353     Set_UInt16( pData, wSpare );
6354     Set_UInt16( pData, dxaHotZ );
6355     Set_UInt16( pData, cConsecHypLim );
6356     Set_UInt16( pData, wSpare2 );
6357     Set_UInt32( pData, dttmCreated );
6358     Set_UInt32( pData, dttmRevised );
6359     Set_UInt32( pData, dttmLastPrint );
6360     Set_UInt16( pData, nRevision );
6361     Set_UInt32( pData, tmEdited );
6362     Set_UInt32( pData, cWords );
6363     Set_UInt32( pData, cCh );
6364     Set_UInt16( pData, cPg );
6365     Set_UInt32( pData, cParas );
6366 
6367     a16Bit = 0;
6368     a16Bit |= ( 0x0003 & rncEdn );
6369     a16Bit |= (~0x0003 & ( nEdn << 2));
6370     Set_UInt16( pData, a16Bit );
6371 
6372     a16Bit = 0;
6373     a16Bit |= (0x0003 & epc );
6374     a16Bit |= (0x003c & (nfcFtnRef << 2));
6375     a16Bit |= (0x03c0 & (nfcEdnRef << 6));
6376     if( fPrintFormData )    a16Bit |= 0x0400;
6377     if( fSaveFormData )     a16Bit |= 0x0800;
6378     if( fShadeFormData )    a16Bit |= 0x1000;
6379     if( fWCFtnEdn )         a16Bit |= 0x8000;
6380     Set_UInt16( pData, a16Bit );
6381 
6382     Set_UInt32( pData, cLines );
6383     Set_UInt32( pData, cWordsFtnEnd );
6384     Set_UInt32( pData, cChFtnEdn );
6385     Set_UInt16( pData, cPgFtnEdn );
6386     Set_UInt32( pData, cParasFtnEdn );
6387     Set_UInt32( pData, cLinesFtnEdn );
6388     Set_UInt32( pData, lKeyProtDoc );
6389 
6390     a16Bit = 0;
6391     if (wvkSaved)
6392         a16Bit |= 0x0007;
6393     a16Bit |= (0x0ff8 & (wScaleSaved << 3));
6394     a16Bit |= (0x3000 & (zkSaved << 12));
6395     Set_UInt16( pData, a16Bit );
6396 
6397     if( 8 == rFib.nVersion )
6398     {
6399         Set_UInt32(pData, GetCompatabilityOptions());
6400 
6401         Set_UInt16( pData, adt );
6402 
6403         doptypography.WriteToMem(pData);
6404 
6405         memcpy( pData, &dogrid, sizeof( WW8_DOGRID ));
6406         pData += sizeof( WW8_DOGRID );
6407 
6408         a16Bit = 0x12;      // lvl auf 9 setzen
6409         if( fHtmlDoc )          a16Bit |= 0x0200;
6410         if( fSnapBorder )       a16Bit |= 0x0800;
6411         if( fIncludeHeader )    a16Bit |= 0x1000;
6412         if( fIncludeFooter )    a16Bit |= 0x2000;
6413         if( fForcePageSizePag ) a16Bit |= 0x4000;
6414         if( fMinFontSizePag )   a16Bit |= 0x8000;
6415         Set_UInt16( pData, a16Bit );
6416 
6417         a16Bit = 0;
6418         if( fHaveVersions ) a16Bit |= 0x0001;
6419         if( fAutoVersion )  a16Bit |= 0x0002;
6420         Set_UInt16( pData, a16Bit );
6421 
6422         pData += 12;
6423 
6424         Set_UInt32( pData, cChWS );
6425         Set_UInt32( pData, cChWSFtnEdn );
6426         Set_UInt32( pData, grfDocEvents );
6427 
6428         pData += 4+30+8;
6429 
6430         Set_UInt32( pData, cDBC );
6431         Set_UInt32( pData, cDBCFtnEdn );
6432 
6433         pData += 1 * sizeof( long );
6434 
6435         Set_UInt16( pData, nfcFtnRef );
6436         Set_UInt16( pData, nfcEdnRef );
6437         Set_UInt16( pData, hpsZoonFontPag );
6438         Set_UInt16( pData, dywDispPag );
6439 
6440         //500 -> 508, Appear to be repeated here in 2000+
6441         pData += 8;
6442         Set_UInt32(pData, GetCompatabilityOptions());
6443     }
6444     rStrm.Write( aData, nLen );
6445     return 0 == rStrm.GetError();
6446 }
6447 
ReadFromMem(sal_uInt8 * & pData)6448 void WW8DopTypography::ReadFromMem(sal_uInt8 *&pData)
6449 {
6450     sal_uInt16 a16Bit = Get_UShort(pData);
6451     fKerningPunct = (a16Bit & 0x0001);
6452     iJustification = (a16Bit & 0x0006) >>  1;
6453     iLevelOfKinsoku = (a16Bit & 0x0018) >>  3;
6454     f2on1 = (a16Bit & 0x0020) >>  5;
6455     reserved1 = (a16Bit & 0x03C0) >>  6;
6456     reserved2 = (a16Bit & 0xFC00) >>  10;
6457 
6458     cchFollowingPunct = Get_Short(pData);
6459     cchLeadingPunct = Get_Short(pData);
6460 
6461     sal_Int16 i;
6462     for (i=0; i < nMaxFollowing; ++i)
6463         rgxchFPunct[i] = Get_Short(pData);
6464     for (i=0; i < nMaxLeading; ++i)
6465         rgxchLPunct[i] = Get_Short(pData);
6466 
6467     rgxchFPunct[cchFollowingPunct]=0;
6468     rgxchLPunct[cchLeadingPunct]=0;
6469 }
6470 
WriteToMem(sal_uInt8 * & pData) const6471 void WW8DopTypography::WriteToMem(sal_uInt8 *&pData) const
6472 {
6473     sal_uInt16 a16Bit = fKerningPunct;
6474     a16Bit |= (iJustification << 1) & 0x0006;
6475     a16Bit |= (iLevelOfKinsoku << 3) & 0x0018;
6476     a16Bit |= (f2on1 << 5) & 0x002;
6477     a16Bit |= (reserved1 << 6) & 0x03C0;
6478     a16Bit |= (reserved2 << 10) & 0xFC00;
6479     Set_UInt16(pData,a16Bit);
6480 
6481     Set_UInt16(pData,cchFollowingPunct);
6482     Set_UInt16(pData,cchLeadingPunct);
6483 
6484     sal_Int16 i;
6485     for (i=0; i < nMaxFollowing; ++i)
6486         Set_UInt16(pData,rgxchFPunct[i]);
6487     for (i=0; i < nMaxLeading; ++i)
6488         Set_UInt16(pData,rgxchLPunct[i]);
6489 }
6490 
GetConvertedLang() const6491 sal_uInt16 WW8DopTypography::GetConvertedLang() const
6492 {
6493     sal_uInt16 nLang;
6494     //I have assumed peoples republic/taiwan == simplified/traditional
6495 
6496     //This isn't a documented issue, so we might have it all wrong,
6497     //i.e. i.e. whats with the powers of two ?
6498 
6499     /*
6500     #84082#
6501     One example of 3 for reserved1 which was really Japanese, perhaps last bit
6502     is for some other use ?, or redundant. If more examples trigger the assert
6503     we might be able to figure it out.
6504     */
6505     switch(reserved1 & 0xE)
6506     {
6507         case 2:     //Japan
6508             nLang = LANGUAGE_JAPANESE;
6509             break;
6510         case 4:     //Chinese (Peoples Republic)
6511             nLang = LANGUAGE_CHINESE_SIMPLIFIED;
6512             break;
6513         case 6:     //Korean
6514             nLang = LANGUAGE_KOREAN;
6515             break;
6516         case 8:     //Chinese (Taiwan)
6517             nLang = LANGUAGE_CHINESE_TRADITIONAL;
6518             break;
6519         default:
6520             ASSERT(!this, "Unknown MS Asian Typography language, report");
6521             nLang = LANGUAGE_CHINESE;
6522             break;
6523         case 0:
6524             //And here we have the possibility that it says 2, but its really
6525             //a bug and only japanese level 2 has been selected after a custom
6526             //version was chosen on last save!
6527             nLang = LANGUAGE_JAPANESE;
6528             break;
6529     }
6530     return nLang;
6531 }
6532 
6533 //-----------------------------------------
6534 //              Sprms
6535 //-----------------------------------------
GetSprmTailLen(sal_uInt16 nId,const sal_uInt8 * pSprm) const6536 sal_uInt16 wwSprmParser::GetSprmTailLen(sal_uInt16 nId, const sal_uInt8* pSprm)
6537     const
6538 {
6539     SprmInfo aSprm = GetSprmInfo(nId);
6540     sal_uInt16 nL = 0;                      // number of Bytes to read
6541 
6542     //sprmPChgTabs
6543     switch( nId )
6544     {
6545         case 23:
6546         case 0xC615:
6547             if( pSprm[1 + mnDelta] != 255 )
6548                 nL = pSprm[1 + mnDelta] + aSprm.nLen;
6549             else
6550             {
6551                 sal_uInt8 nDel = pSprm[2 + mnDelta];
6552                 sal_uInt8 nIns = pSprm[3 + mnDelta + 4 * nDel];
6553 
6554                 nL = 2 + 4 * nDel + 3 * nIns;
6555             }
6556             break;
6557         case 0xD608:
6558             nL = SVBT16ToShort( &pSprm[1 + mnDelta] );
6559             break;
6560         default:
6561             switch (aSprm.nVari)
6562             {
6563                 case L_FIX:
6564                     nL = aSprm.nLen;        // Excl. Token
6565                     break;
6566                 case L_VAR:
6567                     // Variable 1-Byte Length?
6568                     // Excl. Token + Var-Lengthbyte
6569                     nL = pSprm[1 + mnDelta] + aSprm.nLen;
6570                     break;
6571                 case L_VAR2:
6572                     // Variable 2-Byte Length?
6573                     // Excl. Token + Var-Lengthbyte
6574                     nL = SVBT16ToShort( &pSprm[1 + mnDelta] ) + aSprm.nLen - 1;
6575                     break;
6576                 default:
6577                     ASSERT(!this, "Unknown sprm variant");
6578                     break;
6579             }
6580             break;
6581     }
6582     return nL;
6583 }
6584 
CountSprms(const sal_uInt8 * pSp,long nSprmSiz,const wwSprmSequence * pIgnoreSprms) const6585 int wwSprmParser::CountSprms(const sal_uInt8* pSp, long nSprmSiz,
6586     const wwSprmSequence* pIgnoreSprms) const
6587 {
6588     sal_uInt16 nMySprms = 0;
6589     sal_uInt16 i=0;
6590     while (i+1+mnDelta < nSprmSiz)
6591     {
6592         sal_uInt16 nSpId = GetSprmId(pSp);
6593 
6594         if( !nSpId )
6595             break;
6596 
6597         sal_uInt16 nSpLen = GetSprmSize(nSpId, pSp);
6598         // increase pointers so to point to next sprm
6599         i += nSpLen;
6600         pSp += nSpLen;
6601 
6602         if (!pIgnoreSprms || !pIgnoreSprms->search(nSpId))
6603             ++nMySprms;
6604     }
6605     return nMySprms;
6606 }
6607 
6608 // one or two bytes at the beginning at the sprm id
GetSprmId(const sal_uInt8 * pSp) const6609 sal_uInt16 wwSprmParser::GetSprmId(const sal_uInt8* pSp) const
6610 {
6611     ASSERT_RET_ON_FAIL(pSp, "Why GetSprmId with pSp of 0", 0);
6612 
6613     sal_uInt16 nId = 0;
6614     switch (mnVersion)  // 6 stands for "6 OR 7",  7 stands for "ONLY 7"
6615     {
6616         case 6:
6617         case 7:
6618             nId = *pSp;
6619             if (0x0100 < nId)
6620                 nId = 0;
6621             break;
6622         default:
6623         case 8:
6624             nId = SVBT16ToShort(pSp);
6625             if (0x0800 > nId)
6626                 nId = 0;
6627             break;
6628     }
6629     return nId;
6630 }
6631 
6632 // with tokens and length byte
GetSprmSize(sal_uInt16 nId,const sal_uInt8 * pSprm) const6633 sal_uInt16 wwSprmParser::GetSprmSize(sal_uInt16 nId, const sal_uInt8* pSprm) const
6634 {
6635     return GetSprmTailLen(nId, pSprm) + 1 + mnDelta + SprmDataOfs(nId);
6636 }
6637 
SprmDataOfs(sal_uInt16 nId) const6638 sal_uInt8 wwSprmParser::SprmDataOfs(sal_uInt16 nId) const
6639 {
6640     return GetSprmInfo(nId).nVari;
6641 }
6642 
DistanceToData(sal_uInt16 nId) const6643 sal_uInt16 wwSprmParser::DistanceToData(sal_uInt16 nId) const
6644 {
6645     return 1 + mnDelta + SprmDataOfs(nId);
6646 }
6647 
SEPr()6648 SEPr::SEPr() :
6649     bkc(2), fTitlePage(0), fAutoPgn(0), nfcPgn(0), fUnlocked(0), cnsPgn(0),
6650     fPgnRestart(0), fEndNote(1), lnc(0), grpfIhdt(0), nLnnMod(0), dxaLnn(0),
6651     dxaPgn(720), dyaPgn(720), fLBetween(0), vjc(0), dmBinFirst(0),
6652     dmBinOther(0), dmPaperReq(0), fPropRMark(0), ibstPropRMark(0),
6653     dttmPropRMark(0), dxtCharSpace(0), dyaLinePitch(0), clm(0), reserved1(0),
6654     dmOrientPage(0), iHeadingPgn(0), pgnStart(1), lnnMin(0), wTextFlow(0),
6655     reserved2(0), pgbApplyTo(0), pgbPageDepth(0), pgbOffsetFrom(0),
6656     xaPage(12242), yaPage(15842), xaPageNUp(12242), yaPageNUp(15842),
6657     dxaLeft(1800), dxaRight(1800), dyaTop(1440), dyaBottom(1440), dzaGutter(0),
6658     dyaHdrTop(720), dyaHdrBottom(720), ccolM1(0), fEvenlySpaced(1),
6659     reserved3(0), fBiDi(0), fFacingCol(0), fRTLGutter(0), fRTLAlignment(0),
6660     dxaColumns(720), dxaColumnWidth(0), dmOrientFirst(0), fLayout(0),
6661     reserved4(0)
6662 {
6663     memset(rgdxaColumnWidthSpacing, 0, sizeof(rgdxaColumnWidthSpacing));
6664 }
6665 
6666 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
6667