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