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