xref: /trunk/main/sw/source/filter/ww8/dump/ww8scan.cxx (revision 3f996c4c)
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 existence 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 separate
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 amount 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 specifying 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 appropriate 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 variant");
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