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