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