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