bump product version to 4.1.6.2
[LibreOffice.git] / sw / source / filter / ww8 / ww8scan.cxx
blob36f7ceb0c4153d69f2c500f30a0e44a7634d03ab
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "ww8scan.hxx"
22 #include <functional>
23 #include <algorithm>
25 #include <string.h>
26 #include <i18nlangtag/mslangid.hxx>
27 #include <rtl/tencinfo.h>
28 #include <sal/macros.h>
30 #ifdef DUMP
32 #define ERR_SWG_READ_ERROR 1234
33 #define OSL_ENSURE( a, b )
35 #else // dump
36 #include <swerror.h> // ERR_WW6_...
37 #include <swtypes.hxx> // DELETEZ
39 #endif // dump
40 #include <comphelper/processfactory.hxx>
41 #include <comphelper/string.hxx>
42 #include <unotools/localedatawrapper.hxx>
43 #include <i18nlangtag/lang.h>
44 #include <editeng/unolingu.hxx>
45 #include <vcl/svapp.hxx> // Application #i90932#
47 #include <stdio.h>
49 #define ASSERT_RET_ON_FAIL( aCon, aError, aRet ) \
50 OSL_ENSURE(aCon, aError); \
51 if (!(aCon)) \
52 return aRet;
54 using namespace ::com::sun::star::lang;
56 //-begin
57 namespace SL
59 # define IMPLCONSTSTRINGARRAY(X) const char a##X[] = "" #X ""
60 IMPLCONSTSTRINGARRAY(ObjectPool);
61 IMPLCONSTSTRINGARRAY(1Table);
62 IMPLCONSTSTRINGARRAY(0Table);
63 IMPLCONSTSTRINGARRAY(Data);
64 IMPLCONSTSTRINGARRAY(CheckBox);
65 IMPLCONSTSTRINGARRAY(ListBox);
66 IMPLCONSTSTRINGARRAY(TextBox);
67 IMPLCONSTSTRINGARRAY(TextField);
68 IMPLCONSTSTRINGARRAY(MSMacroCmds);
71 namespace
73 /**
74 winword strings are typically Belt and Braces strings preceeded with a
75 pascal style count, and ending with a c style 0 terminator. 16bit chars
76 and count for ww8+ and 8bit chars and count for ww7-. The count and 0
77 can be checked for integrity to catch errors (e.g. lotus created
78 documents) where in error 8bit strings are used instead of 16bits
79 strings for style names.
81 template<typename C> bool TestBeltAndBraces(SvStream& rStrm)
83 bool bRet = false;
84 sal_uInt32 nOldPos = rStrm.Tell();
85 C nBelt(0);
86 rStrm >> nBelt;
87 nBelt *= sizeof(C);
88 if (rStrm.good() && (rStrm.remainingSize() >= (nBelt + sizeof(C))))
90 rStrm.SeekRel(nBelt);
91 if (rStrm.good())
93 C cBraces(0);
94 rStrm >> cBraces;
95 if (rStrm.good() && cBraces == 0)
96 bRet = true;
99 rStrm.Seek(nOldPos);
100 return bRet;
104 inline bool operator==(const SprmInfo &rFirst, const SprmInfo &rSecond)
106 return (rFirst.nId == rSecond.nId);
109 const wwSprmSearcher *wwSprmParser::GetWW2SprmSearcher()
111 //double lock me
112 // WW7- Sprms
113 static const SprmInfo aSprms[] =
115 { 0, 0, L_FIX}, // "Default-sprm", will be skipped
116 { 2, 1, L_FIX}, // "sprmPIstd", pap.istd (style code)
117 { 3, 0, L_VAR}, // "sprmPIstdPermute pap.istd permutation
118 { 4, 1, L_FIX}, // "sprmPIncLv1" pap.istddifference
119 { 5, 1, L_FIX}, // "sprmPJc" pap.jc (justification)
120 { 6, 1, L_FIX}, // "sprmPFSideBySide" pap.fSideBySide
121 { 7, 1, L_FIX}, // "sprmPFKeep" pap.fKeep
122 { 8, 1, L_FIX}, // "sprmPFKeepFollow " pap.fKeepFollow
123 { 9, 1, L_FIX}, // "sprmPPageBreakBefore" pap.fPageBreakBefore
124 { 10, 1, L_FIX}, // "sprmPBrcl" pap.brcl
125 { 11, 1, L_FIX}, // "sprmPBrcp" pap.brcp
126 { 12, 1, L_FIX}, // "sprmPNfcSeqNumb" pap.nfcSeqNumb
127 { 13, 1, L_FIX}, // "sprmPNoSeqNumb" pap.nnSeqNumb
128 { 14, 1, L_FIX}, // "sprmPFNoLineNumb" pap.fNoLnn
129 { 15, 0, L_VAR}, // "?sprmPChgTabsPapx" pap.itbdMac, ...
130 { 16, 2, L_FIX}, // "sprmPDxaRight" pap.dxaRight
131 { 17, 2, L_FIX}, // "sprmPDxaLeft" pap.dxaLeft
132 { 18, 2, L_FIX}, // "sprmPNest" pap.dxaLeft
133 { 19, 2, L_FIX}, // "sprmPDxaLeft1" pap.dxaLeft1
134 { 20, 2, L_FIX}, // "sprmPDyaLine" pap.lspd an LSPD
135 { 21, 2, L_FIX}, // "sprmPDyaBefore" pap.dyaBefore
136 { 22, 2, L_FIX}, // "sprmPDyaAfter" pap.dyaAfter
137 { 23, 0, L_VAR}, // "?sprmPChgTabs" pap.itbdMac, pap.rgdxaTab, ...
138 { 24, 1, L_FIX}, // "sprmPFInTable" pap.fInTable
139 { 25, 1, L_FIX}, // "sprmPTtp" pap.fTtp
140 { 26, 2, L_FIX}, // "sprmPDxaAbs" pap.dxaAbs
141 { 27, 2, L_FIX}, // "sprmPDyaAbs" pap.dyaAbs
142 { 28, 2, L_FIX}, // "sprmPDxaWidth" pap.dxaWidth
143 { 29, 1, L_FIX}, // "sprmPPc" pap.pcHorz, pap.pcVert
144 { 30, 2, L_FIX}, // "sprmPBrcTop10" pap.brcTop BRC10
145 { 31, 2, L_FIX}, // "sprmPBrcLeft10" pap.brcLeft BRC10
146 { 32, 2, L_FIX}, // "sprmPBrcBottom10" pap.brcBottom BRC10
147 { 33, 2, L_FIX}, // "sprmPBrcRight10" pap.brcRight BRC10
148 { 34, 2, L_FIX}, // "sprmPBrcBetween10" pap.brcBetween BRC10
149 { 35, 2, L_FIX}, // "sprmPBrcBar10" pap.brcBar BRC10
150 { 36, 2, L_FIX}, // "sprmPFromText10" pap.dxaFromText dxa
151 { 37, 1, L_FIX}, // "sprmPWr" pap.wr wr
152 { 38, 2, L_FIX}, // "sprmPBrcTop" pap.brcTop BRC
153 { 39, 2, L_FIX}, // "sprmPBrcLeft" pap.brcLeft BRC
154 { 40, 2, L_FIX}, // "sprmPBrcBottom" pap.brcBottom BRC
155 { 41, 2, L_FIX}, // "sprmPBrcRight" pap.brcRight BRC
156 { 42, 2, L_FIX}, // "sprmPBrcBetween" pap.brcBetween BRC
157 { 43, 2, L_FIX}, // "sprmPBrcBar" pap.brcBar BRC word
158 { 44, 1, L_FIX}, // "sprmPFNoAutoHyph" pap.fNoAutoHyph
159 { 45, 2, L_FIX}, // "sprmPWHeightAbs" pap.wHeightAbs w
160 { 46, 2, L_FIX}, // "sprmPDcs" pap.dcs DCS
161 { 47, 2, L_FIX}, // "sprmPShd" pap.shd SHD
162 { 48, 2, L_FIX}, // "sprmPDyaFromText" pap.dyaFromText dya
163 { 49, 2, L_FIX}, // "sprmPDxaFromText" pap.dxaFromText dxa
164 { 50, 1, L_FIX}, // "sprmPFBiDi" pap.fBiDi 0 or 1 byte
165 { 51, 1, L_FIX}, // "sprmPFWidowControl" pap.fWidowControl 0 or 1 byte
166 { 52, 0, L_FIX}, // "?sprmPRuler 52"
167 { 53, 1, L_FIX}, // "sprmCFStrikeRM" chp.fRMarkDel 1 or 0 bit
168 { 54, 1, L_FIX}, // "sprmCFRMark" chp.fRMark 1 or 0 bit
169 { 55, 1, L_FIX}, // "sprmCFFldVanish" chp.fFldVanish 1 or 0 bit
170 { 57, 0, L_VAR}, // "sprmCDefault" whole CHP
171 { 58, 0, L_FIX}, // "sprmCPlain" whole CHP
172 { 60, 1, L_FIX}, // "sprmCFBold" chp.fBold 0,1, 128, or 129
173 { 61, 1, L_FIX}, // "sprmCFItalic" chp.fItalic 0,1, 128, or 129
174 { 62, 1, L_FIX}, // "sprmCFStrike" chp.fStrike 0,1, 128, or 129
175 { 63, 1, L_FIX}, // "sprmCFOutline" chp.fOutline 0,1, 128, or 129
176 { 64, 1, L_FIX}, // "sprmCFShadow" chp.fShadow 0,1, 128, or 129
177 { 65, 1, L_FIX}, // "sprmCFSmallCaps" chp.fSmallCaps 0,1, 128, or 129
178 { 66, 1, L_FIX}, // "sprmCFCaps" chp.fCaps 0,1, 128, or 129
179 { 67, 1, L_FIX}, // "sprmCFVanish" chp.fVanish 0,1, 128, or 129
180 { 68, 2, L_FIX}, // "sprmCFtc" chp.ftc ftc word
181 { 69, 1, L_FIX}, // "sprmCKul" chp.kul kul byte
182 { 70, 3, L_FIX}, // "sprmCSizePos" chp.hps, chp.hpsPos
183 { 71, 2, L_FIX}, // "sprmCDxaSpace" chp.dxaSpace dxa
184 { 72, 2, L_FIX}, // "sprmCLid" chp.lid LID
185 { 73, 1, L_FIX}, // "sprmCIco" chp.ico ico byte
186 { 74, 1, L_FIX}, // "sprmCHps" chp.hps hps !word!
187 { 75, 1, L_FIX}, // "sprmCHpsInc" chp.hps
188 { 76, 1, L_FIX}, // "sprmCHpsPos" chp.hpsPos hps !word!
189 { 77, 1, L_FIX}, // "sprmCHpsPosAdj" chp.hpsPos hps
190 { 78, 0, L_VAR}, // "?sprmCMajority" chp.fBold, chp.fItalic, ...
191 { 80, 1, L_FIX}, // "sprmCFBoldBi" chp.fBoldBi
192 { 81, 1, L_FIX}, // "sprmCFItalicBi" chp.fItalicBi
193 { 82, 2, L_FIX}, // "sprmCFtcBi" chp.ftcBi
194 { 83, 2, L_FIX}, // "sprmClidBi" chp.lidBi
195 { 84, 1, L_FIX}, // "sprmCIcoBi" chp.icoBi
196 { 85, 1, L_FIX}, // "sprmCHpsBi" chp.hpsBi
197 { 86, 1, L_FIX}, // "sprmCFBiDi" chp.fBiDi
198 { 87, 1, L_FIX}, // "sprmCFDiacColor" chp.fDiacUSico
199 { 94, 1, L_FIX}, // "sprmPicBrcl" pic.brcl brcl (see PIC definition)
200 { 95,12, L_VAR}, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
201 { 96, 2, L_FIX}, // "sprmPicBrcTop" pic.brcTop BRC word
202 { 97, 2, L_FIX}, // "sprmPicBrcLeft" pic.brcLeft BRC word
203 { 98, 2, L_FIX}, // "sprmPicBrcBottom" pic.brcBottom BRC word
204 { 99, 2, L_FIX}, // "sprmPicBrcRight" pic.brcRight BRC word
205 {112, 1, L_FIX}, // "sprmSFRTLGutter", set to one if gutter is on
206 {114, 1, L_FIX}, // "sprmSFBiDi" ;;;
207 {115, 2, L_FIX}, // "sprmSDmBinFirst" sep.dmBinFirst word
208 {116, 2, L_FIX}, // "sprmSDmBinOther" sep.dmBinOther word
209 {117, 1, L_FIX}, // "sprmSBkc" sep.bkc bkc byte
210 {118, 1, L_FIX}, // "sprmSFTitlePage" sep.fTitlePage 0 or 1 byte
211 {119, 2, L_FIX}, // "sprmSCcolumns" sep.ccolM1 # of cols - 1 word
212 {120, 2, L_FIX}, // "sprmSDxaColumns" sep.dxaColumns dxa word
213 {121, 1, L_FIX}, // "sprmSFAutoPgn" sep.fAutoPgn obsolete byte
214 {122, 1, L_FIX}, // "sprmSNfcPgn" sep.nfcPgn nfc byte
215 {123, 2, L_FIX}, // "sprmSDyaPgn" sep.dyaPgn dya short
216 {124, 2, L_FIX}, // "sprmSDxaPgn" sep.dxaPgn dya short
217 {125, 1, L_FIX}, // "sprmSFPgnRestart" sep.fPgnRestart 0 or 1 byte
218 {126, 1, L_FIX}, // "sprmSFEndnote" sep.fEndnote 0 or 1 byte
219 {127, 1, L_FIX}, // "sprmSLnc" sep.lnc lnc byte
220 {128, 1, L_FIX}, // "sprmSGprfIhdt" sep.grpfIhdt grpfihdt
221 {129, 2, L_FIX}, // "sprmSNLnnMod" sep.nLnnMod non-neg int. word
222 {130, 2, L_FIX}, // "sprmSDxaLnn" sep.dxaLnn dxa word
223 {131, 2, L_FIX}, // "sprmSDyaHdrTop" sep.dyaHdrTop dya word
224 {132, 2, L_FIX}, // "sprmSDyaHdrBottom" sep.dyaHdrBottom dya word
225 {133, 1, L_FIX}, // "sprmSLBetween" sep.fLBetween 0 or 1 byte
226 {134, 1, L_FIX}, // "sprmSVjc" sep.vjc vjc byte
227 {135, 2, L_FIX}, // "sprmSLnnMin" sep.lnnMin lnn word
228 {136, 2, L_FIX}, // "sprmSPgnStart" sep.pgnStart pgn word
229 {137, 1, L_FIX}, // "sprmSBOrientation" sep.dmOrientPage dm byte
230 {138, 1, L_FIX}, // "sprmSFFacingCol" ;;;
231 {139, 2, L_FIX}, // "sprmSXaPage" sep.xaPage xa word
232 {140, 2, L_FIX}, // "sprmSYaPage" sep.yaPage ya word
233 {141, 2, L_FIX}, // "sprmSDxaLeft" sep.dxaLeft dxa word
234 {142, 2, L_FIX}, // "sprmSDxaRight" sep.dxaRight dxa word
235 {143, 2, L_FIX}, // "sprmSDyaTop" sep.dyaTop dya word
236 {144, 2, L_FIX}, // "sprmSDyaBottom" sep.dyaBottom dya word
237 {145, 2, L_FIX}, // "sprmSDzaGutter" sep.dzaGutter dza word
238 {146, 2, L_FIX}, // "sprmTJc" tap.jc jc (low order byte is significant)
239 {147, 2, L_FIX}, // "sprmTDxaLeft" tap.rgdxaCenter dxa word
240 {148, 2, L_FIX}, // "sprmTDxaGapHalf" tap.dxaGapHalf, tap.rgdxaCenter
241 {149, 1, L_FIX}, // "sprmTFBiDi" ;;;
242 {152, 0, L_VAR}, // "sprmTDefTable10" tap.rgdxaCenter, tap.rgtc complex
243 {153, 2, L_FIX}, // "sprmTDyaRowHeight" tap.dyaRowHeight dya word
244 {154, 0, L_VAR2},// "sprmTDefTable" tap.rgtc complex
245 {155, 1, L_VAR}, // "sprmTDefTableShd" tap.rgshd complex
246 {157, 5, L_FIX}, // "sprmTSetBrc" tap.rgtc[].rgbrc complex 5 bytes
247 {158, 4, L_FIX}, // "sprmTInsert" tap.rgdxaCenter,tap.rgtc complex
248 {159, 2, L_FIX}, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc complex
249 {160, 4, L_FIX}, // "sprmTDxaCol" tap.rgdxaCenter complex
250 {161, 2, L_FIX}, // "sprmTMerge" tap.fFirstMerged, tap.fMerged complex
251 {162, 2, L_FIX}, // "sprmTSplit" tap.fFirstMerged, tap.fMerged complex
252 {163, 5, L_FIX}, // "sprmTSetBrc10" tap.rgtc[].rgbrc complex 5 bytes
253 {164, 4, L_FIX}, // "sprmTSetShd", tap.rgshd complex 4 bytes
256 static wwSprmSearcher aSprmSrch(aSprms, sizeof(aSprms) / sizeof(aSprms[0]));
257 return &aSprmSrch;
261 const wwSprmSearcher *wwSprmParser::GetWW6SprmSearcher()
263 //double lock me
264 // WW7- Sprms
265 static const SprmInfo aSprms[] =
267 { 0, 0, L_FIX}, // "Default-sprm", wird uebersprungen
268 { 2, 2, L_FIX}, // "sprmPIstd", pap.istd (style code)
269 { 3, 3, L_VAR}, // "sprmPIstdPermute pap.istd permutation
270 { 4, 1, L_FIX}, // "sprmPIncLv1" pap.istddifference
271 { 5, 1, L_FIX}, // "sprmPJc" pap.jc (justification)
272 { 6, 1, L_FIX}, // "sprmPFSideBySide" pap.fSideBySide
273 { 7, 1, L_FIX}, // "sprmPFKeep" pap.fKeep
274 { 8, 1, L_FIX}, // "sprmPFKeepFollow " pap.fKeepFollow
275 { 9, 1, L_FIX}, // "sprmPPageBreakBefore" pap.fPageBreakBefore
276 { 10, 1, L_FIX}, // "sprmPBrcl" pap.brcl
277 { 11, 1, L_FIX}, // "sprmPBrcp" pap.brcp
278 { 12, 0, L_VAR}, // "sprmPAnld" pap.anld (ANLD structure)
279 { 13, 1, L_FIX}, // "sprmPNLvlAnm" pap.nLvlAnm nn
280 { 14, 1, L_FIX}, // "sprmPFNoLineNumb" pap.fNoLnn
281 { 15, 0, L_VAR}, // "?sprmPChgTabsPapx" pap.itbdMac, ...
282 { 16, 2, L_FIX}, // "sprmPDxaRight" pap.dxaRight
283 { 17, 2, L_FIX}, // "sprmPDxaLeft" pap.dxaLeft
284 { 18, 2, L_FIX}, // "sprmPNest" pap.dxaLeft
285 { 19, 2, L_FIX}, // "sprmPDxaLeft1" pap.dxaLeft1
286 { 20, 4, L_FIX}, // "sprmPDyaLine" pap.lspd an LSPD
287 { 21, 2, L_FIX}, // "sprmPDyaBefore" pap.dyaBefore
288 { 22, 2, L_FIX}, // "sprmPDyaAfter" pap.dyaAfter
289 { 23, 0, L_VAR}, // "?sprmPChgTabs" pap.itbdMac, pap.rgdxaTab, ...
290 { 24, 1, L_FIX}, // "sprmPFInTable" pap.fInTable
291 { 25, 1, L_FIX}, // "sprmPTtp" pap.fTtp
292 { 26, 2, L_FIX}, // "sprmPDxaAbs" pap.dxaAbs
293 { 27, 2, L_FIX}, // "sprmPDyaAbs" pap.dyaAbs
294 { 28, 2, L_FIX}, // "sprmPDxaWidth" pap.dxaWidth
295 { 29, 1, L_FIX}, // "sprmPPc" pap.pcHorz, pap.pcVert
296 { 30, 2, L_FIX}, // "sprmPBrcTop10" pap.brcTop BRC10
297 { 31, 2, L_FIX}, // "sprmPBrcLeft10" pap.brcLeft BRC10
298 { 32, 2, L_FIX}, // "sprmPBrcBottom10" pap.brcBottom BRC10
299 { 33, 2, L_FIX}, // "sprmPBrcRight10" pap.brcRight BRC10
300 { 34, 2, L_FIX}, // "sprmPBrcBetween10" pap.brcBetween BRC10
301 { 35, 2, L_FIX}, // "sprmPBrcBar10" pap.brcBar BRC10
302 { 36, 2, L_FIX}, // "sprmPFromText10" pap.dxaFromText dxa
303 { 37, 1, L_FIX}, // "sprmPWr" pap.wr wr
304 { 38, 2, L_FIX}, // "sprmPBrcTop" pap.brcTop BRC
305 { 39, 2, L_FIX}, // "sprmPBrcLeft" pap.brcLeft BRC
306 { 40, 2, L_FIX}, // "sprmPBrcBottom" pap.brcBottom BRC
307 { 41, 2, L_FIX}, // "sprmPBrcRight" pap.brcRight BRC
308 { 42, 2, L_FIX}, // "sprmPBrcBetween" pap.brcBetween BRC
309 { 43, 2, L_FIX}, // "sprmPBrcBar" pap.brcBar BRC word
310 { 44, 1, L_FIX}, // "sprmPFNoAutoHyph" pap.fNoAutoHyph
311 { 45, 2, L_FIX}, // "sprmPWHeightAbs" pap.wHeightAbs w
312 { 46, 2, L_FIX}, // "sprmPDcs" pap.dcs DCS
313 { 47, 2, L_FIX}, // "sprmPShd" pap.shd SHD
314 { 48, 2, L_FIX}, // "sprmPDyaFromText" pap.dyaFromText dya
315 { 49, 2, L_FIX}, // "sprmPDxaFromText" pap.dxaFromText dxa
316 { 50, 1, L_FIX}, // "sprmPFLocked" pap.fLocked 0 or 1 byte
317 { 51, 1, L_FIX}, // "sprmPFWidowControl" pap.fWidowControl 0 or 1 byte
318 { 52, 0, L_FIX}, // "?sprmPRuler 52"
319 { 64, 0, L_VAR}, // rtl property ?
320 { 65, 1, L_FIX}, // "sprmCFStrikeRM" chp.fRMarkDel 1 or 0 bit
321 { 66, 1, L_FIX}, // "sprmCFRMark" chp.fRMark 1 or 0 bit
322 { 67, 1, L_FIX}, // "sprmCFFldVanish" chp.fFldVanish 1 or 0 bit
323 { 68, 0, L_VAR}, // "sprmCPicLocation" chp.fcPic and chp.fSpec
324 { 69, 2, L_FIX}, // "sprmCIbstRMark" chp.ibstRMark index into sttbRMark
325 { 70, 4, L_FIX}, // "sprmCDttmRMark" chp.dttm DTTM long
326 { 71, 1, L_FIX}, // "sprmCFData" chp.fData 1 or 0 bit
327 { 72, 2, L_FIX}, // "sprmCRMReason" chp.idslRMReason an index to a table
328 { 73, 3, L_FIX}, // "sprmCChse" chp.fChsDiff and chp.chse
329 { 74, 0, L_VAR}, // "sprmCSymbol" chp.fSpec, chp.chSym and chp.ftcSym
330 { 75, 1, L_FIX}, // "sprmCFOle2" chp.fOle2 1 or 0 bit
331 { 77, 0, L_VAR}, // unknown
332 { 79, 0, L_VAR}, // unknown
333 { 80, 2, L_FIX}, // "sprmCIstd" chp.istd istd, see stylesheet definition
334 { 81, 0, L_VAR}, // "sprmCIstdPermute" chp.istd permutation vector
335 { 82, 0, L_VAR}, // "sprmCDefault" whole CHP
336 { 83, 0, L_FIX}, // "sprmCPlain" whole CHP
337 { 85, 1, L_FIX}, // "sprmCFBold" chp.fBold 0,1, 128, or 129
338 { 86, 1, L_FIX}, // "sprmCFItalic" chp.fItalic 0,1, 128, or 129
339 { 87, 1, L_FIX}, // "sprmCFStrike" chp.fStrike 0,1, 128, or 129
340 { 88, 1, L_FIX}, // "sprmCFOutline" chp.fOutline 0,1, 128, or 129
341 { 89, 1, L_FIX}, // "sprmCFShadow" chp.fShadow 0,1, 128, or 129
342 { 90, 1, L_FIX}, // "sprmCFSmallCaps" chp.fSmallCaps 0,1, 128, or 129
343 { 91, 1, L_FIX}, // "sprmCFCaps" chp.fCaps 0,1, 128, or 129
344 { 92, 1, L_FIX}, // "sprmCFVanish" chp.fVanish 0,1, 128, or 129
345 { 93, 2, L_FIX}, // "sprmCFtc" chp.ftc ftc word
346 { 94, 1, L_FIX}, // "sprmCKul" chp.kul kul byte
347 { 95, 3, L_FIX}, // "sprmCSizePos" chp.hps, chp.hpsPos
348 { 96, 2, L_FIX}, // "sprmCDxaSpace" chp.dxaSpace dxa
349 { 97, 2, L_FIX}, // "sprmCLid" chp.lid LID
350 { 98, 1, L_FIX}, // "sprmCIco" chp.ico ico byte
351 { 99, 2, L_FIX}, // "sprmCHps" chp.hps hps !word!
352 {100, 1, L_FIX}, // "sprmCHpsInc" chp.hps
353 {101, 2, L_FIX}, // "sprmCHpsPos" chp.hpsPos hps !word!
354 {102, 1, L_FIX}, // "sprmCHpsPosAdj" chp.hpsPos hps
355 {103, 0, L_VAR}, // "?sprmCMajority" chp.fBold, chp.fItalic, ...
356 {104, 1, L_FIX}, // "sprmCIss" chp.iss iss
357 {105, 0, L_VAR}, // "sprmCHpsNew50" chp.hps hps variable width
358 {106, 0, L_VAR}, // "sprmCHpsInc1" chp.hps complex
359 {107, 2, L_FIX}, // "sprmCHpsKern" chp.hpsKern hps
360 {108, 0, L_VAR}, // "sprmCMajority50" chp.fBold, chp.fItalic, ...
361 {109, 2, L_FIX}, // "sprmCHpsMul" chp.hps percentage to grow hps
362 {110, 2, L_FIX}, // "sprmCCondHyhen" chp.ysri ysri
363 {111, 2, L_FIX}, // rtl bold
364 {112, 2, L_FIX}, // rtl italic
365 {113, 0, L_VAR}, // rtl property ?
366 {115, 0, L_VAR}, // rtl property ?
367 {116, 0, L_VAR}, // unknown
368 {117, 1, L_FIX}, // "sprmCFSpec" chp.fSpec 1 or 0 bit
369 {118, 1, L_FIX}, // "sprmCFObj" chp.fObj 1 or 0 bit
370 {119, 1, L_FIX}, // "sprmPicBrcl" pic.brcl brcl (see PIC definition)
371 {120,12, L_VAR}, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
372 {121, 2, L_FIX}, // "sprmPicBrcTop" pic.brcTop BRC word
373 {122, 2, L_FIX}, // "sprmPicBrcLeft" pic.brcLeft BRC word
374 {123, 2, L_FIX}, // "sprmPicBrcBottom" pic.brcBottom BRC word
375 {124, 2, L_FIX}, // "sprmPicBrcRight" pic.brcRight BRC word
376 {131, 1, L_FIX}, // "sprmSScnsPgn" sep.cnsPgn cns byte
377 {132, 1, L_FIX}, // "sprmSiHeadingPgn" sep.iHeadingPgn
378 {133, 0, L_VAR}, // "sprmSOlstAnm" sep.olstAnm OLST variable length
379 {136, 3, L_FIX}, // "sprmSDxaColWidth" sep.rgdxaColWidthSpacing complex
380 {137, 3, L_FIX}, // "sprmSDxaColSpacing" sep.rgdxaColWidthSpacing
381 {138, 1, L_FIX}, // "sprmSFEvenlySpaced" sep.fEvenlySpaced 1 or 0
382 {139, 1, L_FIX}, // "sprmSFProtected" sep.fUnlocked 1 or 0 byte
383 {140, 2, L_FIX}, // "sprmSDmBinFirst" sep.dmBinFirst word
384 {141, 2, L_FIX}, // "sprmSDmBinOther" sep.dmBinOther word
385 {142, 1, L_FIX}, // "sprmSBkc" sep.bkc bkc byte
386 {143, 1, L_FIX}, // "sprmSFTitlePage" sep.fTitlePage 0 or 1 byte
387 {144, 2, L_FIX}, // "sprmSCcolumns" sep.ccolM1 # of cols - 1 word
388 {145, 2, L_FIX}, // "sprmSDxaColumns" sep.dxaColumns dxa word
389 {146, 1, L_FIX}, // "sprmSFAutoPgn" sep.fAutoPgn obsolete byte
390 {147, 1, L_FIX}, // "sprmSNfcPgn" sep.nfcPgn nfc byte
391 {148, 2, L_FIX}, // "sprmSDyaPgn" sep.dyaPgn dya short
392 {149, 2, L_FIX}, // "sprmSDxaPgn" sep.dxaPgn dya short
393 {150, 1, L_FIX}, // "sprmSFPgnRestart" sep.fPgnRestart 0 or 1 byte
394 {151, 1, L_FIX}, // "sprmSFEndnote" sep.fEndnote 0 or 1 byte
395 {152, 1, L_FIX}, // "sprmSLnc" sep.lnc lnc byte
396 {153, 1, L_FIX}, // "sprmSGprfIhdt" sep.grpfIhdt grpfihdt
397 {154, 2, L_FIX}, // "sprmSNLnnMod" sep.nLnnMod non-neg int. word
398 {155, 2, L_FIX}, // "sprmSDxaLnn" sep.dxaLnn dxa word
399 {156, 2, L_FIX}, // "sprmSDyaHdrTop" sep.dyaHdrTop dya word
400 {157, 2, L_FIX}, // "sprmSDyaHdrBottom" sep.dyaHdrBottom dya word
401 {158, 1, L_FIX}, // "sprmSLBetween" sep.fLBetween 0 or 1 byte
402 {159, 1, L_FIX}, // "sprmSVjc" sep.vjc vjc byte
403 {160, 2, L_FIX}, // "sprmSLnnMin" sep.lnnMin lnn word
404 {161, 2, L_FIX}, // "sprmSPgnStart" sep.pgnStart pgn word
405 {162, 1, L_FIX}, // "sprmSBOrientation" sep.dmOrientPage dm byte
406 {163, 0, L_FIX}, // "?SprmSBCustomize 163"
407 {164, 2, L_FIX}, // "sprmSXaPage" sep.xaPage xa word
408 {165, 2, L_FIX}, // "sprmSYaPage" sep.yaPage ya word
409 {166, 2, L_FIX}, // "sprmSDxaLeft" sep.dxaLeft dxa word
410 {167, 2, L_FIX}, // "sprmSDxaRight" sep.dxaRight dxa word
411 {168, 2, L_FIX}, // "sprmSDyaTop" sep.dyaTop dya word
412 {169, 2, L_FIX}, // "sprmSDyaBottom" sep.dyaBottom dya word
413 {170, 2, L_FIX}, // "sprmSDzaGutter" sep.dzaGutter dza word
414 {171, 2, L_FIX}, // "sprmSDMPaperReq" sep.dmPaperReq dm word
415 {179, 0, L_VAR}, // rtl property ?
416 {181, 0, L_VAR}, // rtl property ?
417 {182, 2, L_FIX}, // "sprmTJc" tap.jc jc (low order byte is significant)
418 {183, 2, L_FIX}, // "sprmTDxaLeft" tap.rgdxaCenter dxa word
419 {184, 2, L_FIX}, // "sprmTDxaGapHalf" tap.dxaGapHalf, tap.rgdxaCenter
420 {185, 1, L_FIX}, // "sprmTFCantSplit" tap.fCantSplit 1 or 0 byte
421 {186, 1, L_FIX}, // "sprmTTableHeader" tap.fTableHeader 1 or 0 byte
422 {187,12, L_FIX}, // "sprmTTableBorders" tap.rgbrcTable complex 12 bytes
423 {188, 0, L_VAR}, // "sprmTDefTable10" tap.rgdxaCenter, tap.rgtc complex
424 {189, 2, L_FIX}, // "sprmTDyaRowHeight" tap.dyaRowHeight dya word
425 {190, 0, L_VAR2},// "sprmTDefTable" tap.rgtc complex
426 {191, 1, L_VAR}, // "sprmTDefTableShd" tap.rgshd complex
427 {192, 4, L_FIX}, // "sprmTTlp" tap.tlp TLP 4 bytes
428 {193, 5, L_FIX}, // "sprmTSetBrc" tap.rgtc[].rgbrc complex 5 bytes
429 {194, 4, L_FIX}, // "sprmTInsert" tap.rgdxaCenter,tap.rgtc complex
430 {195, 2, L_FIX}, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc complex
431 {196, 4, L_FIX}, // "sprmTDxaCol" tap.rgdxaCenter complex
432 {197, 2, L_FIX}, // "sprmTMerge" tap.fFirstMerged, tap.fMerged complex
433 {198, 2, L_FIX}, // "sprmTSplit" tap.fFirstMerged, tap.fMerged complex
434 {199, 5, L_FIX}, // "sprmTSetBrc10" tap.rgtc[].rgbrc complex 5 bytes
435 {200, 4, L_FIX}, // "sprmTSetShd", tap.rgshd complex 4 bytes
436 {207, 0, L_VAR} // rtl property ?
439 static wwSprmSearcher aSprmSrch(aSprms, sizeof(aSprms) / sizeof(aSprms[0]));
440 return &aSprmSrch;
443 const wwSprmSearcher *wwSprmParser::GetWW8SprmSearcher()
445 //double lock me
446 //WW8+ Sprms
447 static const SprmInfo aSprms[] =
449 { 0, 0, L_FIX}, // "Default-sprm"/ wird uebersprungen
450 {0x4600, 2, L_FIX}, // "sprmPIstd" pap.istd;istd (style code);short;
451 {0xC601, 0, L_VAR}, // "sprmPIstdPermute" pap.istd;permutation vector
452 {0x2602, 1, L_FIX}, // "sprmPIncLvl" pap.istd, pap.lvl;difference
453 // between istd of base PAP and istd of PAP to be
454 // produced
455 {0x2403, 1, L_FIX}, // "sprmPJc" pap.jc;jc (justification);byte;
456 {0x2404, 1, L_FIX}, // "sprmPFSideBySide" pap.fSideBySide;0 or 1;byte;
457 {0x2405, 1, L_FIX}, // "sprmPFKeep" pap.fKeep;0 or 1;byte;
458 {0x2406, 1, L_FIX}, // "sprmPFKeepFollow" pap.fKeepFollow;0 or 1;byte;
459 {0x2407, 1, L_FIX}, // "sprmPFPageBreakBefore" pap.fPageBreakBefore;
460 // 0 or 1
461 {0x2408, 1, L_FIX}, // "sprmPBrcl" pap.brcl;brcl;byte;
462 {0x2409, 1, L_FIX}, // "sprmPBrcp" pap.brcp;brcp;byte;
463 {0x260A, 1, L_FIX}, // "sprmPIlvl" pap.ilvl;ilvl;byte;
464 {0x460B, 2, L_FIX}, // "sprmPIlfo" pap.ilfo;ilfo (list index) ;short;
465 {0x240C, 1, L_FIX}, // "sprmPFNoLineNumb" pap.fNoLnn;0 or 1;byte;
466 {0xC60D, 0, L_VAR}, // "sprmPChgTabsPapx" pap.itbdMac, pap.rgdxaTab,
467 // pap.rgtbd;complex
468 {0x840E, 2, L_FIX}, // "sprmPDxaRight" pap.dxaRight;dxa;word;
469 {0x840F, 2, L_FIX}, // "sprmPDxaLeft" pap.dxaLeft;dxa;word;
470 {0x4610, 2, L_FIX}, // "sprmPNest" pap.dxaLeft;dxa
471 {0x8411, 2, L_FIX}, // "sprmPDxaLeft1" pap.dxaLeft1;dxa;word;
472 {0x6412, 4, L_FIX}, // "sprmPDyaLine" pap.lspd;an LSPD, a long word
473 // structure consisting of a short of dyaLine
474 // followed by a short of fMultLinespace
475 {0xA413, 2, L_FIX}, // "sprmPDyaBefore" pap.dyaBefore;dya;word;
476 {0xA414, 2, L_FIX}, // "sprmPDyaAfter" pap.dyaAfter;dya;word;
477 {0xC615, 0, L_VAR}, // "sprmPChgTabs" pap.itbdMac, pap.rgdxaTab,
478 // pap.rgtbd;complex
479 {0x2416, 1, L_FIX}, // "sprmPFInTable" pap.fInTable;0 or 1;byte;
480 {0x2417, 1, L_FIX}, // "sprmPFTtp" pap.fTtp;0 or 1;byte;
481 {0x8418, 2, L_FIX}, // "sprmPDxaAbs" pap.dxaAbs;dxa;word;
482 {0x8419, 2, L_FIX}, // "sprmPDyaAbs" pap.dyaAbs;dya;word;
483 {0x841A, 2, L_FIX}, // "sprmPDxaWidth" pap.dxaWidth;dxa;word;
484 {0x261B, 1, L_FIX}, // "sprmPPc" pap.pcHorz, pap.pcVert;complex
485 {0x461C, 2, L_FIX}, // "sprmPBrcTop10" pap.brcTop;BRC10;word;
486 {0x461D, 2, L_FIX}, // "sprmPBrcLeft10" pap.brcLeft;BRC10;word;
487 {0x461E, 2, L_FIX}, // "sprmPBrcBottom10" pap.brcBottom;BRC10;word;
488 {0x461F, 2, L_FIX}, // "sprmPBrcRight10" pap.brcRight;BRC10;word;
489 {0x4620, 2, L_FIX}, // "sprmPBrcBetween10" pap.brcBetween;BRC10;word;
490 {0x4621, 2, L_FIX}, // "sprmPBrcBar10" pap.brcBar;BRC10;word;
491 {0x4622, 2, L_FIX}, // "sprmPDxaFromText10" pap.dxaFromText;dxa;word;
492 {0x2423, 1, L_FIX}, // "sprmPWr" pap.wr;wr
493 {0x6424, 4, L_FIX}, // "sprmPBrcTop" pap.brcTop;BRC;long;
494 {0x6425, 4, L_FIX}, // "sprmPBrcLeft" pap.brcLeft;BRC;long;
495 {0x6426, 4, L_FIX}, // "sprmPBrcBottom" pap.brcBottom;BRC;long;
496 {0x6427, 4, L_FIX}, // "sprmPBrcRight" pap.brcRight;BRC;long;
497 {0x6428, 4, L_FIX}, // "sprmPBrcBetween" pap.brcBetween;BRC;long;
498 {0x6629, 4, L_FIX}, // "sprmPBrcBar" pap.brcBar;BRC;long;
499 {0x242A, 1, L_FIX}, // "sprmPFNoAutoHyph" pap.fNoAutoHyph;0 or 1;byte;
500 {0x442B, 2, L_FIX}, // "sprmPWHeightAbs" pap.wHeightAbs;w;word;
501 {0x442C, 2, L_FIX}, // "sprmPDcs" pap.dcs;DCS;short;
502 {0x442D, 2, L_FIX}, // "sprmPShd" pap.shd;SHD;word;
503 {0x842E, 2, L_FIX}, // "sprmPDyaFromText" pap.dyaFromText;dya;word;
504 {0x842F, 2, L_FIX}, // "sprmPDxaFromText" pap.dxaFromText;dxa;word;
505 {0x2430, 1, L_FIX}, // "sprmPFLocked" pap.fLocked;0 or 1;byte;
506 {0x2431, 1, L_FIX}, // "sprmPFWidowControl" pap.fWidowControl;0 or 1
507 {0xC632, 0, L_VAR}, // "sprmPRuler" ;;variable length;
508 {0x2433, 1, L_FIX}, // "sprmPFKinsoku" pap.fKinsoku;0 or 1;byte;
509 {0x2434, 1, L_FIX}, // "sprmPFWordWrap" pap.fWordWrap;0 or 1;byte;
510 {0x2435, 1, L_FIX}, // "sprmPFOverflowPunct" pap.fOverflowPunct;0 or 1
511 {0x2436, 1, L_FIX}, // "sprmPFTopLinePunct" pap.fTopLinePunct;0 or 1
512 {0x2437, 1, L_FIX}, // "sprmPFAutoSpaceDE" pap.fAutoSpaceDE;0 or 1
513 {0x2438, 1, L_FIX}, // "sprmPFAutoSpaceDN" pap.fAutoSpaceDN;0 or 1
514 {0x4439, 2, L_FIX}, // "sprmPWAlignFont" pap.wAlignFont;iFa
515 {0x443A, 2, L_FIX}, // "sprmPFrameTextFlow" pap.fVertical pap.fBackward
516 // pap.fRotateFont;complex
517 {0x243B, 1, L_FIX}, // "sprmPISnapBaseLine" obsolete: not applicable in
518 // Word97 and later versions;
519 {0xC63E, 0, L_VAR}, // "sprmPAnld" pap.anld;;variable length;
520 {0xC63F, 0, L_VAR}, // "sprmPPropRMark" pap.fPropRMark;complex
521 {0x2640, 1, L_FIX}, // "sprmPOutLvl" pap.lvl;has no effect if pap.istd
522 // is < 1 or is > 9
523 {0x2441, 1, L_FIX}, // "sprmPFBiDi" ;;byte;
524 {0x2443, 1, L_FIX}, // "sprmPFNumRMIns" pap.fNumRMIns;1 or 0;bit;
525 {0x2444, 1, L_FIX}, // "sprmPCrLf" ;;byte;
526 {0xC645, 0, L_VAR}, // "sprmPNumRM" pap.numrm;;variable length;
527 {0x6645, 4, L_FIX}, // "sprmPHugePapx" fc in the data stream to locate
528 // the huge grpprl
529 {0x6646, 4, L_FIX}, // "sprmPHugePapx" fc in the data stream to locate
530 // the huge grpprl
531 {0x2447, 1, L_FIX}, // "sprmPFUsePgsuSettings" pap.fUsePgsuSettings;
532 // 1 or 0
533 {0x2448, 1, L_FIX}, // "sprmPFAdjustRight" pap.fAdjustRight;1 or 0;byte;
534 {0x0800, 1, L_FIX}, // "sprmCFRMarkDel" chp.fRMarkDel;1 or 0;bit;
535 {0x0801, 1, L_FIX}, // "sprmCFRMark" chp.fRMark;1 or 0;bit;
536 {0x0802, 1, L_FIX}, // "sprmCFFldVanish" chp.fFldVanish;1 or 0;bit;
537 {0x6A03, 4, L_FIX}, // "sprmCPicLocation" chp.fcPic and chp.fSpec;
538 {0x4804, 2, L_FIX}, // "sprmCIbstRMark" chp.ibstRMark;index into
539 // sttbRMark
540 {0x6805, 4, L_FIX}, // "sprmCDttmRMark" chp.dttmRMark;DTTM;long;
541 {0x0806, 1, L_FIX}, // "sprmCFData" chp.fData;1 or 0;bit;
542 {0x4807, 2, L_FIX}, // "sprmCIdslRMark" chp.idslRMReason;an index to a
543 // table of strings defined in Word 6.0
544 // executables;short;
545 {0xEA08, 1, L_FIX}, // "sprmCChs" chp.fChsDiff and chp.chse;
546 {0x6A09, 4, L_FIX}, // "sprmCSymbol" chp.fSpec, chp.xchSym and
547 // chp.ftcSym
548 {0x080A, 1, L_FIX}, // "sprmCFOle2" chp.fOle2;1 or 0;bit;
549 {0x480B, 0, L_FIX}, // "sprmCIdCharType" obsolete: not applicable in
550 // Word97 and later versions;;;
551 {0x2A0C, 1, L_FIX}, // "sprmCHighlight" chp.fHighlight,
552 // chp.icoHighlight;ico (fHighlight is set to 1 iff
553 // ico is not 0)
554 {0x680E, 4, L_FIX}, // "sprmCObjLocation" chp.fcObj;FC;long;
555 {0x2A10, 0, L_FIX}, // "sprmCFFtcAsciSymb" ;;;
556 {0x4A30, 2, L_FIX}, // "sprmCIstd" chp.istd;istd, see stylesheet def
557 {0xCA31, 0, L_VAR}, // "sprmCIstdPermute" chp.istd;permutation vector
558 {0x2A32, 0, L_VAR}, // "sprmCDefault" whole CHP;none;variable length;
559 {0x2A33, 0, L_FIX}, // "sprmCPlain" whole CHP;none;0;
560 {0x2A34, 1, L_FIX}, // "sprmCKcd" ;;;
561 {0x0835, 1, L_FIX}, // "sprmCFBold" chp.fBold;0,1, 128, or 129
562 {0x0836, 1, L_FIX}, // "sprmCFItalic" chp.fItalic;0,1, 128, or 129
563 {0x0837, 1, L_FIX}, // "sprmCFStrike" chp.fStrike;0,1, 128, or 129
564 {0x0838, 1, L_FIX}, // "sprmCFOutline" chp.fOutline;0,1, 128, or 129
565 {0x0839, 1, L_FIX}, // "sprmCFShadow" chp.fShadow;0,1, 128, or 129
566 {0x083A, 1, L_FIX}, // "sprmCFSmallCaps" chp.fSmallCaps;0,1, 128, or 129
567 {0x083B, 1, L_FIX}, // "sprmCFCaps" chp.fCaps;0,1, 128, or 129
568 {0x083C, 1, L_FIX}, // "sprmCFVanish" chp.fVanish;0,1, 128, or 129
569 {0x4A3D, 2, L_FIX}, // "sprmCFtcDefault" ;ftc, only used internally
570 {0x2A3E, 1, L_FIX}, // "sprmCKul" chp.kul;kul;byte;
571 {0xEA3F, 3, L_FIX}, // "sprmCSizePos" chp.hps, chp.hpsPos;3 bytes;
572 {0x8840, 2, L_FIX}, // "sprmCDxaSpace" chp.dxaSpace;dxa;word;
573 {0x4A41, 2, L_FIX}, // "sprmCLid" ;only used internally never stored
574 {0x2A42, 1, L_FIX}, // "sprmCIco" chp.ico;ico;byte;
575 {0x4A43, 2, L_FIX}, // "sprmCHps" chp.hps;hps
576 {0x2A44, 1, L_FIX}, // "sprmCHpsInc" chp.hps;
577 {0x4845, 2, L_FIX}, // "sprmCHpsPos" chp.hpsPos;hps;short; (doc wrong)
578 {0x2A46, 1, L_FIX}, // "sprmCHpsPosAdj" chp.hpsPos;hps
579 {0xCA47, 0, L_VAR}, // "sprmCMajority" chp.fBold, chp.fItalic,
580 // chp.fSmallCaps, chp.fVanish, chp.fStrike,
581 // chp.fCaps, chp.rgftc, chp.hps, chp.hpsPos,
582 // chp.kul, chp.dxaSpace, chp.ico,
583 // chp.rglid;complex;variable length, length byte
584 // plus size of following grpprl;
585 {0x2A48, 1, L_FIX}, // "sprmCIss" chp.iss;iss;byte;
586 {0xCA49, 0, L_VAR}, // "sprmCHpsNew50" chp.hps;hps;variable width
587 {0xCA4A, 0, L_VAR}, // "sprmCHpsInc1" chp.hps;complex
588 {0x484B, 2, L_FIX}, // "sprmCHpsKern" chp.hpsKern;hps;short;
589 {0xCA4C, 2, L_FIX}, // "sprmCMajority50" chp.fBold, chp.fItalic,
590 // chp.fSmallCaps, chp.fVanish, chp.fStrike,
591 // chp.fCaps, chp.ftc, chp.hps, chp.hpsPos, chp.kul,
592 // chp.dxaSpace, chp.ico,;complex
593 {0x4A4D, 2, L_FIX}, // "sprmCHpsMul" chp.hps;percentage to grow hps
594 {0x484E, 2, L_FIX}, // "sprmCYsri" chp.ysri;ysri;short;
595 {0x4A4F, 2, L_FIX}, // "sprmCRgFtc0" chp.rgftc[0];ftc for ASCII text
596 {0x4A50, 2, L_FIX}, // "sprmCRgFtc1" chp.rgftc[1];ftc for Far East text
597 {0x4A51, 2, L_FIX}, // "sprmCRgFtc2" chp.rgftc[2];ftc for non-FE text
598 {0x4852, 2, L_FIX}, // "sprmCCharScale"
599 {0x2A53, 1, L_FIX}, // "sprmCFDStrike" chp.fDStrike;;byte;
600 {0x0854, 1, L_FIX}, // "sprmCFImprint" chp.fImprint;1 or 0;bit;
601 {0x0855, 1, L_FIX}, // "sprmCFSpec" chp.fSpec ;1 or 0;bit;
602 {0x0856, 1, L_FIX}, // "sprmCFObj" chp.fObj;1 or 0;bit;
603 {0xCA57, 0, L_VAR}, // "sprmCPropRMark" chp.fPropRMark,
604 // chp.ibstPropRMark, chp.dttmPropRMark;Complex
605 {0x0858, 1, L_FIX}, // "sprmCFEmboss" chp.fEmboss;1 or 0;bit;
606 {0x2859, 1, L_FIX}, // "sprmCSfxText" chp.sfxtText;text animation;byte;
607 {0x085A, 1, L_FIX}, // "sprmCFBiDi" ;;;
608 {0x085B, 1, L_FIX}, // "sprmCFDiacColor" ;;;
609 {0x085C, 1, L_FIX}, // "sprmCFBoldBi" ;;;
610 {0x085D, 1, L_FIX}, // "sprmCFItalicBi" ;;;
611 {0x4A5E, 2, L_FIX},
612 {0x485F, 2, L_FIX}, // "sprmCLidBi" ;;;
613 {0x4A60, 1, L_FIX}, // "sprmCIcoBi" ;;;
614 {0x4A61, 2, L_FIX}, // "sprmCHpsBi" ;;;
615 {0xCA62, 0, L_VAR}, // "sprmCDispFldRMark" chp.fDispFldRMark,
616 // chp.ibstDispFldRMark, chp.dttmDispFldRMark ;
617 {0x4863, 2, L_FIX}, // "sprmCIbstRMarkDel" chp.ibstRMarkDel;index into
618 // sttbRMark;short;
619 {0x6864, 4, L_FIX}, // "sprmCDttmRMarkDel" chp.dttmRMarkDel;DTTM;long;
620 {0x6865, 4, L_FIX}, // "sprmCBrc" chp.brc;BRC;long;
621 {0x4866, 2, L_FIX}, // "sprmCShd" chp.shd;SHD;short;
622 {0x4867, 2, L_FIX}, // "sprmCIdslRMarkDel" chp.idslRMReasonDel;an index
623 // to a table of strings defined in Word 6.0
624 // executables;short;
625 {0x0868, 1, L_FIX}, // "sprmCFUsePgsuSettings"
626 // chp.fUsePgsuSettings;1 or 0
627 {0x486B, 2, L_FIX}, // "sprmCCpg" ;;word;
628 {0x486D, 2, L_FIX}, // "sprmCRgLid0_80" chp.rglid[0];LID: for non-FE text
629 {0x486E, 2, L_FIX}, // "sprmCRgLid1_80" chp.rglid[1];LID: for Far East text
630 {0x286F, 1, L_FIX}, // "sprmCIdctHint" chp.idctHint;IDCT:
631 {0x2E00, 1, L_FIX}, // "sprmPicBrcl" pic.brcl;brcl (see PIC definition)
632 {0xCE01, 0, L_VAR}, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
633 // pic.dyaCropTop pic.dxaCropRight,
634 // pic.dyaCropBottom;Complex
635 {0x6C02, 4, L_FIX}, // "sprmPicBrcTop" pic.brcTop;BRC;long;
636 {0x6C03, 4, L_FIX}, // "sprmPicBrcLeft" pic.brcLeft;BRC;long;
637 {0x6C04, 4, L_FIX}, // "sprmPicBrcBottom" pic.brcBottom;BRC;long;
638 {0x6C05, 4, L_FIX}, // "sprmPicBrcRight" pic.brcRight;BRC;long;
639 {0x3000, 1, L_FIX}, // "sprmScnsPgn" sep.cnsPgn;cns;byte;
640 {0x3001, 1, L_FIX}, // "sprmSiHeadingPgn" sep.iHeadingPgn;heading number
641 // level;byte;
642 {0xD202, 0, L_VAR}, // "sprmSOlstAnm" sep.olstAnm;OLST;variable length;
643 {0xF203, 3, L_FIX}, // "sprmSDxaColWidth" sep.rgdxaColWidthSpacing;
644 {0xF204, 3, L_FIX}, // "sprmSDxaColSpacing" sep.rgdxaColWidthSpacing;
645 // complex
646 {0x3005, 1, L_FIX}, // "sprmSFEvenlySpaced" sep.fEvenlySpaced;1 or 0
647 {0x3006, 1, L_FIX}, // "sprmSFProtected" sep.fUnlocked;1 or 0;byte;
648 {0x5007, 2, L_FIX}, // "sprmSDmBinFirst" sep.dmBinFirst;;word;
649 {0x5008, 2, L_FIX}, // "sprmSDmBinOther" sep.dmBinOther;;word;
650 {0x3009, 1, L_FIX}, // "sprmSBkc" sep.bkc;bkc;byte;
651 {0x300A, 1, L_FIX}, // "sprmSFTitlePage" sep.fTitlePage;0 or 1;byte;
652 {0x500B, 2, L_FIX}, // "sprmSCcolumns" sep.ccolM1;# of cols - 1;word;
653 {0x900C, 2, L_FIX}, // "sprmSDxaColumns" sep.dxaColumns;dxa;word;
654 {0x300D, 1, L_FIX}, // "sprmSFAutoPgn" sep.fAutoPgn;obsolete;byte;
655 {0x300E, 1, L_FIX}, // "sprmSNfcPgn" sep.nfcPgn;nfc;byte;
656 {0xB00F, 2, L_FIX}, // "sprmSDyaPgn" sep.dyaPgn;dya;short;
657 {0xB010, 2, L_FIX}, // "sprmSDxaPgn" sep.dxaPgn;dya;short;
658 {0x3011, 1, L_FIX}, // "sprmSFPgnRestart" sep.fPgnRestart;0 or 1;byte;
659 {0x3012, 1, L_FIX}, // "sprmSFEndnote" sep.fEndnote;0 or 1;byte;
660 {0x3013, 1, L_FIX}, // "sprmSLnc" sep.lnc;lnc;byte;
661 {0x3014, 1, L_FIX}, // "sprmSGprfIhdt" sep.grpfIhdt;grpfihdt
662 {0x5015, 2, L_FIX}, // "sprmSNLnnMod" sep.nLnnMod;non-neg int.;word;
663 {0x9016, 2, L_FIX}, // "sprmSDxaLnn" sep.dxaLnn;dxa;word;
664 {0xB017, 2, L_FIX}, // "sprmSDyaHdrTop" sep.dyaHdrTop;dya;word;
665 {0xB018, 2, L_FIX}, // "sprmSDyaHdrBottom" sep.dyaHdrBottom;dya;word;
666 {0x3019, 1, L_FIX}, // "sprmSLBetween" sep.fLBetween;0 or 1;byte;
667 {0x301A, 1, L_FIX}, // "sprmSVjc" sep.vjc;vjc;byte;
668 {0x501B, 2, L_FIX}, // "sprmSLnnMin" sep.lnnMin;lnn;word;
669 {0x501C, 2, L_FIX}, // "sprmSPgnStart" sep.pgnStart;pgn;word;
670 {0x301D, 1, L_FIX}, // "sprmSBOrientation" sep.dmOrientPage;dm;byte;
671 {0x301E, 1, L_FIX}, // "sprmSBCustomize" ;;;
672 {0xB01F, 2, L_FIX}, // "sprmSXaPage" sep.xaPage;xa;word;
673 {0xB020, 2, L_FIX}, // "sprmSYaPage" sep.yaPage;ya;word;
674 {0xB021, 2, L_FIX}, // "sprmSDxaLeft" sep.dxaLeft;dxa;word;
675 {0xB022, 2, L_FIX}, // "sprmSDxaRight" sep.dxaRight;dxa;word;
676 {0x9023, 2, L_FIX}, // "sprmSDyaTop" sep.dyaTop;dya;word;
677 {0x9024, 2, L_FIX}, // "sprmSDyaBottom" sep.dyaBottom;dya;word;
678 {0xB025, 2, L_FIX}, // "sprmSDzaGutter" sep.dzaGutter;dza;word;
679 {0x5026, 2, L_FIX}, // "sprmSDmPaperReq" sep.dmPaperReq;dm;word;
680 {0xD227, 0, L_VAR}, // "sprmSPropRMark" sep.fPropRMark,
681 // sep.ibstPropRMark, sep.dttmPropRMark ;complex
682 {0x3228, 1, L_FIX}, // "sprmSFBiDi" ;;;
683 {0x3229, 1, L_FIX}, // "sprmSFFacingCol" ;;;
684 {0x322A, 1, L_FIX}, // "sprmSFRTLGutter", set to one if gutter is on
685 // right
686 {0x702B, 4, L_FIX}, // "sprmSBrcTop" sep.brcTop;BRC;long;
687 {0x702C, 4, L_FIX}, // "sprmSBrcLeft" sep.brcLeft;BRC;long;
688 {0x702D, 4, L_FIX}, // "sprmSBrcBottom" sep.brcBottom;BRC;long;
689 {0x702E, 4, L_FIX}, // "sprmSBrcRight" sep.brcRight;BRC;long;
690 {0x522F, 2, L_FIX}, // "sprmSPgbProp" sep.pgbProp;;word;
691 {0x7030, 4, L_FIX}, // "sprmSDxtCharSpace" sep.dxtCharSpace;dxt;long;
692 {0x9031, 2, L_FIX}, // "sprmSDyaLinePitch"
693 // sep.dyaLinePitch;dya; WRONG:long; RIGHT:short; !
694 {0x5032, 2, L_FIX}, // "sprmSClm" ;;;
695 {0x5033, 2, L_FIX}, // "sprmSTextFlow" sep.wTextFlow;complex
696 {0x5400, 2, L_FIX}, // "sprmTJc" tap.jc;jc;word (low order byte is
697 // significant);
698 {0x9601, 2, L_FIX}, // "sprmTDxaLeft" tap.rgdxaCenter
699 {0x9602, 2, L_FIX}, // "sprmTDxaGapHalf" tap.dxaGapHalf,
700 // tap.rgdxaCenter
701 {0x3403, 1, L_FIX}, // "sprmTFCantSplit" tap.fCantSplit;1 or 0;byte;
702 {0x3404, 1, L_FIX}, // "sprmTTableHeader" tap.fTableHeader;1 or 0;byte;
703 {0x3466, 1, L_FIX}, // "sprmTFCantSplit90" tap.fCantSplit90;1 or 0;byte;
704 {0xD605, 0, L_VAR}, // "sprmTTableBorders" tap.rgbrcTable;complex
705 {0xD606, 0, L_VAR}, // "sprmTDefTable10" tap.rgdxaCenter,
706 // tap.rgtc;complex
707 {0x9407, 2, L_FIX}, // "sprmTDyaRowHeight" tap.dyaRowHeight;dya;word;
708 {0xD608, 0, L_VAR}, // "sprmTDefTable" tap.rgtc;complex
709 {0xD609, 0, L_VAR}, // "sprmTDefTableShd" tap.rgshd;complex
710 {0x740A, 4, L_FIX}, // "sprmTTlp" tap.tlp;TLP;4 bytes;
711 {0x560B, 2, L_FIX}, // "sprmTFBiDi" ;;;
712 {0x740C, 1, L_FIX}, // "sprmTHTMLProps" ;;;
713 {0xD620, 0, L_VAR}, // "sprmTSetBrc" tap.rgtc[].rgbrc;complex
714 {0x7621, 4, L_FIX}, // "sprmTInsert" tap.rgdxaCenter, tap.rgtc;complex
715 {0x5622, 2, L_FIX}, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc;complex
716 {0x7623, 4, L_FIX}, // "sprmTDxaCol" tap.rgdxaCenter;complex
717 {0x5624, 0, L_VAR}, // "sprmTMerge" tap.fFirstMerged, tap.fMerged;
718 {0x5625, 0, L_VAR}, // "sprmTSplit" tap.fFirstMerged, tap.fMerged;
719 {0xD626, 0, L_VAR}, // "sprmTSetBrc10" tap.rgtc[].rgbrc;complex
720 {0x7627, 0, L_VAR}, // "sprmTSetShd" tap.rgshd;complex
721 {0x7628, 0, L_VAR}, // "sprmTSetShdOdd" tap.rgshd;complex
722 {0x7629, 4, L_FIX}, // "sprmTTextFlow" tap.rgtc[].fVerticaltap,
723 // rgtc[].fBackwardtap, rgtc[].fRotateFont;0 or 10
724 // or 10 or 1;word;
725 {0xD62A, 1, L_FIX}, // "sprmTDiagLine" ;;;
726 {0xD62B, 0, L_VAR}, // "sprmTVertMerge" tap.rgtc[].vertMerge
727 {0xD62C, 0, L_VAR}, // "sprmTVertAlign" tap.rgtc[].vertAlign
728 {0xCA78, 0, L_VAR}, // undocumented "sprmCDoubleLine ?"
729 {0x6649, 4, L_FIX}, // undocumented
730 {0xF614, 3, L_FIX}, // undocumented
731 {0xD612, 0, L_VAR}, // undocumented, new background colours.
732 {0xD613, 0, L_VAR}, // undocumented
733 {0xD61A, 0, L_VAR}, // undocumented
734 {0xD61B, 0, L_VAR}, // undocumented
735 {0xD61C, 0, L_VAR}, // undocumented
736 {0xD61D, 0, L_VAR}, // undocumented
737 {0xD632, 0, L_VAR}, // undocumented
738 {0xD634, 0, L_VAR}, // undocumented
739 {0xD238, 0, L_VAR}, // undocumented sep
740 {0xC64E, 0, L_VAR}, // undocumented
741 {0xC64F, 0, L_VAR}, // undocumented
742 {0xC650, 0, L_VAR}, // undocumented
743 {0xC651, 0, L_VAR}, // undocumented
744 {0xF661, 3, L_FIX}, // undocumented
745 {0x4873, 2, L_FIX}, // "sprmCRgLid0" chp.rglid[0];LID: for non-FE text
746 {0x4874, 2, L_FIX}, // "sprmCRgLid1" chp.rglid[1];LID: for Far East text
747 {0x6463, 4, L_FIX}, // undocumented
748 {0x2461, 1, L_FIX}, // undoc, must be asian version of "sprmPJc"
749 {0x845D, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaRight"
750 {0x845E, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaLeft"
751 {0x8460, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaLeft1"
752 {0x3615, 1, L_FIX}, // undocumented
753 {0x360D, 1, L_FIX}, // undocumented
754 {0x703A, 4, L_FIX}, // undocumented, sep, perhaps related to textgrids ?
755 {0x303B, 1, L_FIX}, // undocumented, sep
756 {0x244B, 1, L_FIX}, // undocumented, subtable "sprmPFInTable" equiv ?
757 {0x244C, 1, L_FIX}, // undocumented, subtable "sprmPFTtp" equiv ?
758 {0x940E, 2, L_FIX}, // undocumented
759 {0x940F, 2, L_FIX}, // undocumented
760 {0x9410, 2, L_FIX}, // undocumented
761 {0x6815, 4, L_FIX}, // undocumented
762 {0x6816, 4, L_FIX}, // undocumented
763 {0x6870, 4, L_FIX}, // undocumented, text colour
764 {0xC64D, 0, L_VAR}, // undocumented, para back colour
765 {0x6467, 4, L_FIX}, // undocumented
766 {0x646B, 4, L_FIX}, // undocumented
767 {0xF617, 3, L_FIX}, // undocumented
768 {0xD660, 0, L_VAR}, // undocumented, something to do with colour.
769 {0xD670, 0, L_VAR}, // undocumented, something to do with colour.
770 {0xCA71, 0, L_VAR}, // undocumented, text backcolour
771 {0x303C, 1, L_FIX}, // undocumented, sep
772 {0x245B, 1, L_FIX}, // undocumented, para autobefore
773 {0x245C, 1, L_FIX}, // undocumented, para autoafter
774 // "sprmPFContextualSpacing", don't add space between para of the same style
775 {0x246D, 1, L_FIX}
778 static wwSprmSearcher aSprmSrch(aSprms, sizeof(aSprms) / sizeof(aSprms[0]));
779 return &aSprmSrch;
782 wwSprmParser::wwSprmParser(ww::WordVersion eVersion) : meVersion(eVersion)
784 OSL_ENSURE((meVersion >= ww::eWW2 && meVersion <= ww::eWW8),
785 "Impossible value for version");
787 mnDelta = (ww::IsSevenMinus(meVersion)) ? 0 : 1;
789 if (meVersion <= ww::eWW2)
790 mpKnownSprms = GetWW2SprmSearcher();
791 else if (meVersion < ww::eWW8)
792 mpKnownSprms = GetWW6SprmSearcher();
793 else
794 mpKnownSprms = GetWW8SprmSearcher();
797 SprmInfo wwSprmParser::GetSprmInfo(sal_uInt16 nId) const
799 // Find sprm
800 SprmInfo aSrch={0,0,0};
801 aSrch.nId = nId;
802 const SprmInfo* pFound = mpKnownSprms->search(aSrch);
803 if (pFound == 0)
805 OSL_ENSURE(ww::IsEightPlus(meVersion),
806 "Unknown ww7- sprm, dangerous, report to development");
808 aSrch.nId = 0;
809 aSrch.nLen = 0;
810 //All the unknown ww7 sprms appear to be variable (which makes sense)
811 aSrch.nVari = L_VAR;
813 if (ww::IsEightPlus(meVersion)) //We can recover perfectly in this case
815 aSrch.nVari = L_FIX;
816 switch (nId >> 13)
818 case 0:
819 case 1:
820 aSrch.nLen = 1;
821 break;
822 case 2:
823 aSrch.nLen = 2;
824 break;
825 case 3:
826 aSrch.nLen = 4;
827 break;
828 case 4:
829 case 5:
830 aSrch.nLen = 2;
831 break;
832 case 6:
833 aSrch.nLen = 0;
834 aSrch.nVari = L_VAR;
835 break;
836 case 7:
837 default:
838 aSrch.nLen = 3;
839 break;
843 pFound = &aSrch;
845 return *pFound;
848 //-end
850 inline sal_uInt8 Get_Byte( sal_uInt8 *& p )
852 sal_uInt8 n = SVBT8ToByte( *(SVBT8*)p );
853 p += 1;
854 return n;
857 inline sal_uInt16 Get_UShort( sal_uInt8 *& p )
859 sal_uInt16 n = SVBT16ToShort( *(SVBT16*)p );
860 p += 2;
861 return n;
864 inline short Get_Short( sal_uInt8 *& p )
866 return Get_UShort(p);
869 inline sal_uLong Get_ULong( sal_uInt8 *& p )
871 sal_uLong n = SVBT32ToUInt32( *(SVBT32*)p );
872 p += 4;
873 return n;
876 inline long Get_Long( sal_uInt8 *& p )
878 return Get_ULong(p);
881 WW8SprmIter::WW8SprmIter(const sal_uInt8* pSprms_, long nLen_,
882 const wwSprmParser &rParser)
883 : mrSprmParser(rParser), pSprms( pSprms_), nRemLen( nLen_)
885 UpdateMyMembers();
888 void WW8SprmIter::SetSprms(const sal_uInt8* pSprms_, long nLen_)
890 pSprms = pSprms_;
891 nRemLen = nLen_;
892 UpdateMyMembers();
895 void WW8SprmIter::advance()
897 if (nRemLen > 0 )
899 sal_uInt16 nSize = nAktSize;
900 if (nSize > nRemLen)
901 nSize = nRemLen;
902 pSprms += nSize;
903 nRemLen -= nSize;
904 UpdateMyMembers();
908 void WW8SprmIter::UpdateMyMembers()
910 bool bValid = (pSprms && nRemLen >= mrSprmParser.MinSprmLen());
912 if (bValid)
914 nAktId = mrSprmParser.GetSprmId(pSprms);
915 nAktSize = mrSprmParser.GetSprmSize(nAktId, pSprms);
916 pAktParams = pSprms + mrSprmParser.DistanceToData(nAktId);
917 bValid = nAktSize <= nRemLen;
918 SAL_WARN_IF(!bValid, "sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong");
921 if (!bValid)
923 nAktId = 0;
924 pAktParams = 0;
925 nAktSize = 0;
926 nRemLen = 0;
930 const sal_uInt8* WW8SprmIter::FindSprm(sal_uInt16 nId)
932 while (GetSprms())
934 if (GetAktId() == nId)
935 return GetAktParams(); // SPRM found!
936 advance();
939 return 0; // SPRM _not_ found
942 // temporary test
943 // WW8PLCFx_PCDAttrs cling to WW8PLCF_Pcd and therefore do not have their own iterators.
944 // All methods relating to iterators are therefore dummies.
945 WW8PLCFx_PCDAttrs::WW8PLCFx_PCDAttrs(ww::WordVersion eVersion,
946 WW8PLCFx_PCD* pPLCFx_PCD, const WW8ScannerBase* pBase)
947 : WW8PLCFx(eVersion, true), pPcdI(pPLCFx_PCD->GetPLCFIter()),
948 pPcd(pPLCFx_PCD), pGrpprls(pBase->pPieceGrpprls),
949 nGrpprls(pBase->nPieceGrpprls)
953 sal_uLong WW8PLCFx_PCDAttrs::GetIdx() const
955 return 0;
958 void WW8PLCFx_PCDAttrs::SetIdx( sal_uLong )
962 bool WW8PLCFx_PCDAttrs::SeekPos(WW8_CP )
964 return true;
967 void WW8PLCFx_PCDAttrs::advance()
971 WW8_CP WW8PLCFx_PCDAttrs::Where()
973 return ( pPcd ) ? pPcd->Where() : WW8_CP_MAX;
976 void WW8PLCFx_PCDAttrs::GetSprms(WW8PLCFxDesc* p)
978 void* pData;
980 p->bRealLineEnd = false;
981 if ( !pPcdI || !pPcdI->Get(p->nStartPos, p->nEndPos, pData) )
983 // PLCF fully processed
984 p->nStartPos = p->nEndPos = WW8_CP_MAX;
985 p->pMemPos = 0;
986 p->nSprmsLen = 0;
987 return;
990 sal_uInt16 nPrm = SVBT16ToShort( ( (WW8_PCD*)pData )->prm );
991 if ( nPrm & 1 )
993 // PRM Variant 2
994 sal_uInt16 nSprmIdx = nPrm >> 1;
996 if( nSprmIdx >= nGrpprls )
998 // Invalid Index
999 p->nStartPos = p->nEndPos = WW8_CP_MAX;
1000 p->pMemPos = 0;
1001 p->nSprmsLen = 0;
1002 return;
1004 const sal_uInt8* pSprms = pGrpprls[ nSprmIdx ];
1006 p->nSprmsLen = SVBT16ToShort( pSprms ); // Length
1007 pSprms += 2;
1008 p->pMemPos = pSprms; // Position
1010 else
1012 // SPRM is stored directly into members var
1014 These are the attr that are in the piece-table instead of in the text!
1017 if (IsSevenMinus(GetFIBVersion()))
1019 aShortSprm[0] = (sal_uInt8)( ( nPrm & 0xfe) >> 1 );
1020 aShortSprm[1] = (sal_uInt8)( nPrm >> 8 );
1021 p->nSprmsLen = ( nPrm ) ? 2 : 0; // length
1023 // store Postion of internal mini storage in Data Pointer
1024 p->pMemPos = aShortSprm;
1026 else
1028 p->pMemPos = 0;
1029 p->nSprmsLen = 0;
1030 sal_uInt8 nSprmListIdx = (sal_uInt8)((nPrm & 0xfe) >> 1);
1031 if( nSprmListIdx )
1033 // process Sprm Id Matching as explained in MS Documentation
1035 // ''Property Modifier(variant 1) (PRM)''
1036 // see file: s62f39.htm
1038 // Since isprm is 7 bits, rgsprmPrm can hold 0x80 entries.
1039 static const sal_uInt16 aSprmId[0x80] =
1041 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1042 0x0000,0x0000,0x0000,0x0000,
1043 // sprmPIncLvl, sprmPJc, sprmPFSideBySide, sprmPFKeep
1044 0x2402,0x2403,0x2404,0x2405,
1045 // sprmPFKeepFollow, sprmPFPageBreakBefore, sprmPBrcl,
1046 // sprmPBrcp
1047 0x2406,0x2407,0x2408,0x2409,
1048 // sprmPIlvl, sprmNoop, sprmPFNoLineNumb, sprmNoop
1049 0x260A,0x0000,0x240C,0x0000,
1050 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1051 0x0000,0x0000,0x0000,0x0000,
1052 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1053 0x0000,0x0000,0x0000,0x0000,
1054 // sprmPFInTable, sprmPFTtp, sprmNoop, sprmNoop
1055 0x2416,0x2417,0x0000,0x0000,
1056 // sprmNoop, sprmPPc, sprmNoop, sprmNoop
1057 0x0000,0x261B,0x0000,0x0000,
1058 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1059 0x0000,0x0000,0x0000,0x0000,
1060 // sprmNoop, sprmPWr, sprmNoop, sprmNoop
1061 0x0000,0x2423,0x0000,0x0000,
1062 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1063 0x0000,0x0000,0x0000,0x0000,
1064 // sprmPFNoAutoHyph, sprmNoop, sprmNoop, sprmNoop
1065 0x242A,0x0000,0x0000,0x0000,
1066 // sprmNoop, sprmNoop, sprmPFLocked, sprmPFWidowControl
1067 0x0000,0x0000,0x2430,0x2431,
1068 // sprmNoop, sprmPFKinsoku, sprmPFWordWrap,
1069 // sprmPFOverflowPunct
1070 0x0000,0x2433,0x2434,0x2435,
1071 // sprmPFTopLinePunct, sprmPFAutoSpaceDE,
1072 // sprmPFAutoSpaceDN, sprmNoop
1073 0x2436,0x2437,0x2438,0x0000,
1074 // sprmNoop, sprmPISnapBaseLine, sprmNoop, sprmNoop
1075 0x0000,0x243B,0x000,0x0000,
1076 // sprmNoop, sprmCFStrikeRM, sprmCFRMark, sprmCFFldVanish
1077 0x0000,0x0800,0x0801,0x0802,
1078 // sprmNoop, sprmNoop, sprmNoop, sprmCFData
1079 0x0000,0x0000,0x0000,0x0806,
1080 // sprmNoop, sprmNoop, sprmNoop, sprmCFOle2
1081 0x0000,0x0000,0x0000,0x080A,
1082 // sprmNoop, sprmCHighlight, sprmCFEmboss, sprmCSfxText
1083 0x0000,0x2A0C,0x0858,0x2859,
1084 // sprmNoop, sprmNoop, sprmNoop, sprmCPlain
1085 0x0000,0x0000,0x0000,0x2A33,
1086 // sprmNoop, sprmCFBold, sprmCFItalic, sprmCFStrike
1087 0x0000,0x0835,0x0836,0x0837,
1088 // sprmCFOutline, sprmCFShadow, sprmCFSmallCaps, sprmCFCaps,
1089 0x0838,0x0839,0x083a,0x083b,
1090 // sprmCFVanish, sprmNoop, sprmCKul, sprmNoop,
1091 0x083C,0x0000,0x2A3E,0x0000,
1092 // sprmNoop, sprmNoop, sprmCIco, sprmNoop,
1093 0x0000,0x0000,0x2A42,0x0000,
1094 // sprmCHpsInc, sprmNoop, sprmCHpsPosAdj, sprmNoop,
1095 0x2A44,0x0000,0x2A46,0x0000,
1096 // sprmCIss, sprmNoop, sprmNoop, sprmNoop,
1097 0x2A48,0x0000,0x0000,0x0000,
1098 // sprmNoop, sprmNoop, sprmNoop, sprmNoop,
1099 0x0000,0x0000,0x0000,0x0000,
1100 // sprmNoop, sprmNoop, sprmNoop, sprmCFDStrike,
1101 0x0000,0x0000,0x0000,0x2A53,
1102 // sprmCFImprint, sprmCFSpec, sprmCFObj, sprmPicBrcl,
1103 0x0854,0x0855,0x0856,0x2E00,
1104 // sprmPOutLvl, sprmPFBiDi, sprmNoop, sprmNoop,
1105 0x2640,0x2441,0x0000,0x0000,
1106 // sprmNoop, sprmNoop, sprmPPnbrRMarkNot
1107 0x0000,0x0000,0x0000,0x0000
1110 // find real Sprm Id:
1111 sal_uInt16 nSprmId = aSprmId[ nSprmListIdx ];
1113 if( nSprmId )
1115 // move Sprm Id and Sprm Param to internal mini storage:
1116 aShortSprm[0] = (sal_uInt8)( ( nSprmId & 0x00ff) );
1117 aShortSprm[1] = (sal_uInt8)( ( nSprmId & 0xff00) >> 8 );
1118 aShortSprm[2] = (sal_uInt8)( nPrm >> 8 );
1120 // store Sprm Length in member:
1121 p->nSprmsLen = ( nPrm ) ? 3 : 0;
1123 // store Postion of internal mini storage in Data Pointer
1124 p->pMemPos = aShortSprm;
1131 WW8PLCFx_PCD::WW8PLCFx_PCD(ww::WordVersion eVersion, WW8PLCFpcd* pPLCFpcd,
1132 WW8_CP nStartCp, bool bVer67P)
1133 : WW8PLCFx(eVersion, false), nClipStart(-1)
1135 // construct own iterator
1136 pPcdI = new WW8PLCFpcd_Iter(*pPLCFpcd, nStartCp);
1137 bVer67= bVer67P;
1140 WW8PLCFx_PCD::~WW8PLCFx_PCD()
1142 // pPcd-Dtor which in called from WW8ScannerBase
1143 delete pPcdI;
1146 sal_uLong WW8PLCFx_PCD::GetIMax() const
1148 return pPcdI ? pPcdI->GetIMax() : 0;
1151 sal_uLong WW8PLCFx_PCD::GetIdx() const
1153 return pPcdI ? pPcdI->GetIdx() : 0;
1156 void WW8PLCFx_PCD::SetIdx( sal_uLong nIdx )
1158 if (pPcdI)
1159 pPcdI->SetIdx( nIdx );
1162 bool WW8PLCFx_PCD::SeekPos(WW8_CP nCpPos)
1164 return pPcdI ? pPcdI->SeekPos( nCpPos ) : false;
1167 WW8_CP WW8PLCFx_PCD::Where()
1169 return pPcdI ? pPcdI->Where() : WW8_CP_MAX;
1172 long WW8PLCFx_PCD::GetNoSprms( WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen )
1174 void* pData;
1175 rLen = 0;
1177 if ( !pPcdI || !pPcdI->Get(rStart, rEnd, pData) )
1179 rStart = rEnd = WW8_CP_MAX;
1180 return -1;
1182 return pPcdI->GetIdx();
1185 void WW8PLCFx_PCD::advance()
1187 OSL_ENSURE(pPcdI , "missing pPcdI");
1188 if (pPcdI)
1189 pPcdI->advance();
1192 WW8_FC WW8PLCFx_PCD::AktPieceStartCp2Fc( WW8_CP nCp )
1194 WW8_CP nCpStart, nCpEnd;
1195 void* pData;
1197 if ( !pPcdI->Get(nCpStart, nCpEnd, pData) )
1199 OSL_ENSURE( !this, "AktPieceStartCp2Fc() with false Cp found (1)" );
1200 return WW8_FC_MAX;
1203 OSL_ENSURE( nCp >= nCpStart && nCp < nCpEnd,
1204 "AktPieceCp2Fc() with false Cp found (2)" );
1206 if( nCp < nCpStart )
1207 nCp = nCpStart;
1208 if( nCp >= nCpEnd )
1209 nCp = nCpEnd - 1;
1211 bool bIsUnicode = false;
1212 WW8_FC nFC = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
1213 if( !bVer67 )
1214 nFC = WW8PLCFx_PCD::TransformPieceAddress( nFC, bIsUnicode );
1216 return nFC + (nCp - nCpStart) * (bIsUnicode ? 2 : 1);
1220 void WW8PLCFx_PCD::AktPieceFc2Cp( WW8_CP& rStartPos, WW8_CP& rEndPos,
1221 const WW8ScannerBase *pSBase )
1223 //No point going anywhere with this
1224 if ((rStartPos == WW8_CP_MAX) && (rEndPos == WW8_CP_MAX))
1225 return;
1227 rStartPos = pSBase->WW8Fc2Cp( rStartPos );
1228 rEndPos = pSBase->WW8Fc2Cp( rEndPos );
1231 WW8_CP WW8PLCFx_PCD::AktPieceStartFc2Cp( WW8_FC nStartPos )
1233 WW8_CP nCpStart, nCpEnd;
1234 void* pData;
1235 if ( !pPcdI->Get( nCpStart, nCpEnd, pData ) )
1237 OSL_ENSURE( !this, "AktPieceStartFc2Cp() - error" );
1238 return WW8_CP_MAX;
1240 bool bIsUnicode = false;
1241 sal_Int32 nFcStart = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
1242 if( !bVer67 )
1243 nFcStart = WW8PLCFx_PCD::TransformPieceAddress( nFcStart, bIsUnicode );
1245 sal_Int32 nUnicodeFactor = bIsUnicode ? 2 : 1;
1247 if( nStartPos < nFcStart )
1248 nStartPos = nFcStart;
1250 if( nStartPos >= nFcStart + (nCpEnd - nCpStart) * nUnicodeFactor )
1251 nStartPos = nFcStart + (nCpEnd - nCpStart - 1) * nUnicodeFactor;
1253 return nCpStart + (nStartPos - nFcStart) / nUnicodeFactor;
1256 // Helper routines for all
1258 short WW8_BRC::DetermineBorderProperties(bool bVer67, short *pSpace,
1259 sal_uInt8 *pCol, short *pIdx) const
1262 Word does not factor the width of the border into the width/height
1263 stored in the information for graphic/table/object widths, so we need
1264 to figure out this extra width here and utilize the returned size in
1265 our calculations
1267 short nMSTotalWidth;
1268 sal_uInt8 nCol;
1269 short nIdx,nSpace;
1270 if( bVer67 )
1272 sal_uInt16 aBrc1 = SVBT16ToShort(aBits1);
1273 nCol = static_cast< sal_uInt8 >((aBrc1 >> 6) & 0x1f); // aBor.ico
1274 nSpace = (aBrc1 & 0xF800) >> 11;
1276 nMSTotalWidth = aBrc1 & 0x07;
1277 nIdx = (aBrc1 & 0x18) >> 3;
1278 //Dashed/Dotted unsets double/thick
1279 if (nMSTotalWidth > 5)
1281 nIdx = nMSTotalWidth;
1282 nMSTotalWidth=1;
1284 nMSTotalWidth = nMSTotalWidth * nIdx * 15;
1286 else
1288 nIdx = aBits1[1];
1289 nCol = aBits2[0]; // aBor.ico
1290 nSpace = aBits2[1] & 0x1F; //space between line and object
1292 //Specification in 8ths of a point, 1 Point = 20 Twips, so by 2.5
1293 nMSTotalWidth = aBits1[ 0 ] * 20 / 8;
1295 //Figure out the real size of the border according to word
1296 switch (nIdx)
1298 //Note that codes over 25 are undocumented, and I can't create
1299 //these 4 here in the wild.
1300 case 2:
1301 case 4:
1302 case 5:
1303 case 22:
1304 OSL_FAIL("Can't create these from the menus, please report");
1305 default:
1306 case 23: //Only 3pt in the menus, but honours the size setting.
1307 break;
1308 case 10:
1310 triple line is five times the width of an ordinary line,
1311 except that the smallest 1/4 point size appears to have
1312 exactly the same total border width as a 3/4 point size
1313 ordinary line, i.e. three times the nominal line width. The
1314 second smallest 1/2 point size appears to have exactly the
1315 total border width as a 2 1/4 border, i.e 4.5 times the size.
1317 if (nMSTotalWidth == 5)
1318 nMSTotalWidth*=3;
1319 else if (nMSTotalWidth == 10)
1320 nMSTotalWidth = nMSTotalWidth*9/2;
1321 else
1322 nMSTotalWidth*=5;
1323 break;
1324 case 20:
1326 wave, the dimensions appear to be created by the drawing of
1327 the wave, so we have only two possibilites in the menus, 3/4
1328 point is equal to solid 3 point. This calculation seems to
1329 match well to results.
1331 nMSTotalWidth +=45;
1332 break;
1333 case 21:
1335 double wave, the dimensions appear to be created by the
1336 drawing of the wave, so we have only one possibilites in the
1337 menus, that of 3/4 point is equal to solid 3 point. This
1338 calculation seems to match well to results.
1340 nMSTotalWidth += 45*2;
1341 break;
1345 if (pIdx)
1346 *pIdx = nIdx;
1347 if (pSpace)
1348 *pSpace = nSpace*20;
1349 if (pCol)
1350 *pCol = nCol;
1351 return nMSTotalWidth;
1355 * WW8Cp2Fc is a good method, a CP always maps to a FC
1356 * WW8Fc2Cp on the other hand is more dubious, a random FC
1357 * may not map to a valid CP. Try and avoid WW8Fc2Cp where
1358 * possible
1360 WW8_CP WW8ScannerBase::WW8Fc2Cp( WW8_FC nFcPos ) const
1362 WW8_CP nFallBackCpEnd = WW8_CP_MAX;
1363 if( nFcPos == WW8_FC_MAX )
1364 return nFallBackCpEnd;
1366 bool bIsUnicode;
1367 if (pWw8Fib->nVersion >= 8)
1368 bIsUnicode = false;
1369 else
1370 bIsUnicode = pWw8Fib->fExtChar ? true : false;
1372 if( pPieceIter ) // Complex File ?
1374 sal_uLong nOldPos = pPieceIter->GetIdx();
1376 for (pPieceIter->SetIdx(0);
1377 pPieceIter->GetIdx() < pPieceIter->GetIMax(); pPieceIter->advance())
1379 WW8_CP nCpStart, nCpEnd;
1380 void* pData;
1381 if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) )
1382 { // outside PLCFfpcd ?
1383 OSL_ENSURE( !this, "PLCFpcd-WW8Fc2Cp() went wrong" );
1384 break;
1386 sal_Int32 nFcStart = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
1387 if (pWw8Fib->nVersion >= 8)
1389 nFcStart = WW8PLCFx_PCD::TransformPieceAddress( nFcStart,
1390 bIsUnicode );
1392 else
1394 bIsUnicode = pWw8Fib->fExtChar ? true : false;
1396 sal_Int32 nLen = (nCpEnd - nCpStart) * (bIsUnicode ? 2 : 1);
1399 If this cp is inside this piece, or its the last piece and we are
1400 on the very last cp of that piece
1402 if (nFcPos >= nFcStart)
1404 // found
1405 WW8_CP nTempCp =
1406 nCpStart + ((nFcPos - nFcStart) / (bIsUnicode ? 2 : 1));
1407 if (nFcPos < nFcStart + nLen)
1409 pPieceIter->SetIdx( nOldPos );
1410 return nTempCp;
1412 else if (nFcPos == nFcStart + nLen)
1414 //Keep this cp as its on a piece boundary because we might
1415 //need it if tests fail
1416 nFallBackCpEnd = nTempCp;
1420 // not found
1421 pPieceIter->SetIdx( nOldPos ); // not found
1423 If it was not found, then this is because it has fallen between two
1424 stools, i.e. either it is the last cp/fc of the last piece, or it is
1425 the last cp/fc of a disjoint piece.
1427 return nFallBackCpEnd;
1430 // No complex file
1431 if (!bIsUnicode)
1432 nFallBackCpEnd = (nFcPos - pWw8Fib->fcMin);
1433 else
1434 nFallBackCpEnd = (nFcPos - pWw8Fib->fcMin + 1) / 2;
1436 return nFallBackCpEnd;
1439 WW8_FC WW8ScannerBase::WW8Cp2Fc(WW8_CP nCpPos, bool* pIsUnicode,
1440 WW8_CP* pNextPieceCp, bool* pTestFlag) const
1442 if( pTestFlag )
1443 *pTestFlag = true;
1444 if( WW8_CP_MAX == nCpPos )
1445 return WW8_CP_MAX;
1447 bool bIsUnicode;
1448 if( !pIsUnicode )
1449 pIsUnicode = &bIsUnicode;
1451 if (pWw8Fib->nVersion >= 8)
1452 *pIsUnicode = false;
1453 else
1454 *pIsUnicode = pWw8Fib->fExtChar ? true : false;
1456 if( pPieceIter )
1458 // Complex File
1459 if( pNextPieceCp )
1460 *pNextPieceCp = WW8_CP_MAX;
1462 if( !pPieceIter->SeekPos( nCpPos ) )
1464 if( pTestFlag )
1465 *pTestFlag = false;
1466 else {
1467 OSL_ENSURE( !this, "Handed over wrong CP to WW8Cp2Fc()" );
1469 return WW8_FC_MAX;
1471 WW8_CP nCpStart, nCpEnd;
1472 void* pData;
1473 if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) )
1475 if( pTestFlag )
1476 *pTestFlag = false;
1477 else {
1478 OSL_ENSURE( !this, "PLCFfpcd-Get went wrong" );
1480 return WW8_FC_MAX;
1482 if( pNextPieceCp )
1483 *pNextPieceCp = nCpEnd;
1485 WW8_FC nRet = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
1486 if (pWw8Fib->nVersion >= 8)
1487 nRet = WW8PLCFx_PCD::TransformPieceAddress( nRet, *pIsUnicode );
1488 else
1489 *pIsUnicode = pWw8Fib->fExtChar ? true : false;
1491 nRet += (nCpPos - nCpStart) * (*pIsUnicode ? 2 : 1);
1493 return nRet;
1496 // No complex file
1497 return pWw8Fib->fcMin + nCpPos * (*pIsUnicode ? 2 : 1);
1500 // class WW8ScannerBase
1501 WW8PLCFpcd* WW8ScannerBase::OpenPieceTable( SvStream* pStr, const WW8Fib* pWwF )
1503 if ( ((8 > pWw8Fib->nVersion) && !pWwF->fComplex) || !pWwF->lcbClx )
1504 return NULL;
1506 WW8_FC nClxPos = pWwF->fcClx;
1507 sal_Int32 nClxLen = pWwF->lcbClx;
1508 sal_Int32 nLeft = nClxLen;
1509 sal_Int16 nGrpprl = 0;
1511 if (!checkSeek(*pStr, nClxPos))
1512 return NULL;
1514 while( 1 ) // Zaehle Zahl der Grpprls
1516 sal_uInt8 clxt(2);
1517 *pStr >> clxt;
1518 nLeft--;
1519 if( 2 == clxt ) // PLCFfpcd ?
1520 break; // PLCFfpcd gefunden
1521 if( 1 == clxt ) // clxtGrpprl ?
1522 nGrpprl++;
1523 sal_uInt16 nLen(0);
1524 *pStr >> nLen;
1525 nLeft -= 2 + nLen;
1526 if( nLeft < 0 )
1527 return NULL; // gone wrong
1528 pStr->SeekRel( nLen ); // ueberlies grpprl
1531 if (!checkSeek(*pStr, nClxPos))
1532 return NULL;
1534 nLeft = nClxLen;
1535 pPieceGrpprls = new sal_uInt8*[nGrpprl + 1];
1536 memset( pPieceGrpprls, 0, ( nGrpprl + 1 ) * sizeof(sal_uInt8 *) );
1537 nPieceGrpprls = nGrpprl;
1538 sal_Int16 nAktGrpprl = 0; // read Grpprls
1539 while( 1 )
1541 sal_uInt8 clxt(2);
1542 *pStr >> clxt;
1543 nLeft--;
1544 if( 2 == clxt) // PLCFfpcd ?
1545 break; // PLCFfpcd found
1546 sal_uInt16 nLen(0);
1547 *pStr >> nLen;
1548 nLeft -= 2 + nLen;
1549 if( nLeft < 0 )
1550 return NULL; // gone wrong
1551 if( 1 == clxt ) // clxtGrpprl ?
1553 sal_uInt8* p = new sal_uInt8[nLen+2]; // allocate
1554 ShortToSVBT16(nLen, p); // trage Laenge ein
1555 if (!checkRead(*pStr, p+2, nLen)) // read grpprl
1557 delete[] p;
1558 return NULL;
1560 pPieceGrpprls[nAktGrpprl++] = p; // trage in Array ein
1562 else
1563 pStr->SeekRel( nLen ); // ueberlies nicht-Grpprl
1565 // lies Piece Table PLCF ein
1566 sal_Int32 nPLCFfLen(0);
1567 if (pWwF->GetFIBVersion() <= ww::eWW2)
1569 sal_Int16 nWordTwoLen(0);
1570 *pStr >> nWordTwoLen;
1571 nPLCFfLen = nWordTwoLen;
1573 else
1574 *pStr >> nPLCFfLen;
1575 OSL_ENSURE( 65536 > nPLCFfLen, "PLCFfpcd above 64 k" );
1576 return new WW8PLCFpcd( pStr, pStr->Tell(), nPLCFfLen, 8 );
1579 void WW8ScannerBase::DeletePieceTable()
1581 if( pPieceGrpprls )
1583 for( sal_uInt8** p = pPieceGrpprls; *p; p++ )
1584 delete[] (*p);
1585 delete[] pPieceGrpprls;
1586 pPieceGrpprls = 0;
1590 WW8ScannerBase::WW8ScannerBase( SvStream* pSt, SvStream* pTblSt,
1591 SvStream* pDataSt, WW8Fib* pWwFib )
1592 : pWw8Fib(pWwFib), pMainFdoa(0), pHdFtFdoa(0), pMainTxbx(0),
1593 pMainTxbxBkd(0), pHdFtTxbx(0), pHdFtTxbxBkd(0), pMagicTables(0),
1594 pSubdocs(0), pExtendedAtrds(0), pPieceGrpprls(0)
1596 pPiecePLCF = OpenPieceTable( pTblSt, pWw8Fib ); // Complex
1597 if( pPiecePLCF )
1599 pPieceIter = new WW8PLCFpcd_Iter( *pPiecePLCF );
1600 pPLCFx_PCD = new WW8PLCFx_PCD(pWwFib->GetFIBVersion(), pPiecePLCF, 0,
1601 IsSevenMinus(pWw8Fib->GetFIBVersion()));
1602 pPLCFx_PCDAttrs = new WW8PLCFx_PCDAttrs(pWwFib->GetFIBVersion(),
1603 pPLCFx_PCD, this);
1605 else
1607 pPieceIter = 0;
1608 pPLCFx_PCD = 0;
1609 pPLCFx_PCDAttrs = 0;
1612 // pChpPLCF and pPapPLCF may NOT be created before pPLCFx_PCD !!
1613 pChpPLCF = new WW8PLCFx_Cp_FKP( pSt, pTblSt, pDataSt, *this, CHP ); // CHPX
1614 pPapPLCF = new WW8PLCFx_Cp_FKP( pSt, pTblSt, pDataSt, *this, PAP ); // PAPX
1616 pSepPLCF = new WW8PLCFx_SEPX( pSt, pTblSt, *pWwFib, 0 ); // SEPX
1618 // Footnotes
1619 pFtnPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->GetFIBVersion(), 0,
1620 pWwFib->fcPlcffndRef, pWwFib->lcbPlcffndRef, pWwFib->fcPlcffndTxt,
1621 pWwFib->lcbPlcffndTxt, 2 );
1622 // Endnotes
1623 pEdnPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->GetFIBVersion(), 0,
1624 pWwFib->fcPlcfendRef, pWwFib->lcbPlcfendRef, pWwFib->fcPlcfendTxt,
1625 pWwFib->lcbPlcfendTxt, 2 );
1626 // Comments
1627 pAndPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->GetFIBVersion(), 0,
1628 pWwFib->fcPlcfandRef, pWwFib->lcbPlcfandRef, pWwFib->fcPlcfandTxt,
1629 pWwFib->lcbPlcfandTxt, IsSevenMinus(pWwFib->GetFIBVersion()) ? 20 : 30);
1631 // Fields Main Text
1632 pFldPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_MAINTEXT);
1633 // Fields Header / Footer
1634 pFldHdFtPLCF= new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_HDFT);
1635 // Fields Footnote
1636 pFldFtnPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_FTN);
1637 // Fields Endnote
1638 pFldEdnPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_EDN);
1639 // Fields Comments
1640 pFldAndPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_AND);
1641 // Fields in Textboxes in Main Text
1642 pFldTxbxPLCF= new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_TXBX);
1643 // Fields in Textboxes in Header / Footer
1644 pFldTxbxHdFtPLCF = new WW8PLCFx_FLD(pTblSt,*pWwFib,MAN_TXBX_HDFT);
1646 // Note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
1647 switch( pWw8Fib->nVersion )
1649 case 6:
1650 case 7:
1651 if( pWwFib->fcPlcfdoaMom && pWwFib->lcbPlcfdoaMom )
1653 pMainFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfdoaMom,
1654 pWwFib->lcbPlcfdoaMom, 6 );
1656 if( pWwFib->fcPlcfdoaHdr && pWwFib->lcbPlcfdoaHdr )
1658 pHdFtFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfdoaHdr,
1659 pWwFib->lcbPlcfdoaHdr, 6 );
1661 break;
1662 case 8:
1663 if( pWwFib->fcPlcfspaMom && pWwFib->lcbPlcfspaMom )
1665 pMainFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfspaMom,
1666 pWwFib->lcbPlcfspaMom, 26 );
1668 if( pWwFib->fcPlcfspaHdr && pWwFib->lcbPlcfspaHdr )
1670 pHdFtFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfspaHdr,
1671 pWwFib->lcbPlcfspaHdr, 26 );
1673 // PLCF for TextBox break-descriptors in the main text
1674 if( pWwFib->fcPlcftxbxBkd && pWwFib->lcbPlcftxbxBkd )
1676 pMainTxbxBkd = new WW8PLCFspecial( pTblSt,
1677 pWwFib->fcPlcftxbxBkd, pWwFib->lcbPlcftxbxBkd, 0);
1679 // PLCF for TextBox break-descriptors in Header/Footer range
1680 if( pWwFib->fcPlcfHdrtxbxBkd && pWwFib->lcbPlcfHdrtxbxBkd )
1682 pHdFtTxbxBkd = new WW8PLCFspecial( pTblSt,
1683 pWwFib->fcPlcfHdrtxbxBkd, pWwFib->lcbPlcfHdrtxbxBkd, 0);
1685 // Sub table cp positions
1686 if (pWwFib->fcPlcfTch && pWwFib->lcbPlcfTch)
1688 pMagicTables = new WW8PLCFspecial( pTblSt,
1689 pWwFib->fcPlcfTch, pWwFib->lcbPlcfTch, 4);
1691 // Sub document cp positions
1692 if (pWwFib->fcPlcfwkb && pWwFib->lcbPlcfwkb)
1694 pSubdocs = new WW8PLCFspecial( pTblSt,
1695 pWwFib->fcPlcfwkb, pWwFib->lcbPlcfwkb, 12);
1697 // Extended ATRD
1698 if (pWwFib->fcAtrdExtra && pWwFib->lcbAtrdExtra)
1700 sal_Size nOldPos = pTblSt->Tell();
1701 if (checkSeek(*pTblSt, pWwFib->fcAtrdExtra) && (pTblSt->remainingSize() >= pWwFib->lcbAtrdExtra))
1703 pExtendedAtrds = new sal_uInt8[pWwFib->lcbAtrdExtra];
1704 pWwFib->lcbAtrdExtra = pTblSt->Read(pExtendedAtrds, pWwFib->lcbAtrdExtra);
1706 else
1707 pWwFib->lcbAtrdExtra = 0;
1708 pTblSt->Seek(nOldPos);
1711 break;
1712 default:
1713 OSL_ENSURE( !this, "Es wurde vergessen, nVersion zu kodieren!" );
1714 break;
1717 // PLCF for TextBox stories in main text
1718 sal_uInt32 nLenTxBxS = (8 > pWw8Fib->nVersion) ? 0 : 22;
1719 if( pWwFib->fcPlcftxbxTxt && pWwFib->lcbPlcftxbxTxt )
1721 pMainTxbx = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcftxbxTxt,
1722 pWwFib->lcbPlcftxbxTxt, nLenTxBxS );
1725 // PLCF for TextBox stories in Header/Footer range
1726 if( pWwFib->fcPlcfHdrtxbxTxt && pWwFib->lcbPlcfHdrtxbxTxt )
1728 pHdFtTxbx = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfHdrtxbxTxt,
1729 pWwFib->lcbPlcfHdrtxbxTxt, nLenTxBxS );
1732 pBook = new WW8PLCFx_Book(pTblSt, *pWwFib);
1735 WW8ScannerBase::~WW8ScannerBase()
1737 DeletePieceTable();
1738 delete pPLCFx_PCDAttrs;
1739 delete pPLCFx_PCD;
1740 delete pPieceIter;
1741 delete pPiecePLCF;
1742 delete pBook;
1743 delete pFldEdnPLCF;
1744 delete pFldFtnPLCF;
1745 delete pFldAndPLCF;
1746 delete pFldHdFtPLCF;
1747 delete pFldPLCF;
1748 delete pFldTxbxPLCF;
1749 delete pFldTxbxHdFtPLCF;
1750 delete pEdnPLCF;
1751 delete pFtnPLCF;
1752 delete pAndPLCF;
1753 delete pSepPLCF;
1754 delete pPapPLCF;
1755 delete pChpPLCF;
1756 // vergessene Schaeflein
1757 delete pMainFdoa;
1758 delete pHdFtFdoa;
1759 delete pMainTxbx;
1760 delete pMainTxbxBkd;
1761 delete pHdFtTxbx;
1762 delete pHdFtTxbxBkd;
1763 delete pMagicTables;
1764 delete pSubdocs;
1765 delete [] pExtendedAtrds;
1768 // Fields
1770 static bool WW8SkipField(WW8PLCFspecial& rPLCF)
1772 void* pData;
1773 WW8_CP nP;
1775 if (!rPLCF.Get(nP, pData)) // End of PLCFspecial?
1776 return false;
1778 rPLCF.advance();
1780 if((((sal_uInt8*)pData)[0] & 0x1f ) != 0x13 ) // No beginning?
1781 return true; // Do not terminate on error
1783 if( !rPLCF.Get( nP, pData ) )
1784 return false;
1787 while((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13 )
1789 // still new (nested) beginnings ?
1790 WW8SkipField( rPLCF ); // nested Field in description
1791 if( !rPLCF.Get( nP, pData ) )
1792 return false;
1795 if((((sal_uInt8*)pData)[0] & 0x1f ) == 0x14 )
1798 // Field Separator ?
1799 rPLCF.advance();
1801 if( !rPLCF.Get( nP, pData ) )
1802 return false;
1804 while ((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13)
1806 // still new (nested) beginnings?
1807 WW8SkipField( rPLCF ); // nested Field in Results
1808 if( !rPLCF.Get( nP, pData ) )
1809 return false;
1812 rPLCF.advance();
1814 return true;
1817 static bool WW8GetFieldPara(WW8PLCFspecial& rPLCF, WW8FieldDesc& rF)
1819 void* pData;
1820 sal_uLong nOldIdx = rPLCF.GetIdx();
1822 rF.nLen = rF.nId = rF.nOpt = rF.bCodeNest = rF.bResNest = 0;
1824 if( !rPLCF.Get( rF.nSCode, pData ) ) // end of PLCFspecial?
1825 goto Err;
1827 rPLCF.advance();
1829 if((((sal_uInt8*)pData)[0] & 0x1f ) != 0x13 ) // No beginning?
1830 goto Err;
1832 rF.nId = ((sal_uInt8*)pData)[1];
1834 if( !rPLCF.Get( rF.nLCode, pData ) )
1835 goto Err;
1837 rF.nSRes = rF.nLCode; // Default
1838 rF.nSCode++; // without markers
1839 rF.nLCode -= rF.nSCode; // Pos -> length
1841 while((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13 )
1843 // still new (nested) beginnings ?
1844 WW8SkipField( rPLCF ); // nested Field in description
1845 rF.bCodeNest = true;
1846 if( !rPLCF.Get( rF.nSRes, pData ) )
1847 goto Err;
1850 if ((((sal_uInt8*)pData)[0] & 0x1f ) == 0x14 ) // Field Separator?
1852 rPLCF.advance();
1854 if( !rPLCF.Get( rF.nLRes, pData ) )
1855 goto Err;
1857 while((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13 )
1859 // still new (nested) beginnings ?
1860 WW8SkipField( rPLCF ); // nested Field in results
1861 rF.bResNest = true;
1862 if( !rPLCF.Get( rF.nLRes, pData ) )
1863 goto Err;
1865 rF.nLen = rF.nLRes - rF.nSCode + 2; // nLRes is still the final position
1866 rF.nLRes -= rF.nSRes; // now: nLRes = length
1867 rF.nSRes++; // Endpos encluding Markers
1868 rF.nLRes--;
1869 }else{
1870 rF.nLRes = 0; // no result found
1871 rF.nLen = rF.nSRes - rF.nSCode + 2; // total length
1874 rPLCF.advance();
1875 if((((sal_uInt8*)pData)[0] & 0x1f ) == 0x15 )
1877 // Field end ?
1878 // INDEX-Fld has set Bit7?
1879 rF.nOpt = ((sal_uInt8*)pData)[1]; // yes -> copy flags
1880 }else{
1881 rF.nId = 0; // no -> Field invalid
1884 rPLCF.SetIdx( nOldIdx );
1885 return true;
1886 Err:
1887 rPLCF.SetIdx( nOldIdx );
1888 return false;
1891 String read_uInt8_BeltAndBracesString(SvStream& rStrm, rtl_TextEncoding eEnc)
1893 OUString aRet = read_lenPrefixed_uInt8s_ToOUString<sal_uInt8>(rStrm, eEnc);
1894 rStrm.SeekRel(sizeof(sal_uInt8)); // skip null-byte at end
1895 return aRet;
1898 String read_uInt16_BeltAndBracesString(SvStream& rStrm)
1900 String aRet = read_uInt16_PascalString(rStrm);
1901 rStrm.SeekRel(sizeof(sal_Unicode)); // skip null-byte at end
1902 return aRet;
1905 xub_StrLen WW8ScannerBase::WW8ReadString( SvStream& rStrm, String& rStr,
1906 WW8_CP nAktStartCp, long nTotalLen, rtl_TextEncoding eEnc ) const
1908 // Read in plain text, which can extend over several pieces
1909 rStr.Erase();
1911 long nTotalRead = 0;
1912 WW8_CP nBehindTextCp = nAktStartCp + nTotalLen;
1913 WW8_CP nNextPieceCp = nBehindTextCp; // Initialization, important for Ver6
1916 bool bIsUnicode, bPosOk;
1917 WW8_FC fcAct = WW8Cp2Fc(nAktStartCp,&bIsUnicode,&nNextPieceCp,&bPosOk);
1919 // Probably aimed beyond file end, doesn't matter!
1920 if( !bPosOk )
1921 break;
1923 rStrm.Seek( fcAct );
1925 long nLen = ( (nNextPieceCp < nBehindTextCp) ? nNextPieceCp
1926 : nBehindTextCp ) - nAktStartCp;
1928 if( 0 >= nLen )
1929 break;
1931 if( nLen > USHRT_MAX - 1 )
1932 nLen = USHRT_MAX - 1;
1934 if( bIsUnicode )
1935 rStr.Append(String(read_uInt16s_ToOUString(rStrm, nLen)));
1936 else
1937 rStr.Append(String(read_uInt8s_ToOUString(rStrm, nLen, eEnc)));
1938 nTotalRead += nLen;
1939 nAktStartCp += nLen;
1940 if ( nTotalRead != rStr.Len() )
1941 break;
1943 while( nTotalRead < nTotalLen );
1945 return rStr.Len();
1948 WW8PLCFspecial::WW8PLCFspecial(SvStream* pSt, sal_uInt32 nFilePos,
1949 sal_uInt32 nPLCF, sal_uInt32 nStruct)
1950 : nIdx(0), nStru(nStruct)
1952 const sal_uInt32 nValidMin=4;
1954 sal_Size nOldPos = pSt->Tell();
1956 bool bValid = checkSeek(*pSt, nFilePos);
1957 sal_Size nRemainingSize = pSt->remainingSize();
1958 if( !(nRemainingSize >= nValidMin && nPLCF >= nValidMin ))
1959 bValid = false;
1960 nPLCF = bValid ? std::min(nRemainingSize, static_cast<sal_Size>(nPLCF)) : nValidMin;
1962 // Pointer to Pos- and Struct-array
1963 pPLCF_PosArray = new sal_Int32[ ( nPLCF + 3 ) / 4 ];
1964 pPLCF_PosArray[0] = 0;
1966 nPLCF = bValid ? pSt->Read(pPLCF_PosArray, nPLCF) : nValidMin;
1968 nPLCF = std::max(nPLCF, nValidMin);
1970 nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
1971 #ifdef OSL_BIGENDIAN
1972 for( nIdx = 0; nIdx <= nIMax; nIdx++ )
1973 pPLCF_PosArray[nIdx] = OSL_SWAPDWORD( pPLCF_PosArray[nIdx] );
1974 nIdx = 0;
1975 #endif // OSL_BIGENDIAN
1976 if( nStruct ) // Pointer to content array
1977 pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
1978 else
1979 pPLCF_Contents = 0; // no content
1981 pSt->Seek(nOldPos);
1984 // WW8PLCFspecial::SeekPos() sets WW8PLCFspecial to position nPos, while also the entry is used
1985 // that begins before nPos and ends after nPos.
1986 // Suitable for normal attributes. However, the beginning of the attribute is not corrected onto
1987 // the position nPos.
1988 bool WW8PLCFspecial::SeekPos(long nP)
1990 if( nP < pPLCF_PosArray[0] )
1992 nIdx = 0;
1993 return false; // Not found: nP less than smallest entry
1996 // Search from beginning?
1997 if( (1 > nIdx) || (nP < pPLCF_PosArray[ nIdx-1 ]) )
1998 nIdx = 1;
2000 long nI = nIdx ? nIdx : 1;
2001 long nEnd = nIMax;
2003 for(int n = (1==nIdx ? 1 : 2); n; --n )
2005 for( ; nI <=nEnd; ++nI)
2006 { // search with an index that is incremented by 1
2007 if( nP < pPLCF_PosArray[nI] )
2008 { // found position
2009 nIdx = nI - 1; // nI - 1 is the correct index
2010 return true; // done
2013 nI = 1;
2014 nEnd = nIdx-1;
2016 nIdx = nIMax; // not found, greater than all entries
2017 return false;
2020 // WW8PLCFspecial::SeekPosExact() like SeekPos(), but it is ensured that no attribute is cut,
2021 // i.e. the next given attribute begins at or after nPos.
2022 // Is used for fields and bookmarks.
2023 bool WW8PLCFspecial::SeekPosExact(long nP)
2025 if( nP < pPLCF_PosArray[0] )
2027 nIdx = 0;
2028 return false; // Not found: nP less than smallest entry
2030 // Search from beginning?
2031 if( nP <=pPLCF_PosArray[nIdx] )
2032 nIdx = 0;
2034 long nI = nIdx ? nIdx-1 : 0;
2035 long nEnd = nIMax;
2037 for(int n = (0==nIdx ? 1 : 2); n; --n )
2039 for( ; nI < nEnd; ++nI)
2041 if( nP <=pPLCF_PosArray[nI] )
2042 { // found position
2043 nIdx = nI; // nI is the correct index
2044 return true; // done
2047 nI = 0;
2048 nEnd = nIdx;
2050 nIdx = nIMax; // Not found, greater than all entries
2051 return false;
2054 bool WW8PLCFspecial::Get(WW8_CP& rPos, void*& rpValue) const
2056 return GetData( nIdx, rPos, rpValue );
2059 bool WW8PLCFspecial::GetData(long nInIdx, WW8_CP& rPos, void*& rpValue) const
2061 if ( nInIdx >= nIMax )
2063 rPos = WW8_CP_MAX;
2064 return false;
2066 rPos = pPLCF_PosArray[nInIdx];
2067 rpValue = pPLCF_Contents ? (void*)&pPLCF_Contents[nInIdx * nStru] : 0;
2068 return true;
2071 // WW8PLCF e.g. for SEPX
2072 // Ctor for *others* than Fkps
2073 // With nStartPos < 0, the first element of PLCFs will be taken
2074 WW8PLCF::WW8PLCF(SvStream& rSt, WW8_FC nFilePos, sal_Int32 nPLCF, int nStruct,
2075 WW8_CP nStartPos) : pPLCF_PosArray(0), nIdx(0), nStru(nStruct)
2077 OSL_ENSURE( nPLCF, "WW8PLCF: nPLCF is zero!" );
2079 nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
2081 ReadPLCF(rSt, nFilePos, nPLCF);
2083 if( nStartPos >= 0 )
2084 SeekPos( nStartPos );
2087 // Ctor *only* for Fkps
2088 // The last 2 parameters are needed for PLCF.Chpx and PLCF.Papx.
2089 // If ncpN != 0, then an incomple PLCF will be completed. This is always required for WW6 with
2090 // lack of resources and for WordPad (W95).
2091 // With nStartPos < 0, the first element of the PLCFs is taken.
2092 WW8PLCF::WW8PLCF(SvStream& rSt, WW8_FC nFilePos, sal_Int32 nPLCF, int nStruct,
2093 WW8_CP nStartPos, sal_Int32 nPN, sal_Int32 ncpN): pPLCF_PosArray(0), nIdx(0),
2094 nStru(nStruct)
2096 nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
2098 if( nIMax >= ncpN )
2099 ReadPLCF(rSt, nFilePos, nPLCF);
2100 else
2101 GeneratePLCF(rSt, nPN, ncpN);
2103 if( nStartPos >= 0 )
2104 SeekPos( nStartPos );
2107 void WW8PLCF::ReadPLCF(SvStream& rSt, WW8_FC nFilePos, sal_uInt32 nPLCF)
2109 sal_Size nOldPos = rSt.Tell();
2110 bool bValid = checkSeek(rSt, nFilePos) && (rSt.remainingSize() >= nPLCF);
2112 if (bValid)
2114 // Pointer to Pos-array
2115 pPLCF_PosArray = new WW8_CP[ ( nPLCF + 3 ) / 4 ];
2116 bValid = checkRead(rSt, pPLCF_PosArray, nPLCF);
2119 if (bValid)
2121 #ifdef OSL_BIGENDIAN
2122 for( nIdx = 0; nIdx <= nIMax; nIdx++ )
2123 pPLCF_PosArray[nIdx] = OSL_SWAPDWORD( pPLCF_PosArray[nIdx] );
2124 nIdx = 0;
2125 #endif // OSL_BIGENDIAN
2126 // Pointer to content array
2127 pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
2130 OSL_ENSURE(bValid, "Document has corrupt PLCF, ignoring it");
2132 if (!bValid)
2133 MakeFailedPLCF();
2135 rSt.Seek(nOldPos);
2138 void WW8PLCF::MakeFailedPLCF()
2140 nIMax = 0;
2141 delete[] pPLCF_PosArray;
2142 pPLCF_PosArray = new sal_Int32[2];
2143 pPLCF_PosArray[0] = pPLCF_PosArray[1] = WW8_CP_MAX;
2144 pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
2147 void WW8PLCF::GeneratePLCF(SvStream& rSt, sal_Int32 nPN, sal_Int32 ncpN)
2149 OSL_ENSURE( nIMax < ncpN, "Pcl.Fkp: Why is PLCF too big?" );
2151 bool failure = false;
2152 nIMax = ncpN;
2154 if ((nIMax < 1) || (nIMax > (WW8_CP_MAX - 4)/6) || ((nPN + ncpN) > USHRT_MAX))
2155 failure = true;
2157 if (!failure)
2159 size_t nSiz = 6 * nIMax + 4;
2160 size_t nElems = ( nSiz + 3 ) / 4;
2161 pPLCF_PosArray = new sal_Int32[ nElems ]; // Pointer to Pos-array
2163 for (sal_Int32 i = 0; i < ncpN && !failure; ++i)
2165 failure = true;
2166 // construct FC entries
2167 // first FC entry of each Fkp
2168 if (checkSeek(rSt, ( nPN + i ) << 9 ))
2169 continue;
2170 WW8_CP nFc(0);
2171 rSt >> nFc;
2172 pPLCF_PosArray[i] = nFc;
2173 failure = rSt.GetError();
2177 if (!failure)
2181 failure = true;
2183 sal_Size nLastFkpPos = ( ( nPN + nIMax - 1 ) << 9 );
2184 // Anz. Fkp-Eintraege des letzten Fkp
2185 if (!checkSeek(rSt, nLastFkpPos + 511))
2186 break;
2188 sal_uInt8 nb(0);
2189 rSt >> nb;
2190 // letzer FC-Eintrag des letzten Fkp
2191 if (!checkSeek(rSt, nLastFkpPos + nb * 4))
2192 break;
2194 WW8_CP nFc(0);
2195 rSt >> nFc;
2196 pPLCF_PosArray[nIMax] = nFc; // end of the last Fkp
2198 failure = rSt.GetError();
2199 } while(0);
2202 if (!failure)
2204 // Pointer to content array
2205 pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
2206 sal_uInt8* p = pPLCF_Contents;
2208 for (sal_Int32 i = 0; i < ncpN; ++i) // construct PNs
2210 ShortToSVBT16(static_cast<sal_uInt16>(nPN + i), p);
2211 p+=2;
2215 OSL_ENSURE( !failure, "Document has corrupt PLCF, ignoring it" );
2217 if (failure)
2218 MakeFailedPLCF();
2221 bool WW8PLCF::SeekPos(WW8_CP nPos)
2223 WW8_CP nP = nPos;
2225 if( nP < pPLCF_PosArray[0] )
2227 nIdx = 0;
2228 // not found: nPos less than smallest entry
2229 return false;
2232 // Search from beginning?
2233 if( (1 > nIdx) || (nP < pPLCF_PosArray[ nIdx-1 ]) )
2234 nIdx = 1;
2236 sal_Int32 nI = nIdx ? nIdx : 1;
2237 sal_Int32 nEnd = nIMax;
2239 for(int n = (1==nIdx ? 1 : 2); n; --n )
2241 for( ; nI <=nEnd; ++nI) // search with an index that is incremented by 1
2243 if( nP < pPLCF_PosArray[nI] ) // found position
2245 nIdx = nI - 1; // nI - 1 is the correct index
2246 return true; // done
2249 nI = 1;
2250 nEnd = nIdx-1;
2253 nIdx = nIMax; // not found, greater than all entries
2254 return false;
2257 bool WW8PLCF::Get(WW8_CP& rStart, WW8_CP& rEnd, void*& rpValue) const
2259 if ( nIdx >= nIMax )
2261 rStart = rEnd = WW8_CP_MAX;
2262 return false;
2264 rStart = pPLCF_PosArray[ nIdx ];
2265 rEnd = pPLCF_PosArray[ nIdx + 1 ];
2266 rpValue = (void*)&pPLCF_Contents[nIdx * nStru];
2267 return true;
2270 WW8_CP WW8PLCF::Where() const
2272 if ( nIdx >= nIMax )
2273 return WW8_CP_MAX;
2275 return pPLCF_PosArray[nIdx];
2278 WW8PLCFpcd::WW8PLCFpcd(SvStream* pSt, sal_uInt32 nFilePos,
2279 sal_uInt32 nPLCF, sal_uInt32 nStruct)
2280 : nStru( nStruct )
2282 const sal_uInt32 nValidMin=4;
2284 sal_Size nOldPos = pSt->Tell();
2286 bool bValid = checkSeek(*pSt, nFilePos);
2287 sal_Size nRemainingSize = pSt->remainingSize();
2288 if( !(nRemainingSize >= nValidMin && nPLCF >= nValidMin ))
2289 bValid = false;
2290 nPLCF = bValid ? std::min(nRemainingSize, static_cast<sal_Size>(nPLCF)) : nValidMin;
2292 pPLCF_PosArray = new sal_Int32[ ( nPLCF + 3 ) / 4 ]; // Pointer to Pos-array
2293 pPLCF_PosArray[0] = 0;
2295 nPLCF = bValid ? pSt->Read(pPLCF_PosArray, nPLCF) : nValidMin;
2296 nPLCF = std::max(nPLCF, nValidMin);
2298 nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
2299 #ifdef OSL_BIGENDIAN
2300 for( long nI = 0; nI <= nIMax; nI++ )
2301 pPLCF_PosArray[nI] = OSL_SWAPDWORD( pPLCF_PosArray[nI] );
2302 #endif // OSL_BIGENDIAN
2304 // Pointer to content array
2305 pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
2307 pSt->Seek( nOldPos );
2310 // If nStartPos < 0, the first element of PLCFs will be taken
2311 WW8PLCFpcd_Iter::WW8PLCFpcd_Iter( WW8PLCFpcd& rPLCFpcd, long nStartPos )
2312 :rPLCF( rPLCFpcd ), nIdx( 0 )
2314 if( nStartPos >= 0 )
2315 SeekPos( nStartPos );
2318 bool WW8PLCFpcd_Iter::SeekPos(long nPos)
2320 long nP = nPos;
2322 if( nP < rPLCF.pPLCF_PosArray[0] )
2324 nIdx = 0;
2325 return false; // not found: nPos less than smallest entry
2327 // Search from beginning?
2328 if( (1 > nIdx) || (nP < rPLCF.pPLCF_PosArray[ nIdx-1 ]) )
2329 nIdx = 1;
2331 long nI = nIdx ? nIdx : 1;
2332 long nEnd = rPLCF.nIMax;
2334 for(int n = (1==nIdx ? 1 : 2); n; --n )
2336 for( ; nI <=nEnd; ++nI)
2337 { // search with an index that is incremented by 1
2338 if( nP < rPLCF.pPLCF_PosArray[nI] )
2339 { // found position
2340 nIdx = nI - 1; // nI - 1 is the correct index
2341 return true; // done
2344 nI = 1;
2345 nEnd = nIdx-1;
2347 nIdx = rPLCF.nIMax; // not found, greater than all entries
2348 return false;
2351 bool WW8PLCFpcd_Iter::Get(WW8_CP& rStart, WW8_CP& rEnd, void*& rpValue) const
2353 if( nIdx >= rPLCF.nIMax )
2355 rStart = rEnd = WW8_CP_MAX;
2356 return false;
2358 rStart = rPLCF.pPLCF_PosArray[nIdx];
2359 rEnd = rPLCF.pPLCF_PosArray[nIdx + 1];
2360 rpValue = (void*)&rPLCF.pPLCF_Contents[nIdx * rPLCF.nStru];
2361 return true;
2364 sal_Int32 WW8PLCFpcd_Iter::Where() const
2366 if ( nIdx >= rPLCF.nIMax )
2367 return SAL_MAX_INT32;
2369 return rPLCF.pPLCF_PosArray[nIdx];
2373 bool WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator<
2374 (const WW8PLCFx_Fc_FKP::WW8Fkp::Entry& rSecond) const
2376 return (mnFC < rSecond.mnFC);
2379 bool IsReplaceAllSprm(sal_uInt16 nSpId)
2381 return (0x6645 == nSpId || 0x6646 == nSpId);
2384 bool IsExpandableSprm(sal_uInt16 nSpId)
2386 return 0x646B == nSpId;
2389 void WW8PLCFx_Fc_FKP::WW8Fkp::FillEntry(WW8PLCFx_Fc_FKP::WW8Fkp::Entry &rEntry,
2390 sal_Size nDataOffset, sal_uInt16 nLen)
2392 bool bValidPos = (nDataOffset < sizeof(maRawData));
2394 OSL_ENSURE(bValidPos, "sprm sequence offset is out of range, ignoring");
2396 if (!bValidPos)
2398 rEntry.mnLen = 0;
2399 return;
2402 sal_uInt16 nAvailableData = sizeof(maRawData)-nDataOffset;
2403 OSL_ENSURE(nLen <= nAvailableData, "srpm sequence len is out of range, clipping");
2404 rEntry.mnLen = std::min(nLen, nAvailableData);
2405 rEntry.mpData = maRawData + nDataOffset;
2408 WW8PLCFx_Fc_FKP::WW8Fkp::WW8Fkp(ww::WordVersion eVersion, SvStream* pSt,
2409 SvStream* pDataSt, long _nFilePos, long nItemSiz, ePLCFT ePl,
2410 WW8_FC nStartFc)
2411 : nItemSize(nItemSiz), nFilePos(_nFilePos), mnIdx(0), ePLCF(ePl),
2412 maSprmParser(eVersion)
2414 memset(maRawData, 0, 512);
2416 sal_Size nOldPos = pSt->Tell();
2418 bool bCouldSeek = checkSeek(*pSt, nFilePos);
2419 bool bCouldRead = bCouldSeek ? checkRead(*pSt, maRawData, 512) : false;
2421 mnIMax = bCouldRead ? maRawData[511] : 0;
2423 sal_uInt8 *pStart = maRawData;
2424 // Offset-Location in maRawData
2425 const size_t nRawDataStart = (mnIMax + 1) * 4;
2427 for (mnIdx = 0; mnIdx < mnIMax; ++mnIdx)
2429 const size_t nRawDataOffset = nRawDataStart + mnIdx * nItemSize;
2431 //clip to available data, corrupt fkp
2432 if (nRawDataOffset >= 511)
2434 mnIMax = mnIdx;
2435 break;
2438 unsigned int nOfs = maRawData[nRawDataOffset] * 2;
2440 //clip to available data, corrupt fkp
2441 if (nOfs >= 511)
2443 mnIMax = mnIdx;
2444 break;
2447 Entry aEntry(Get_Long(pStart));
2449 if (nOfs)
2451 switch (ePLCF)
2453 case CHP:
2455 aEntry.mnLen = maRawData[nOfs];
2457 //len byte
2458 sal_Size nDataOffset = nOfs + 1;
2460 FillEntry(aEntry, nDataOffset, aEntry.mnLen);
2462 if (aEntry.mnLen && eVersion == ww::eWW2)
2464 Word2CHPX aChpx = ReadWord2Chpx(*pSt, nFilePos + nOfs + 1, static_cast< sal_uInt8 >(aEntry.mnLen));
2465 std::vector<sal_uInt8> aSprms = ChpxToSprms(aChpx);
2466 aEntry.mnLen = static_cast< sal_uInt16 >(aSprms.size());
2467 if (aEntry.mnLen)
2469 aEntry.mpData = new sal_uInt8[aEntry.mnLen];
2470 memcpy(aEntry.mpData, &(aSprms[0]), aEntry.mnLen);
2471 aEntry.mbMustDelete = true;
2474 break;
2476 case PAP:
2478 sal_uInt8 nDelta = 0;
2480 aEntry.mnLen = maRawData[nOfs];
2481 if (IsEightPlus(eVersion) && !aEntry.mnLen)
2483 aEntry.mnLen = maRawData[nOfs+1];
2484 nDelta++;
2486 aEntry.mnLen *= 2;
2488 //stylecode, std/istd
2489 if (eVersion == ww::eWW2)
2491 if (aEntry.mnLen >= 1)
2493 aEntry.mnIStd = *(maRawData+nOfs+1+nDelta);
2494 aEntry.mnLen--; //style code
2495 if (aEntry.mnLen >= 6)
2497 aEntry.mnLen-=6; //PHE
2498 //skipi stc, len byte + 6 byte PHE
2499 unsigned int nOffset = nOfs + 8;
2500 if (nOffset >= 511) //Bad offset
2501 aEntry.mnLen=0;
2502 if (aEntry.mnLen) //start is ok
2504 if (nOffset + aEntry.mnLen > 512) //Bad end, clip
2505 aEntry.mnLen = 512 - nOffset;
2506 aEntry.mpData = maRawData + nOffset;
2509 else
2510 aEntry.mnLen=0; //Too short
2513 else
2515 if (aEntry.mnLen >= 2)
2517 //len byte + optional extra len byte
2518 sal_Size nDataOffset = nOfs + 1 + nDelta;
2519 aEntry.mnIStd = nDataOffset <= sizeof(maRawData)-sizeof(aEntry.mnIStd) ?
2520 SVBT16ToShort(maRawData+nDataOffset) : 0;
2521 aEntry.mnLen-=2; //istd
2522 if (aEntry.mnLen)
2524 //additional istd
2525 nDataOffset += sizeof(aEntry.mnIStd);
2527 FillEntry(aEntry, nDataOffset, aEntry.mnLen);
2530 else
2531 aEntry.mnLen=0; //Too short, ignore
2534 sal_uInt16 nSpId = aEntry.mnLen ? maSprmParser.GetSprmId(aEntry.mpData) : 0;
2537 If we replace then we throw away the old data, if we
2538 are expanding, then we tack the old data onto the end
2539 of the new data
2541 bool bExpand = IsExpandableSprm(nSpId);
2542 if (IsReplaceAllSprm(nSpId) || bExpand)
2544 sal_uInt32 nCurr = pDataSt->Tell();
2545 sal_uInt32 nPos = SVBT32ToUInt32(aEntry.mpData + 2);
2546 if (checkSeek(*pDataSt, nPos))
2548 sal_uInt16 nOrigLen = bExpand ? aEntry.mnLen : 0;
2549 sal_uInt8 *pOrigData = bExpand ? aEntry.mpData : 0;
2551 *pDataSt >> aEntry.mnLen;
2552 aEntry.mpData =
2553 new sal_uInt8[aEntry.mnLen + nOrigLen];
2554 aEntry.mbMustDelete = true;
2555 aEntry.mnLen =
2556 pDataSt->Read(aEntry.mpData, aEntry.mnLen);
2558 pDataSt->Seek( nCurr );
2560 if (pOrigData)
2562 memcpy(aEntry.mpData + aEntry.mnLen,
2563 pOrigData, nOrigLen);
2564 aEntry.mnLen = aEntry.mnLen + nOrigLen;
2569 break;
2570 default:
2571 OSL_FAIL("sweet god, what have you done!");
2572 break;
2576 maEntries.push_back(aEntry);
2578 #ifdef DEBUGSPRMREADER
2580 sal_Int32 nLen;
2581 sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
2583 WW8SprmIter aIter(pSprms, nLen, maSprmParser);
2584 while (aIter.GetSprms())
2586 fprintf(stderr, "id is %x\n", aIter.GetAktId());
2587 aIter.advance();
2590 #endif
2593 //one more FC than grrpl entries
2594 maEntries.push_back(Entry(Get_Long(pStart)));
2596 //we expect them sorted, but it appears possible for them to arive unsorted
2597 std::sort(maEntries.begin(), maEntries.end());
2599 mnIdx = 0;
2601 if (nStartFc >= 0)
2602 SeekPos(nStartFc);
2604 pSt->Seek(nOldPos);
2607 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::Entry(const Entry &rEntry)
2608 : mnFC(rEntry.mnFC), mnLen(rEntry.mnLen), mnIStd(rEntry.mnIStd),
2609 mbMustDelete(rEntry.mbMustDelete)
2611 if (mbMustDelete)
2613 mpData = new sal_uInt8[mnLen];
2614 memcpy(mpData, rEntry.mpData, mnLen);
2616 else
2617 mpData = rEntry.mpData;
2620 WW8PLCFx_Fc_FKP::WW8Fkp::Entry&
2621 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator=(const Entry &rEntry)
2623 if (this == &rEntry)
2624 return *this;
2626 if (mbMustDelete)
2627 delete[] mpData;
2629 mnFC = rEntry.mnFC;
2630 mnLen = rEntry.mnLen;
2631 mnIStd = rEntry.mnIStd;
2632 mbMustDelete = rEntry.mbMustDelete;
2634 if (mbMustDelete)
2636 mpData = new sal_uInt8[mnLen];
2637 memcpy(mpData, rEntry.mpData, mnLen);
2639 else
2640 mpData = rEntry.mpData;
2641 return *this;
2644 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::~Entry()
2646 if (mbMustDelete)
2647 delete[] mpData;
2650 void WW8PLCFx_Fc_FKP::WW8Fkp::Reset(WW8_FC nFc)
2652 SetIdx(0);
2653 if (nFc >= 0)
2654 SeekPos(nFc);
2657 bool WW8PLCFx_Fc_FKP::WW8Fkp::SeekPos(WW8_FC nFc)
2659 if (nFc < maEntries[0].mnFC)
2661 mnIdx = 0;
2662 return false; // not found: nPos less than smallest entry
2665 // Search from beginning?
2666 if ((1 > mnIdx) || (nFc < maEntries[mnIdx-1].mnFC))
2667 mnIdx = 1;
2669 sal_uInt8 nI = mnIdx ? mnIdx : 1;
2670 sal_uInt8 nEnd = mnIMax;
2672 for(sal_uInt8 n = (1==mnIdx ? 1 : 2); n; --n )
2674 for( ; nI <=nEnd; ++nI)
2675 { // search with an index that is incremented by 1
2676 if (nFc < maEntries[nI].mnFC)
2677 { // found position
2678 mnIdx = nI - 1; // nI - 1 is the correct index
2679 return true; // done
2682 nI = 1;
2683 nEnd = mnIdx-1;
2685 mnIdx = mnIMax; // not found, greater than all entries
2686 return false;
2689 sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::Get(WW8_FC& rStart, WW8_FC& rEnd, sal_Int32& rLen)
2690 const
2692 rLen = 0;
2694 if (mnIdx >= mnIMax)
2696 rStart = WW8_FC_MAX;
2697 return 0;
2700 rStart = maEntries[mnIdx].mnFC;
2701 rEnd = maEntries[mnIdx + 1].mnFC;
2703 sal_uInt8* pSprms = GetLenAndIStdAndSprms( rLen );
2704 return pSprms;
2707 bool WW8PLCFx_Fc_FKP::WW8Fkp::SetIdx(sal_uInt8 nI)
2709 if (nI < mnIMax)
2711 mnIdx = nI;
2712 return true;
2714 return false;
2717 sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::GetLenAndIStdAndSprms(sal_Int32& rLen) const
2719 rLen = maEntries[mnIdx].mnLen;
2720 return maEntries[mnIdx].mpData;
2723 const sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm( sal_uInt16 nId )
2725 if (mnIdx >= mnIMax)
2726 return 0;
2728 sal_Int32 nLen;
2729 sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
2731 WW8SprmIter aIter(pSprms, nLen, maSprmParser);
2732 return aIter.FindSprm(nId);
2735 bool WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm(sal_uInt16 nId,
2736 std::vector<const sal_uInt8 *> &rResult)
2738 if (mnIdx >= mnIMax)
2739 return false;
2741 sal_Int32 nLen;
2742 sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
2744 WW8SprmIter aIter(pSprms, nLen, maSprmParser);
2746 while(aIter.GetSprms())
2748 if (aIter.GetAktId() == nId)
2749 rResult.push_back(aIter.GetAktParams());
2750 aIter.advance();
2752 return !rResult.empty();
2756 void WW8PLCFx::GetSprms( WW8PLCFxDesc* p )
2758 OSL_ENSURE( !this, "Called wrong GetSprms" );
2759 p->nStartPos = p->nEndPos = WW8_CP_MAX;
2760 p->pMemPos = 0;
2761 p->nSprmsLen = 0;
2762 p->bRealLineEnd = false;
2763 return;
2766 long WW8PLCFx::GetNoSprms( WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen )
2768 OSL_ENSURE( !this, "Called wrong GetNoSprms" );
2769 rStart = rEnd = WW8_CP_MAX;
2770 rLen = 0;
2771 return 0;
2774 // ...Idx2: Default: ignore
2775 sal_uLong WW8PLCFx::GetIdx2() const
2777 return 0;
2780 void WW8PLCFx::SetIdx2(sal_uLong )
2784 class SamePos :
2785 public std::unary_function<const WW8PLCFx_Fc_FKP::WW8Fkp *, bool>
2787 private:
2788 long mnPo;
2789 public:
2790 SamePos(long nPo) : mnPo(nPo) {}
2791 bool operator()(const WW8PLCFx_Fc_FKP::WW8Fkp *pFkp)
2792 {return mnPo == pFkp->GetFilePos();}
2796 bool WW8PLCFx_Fc_FKP::NewFkp()
2798 WW8_CP nPLCFStart, nPLCFEnd;
2799 void* pPage;
2801 static const int WW8FkpSizeTabVer2[ PLCF_END ] =
2803 1, 1, 0 /*, 0, 0, 0*/
2805 static const int WW8FkpSizeTabVer6[ PLCF_END ] =
2807 1, 7, 0 /*, 0, 0, 0*/
2809 static const int WW8FkpSizeTabVer8[ PLCF_END ] =
2811 1, 13, 0 /*, 0, 0, 0*/
2813 const int* pFkpSizeTab;
2815 switch (GetFIBVersion())
2817 case ww::eWW2:
2818 pFkpSizeTab = WW8FkpSizeTabVer2;
2819 break;
2820 case ww::eWW6:
2821 case ww::eWW7:
2822 pFkpSizeTab = WW8FkpSizeTabVer6;
2823 break;
2824 case ww::eWW8:
2825 pFkpSizeTab = WW8FkpSizeTabVer8;
2826 break;
2827 default:
2828 // program error!
2829 OSL_ENSURE( !this, "Someone forgot to encode nVersion!" );
2830 return false;
2833 if (!pPLCF->Get( nPLCFStart, nPLCFEnd, pPage ))
2835 pFkp = 0;
2836 return false; // PLCF completely processed
2838 pPLCF->advance();
2839 long nPo = SVBT16ToShort( (sal_uInt8 *)pPage );
2840 nPo <<= 9; // shift as LONG
2842 long nAktFkpFilePos = pFkp ? pFkp->GetFilePos() : -1;
2843 if (nAktFkpFilePos == nPo)
2844 pFkp->Reset(GetStartFc());
2845 else
2847 myiter aIter =
2848 std::find_if(maFkpCache.begin(), maFkpCache.end(), SamePos(nPo));
2849 if (aIter != maFkpCache.end())
2851 pFkp = *aIter;
2852 pFkp->Reset(GetStartFc());
2854 else if (0 != (pFkp = new WW8Fkp(GetFIBVersion(), pFKPStrm, pDataStrm, nPo,
2855 pFkpSizeTab[ ePLCF ], ePLCF, GetStartFc())))
2857 maFkpCache.push_back(pFkp);
2859 if (maFkpCache.size() > eMaxCache)
2861 delete maFkpCache.front();
2862 maFkpCache.pop_front();
2867 SetStartFc( -1 ); // only the first time
2868 return true;
2871 WW8PLCFx_Fc_FKP::WW8PLCFx_Fc_FKP(SvStream* pSt, SvStream* pTblSt,
2872 SvStream* pDataSt, const WW8Fib& rFib, ePLCFT ePl, WW8_FC nStartFcL)
2873 : WW8PLCFx(rFib.GetFIBVersion(), true), pFKPStrm(pSt), pDataStrm(pDataSt),
2874 pFkp(0), ePLCF(ePl), pPCDAttrs(0)
2876 SetStartFc(nStartFcL);
2877 long nLenStruct = (8 > rFib.nVersion) ? 2 : 4;
2878 if (ePl == CHP)
2880 pPLCF = new WW8PLCF(*pTblSt, rFib.fcPlcfbteChpx, rFib.lcbPlcfbteChpx,
2881 nLenStruct, GetStartFc(), rFib.pnChpFirst, rFib.cpnBteChp);
2883 else
2885 pPLCF = new WW8PLCF(*pTblSt, rFib.fcPlcfbtePapx, rFib.lcbPlcfbtePapx,
2886 nLenStruct, GetStartFc(), rFib.pnPapFirst, rFib.cpnBtePap);
2890 WW8PLCFx_Fc_FKP::~WW8PLCFx_Fc_FKP()
2892 myiter aEnd = maFkpCache.end();
2893 for (myiter aIter = maFkpCache.begin(); aIter != aEnd; ++aIter)
2894 delete *aIter;
2895 delete pPLCF;
2896 delete pPCDAttrs;
2899 sal_uLong WW8PLCFx_Fc_FKP::GetIdx() const
2901 sal_uLong u = pPLCF->GetIdx() << 8;
2902 if (pFkp)
2903 u |= pFkp->GetIdx();
2904 return u;
2907 void WW8PLCFx_Fc_FKP::SetIdx( sal_uLong nIdx )
2909 if( !( nIdx & 0xffffff00L ) )
2911 pPLCF->SetIdx( nIdx >> 8 );
2912 pFkp = 0;
2914 else
2915 { // there was a Fkp
2916 // Set PLCF one position back to retrieve the address of the Fkp
2917 pPLCF->SetIdx( ( nIdx >> 8 ) - 1 );
2918 if (NewFkp()) // read Fkp again
2920 sal_uInt8 nFkpIdx = static_cast<sal_uInt8>(nIdx & 0xff);
2921 pFkp->SetIdx(nFkpIdx); // set Fkp-Pos again
2926 bool WW8PLCFx_Fc_FKP::SeekPos(WW8_FC nFcPos)
2928 // StartPos for next Where()
2929 SetStartFc( nFcPos );
2931 // find StartPos for next pPLCF->Get()
2932 bool bRet = pPLCF->SeekPos(nFcPos);
2934 // make FKP invalid?
2935 WW8_CP nPLCFStart, nPLCFEnd;
2936 void* pPage;
2937 if( pFkp && pPLCF->Get( nPLCFStart, nPLCFEnd, pPage ) )
2939 long nPo = SVBT16ToShort( (sal_uInt8 *)pPage );
2940 nPo <<= 9; // shift as LONG
2941 if (nPo != pFkp->GetFilePos())
2942 pFkp = 0;
2943 else
2944 pFkp->SeekPos( nFcPos );
2946 return bRet;
2949 WW8_FC WW8PLCFx_Fc_FKP::Where()
2951 if( !pFkp )
2953 if( !NewFkp() )
2954 return WW8_FC_MAX;
2956 WW8_FC nP = pFkp->Where();
2957 if( nP != WW8_FC_MAX )
2958 return nP;
2960 pFkp = 0; // FKP finished -> get new
2961 return Where(); // easiest way: do it recursively
2964 sal_uInt8* WW8PLCFx_Fc_FKP::GetSprmsAndPos(WW8_FC& rStart, WW8_FC& rEnd, sal_Int32& rLen)
2966 rLen = 0; // Default
2967 rStart = rEnd = WW8_FC_MAX;
2969 if( !pFkp ) // Fkp not there ?
2971 if( !NewFkp() )
2972 return 0;
2975 sal_uInt8* pPos = pFkp->Get( rStart, rEnd, rLen );
2976 if( rStart == WW8_FC_MAX ) //Not found
2977 return 0;
2978 return pPos;
2981 void WW8PLCFx_Fc_FKP::advance()
2983 if( !pFkp )
2985 if( !NewFkp() )
2986 return;
2989 pFkp->advance();
2990 if( pFkp->Where() == WW8_FC_MAX )
2991 NewFkp();
2994 sal_uInt16 WW8PLCFx_Fc_FKP::GetIstd() const
2996 return pFkp ? pFkp->GetIstd() : 0xFFFF;
2999 void WW8PLCFx_Fc_FKP::GetPCDSprms( WW8PLCFxDesc& rDesc )
3001 rDesc.pMemPos = 0;
3002 rDesc.nSprmsLen = 0;
3003 if( pPCDAttrs )
3005 if( !pFkp )
3007 OSL_FAIL("+Problem: GetPCDSprms: NewFkp necessary (not possible!)" );
3008 if( !NewFkp() )
3009 return;
3011 pPCDAttrs->GetSprms(&rDesc);
3015 const sal_uInt8* WW8PLCFx_Fc_FKP::HasSprm( sal_uInt16 nId )
3017 // const would be nicer, but for that, NewFkp() would need to be replaced or eliminated
3018 if( !pFkp )
3020 OSL_FAIL( "+Motz: HasSprm: NewFkp needed ( no const possible )" );
3021 // happens in BugDoc 31722
3022 if( !NewFkp() )
3023 return 0;
3026 const sal_uInt8* pRes = pFkp->HasSprm( nId );
3028 if( !pRes )
3030 WW8PLCFxDesc aDesc;
3031 GetPCDSprms( aDesc );
3033 if (aDesc.pMemPos)
3035 WW8SprmIter aIter(aDesc.pMemPos, aDesc.nSprmsLen,
3036 pFkp->GetSprmParser());
3037 pRes = aIter.FindSprm(nId);
3041 return pRes;
3044 bool WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId, std::vector<const sal_uInt8 *> &rResult)
3046 // const would be nicer, but for that, NewFkp() would need to be replaced or eliminated
3047 if (!pFkp)
3049 OSL_FAIL( "+Motz: HasSprm: NewFkp needed ( no const possible )" );
3050 // happens in BugDoc 31722
3051 if( !NewFkp() )
3052 return 0;
3055 pFkp->HasSprm(nId, rResult);
3057 WW8PLCFxDesc aDesc;
3058 GetPCDSprms( aDesc );
3060 if (aDesc.pMemPos)
3062 WW8SprmIter aIter(aDesc.pMemPos, aDesc.nSprmsLen,
3063 pFkp->GetSprmParser());
3064 while(aIter.GetSprms())
3066 if (aIter.GetAktId() == nId)
3067 rResult.push_back(aIter.GetAktParams());
3068 aIter.advance();
3071 return !rResult.empty();
3074 WW8PLCFx_Cp_FKP::WW8PLCFx_Cp_FKP( SvStream* pSt, SvStream* pTblSt,
3075 SvStream* pDataSt, const WW8ScannerBase& rBase, ePLCFT ePl )
3076 : WW8PLCFx_Fc_FKP(pSt, pTblSt, pDataSt, *rBase.pWw8Fib, ePl,
3077 rBase.WW8Cp2Fc(0)), rSBase(rBase), nAttrStart(-1), nAttrEnd(-1),
3078 bLineEnd(false),
3079 bComplex( (7 < rBase.pWw8Fib->nVersion) || (0 != rBase.pWw8Fib->fComplex) )
3081 ResetAttrStartEnd();
3083 pPcd = rSBase.pPiecePLCF ? new WW8PLCFx_PCD(GetFIBVersion(),
3084 rBase.pPiecePLCF, 0, IsSevenMinus(GetFIBVersion())) : 0;
3087 Make a copy of the piece attributes for so that the calls to HasSprm on a
3088 Fc_FKP will be able to take into account the current piece attributes,
3089 despite the fact that such attributes can only be found through a cp based
3090 mechanism.
3092 if (pPcd)
3094 pPCDAttrs = rSBase.pPLCFx_PCDAttrs ? new WW8PLCFx_PCDAttrs(
3095 rSBase.pWw8Fib->GetFIBVersion(), pPcd, &rSBase) : 0;
3098 pPieceIter = rSBase.pPieceIter;
3101 WW8PLCFx_Cp_FKP::~WW8PLCFx_Cp_FKP()
3103 delete pPcd;
3106 void WW8PLCFx_Cp_FKP::ResetAttrStartEnd()
3108 nAttrStart = -1;
3109 nAttrEnd = -1;
3110 bLineEnd = false;
3113 sal_uLong WW8PLCFx_Cp_FKP::GetPCDIMax() const
3115 return pPcd ? pPcd->GetIMax() : 0;
3118 sal_uLong WW8PLCFx_Cp_FKP::GetPCDIdx() const
3120 return pPcd ? pPcd->GetIdx() : 0;
3123 void WW8PLCFx_Cp_FKP::SetPCDIdx( sal_uLong nIdx )
3125 if( pPcd )
3126 pPcd->SetIdx( nIdx );
3129 bool WW8PLCFx_Cp_FKP::SeekPos(WW8_CP nCpPos)
3131 if( pPcd ) // Complex
3133 if( !pPcd->SeekPos( nCpPos ) ) // set piece
3134 return false;
3135 if (pPCDAttrs && !pPCDAttrs->GetIter()->SeekPos(nCpPos))
3136 return false;
3137 return WW8PLCFx_Fc_FKP::SeekPos(pPcd->AktPieceStartCp2Fc(nCpPos));
3139 // NO piece table !!!
3140 return WW8PLCFx_Fc_FKP::SeekPos( rSBase.WW8Cp2Fc(nCpPos) );
3143 WW8_CP WW8PLCFx_Cp_FKP::Where()
3145 WW8_FC nFc = WW8PLCFx_Fc_FKP::Where();
3146 if( pPcd )
3147 return pPcd->AktPieceStartFc2Cp( nFc ); // identify piece
3148 return rSBase.WW8Fc2Cp( nFc ); // NO piece table !!!
3151 void WW8PLCFx_Cp_FKP::GetSprms(WW8PLCFxDesc* p)
3153 WW8_CP nOrigCp = p->nStartPos;
3155 if (!GetDirty()) //Normal case
3157 p->pMemPos = WW8PLCFx_Fc_FKP::GetSprmsAndPos(p->nStartPos, p->nEndPos,
3158 p->nSprmsLen);
3160 else
3163 For the odd case where we have a location in a fastsaved file which
3164 does not have an entry in the FKP, perhaps its para end is in the next
3165 piece, or perhaps the cp just doesn't exist at all in this document.
3166 AdvSprm doesn't know so it sets the PLCF as dirty and we figure out
3167 in this method what the situation is
3169 It doesn't exist then the piece iterator will not be able to find it.
3170 Otherwise our cool fastsave algorithm can be brought to bear on the
3171 problem.
3173 if( !pPieceIter )
3174 return;
3175 sal_uLong nOldPos = pPieceIter->GetIdx();
3176 bool bOk = pPieceIter->SeekPos(nOrigCp);
3177 pPieceIter->SetIdx( nOldPos );
3178 if (!bOk)
3179 return;
3182 if( pPcd ) // piece table available
3184 // Init ( no ++ called, yet )
3185 if( (nAttrStart > nAttrEnd) || (nAttrStart == -1) )
3187 p->bRealLineEnd = (ePLCF == PAP);
3189 if ( ((ePLCF == PAP ) || (ePLCF == CHP)) && (nOrigCp != WW8_CP_MAX) )
3191 bool bIsUnicode=false;
3193 To find the end of a paragraph for a character in a
3194 complex format file.
3196 It is necessary to know the piece that contains the
3197 character and the FC assigned to the character.
3200 //We set the piece iterator to the piece that contains the
3201 //character, now we have the correct piece for this character
3202 sal_uLong nOldPos = pPieceIter->GetIdx();
3203 p->nStartPos = nOrigCp;
3204 pPieceIter->SeekPos( p->nStartPos);
3206 //This is the FC assigned to the character, but we already
3207 //have the result of the next stage, so we can skip this step
3208 //WW8_FC nStartFc = rSBase.WW8Cp2Fc(p->nStartPos, &bIsUnicode);
3211 Using the FC of the character, first search the FKP that
3212 describes the character to find the smallest FC in the rgfc
3213 that is larger than the character FC.
3215 //But the search has already been done, the next largest FC is
3216 //p->nEndPos.
3217 WW8_FC nOldEndPos = p->nEndPos;
3220 If the FC found in the FKP is less than or equal to the limit
3221 FC of the piece, the end of the paragraph that contains the
3222 character is at the FKP FC minus 1.
3224 WW8_CP nCpStart, nCpEnd;
3225 void* pData=NULL;
3226 pPieceIter->Get(nCpStart, nCpEnd, pData);
3228 WW8_FC nLimitFC = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
3229 WW8_FC nBeginLimitFC = nLimitFC;
3230 if (IsEightPlus(GetFIBVersion()))
3232 nBeginLimitFC =
3233 WW8PLCFx_PCD::TransformPieceAddress(nLimitFC,
3234 bIsUnicode);
3237 nLimitFC = nBeginLimitFC +
3238 (nCpEnd - nCpStart) * (bIsUnicode ? 2 : 1);
3240 if (nOldEndPos <= nLimitFC)
3242 p->nEndPos = nCpEnd -
3243 (nLimitFC-nOldEndPos) / (bIsUnicode ? 2 : 1);
3245 else
3247 if (ePLCF == CHP)
3248 p->nEndPos = nCpEnd;
3249 else
3252 If the FKP FC that was found was greater than the FC
3253 of the end of the piece, scan piece by piece toward
3254 the end of the document until a piece is found that
3255 contains a paragraph end mark.
3259 It's possible to check if a piece contains a paragraph
3260 mark by using the FC of the beginning of the piece to
3261 search in the FKPs for the smallest FC in the FKP rgfc
3262 that is greater than the FC of the beginning of the
3263 piece. If the FC found is less than or equal to the
3264 limit FC of the piece, then the character that ends
3265 the paragraph is the character immediately before the
3266 FKP fc
3269 pPieceIter->advance();
3271 for (;pPieceIter->GetIdx() < pPieceIter->GetIMax();
3272 pPieceIter->advance())
3274 if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) )
3276 OSL_ENSURE( !this, "piece iter broken!" );
3277 break;
3279 bIsUnicode = false;
3280 sal_Int32 nFcStart=SVBT32ToUInt32(((WW8_PCD*)pData)->fc);
3282 if (IsEightPlus(GetFIBVersion()))
3284 nFcStart =
3285 WW8PLCFx_PCD::TransformPieceAddress(
3286 nFcStart,bIsUnicode );
3289 nLimitFC = nFcStart + (nCpEnd - nCpStart) *
3290 (bIsUnicode ? 2 : 1);
3292 //if it doesn't exist, skip it
3293 if (!SeekPos(nCpStart))
3294 continue;
3296 WW8_FC nOne,nSmallest;
3297 p->pMemPos = WW8PLCFx_Fc_FKP::GetSprmsAndPos(nOne,
3298 nSmallest, p->nSprmsLen);
3300 if (nSmallest <= nLimitFC)
3302 WW8_CP nEndPos = nCpEnd -
3303 (nLimitFC-nSmallest) / (bIsUnicode ? 2 : 1);
3305 OSL_ENSURE(nEndPos >= p->nStartPos, "EndPos before StartPos");
3307 if (nEndPos >= p->nStartPos)
3308 p->nEndPos = nEndPos;
3310 break;
3315 pPieceIter->SetIdx( nOldPos );
3317 else
3318 pPcd->AktPieceFc2Cp( p->nStartPos, p->nEndPos,&rSBase );
3320 else
3322 p->nStartPos = nAttrStart;
3323 p->nEndPos = nAttrEnd;
3324 p->bRealLineEnd = bLineEnd;
3327 else // NO piece table !!!
3329 p->nStartPos = rSBase.WW8Fc2Cp( p->nStartPos );
3330 p->nEndPos = rSBase.WW8Fc2Cp( p->nEndPos );
3331 p->bRealLineEnd = ePLCF == PAP;
3335 void WW8PLCFx_Cp_FKP::advance()
3337 WW8PLCFx_Fc_FKP::advance();
3338 // !pPcd: emergency break
3339 if ( !bComplex || !pPcd )
3340 return;
3342 if( GetPCDIdx() >= GetPCDIMax() ) // End of PLCF
3344 nAttrStart = nAttrEnd = WW8_CP_MAX;
3345 return;
3348 sal_Int32 nFkpLen; // Fkp entry
3349 // get Fkp entry
3350 WW8PLCFx_Fc_FKP::GetSprmsAndPos(nAttrStart, nAttrEnd, nFkpLen);
3352 pPcd->AktPieceFc2Cp( nAttrStart, nAttrEnd, &rSBase );
3353 bLineEnd = (ePLCF == PAP);
3356 WW8PLCFx_SEPX::WW8PLCFx_SEPX(SvStream* pSt, SvStream* pTblSt,
3357 const WW8Fib& rFib, WW8_CP nStartCp)
3358 : WW8PLCFx(rFib.GetFIBVersion(), true), maSprmParser(rFib.GetFIBVersion()),
3359 pStrm(pSt), nArrMax(256), nSprmSiz(0)
3361 pPLCF = rFib.lcbPlcfsed
3362 ? new WW8PLCF(*pTblSt, rFib.fcPlcfsed, rFib.lcbPlcfsed,
3363 GetFIBVersion() <= ww::eWW2 ? 6 : 12, nStartCp)
3364 : 0;
3366 pSprms = new sal_uInt8[nArrMax]; // maximum length
3369 WW8PLCFx_SEPX::~WW8PLCFx_SEPX()
3371 delete pPLCF;
3372 delete[] pSprms;
3375 sal_uLong WW8PLCFx_SEPX::GetIdx() const
3377 return pPLCF ? pPLCF->GetIdx() : 0;
3380 void WW8PLCFx_SEPX::SetIdx( sal_uLong nIdx )
3382 if( pPLCF ) pPLCF->SetIdx( nIdx );
3385 bool WW8PLCFx_SEPX::SeekPos(WW8_CP nCpPos)
3387 return pPLCF ? pPLCF->SeekPos( nCpPos ) : 0;
3390 WW8_CP WW8PLCFx_SEPX::Where()
3392 return pPLCF ? pPLCF->Where() : 0;
3395 void WW8PLCFx_SEPX::GetSprms(WW8PLCFxDesc* p)
3397 if( !pPLCF ) return;
3399 void* pData;
3401 p->bRealLineEnd = false;
3402 if (!pPLCF->Get( p->nStartPos, p->nEndPos, pData ))
3404 p->nStartPos = p->nEndPos = WW8_CP_MAX; // PLCF completely processed
3405 p->pMemPos = 0;
3406 p->nSprmsLen = 0;
3408 else
3410 sal_uInt32 nPo = SVBT32ToUInt32( (sal_uInt8*)pData+2 );
3411 if (nPo == 0xFFFFFFFF)
3413 p->nStartPos = p->nEndPos = WW8_CP_MAX; // Sepx empty
3414 p->pMemPos = 0;
3415 p->nSprmsLen = 0;
3417 else
3419 pStrm->Seek( nPo );
3421 // read len
3422 if (GetFIBVersion() <= ww::eWW2) // eWW6 ?, docs say yes, but...
3424 sal_uInt8 nSiz(0);
3425 *pStrm >> nSiz;
3426 nSprmSiz = nSiz;
3428 else
3429 *pStrm >> nSprmSiz;
3431 if( nSprmSiz > nArrMax )
3432 { // does not fit
3433 delete[] pSprms;
3434 nArrMax = nSprmSiz; // Get more memory
3435 pSprms = new sal_uInt8[nArrMax];
3437 nSprmSiz = pStrm->Read(pSprms, nSprmSiz); // read Sprms
3439 p->nSprmsLen = nSprmSiz;
3440 p->pMemPos = pSprms; // return Position
3445 void WW8PLCFx_SEPX::advance()
3447 if (pPLCF)
3448 pPLCF->advance();
3451 const sal_uInt8* WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId ) const
3453 return HasSprm( nId, pSprms, nSprmSiz);
3456 const sal_uInt8* WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId, const sal_uInt8* pOtherSprms,
3457 long nOtherSprmSiz ) const
3459 const sal_uInt8 *pRet = 0;
3460 if (pPLCF)
3462 WW8SprmIter aIter(pOtherSprms, nOtherSprmSiz, maSprmParser);
3463 pRet = aIter.FindSprm(nId);
3465 return pRet;
3468 bool WW8PLCFx_SEPX::Find4Sprms(sal_uInt16 nId1,sal_uInt16 nId2,sal_uInt16 nId3,sal_uInt16 nId4,
3469 sal_uInt8*& p1, sal_uInt8*& p2, sal_uInt8*& p3, sal_uInt8*& p4) const
3471 if( !pPLCF )
3472 return 0;
3474 bool bFound = false;
3475 p1 = 0;
3476 p2 = 0;
3477 p3 = 0;
3478 p4 = 0;
3480 sal_uInt8* pSp = pSprms;
3481 sal_uInt16 i=0;
3482 while (i + maSprmParser.MinSprmLen() <= nSprmSiz)
3484 // Sprm found?
3485 sal_uInt16 nAktId = maSprmParser.GetSprmId(pSp);
3486 bool bOk = true;
3487 if( nAktId == nId1 )
3488 p1 = pSp + maSprmParser.DistanceToData(nId1);
3489 else if( nAktId == nId2 )
3490 p2 = pSp + maSprmParser.DistanceToData(nId2);
3491 else if( nAktId == nId3 )
3492 p3 = pSp + maSprmParser.DistanceToData(nId3);
3493 else if( nAktId == nId4 )
3494 p4 = pSp + maSprmParser.DistanceToData(nId4);
3495 else
3496 bOk = false;
3497 bFound |= bOk;
3498 // increment pointer so that it points to next SPRM
3499 sal_uInt16 x = maSprmParser.GetSprmSize(nAktId, pSp);
3500 i = i + x;
3501 pSp += x;
3503 return bFound;
3506 const sal_uInt8* WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId, sal_uInt8 n2nd ) const
3508 if( !pPLCF )
3509 return 0;
3511 sal_uInt8* pSp = pSprms;
3513 sal_uInt16 i=0;
3514 while (i + maSprmParser.MinSprmLen() <= nSprmSiz)
3516 // Sprm found?
3517 sal_uInt16 nAktId = maSprmParser.GetSprmId(pSp);
3518 if (nAktId == nId)
3520 sal_uInt8 *pRet = pSp + maSprmParser.DistanceToData(nId);
3521 if (*pRet == n2nd)
3522 return pRet;
3524 // increment pointer so that it points to next SPRM
3525 sal_uInt16 x = maSprmParser.GetSprmSize(nAktId, pSp);
3526 i = i + x;
3527 pSp += x;
3530 return 0; // Sprm not found
3534 WW8PLCFx_SubDoc::WW8PLCFx_SubDoc(SvStream* pSt, ww::WordVersion eVersion,
3535 WW8_CP nStartCp, long nFcRef, long nLenRef, long nFcTxt, long nLenTxt,
3536 long nStruct)
3537 : WW8PLCFx(eVersion, true), pRef(0), pTxt(0)
3539 if( nLenRef && nLenTxt )
3541 pRef = new WW8PLCF(*pSt, nFcRef, nLenRef, nStruct, nStartCp);
3542 pTxt = new WW8PLCF(*pSt, nFcTxt, nLenTxt, 0, nStartCp);
3546 WW8PLCFx_SubDoc::~WW8PLCFx_SubDoc()
3548 delete pRef;
3549 delete pTxt;
3552 sal_uLong WW8PLCFx_SubDoc::GetIdx() const
3554 // Probably pTxt ... no need for it
3555 if( pRef )
3556 return ( pRef->GetIdx() << 16 | pTxt->GetIdx() );
3557 return 0;
3560 void WW8PLCFx_SubDoc::SetIdx( sal_uLong nIdx )
3562 if( pRef )
3564 pRef->SetIdx( nIdx >> 16 );
3565 // Probably pTxt ... no need for it
3566 pTxt->SetIdx( nIdx & 0xFFFF );
3570 bool WW8PLCFx_SubDoc::SeekPos( WW8_CP nCpPos )
3572 return ( pRef ) ? pRef->SeekPos( nCpPos ) : false;
3575 WW8_CP WW8PLCFx_SubDoc::Where()
3577 return ( pRef ) ? pRef->Where() : WW8_CP_MAX;
3580 void WW8PLCFx_SubDoc::GetSprms(WW8PLCFxDesc* p)
3582 p->nStartPos = p->nEndPos = WW8_CP_MAX;
3583 p->pMemPos = 0;
3584 p->nSprmsLen = 0;
3585 p->bRealLineEnd = false;
3587 if (!pRef)
3588 return;
3590 sal_uLong nNr = pRef->GetIdx();
3592 void *pData;
3593 WW8_CP nFoo;
3594 if (!pRef->Get(p->nStartPos, nFoo, pData))
3596 p->nEndPos = p->nStartPos = WW8_CP_MAX;
3597 return;
3600 p->nEndPos = p->nStartPos + 1;
3602 if (!pTxt)
3603 return;
3605 pTxt->SetIdx(nNr);
3607 if (!pTxt->Get(p->nCp2OrIdx, p->nSprmsLen, pData))
3609 p->nEndPos = p->nStartPos = WW8_CP_MAX;
3610 p->nSprmsLen = 0;
3611 return;
3614 p->nSprmsLen -= p->nCp2OrIdx;
3617 void WW8PLCFx_SubDoc::advance()
3619 if (pRef && pTxt)
3621 pRef->advance();
3622 pTxt->advance();
3626 // fields
3627 WW8PLCFx_FLD::WW8PLCFx_FLD( SvStream* pSt, const WW8Fib& rMyFib, short nType)
3628 : WW8PLCFx(rMyFib.GetFIBVersion(), true), pPLCF(0), rFib(rMyFib)
3630 long nFc, nLen;
3632 switch( nType )
3634 case MAN_HDFT:
3635 nFc = rFib.fcPlcffldHdr;
3636 nLen = rFib.lcbPlcffldHdr;
3637 break;
3638 case MAN_FTN:
3639 nFc = rFib.fcPlcffldFtn;
3640 nLen = rFib.lcbPlcffldFtn;
3641 break;
3642 case MAN_EDN:
3643 nFc = rFib.fcPlcffldEdn;
3644 nLen = rFib.lcbPlcffldEdn;
3645 break;
3646 case MAN_AND:
3647 nFc = rFib.fcPlcffldAtn;
3648 nLen = rFib.lcbPlcffldAtn;
3649 break;
3650 case MAN_TXBX:
3651 nFc = rFib.fcPlcffldTxbx;
3652 nLen = rFib.lcbPlcffldTxbx;
3653 break;
3654 case MAN_TXBX_HDFT:
3655 nFc = rFib.fcPlcffldHdrTxbx;
3656 nLen = rFib.lcbPlcffldHdrTxbx;
3657 break;
3658 default:
3659 nFc = rFib.fcPlcffldMom;
3660 nLen = rFib.lcbPlcffldMom;
3661 break;
3664 if( nLen )
3665 pPLCF = new WW8PLCFspecial( pSt, nFc, nLen, 2 );
3668 WW8PLCFx_FLD::~WW8PLCFx_FLD()
3670 delete pPLCF;
3673 sal_uLong WW8PLCFx_FLD::GetIdx() const
3675 return pPLCF ? pPLCF->GetIdx() : 0;
3678 void WW8PLCFx_FLD::SetIdx( sal_uLong nIdx )
3680 if( pPLCF )
3681 pPLCF->SetIdx( nIdx );
3684 bool WW8PLCFx_FLD::SeekPos(WW8_CP nCpPos)
3686 return pPLCF ? pPLCF->SeekPosExact( nCpPos ) : false;
3689 WW8_CP WW8PLCFx_FLD::Where()
3691 return pPLCF ? pPLCF->Where() : WW8_CP_MAX;
3694 bool WW8PLCFx_FLD::StartPosIsFieldStart()
3696 void* pData;
3697 sal_Int32 nTest;
3698 if (
3699 (!pPLCF || !pPLCF->Get(nTest, pData) ||
3700 ((((sal_uInt8*)pData)[0] & 0x1f) != 0x13))
3702 return false;
3703 return true;
3706 bool WW8PLCFx_FLD::EndPosIsFieldEnd()
3708 bool bRet = false;
3710 if (pPLCF)
3712 long n = pPLCF->GetIdx();
3714 pPLCF->advance();
3716 void* pData;
3717 sal_Int32 nTest;
3718 if ( pPLCF->Get(nTest, pData) && ((((sal_uInt8*)pData)[0] & 0x1f) == 0x15) )
3719 bRet = true;
3721 pPLCF->SetIdx(n);
3724 return bRet;
3727 void WW8PLCFx_FLD::GetSprms(WW8PLCFxDesc* p)
3729 p->nStartPos = p->nEndPos = WW8_CP_MAX;
3730 p->pMemPos = 0;
3731 p->nSprmsLen = 0;
3732 p->bRealLineEnd = false;
3734 if (!pPLCF)
3736 p->nStartPos = WW8_CP_MAX; // there are no fields
3737 return;
3740 long n = pPLCF->GetIdx();
3742 sal_Int32 nP;
3743 void *pData;
3744 if (!pPLCF->Get(nP, pData)) // end of PLCFspecial?
3746 p->nStartPos = WW8_CP_MAX; // PLCF completely processed
3747 return;
3750 p->nStartPos = nP;
3752 pPLCF->advance();
3753 if (!pPLCF->Get(nP, pData)) // end of PLCFspecial?
3755 p->nStartPos = WW8_CP_MAX; // PLCF completely processed
3756 return;
3759 p->nEndPos = nP;
3761 pPLCF->SetIdx(n);
3763 p->nCp2OrIdx = pPLCF->GetIdx();
3766 void WW8PLCFx_FLD::advance()
3768 pPLCF->advance();
3771 bool WW8PLCFx_FLD::GetPara(long nIdx, WW8FieldDesc& rF)
3773 OSL_ENSURE( pPLCF, "Call without PLCFspecial field" );
3774 if( !pPLCF )
3775 return false;
3777 long n = pPLCF->GetIdx();
3778 pPLCF->SetIdx(nIdx);
3780 bool bOk = WW8GetFieldPara(*pPLCF, rF);
3782 pPLCF->SetIdx(n);
3783 return bOk;
3786 // WW8PLCF_Book
3788 /* to be optimized like this: */
3789 void WW8ReadSTTBF(bool bVer8, SvStream& rStrm, sal_uInt32 nStart, sal_Int32 nLen,
3790 sal_uInt16 nExtraLen, rtl_TextEncoding eCS, std::vector<String> &rArray,
3791 std::vector<ww::bytes>* pExtraArray, ::std::vector<String>* pValueArray)
3793 if (nLen==0) // Handle Empty STTBF
3794 return;
3796 sal_Size nOldPos = rStrm.Tell();
3797 if (checkSeek(rStrm, nStart))
3799 sal_uInt16 nLen2(0);
3800 rStrm >> nLen2; // bVer67: total length of structure
3801 // bVer8 : count of strings
3803 if( bVer8 )
3805 sal_uInt16 nStrings(0);
3806 bool bUnicode = (0xFFFF == nLen2);
3807 if (bUnicode)
3808 rStrm >> nStrings;
3809 else
3810 nStrings = nLen2;
3812 rStrm >> nExtraLen;
3814 for (sal_uInt16 i=0; i < nStrings; ++i)
3816 if (bUnicode)
3817 rArray.push_back(read_uInt16_PascalString(rStrm));
3818 else
3820 OString aTmp = read_lenPrefixed_uInt8s_ToOString<sal_uInt8>(rStrm);
3821 rArray.push_back(OStringToOUString(aTmp, eCS));
3824 // Skip the extra data
3825 if (nExtraLen)
3827 if (pExtraArray)
3829 ww::bytes extraData;
3830 for (sal_uInt16 j = 0; j < nExtraLen; ++j)
3832 sal_uInt8 iTmp(0);
3833 rStrm >> iTmp;
3834 extraData.push_back(iTmp);
3836 pExtraArray->push_back(extraData);
3838 else
3839 rStrm.SeekRel( nExtraLen );
3842 // read the value of the document variables, if requested.
3843 if (pValueArray)
3845 for (sal_uInt16 i=0; i < nStrings; ++i)
3847 if( bUnicode )
3848 pValueArray->push_back(read_uInt16_PascalString(rStrm));
3849 else
3851 OString aTmp = read_lenPrefixed_uInt8s_ToOString<sal_uInt8>(rStrm);
3852 pValueArray->push_back(OStringToOUString(aTmp, eCS));
3857 else
3859 if( nLen2 != nLen )
3861 OSL_ENSURE(nLen2 == nLen,
3862 "Fib length and read length are different");
3863 if (nLen > USHRT_MAX)
3864 nLen = USHRT_MAX;
3865 else if (nLen < 2 )
3866 nLen = 2;
3867 nLen2 = static_cast<sal_uInt16>(nLen);
3869 sal_uLong nRead = 0;
3870 for( nLen2 -= 2; nRead < nLen2; )
3872 sal_uInt8 nBChar(0);
3873 rStrm >> nBChar;
3874 ++nRead;
3875 if (nBChar)
3877 OString aTmp = read_uInt8s_ToOString(rStrm, nBChar);
3878 nRead += aTmp.getLength();
3879 rArray.push_back(OStringToOUString(aTmp, eCS));
3881 else
3882 rArray.push_back(aEmptyStr);
3884 // Skip the extra data (for bVer67 versions this must come from
3885 // external knowledge)
3886 if (nExtraLen)
3888 if (pExtraArray)
3890 ww::bytes extraData;
3891 for (sal_uInt16 i=0;i < nExtraLen;++i)
3893 sal_uInt8 iTmp(0);
3894 rStrm >> iTmp;
3895 extraData.push_back(iTmp);
3897 pExtraArray->push_back(extraData);
3899 else
3900 rStrm.SeekRel( nExtraLen );
3901 nRead+=nExtraLen;
3906 rStrm.Seek(nOldPos);
3909 WW8PLCFx_Book::WW8PLCFx_Book(SvStream* pTblSt, const WW8Fib& rFib)
3910 : WW8PLCFx(rFib.GetFIBVersion(), false), pStatus(0), nIsEnd(0), nBookmarkId(1)
3912 if( !rFib.fcPlcfbkf || !rFib.lcbPlcfbkf || !rFib.fcPlcfbkl ||
3913 !rFib.lcbPlcfbkl || !rFib.fcSttbfbkmk || !rFib.lcbSttbfbkmk )
3915 pBook[0] = pBook[1] = 0;
3916 nIMax = 0;
3918 else
3920 pBook[0] = new WW8PLCFspecial(pTblSt,rFib.fcPlcfbkf,rFib.lcbPlcfbkf,4);
3922 pBook[1] = new WW8PLCFspecial(pTblSt,rFib.fcPlcfbkl,rFib.lcbPlcfbkl,0);
3924 rtl_TextEncoding eStructChrSet = WW8Fib::GetFIBCharset(rFib.chseTables);
3926 WW8ReadSTTBF( (7 < rFib.nVersion), *pTblSt, rFib.fcSttbfbkmk,
3927 rFib.lcbSttbfbkmk, 0, eStructChrSet, aBookNames );
3929 nIMax = aBookNames.size();
3931 if( pBook[0]->GetIMax() < nIMax ) // Count of Bookmarks
3932 nIMax = pBook[0]->GetIMax();
3933 if( pBook[1]->GetIMax() < nIMax )
3934 nIMax = pBook[1]->GetIMax();
3935 pStatus = new eBookStatus[ nIMax ];
3936 memset( pStatus, 0, nIMax * sizeof( eBookStatus ) );
3940 WW8PLCFx_Book::~WW8PLCFx_Book()
3942 delete[] pStatus;
3943 delete pBook[1];
3944 delete pBook[0];
3947 sal_uLong WW8PLCFx_Book::GetIdx() const
3949 return nIMax ? pBook[0]->GetIdx() : 0;
3952 void WW8PLCFx_Book::SetIdx( sal_uLong nI )
3954 if( nIMax )
3955 pBook[0]->SetIdx( nI );
3958 sal_uLong WW8PLCFx_Book::GetIdx2() const
3960 return nIMax ? ( pBook[1]->GetIdx() | ( ( nIsEnd ) ? 0x80000000 : 0 ) ) : 0;
3963 void WW8PLCFx_Book::SetIdx2( sal_uLong nI )
3965 if( nIMax )
3967 pBook[1]->SetIdx( nI & 0x7fffffff );
3968 nIsEnd = (sal_uInt16)( ( nI >> 31 ) & 1 ); // 0 oder 1
3972 bool WW8PLCFx_Book::SeekPos(WW8_CP nCpPos)
3974 if( !pBook[0] )
3975 return false;
3977 bool bOk = pBook[0]->SeekPosExact( nCpPos );
3978 bOk &= pBook[1]->SeekPosExact( nCpPos );
3979 nIsEnd = 0;
3981 return bOk;
3984 WW8_CP WW8PLCFx_Book::Where()
3986 return pBook[nIsEnd]->Where();
3989 long WW8PLCFx_Book::GetNoSprms( WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen )
3991 void* pData;
3992 rEnd = WW8_CP_MAX;
3993 rLen = 0;
3995 if (!pBook[0] || !pBook[1] || !nIMax || (pBook[nIsEnd]->GetIdx()) >= nIMax)
3997 rStart = rEnd = WW8_CP_MAX;
3998 return -1;
4001 pBook[nIsEnd]->Get( rStart, pData ); // query position
4002 return pBook[nIsEnd]->GetIdx();
4005 // Der Operator ++ hat eine Tuecke: Wenn 2 Bookmarks aneinandergrenzen, dann
4006 // sollte erst das Ende des ersten und dann der Anfang des 2. erreicht werden.
4007 // Liegen jedoch 2 Bookmarks der Laenge 0 aufeinander, *muss* von jedem Bookmark
4008 // erst der Anfang und dann das Ende gefunden werden.
4009 // Der Fall: ][
4010 // [...]
4011 // ][
4012 // ist noch nicht geloest, dabei muesste ich in den Anfangs- und Endindices
4013 // vor- und zurueckspringen, wobei ein weiterer Index oder ein Bitfeld
4014 // oder etwas aehnliches zum Merken der bereits abgearbeiteten Bookmarks
4015 // noetig wird.
4016 void WW8PLCFx_Book::advance()
4018 if( pBook[0] && pBook[1] && nIMax )
4020 (*pBook[nIsEnd]).advance();
4022 sal_uLong l0 = pBook[0]->Where();
4023 sal_uLong l1 = pBook[1]->Where();
4024 if( l0 < l1 )
4025 nIsEnd = 0;
4026 else if( l1 < l0 )
4027 nIsEnd = 1;
4028 else
4029 nIsEnd = ( nIsEnd ) ? 0 : 1;
4033 long WW8PLCFx_Book::GetLen() const
4035 if( nIsEnd )
4037 OSL_ENSURE( !this, "Incorrect call (1) of PLCF_Book::GetLen()" );
4038 return 0;
4040 void * p;
4041 WW8_CP nStartPos;
4042 if( !pBook[0]->Get( nStartPos, p ) )
4044 OSL_ENSURE( !this, "Incorrect call (2) of PLCF_Book::GetLen()" );
4045 return 0;
4047 sal_uInt16 nEndIdx = SVBT16ToShort( *((SVBT16*)p) );
4048 long nNum = pBook[1]->GetPos( nEndIdx );
4049 nNum -= nStartPos;
4050 return nNum;
4053 void WW8PLCFx_Book::SetStatus(sal_uInt16 nIndex, eBookStatus eStat )
4055 OSL_ENSURE(nIndex < nIMax, "set status of non existing bookmark!");
4056 pStatus[nIndex] = (eBookStatus)( pStatus[nIndex] | eStat );
4059 eBookStatus WW8PLCFx_Book::GetStatus() const
4061 if( !pStatus )
4062 return BOOK_NORMAL;
4063 long nEndIdx = GetHandle();
4064 return ( nEndIdx < nIMax ) ? pStatus[nEndIdx] : BOOK_NORMAL;
4067 long WW8PLCFx_Book::GetHandle() const
4069 if( !pBook[0] || !pBook[1] )
4070 return LONG_MAX;
4072 if( nIsEnd )
4073 return pBook[1]->GetIdx();
4074 else
4076 if (const void* p = pBook[0]->GetData(pBook[0]->GetIdx()))
4077 return SVBT16ToShort( *((SVBT16*)p) );
4078 else
4079 return LONG_MAX;
4083 String WW8PLCFx_Book::GetBookmark(long nStart,long nEnd, sal_uInt16 &nIndex)
4085 bool bFound = false;
4086 sal_uInt16 i = 0;
4087 if( pBook[0] && pBook[1] )
4089 WW8_CP nStartAkt, nEndAkt;
4092 void* p;
4093 sal_uInt16 nEndIdx;
4095 if( pBook[0]->GetData( i, nStartAkt, p ) && p )
4096 nEndIdx = SVBT16ToShort( *((SVBT16*)p) );
4097 else
4099 OSL_ENSURE( !this, "Bookmark-EndIdx not readable" );
4100 nEndIdx = i;
4103 nEndAkt = pBook[1]->GetPos( nEndIdx );
4105 if ((nStartAkt >= nStart) && (nEndAkt <= nEnd))
4107 nIndex = i;
4108 bFound=true;
4109 break;
4111 ++i;
4113 while (i < pBook[0]->GetIMax());
4115 return bFound ? aBookNames[i] : aEmptyStr;
4118 OUString WW8PLCFx_Book::GetUniqueBookmarkName(const OUString &rSuggestedName)
4120 OUString aRet(rSuggestedName.isEmpty() ? OUString("Unnamed") : rSuggestedName);
4121 size_t i = 0;
4122 while (i < aBookNames.size())
4124 if (aRet.equals(aBookNames[i]))
4126 sal_Int32 len = aRet.getLength();
4127 sal_Int32 p = len - 1;
4128 while (p > 0 && aRet[p] >= '0' && aRet[p] <= '9')
4129 --p;
4130 aRet = aRet.copy(0, p+1) + OUString::valueOf(nBookmarkId++);
4131 i = 0; // start search from beginning
4133 else
4134 ++i;
4136 return aRet;
4139 bool WW8PLCFx_Book::MapName(String& rName)
4141 if( !pBook[0] || !pBook[1] )
4142 return false;
4144 bool bFound = false;
4145 sal_uInt16 i = 0;
4148 if (COMPARE_EQUAL == rName.CompareIgnoreCaseToAscii(aBookNames[i]))
4150 rName = aBookNames[i];
4151 bFound = true;
4153 ++i;
4155 while (!bFound && i < pBook[0]->GetIMax());
4156 return bFound;
4159 const String* WW8PLCFx_Book::GetName() const
4161 const String *pRet = 0;
4162 if (!nIsEnd && (pBook[0]->GetIdx() < nIMax))
4163 pRet = &(aBookNames[pBook[0]->GetIdx()]);
4164 return pRet;
4167 #ifndef DUMP
4169 // Am Ende eines Absatzes reichen bei WW6 die Attribute bis hinter das <CR>.
4170 // Das wird fuer die Verwendung mit dem SW um 1 Zeichen zurueckgesetzt, wenn
4171 // dadurch kein AErger zu erwarten ist.
4172 void WW8PLCFMan::AdjustEnds( WW8PLCFxDesc& rDesc )
4174 //Store old end position for supercool new property finder that uses
4175 //cp instead of fc's as nature intended
4176 rDesc.nOrigEndPos = rDesc.nEndPos;
4177 rDesc.nOrigStartPos = rDesc.nStartPos;
4180 Normally given ^XXX{para end}^ we don't actually insert a para end
4181 character into the document, so we clip the para end property one to the
4182 left to make the para properties end when the paragraph text does. In a
4183 drawing textbox we actually do insert a para end character, so we don't
4184 clip it. Making the para end properties end after the para end char.
4186 if (GetDoingDrawTextBox())
4187 return;
4189 if ( (&rDesc == pPap) && rDesc.bRealLineEnd )
4191 if ( pPap->nEndPos != WW8_CP_MAX ) // Para adjust
4193 nLineEnd = pPap->nEndPos;// nLineEnd zeigt *hinter* das <CR>
4194 pPap->nEndPos--; // Absatzende um 1 Zeichen verkuerzen
4196 // gibt es bereits ein CharAttr-Ende das auf das jetzige
4197 // Absatzende zeigt ? ... dann auch um 1 Zeichen verkuerzen
4198 if (pChp->nEndPos == nLineEnd)
4199 pChp->nEndPos--;
4201 // gibt es bereits ein Sep-Ende, das auf das jetzige Absatzende
4202 // zeigt ? ... dann auch um 1 Zeichen verkuerzen
4203 if( pSep->nEndPos == nLineEnd )
4204 pSep->nEndPos--;
4207 else if ( (&rDesc == pChp) || (&rDesc == pSep) )
4209 // Char Adjust oder Sep Adjust Wenn Ende Char-Attr == Absatzende ...
4210 if( (rDesc.nEndPos == nLineEnd) && (rDesc.nEndPos > rDesc.nStartPos) )
4211 rDesc.nEndPos--; // ... dann um 1 Zeichen verkuerzen
4215 void WW8PLCFxDesc::ReduceByOffset()
4217 OSL_ENSURE((WW8_CP_MAX == nStartPos) || (nStartPos <= nEndPos),
4218 "Attr-Anfang und -Ende ueber Kreuz" );
4220 if( nStartPos != WW8_CP_MAX )
4223 ##516##,##517##
4224 Force the property change to happen at the beginning of this
4225 subdocument, same as in GetNewNoSprms, except that the target type is
4226 attributes attached to a piece that might span subdocument boundaries
4228 if (nCpOfs > nStartPos)
4229 nStartPos = 0;
4230 else
4231 nStartPos -= nCpOfs;
4233 if( nEndPos != WW8_CP_MAX )
4235 OSL_ENSURE(nCpOfs <= nEndPos,
4236 "oh oh, so much for the subdocument piece theory");
4237 nEndPos -= nCpOfs;
4241 void WW8PLCFMan::GetNewSprms( WW8PLCFxDesc& rDesc )
4243 rDesc.pPLCFx->GetSprms(&rDesc);
4244 rDesc.ReduceByOffset();
4246 rDesc.bFirstSprm = true;
4247 AdjustEnds( rDesc );
4248 rDesc.nOrigSprmsLen = rDesc.nSprmsLen;
4251 void WW8PLCFMan::GetNewNoSprms( WW8PLCFxDesc& rDesc )
4253 rDesc.nCp2OrIdx = rDesc.pPLCFx->GetNoSprms(rDesc.nStartPos, rDesc.nEndPos,
4254 rDesc.nSprmsLen);
4256 OSL_ENSURE((WW8_CP_MAX == rDesc.nStartPos) || (rDesc.nStartPos <= rDesc.nEndPos),
4257 "Attr-Anfang und -Ende ueber Kreuz" );
4259 rDesc.ReduceByOffset();
4261 rDesc.bFirstSprm = true;
4262 rDesc.nOrigSprmsLen = rDesc.nSprmsLen;
4265 sal_uInt16 WW8PLCFMan::GetId(const WW8PLCFxDesc* p) const
4267 sal_uInt16 nId = 0; // Id = 0 for empty attributes
4269 if (p == pFld)
4270 nId = eFLD;
4271 else if (p == pFtn)
4272 nId = eFTN;
4273 else if (p == pEdn)
4274 nId = eEDN;
4275 else if (p == pAnd)
4276 nId = eAND;
4277 else if (p->nSprmsLen >= maSprmParser.MinSprmLen())
4278 nId = maSprmParser.GetSprmId(p->pMemPos);
4280 return nId;
4283 WW8PLCFMan::WW8PLCFMan(WW8ScannerBase* pBase, ManTypes nType, long nStartCp,
4284 bool bDoingDrawTextBox)
4285 : maSprmParser(pBase->pWw8Fib->GetFIBVersion()),
4286 mbDoingDrawTextBox(bDoingDrawTextBox)
4288 pWwFib = pBase->pWw8Fib;
4290 nLastWhereIdxCp = 0;
4291 memset( aD, 0, sizeof( aD ) );
4292 nLineEnd = WW8_CP_MAX;
4293 nManType = nType;
4294 sal_uInt16 i;
4296 if( MAN_MAINTEXT == nType )
4298 // Suchreihenfolge der Attribute
4299 nPLCF = MAN_ANZ_PLCF;
4300 pFld = &aD[0];
4301 pBkm = &aD[1];
4302 pEdn = &aD[2];
4303 pFtn = &aD[3];
4304 pAnd = &aD[4];
4306 pPcd = ( pBase->pPLCFx_PCD ) ? &aD[5] : 0;
4307 //pPcdA index == pPcd index + 1
4308 pPcdA = ( pBase->pPLCFx_PCDAttrs ) ? &aD[6] : 0;
4310 pChp = &aD[7];
4311 pPap = &aD[8];
4312 pSep = &aD[9];
4314 pSep->pPLCFx = pBase->pSepPLCF;
4315 pFtn->pPLCFx = pBase->pFtnPLCF;
4316 pEdn->pPLCFx = pBase->pEdnPLCF;
4317 pBkm->pPLCFx = pBase->pBook;
4318 pAnd->pPLCFx = pBase->pAndPLCF;
4321 else
4323 // Suchreihenfolge der Attribute
4324 nPLCF = 7;
4325 pFld = &aD[0];
4326 pBkm = ( pBase->pBook ) ? &aD[1] : 0;
4328 pPcd = ( pBase->pPLCFx_PCD ) ? &aD[2] : 0;
4329 //pPcdA index == pPcd index + 1
4330 pPcdA= ( pBase->pPLCFx_PCDAttrs ) ? &aD[3] : 0;
4332 pChp = &aD[4];
4333 pPap = &aD[5];
4334 pSep = &aD[6]; // Dummy
4336 pAnd = pFtn = pEdn = 0; // unbenutzt bei SpezText
4339 pChp->pPLCFx = pBase->pChpPLCF;
4340 pPap->pPLCFx = pBase->pPapPLCF;
4341 if( pPcd )
4342 pPcd->pPLCFx = pBase->pPLCFx_PCD;
4343 if( pPcdA )
4344 pPcdA->pPLCFx= pBase->pPLCFx_PCDAttrs;
4345 if( pBkm )
4346 pBkm->pPLCFx = pBase->pBook;
4348 pMagicTables = pBase->pMagicTables;
4349 pSubdocs = pBase->pSubdocs;
4350 pExtendedAtrds = pBase->pExtendedAtrds;
4352 switch( nType ) // Feld-Initialisierung
4354 case MAN_HDFT:
4355 pFld->pPLCFx = pBase->pFldHdFtPLCF;
4356 pFdoa = pBase->pHdFtFdoa;
4357 pTxbx = pBase->pHdFtTxbx;
4358 pTxbxBkd = pBase->pHdFtTxbxBkd;
4359 break;
4360 case MAN_FTN:
4361 pFld->pPLCFx = pBase->pFldFtnPLCF;
4362 pFdoa = pTxbx = pTxbxBkd = 0;
4363 break;
4364 case MAN_EDN:
4365 pFld->pPLCFx = pBase->pFldEdnPLCF;
4366 pFdoa = pTxbx = pTxbxBkd = 0;
4367 break;
4368 case MAN_AND:
4369 pFld->pPLCFx = pBase->pFldAndPLCF;
4370 pFdoa = pTxbx = pTxbxBkd = 0;
4371 break;
4372 case MAN_TXBX:
4373 pFld->pPLCFx = pBase->pFldTxbxPLCF;
4374 pTxbx = pBase->pMainTxbx;
4375 pTxbxBkd = pBase->pMainTxbxBkd;
4376 pFdoa = 0;
4377 break;
4378 case MAN_TXBX_HDFT:
4379 pFld->pPLCFx = pBase->pFldTxbxHdFtPLCF;
4380 pTxbx = pBase->pHdFtTxbx;
4381 pTxbxBkd = pBase->pHdFtTxbxBkd;
4382 pFdoa = 0;
4383 break;
4384 default:
4385 pFld->pPLCFx = pBase->pFldPLCF;
4386 pFdoa = pBase->pMainFdoa;
4387 pTxbx = pBase->pMainTxbx;
4388 pTxbxBkd = pBase->pMainTxbxBkd;
4389 break;
4392 nCpO = pWwFib->GetBaseCp(nType);
4394 if( nStartCp || nCpO )
4395 SeekPos( nStartCp ); // PLCFe auf Text-StartPos einstellen
4397 // initialisieren der Member-Vars Low-Level
4398 GetChpPLCF()->ResetAttrStartEnd();
4399 GetPapPLCF()->ResetAttrStartEnd();
4400 for( i=0; i < nPLCF; i++)
4402 WW8PLCFxDesc* p = &aD[i];
4405 ##516##,##517##
4406 For subdocuments we modify the cp of properties to be relative to
4407 the beginning of subdocuments, we should also do the same for
4408 piecetable changes, and piecetable properties, otherwise a piece
4409 change that happens in a subdocument is lost.
4411 p->nCpOfs = ( p == pChp || p == pPap || p == pBkm || p == pPcd ||
4412 p == pPcdA ) ? nCpO : 0;
4414 p->nCp2OrIdx = 0;
4415 p->bFirstSprm = false;
4416 p->pIdStk = 0;
4418 if ((p == pChp) || (p == pPap))
4419 p->nStartPos = p->nEndPos = nStartCp;
4420 else
4421 p->nStartPos = p->nEndPos = WW8_CP_MAX;
4424 // initialisieren der Member-Vars High-Level
4425 for( i=0; i<nPLCF; i++){
4426 WW8PLCFxDesc* p = &aD[i];
4428 if( !p->pPLCFx )
4430 p->nStartPos = p->nEndPos = WW8_CP_MAX;
4431 continue;
4434 if( p->pPLCFx->IsSprm() )
4436 // Vorsicht: nEndPos muss bereits
4437 p->pIdStk = new std::stack<sal_uInt16>;
4438 if ((p == pChp) || (p == pPap))
4440 WW8_CP nTemp = p->nEndPos+p->nCpOfs;
4441 p->pMemPos = 0;
4442 p->nSprmsLen = 0;
4443 p->nStartPos = nTemp;
4444 if (!(*p->pPLCFx).SeekPos(p->nStartPos))
4445 p->nEndPos = p->nStartPos = WW8_CP_MAX;
4446 else
4447 GetNewSprms( *p );
4449 else
4450 GetNewSprms( *p ); // bei allen PLCFen initialisiert sein
4452 else if( p->pPLCFx )
4453 GetNewNoSprms( *p );
4457 WW8PLCFMan::~WW8PLCFMan()
4459 for( sal_uInt16 i=0; i<nPLCF; i++)
4460 delete aD[i].pIdStk;
4463 // 0. welche Attr.-Klasse,
4464 // 1. ob ein Attr.-Start ist,
4465 // 2. CP, wo ist naechste Attr.-Aenderung
4466 sal_uInt16 WW8PLCFMan::WhereIdx(bool* pbStart, long* pPos) const
4468 OSL_ENSURE(nPLCF,"What the hell");
4469 long nNext = LONG_MAX; // SuchReihenfolge:
4470 sal_uInt16 nNextIdx = nPLCF;// first ending found ( CHP, PAP, ( SEP ) ),
4471 bool bStart = true; // dann Anfaenge finden ( ( SEP ), PAP, CHP )
4472 sal_uInt16 i;
4473 const WW8PLCFxDesc* pD;
4474 for (i=0; i < nPLCF; i++)
4476 pD = &aD[i];
4477 if (pD != pPcdA)
4479 if( (pD->nEndPos < nNext) && (pD->nStartPos == WW8_CP_MAX) )
4481 // sonst ist Anfang = Ende
4482 nNext = pD->nEndPos;
4483 nNextIdx = i;
4484 bStart = false;
4488 for (i=nPLCF; i > 0; i--)
4490 pD = &aD[i-1];
4491 if (pD != pPcdA)
4493 if( pD->nStartPos < nNext )
4495 nNext = pD->nStartPos;
4496 nNextIdx = i-1;
4497 bStart = true;
4501 if( pPos )
4502 *pPos = nNext;
4503 if( pbStart )
4504 *pbStart = bStart;
4505 return nNextIdx;
4508 // gibt die CP-Pos der naechsten Attribut-Aenderung zurueck
4509 WW8_CP WW8PLCFMan::Where() const
4511 long l;
4512 WhereIdx(0, &l);
4513 return l;
4516 void WW8PLCFMan::SeekPos( long nNewCp )
4518 pChp->pPLCFx->SeekPos( nNewCp + nCpO ); // Attribute neu
4519 pPap->pPLCFx->SeekPos( nNewCp + nCpO ); // aufsetzen
4520 pFld->pPLCFx->SeekPos( nNewCp );
4521 if( pPcd )
4522 pPcd->pPLCFx->SeekPos( nNewCp + nCpO );
4523 if( pBkm )
4524 pBkm->pPLCFx->SeekPos( nNewCp + nCpO );
4527 void WW8PLCFMan::SaveAllPLCFx( WW8PLCFxSaveAll& rSave ) const
4529 sal_uInt16 i, n=0;
4530 if( pPcd )
4531 pPcd->Save( rSave.aS[n++] );
4532 if( pPcdA )
4533 pPcdA->Save( rSave.aS[n++] );
4535 for(i=0; i<nPLCF; ++i)
4536 if( pPcd != &aD[i] && pPcdA != &aD[i] )
4537 aD[i].Save( rSave.aS[n++] );
4540 void WW8PLCFMan::RestoreAllPLCFx( const WW8PLCFxSaveAll& rSave )
4542 sal_uInt16 i, n=0;
4543 if( pPcd )
4544 pPcd->Restore( rSave.aS[n++] );
4545 if( pPcdA )
4546 pPcdA->Restore( rSave.aS[n++] );
4548 for(i=0; i<nPLCF; ++i)
4549 if( pPcd != &aD[i] && pPcdA != &aD[i] )
4550 aD[i].Restore( rSave.aS[n++] );
4553 void WW8PLCFMan::GetSprmStart( short nIdx, WW8PLCFManResult* pRes ) const
4555 memset( pRes, 0, sizeof( WW8PLCFManResult ) );
4557 // Pruefen !!!
4559 pRes->nMemLen = 0;
4561 const WW8PLCFxDesc* p = &aD[nIdx];
4563 // first Sprm in a Group
4564 if( p->bFirstSprm )
4566 if( p == pPap )
4567 pRes->nFlags |= MAN_MASK_NEW_PAP;
4568 else if( p == pSep )
4569 pRes->nFlags |= MAN_MASK_NEW_SEP;
4571 pRes->pMemPos = p->pMemPos;
4572 pRes->nSprmId = GetId(p);
4573 pRes->nCp2OrIdx = p->nCp2OrIdx;
4574 if ((p == pFtn) || (p == pEdn) || (p == pAnd))
4575 pRes->nMemLen = p->nSprmsLen;
4576 else if (p->nSprmsLen >= maSprmParser.MinSprmLen()) //Normal
4578 // Length of actual sprm
4579 pRes->nMemLen = maSprmParser.GetSprmSize(pRes->nSprmId, pRes->pMemPos);
4583 void WW8PLCFMan::GetSprmEnd( short nIdx, WW8PLCFManResult* pRes ) const
4585 memset( pRes, 0, sizeof( WW8PLCFManResult ) );
4587 const WW8PLCFxDesc* p = &aD[nIdx];
4589 if (!(p->pIdStk->empty()))
4590 pRes->nSprmId = p->pIdStk->top(); // get end position
4591 else
4593 OSL_ENSURE( !this, "No Id on the Stack" );
4594 pRes->nSprmId = 0;
4598 void WW8PLCFMan::GetNoSprmStart( short nIdx, WW8PLCFManResult* pRes ) const
4600 const WW8PLCFxDesc* p = &aD[nIdx];
4602 pRes->nCpPos = p->nStartPos;
4603 pRes->nMemLen = p->nSprmsLen;
4604 pRes->nCp2OrIdx = p->nCp2OrIdx;
4606 if( p == pFld )
4607 pRes->nSprmId = eFLD;
4608 else if( p == pFtn )
4609 pRes->nSprmId = eFTN;
4610 else if( p == pEdn )
4611 pRes->nSprmId = eEDN;
4612 else if( p == pBkm )
4613 pRes->nSprmId = eBKN;
4614 else if( p == pAnd )
4615 pRes->nSprmId = eAND;
4616 else if( p == pPcd )
4618 //We slave the piece table attributes to the piece table, the piece
4619 //table attribute iterator contains the sprms for this piece.
4620 GetSprmStart( nIdx+1, pRes );
4622 else
4623 pRes->nSprmId = 0; // default: not found
4626 void WW8PLCFMan::GetNoSprmEnd( short nIdx, WW8PLCFManResult* pRes ) const
4628 pRes->nMemLen = -1; // Ende-Kennzeichen
4630 if( &aD[nIdx] == pBkm )
4631 pRes->nSprmId = eBKN;
4632 else if( &aD[nIdx] == pPcd )
4634 //We slave the piece table attributes to the piece table, the piece
4635 //table attribute iterator contains the sprms for this piece.
4636 GetSprmEnd( nIdx+1, pRes );
4638 else
4639 pRes->nSprmId = 0;
4642 bool WW8PLCFMan::TransferOpenSprms(std::stack<sal_uInt16> &rStack)
4644 for (int i = 0; i < nPLCF; ++i)
4646 WW8PLCFxDesc* p = &aD[i];
4647 if (!p || !p->pIdStk)
4648 continue;
4649 while (!p->pIdStk->empty())
4651 rStack.push(p->pIdStk->top());
4652 p->pIdStk->pop();
4655 return rStack.empty();
4658 void WW8PLCFMan::AdvSprm(short nIdx, bool bStart)
4660 WW8PLCFxDesc* p = &aD[nIdx]; // Sprm-Klasse(!) ermitteln
4662 p->bFirstSprm = false;
4663 if( bStart )
4665 sal_uInt16 nLastId = GetId(p);
4666 p->pIdStk->push(nLastId); // merke Id fuer Attribut-Ende
4668 if( p->nSprmsLen )
4669 { /*
4670 Pruefe, ob noch Sprm(s) abzuarbeiten sind
4672 if( p->pMemPos )
4674 // Length of last sprm
4675 sal_uInt16 nSprmL = maSprmParser.GetSprmSize(nLastId, p->pMemPos);
4677 // Gesamtlaenge Sprms um SprmLaenge verringern
4678 p->nSprmsLen -= nSprmL;
4680 // Pos des evtl. naechsten Sprm
4681 if (p->nSprmsLen < maSprmParser.MinSprmLen())
4683 // sicherheitshalber auf Null setzen, da Enden folgen!
4684 p->pMemPos = 0;
4685 p->nSprmsLen = 0;
4687 else
4688 p->pMemPos += nSprmL;
4690 else
4691 p->nSprmsLen = 0;
4693 if (p->nSprmsLen < maSprmParser.MinSprmLen())
4694 p->nStartPos = WW8_CP_MAX; // es folgen Enden
4696 else
4698 if (!(p->pIdStk->empty()))
4699 p->pIdStk->pop();
4700 if (p->pIdStk->empty())
4702 if ( (p == pChp) || (p == pPap) )
4704 p->pMemPos = 0;
4705 p->nSprmsLen = 0;
4706 p->nStartPos = p->nOrigEndPos+p->nCpOfs;
4709 On failed seek we have run out of sprms, probably. But if its
4710 a fastsaved file (has pPcd) then we may be just in a sprm free
4711 gap between pieces that have them, so set dirty flag in sprm
4712 finder to consider than.
4714 if (!(*p->pPLCFx).SeekPos(p->nStartPos))
4716 p->nEndPos = WW8_CP_MAX;
4717 p->pPLCFx->SetDirty(true);
4719 if (!p->pPLCFx->GetDirty() || pPcd)
4720 GetNewSprms( *p );
4721 p->pPLCFx->SetDirty(false);
4724 #i2325#
4725 To get the character and paragraph properties you first get
4726 the pap and chp and then apply the fastsaved pPcd properties
4727 to the range. If a pap or chp starts inside the pPcd range
4728 then we must bring the current pPcd range to a halt so as to
4729 end those sprms, then the pap/chp will be processed, and then
4730 we must force a restart of the pPcd on that pap/chp starting
4731 boundary. Doing that effectively means that the pPcd sprms will
4732 be applied to the new range. Not doing it means that the pPcd
4733 sprms will only be applied to the first pap/chp set of
4734 properties contained in the pap/chp range.
4736 So we bring the pPcd to a halt on this location here, by
4737 settings its end to the current start, then store the starting
4738 position of the current range to clipstart. The pPcd sprms
4739 will end as normal (albeit earlier than originally expected),
4740 and the existance of a clipstart will force the pPcd iterater
4741 to reread the current set of sprms instead of advancing to its
4742 next set. Then the clipstart will be set as the starting
4743 position which will force them to be applied directly after
4744 the pap and chps.
4746 if (pPcd && ((p->nStartPos > pPcd->nStartPos) ||
4747 (pPcd->nStartPos == WW8_CP_MAX)) &&
4748 (pPcd->nEndPos != p->nStartPos))
4750 pPcd->nEndPos = p->nStartPos;
4751 ((WW8PLCFx_PCD *)(pPcd->pPLCFx))->SetClipStart(
4752 p->nStartPos);
4756 else
4758 p->pPLCFx->advance(); // next Group of Sprms
4759 p->pMemPos = 0; // !!!
4760 p->nSprmsLen = 0;
4761 GetNewSprms( *p );
4763 OSL_ENSURE( p->nStartPos <= p->nEndPos, "Attribut ueber Kreuz" );
4768 void WW8PLCFMan::AdvNoSprm(short nIdx, bool bStart)
4771 For the case of a piece table we slave the piece table attribute iterator
4772 to the piece table and access it through that only. They are two separate
4773 structures, but act together as one logical one. The attributes only go
4774 to the next entry when the piece changes
4776 WW8PLCFxDesc* p = &aD[nIdx];
4778 if( p == pPcd )
4780 AdvSprm(nIdx+1,bStart);
4781 if( bStart )
4782 p->nStartPos = aD[nIdx+1].nStartPos;
4783 else
4785 if (aD[nIdx+1].pIdStk->empty())
4787 WW8PLCFx_PCD *pTemp = (WW8PLCFx_PCD*)(pPcd->pPLCFx);
4789 #i2325#
4790 As per normal, go on to the next set of properties, i.e. we
4791 have traversed over to the next piece. With a clipstart set
4792 we are being told to reread the current piece sprms so as to
4793 reapply them to a new chp or pap range.
4795 if (pTemp->GetClipStart() == -1)
4796 p->pPLCFx->advance();
4797 p->pMemPos = 0;
4798 p->nSprmsLen = 0;
4799 GetNewSprms( aD[nIdx+1] );
4800 GetNewNoSprms( *p );
4801 if (pTemp->GetClipStart() != -1)
4804 #i2325#, now we will force our starting position to the
4805 clipping start so as to force the application of these
4806 sprms after the current pap/chp sprms so as to apply the
4807 fastsave sprms to the current range.
4809 p->nStartPos = pTemp->GetClipStart();
4810 pTemp->SetClipStart(-1);
4815 else
4816 { // NoSprm ohne Ende
4817 p->pPLCFx->advance();
4818 p->pMemPos = 0; // MemPos ungueltig
4819 p->nSprmsLen = 0;
4820 GetNewNoSprms( *p );
4824 void WW8PLCFMan::advance()
4826 bool bStart;
4827 sal_uInt16 nIdx = WhereIdx(&bStart);
4828 if (nIdx < nPLCF)
4830 WW8PLCFxDesc* p = &aD[nIdx];
4832 p->bFirstSprm = true; // Default
4834 if( p->pPLCFx->IsSprm() )
4835 AdvSprm( nIdx, bStart );
4836 else // NoSprm
4837 AdvNoSprm( nIdx, bStart );
4841 // Rueckgabe true fuer Anfang eines Attributes oder Fehler,
4842 // false fuer Ende d. Attr
4843 // Restliche Rueckgabewerte werden in der vom Aufrufer zu stellenden Struktur
4844 // WW8PclxManResults geliefert.
4845 bool WW8PLCFMan::Get(WW8PLCFManResult* pRes) const
4847 memset( pRes, 0, sizeof( WW8PLCFManResult ) );
4848 bool bStart;
4849 sal_uInt16 nIdx = WhereIdx(&bStart);
4851 if( nIdx >= nPLCF )
4853 OSL_ENSURE( !this, "Position not found" );
4854 return true;
4857 if( aD[nIdx].pPLCFx->IsSprm() )
4859 if( bStart )
4861 GetSprmStart( nIdx, pRes );
4862 return true;
4864 else
4866 GetSprmEnd( nIdx, pRes );
4867 return false;
4870 else
4872 if( bStart )
4874 GetNoSprmStart( nIdx, pRes );
4875 return true;
4877 else
4879 GetNoSprmEnd( nIdx, pRes );
4880 return false;
4885 sal_uInt16 WW8PLCFMan::GetColl() const
4887 if( pPap->pPLCFx )
4888 return pPap->pPLCFx->GetIstd();
4889 else
4891 OSL_ENSURE( !this, "GetColl ohne PLCF_Pap" );
4892 return 0;
4896 WW8PLCFx_FLD* WW8PLCFMan::GetFld() const
4898 return (WW8PLCFx_FLD*)pFld->pPLCFx;
4901 const sal_uInt8* WW8PLCFMan::HasParaSprm( sal_uInt16 nId ) const
4903 return ((WW8PLCFx_Cp_FKP*)pPap->pPLCFx)->HasSprm( nId );
4906 const sal_uInt8* WW8PLCFMan::HasCharSprm( sal_uInt16 nId ) const
4908 return ((WW8PLCFx_Cp_FKP*)pChp->pPLCFx)->HasSprm( nId );
4911 bool WW8PLCFMan::HasCharSprm(sal_uInt16 nId,
4912 std::vector<const sal_uInt8 *> &rResult) const
4914 return ((WW8PLCFx_Cp_FKP*)pChp->pPLCFx)->HasSprm(nId, rResult);
4917 #endif // !DUMP
4919 void WW8PLCFx::Save( WW8PLCFxSave1& rSave ) const
4921 rSave.nPLCFxPos = GetIdx();
4922 rSave.nPLCFxPos2 = GetIdx2();
4923 rSave.nPLCFxMemOfs = 0;
4924 rSave.nStartFC = GetStartFc();
4927 void WW8PLCFx::Restore( const WW8PLCFxSave1& rSave )
4929 SetIdx( rSave.nPLCFxPos );
4930 SetIdx2( rSave.nPLCFxPos2 );
4931 SetStartFc( rSave.nStartFC );
4934 sal_uLong WW8PLCFx_Cp_FKP::GetIdx2() const
4936 return GetPCDIdx();
4939 void WW8PLCFx_Cp_FKP::SetIdx2( sal_uLong nIdx )
4941 SetPCDIdx( nIdx );
4944 void WW8PLCFx_Cp_FKP::Save( WW8PLCFxSave1& rSave ) const
4946 WW8PLCFx::Save( rSave );
4948 rSave.nAttrStart = nAttrStart;
4949 rSave.nAttrEnd = nAttrEnd;
4950 rSave.bLineEnd = bLineEnd;
4953 void WW8PLCFx_Cp_FKP::Restore( const WW8PLCFxSave1& rSave )
4955 WW8PLCFx::Restore( rSave );
4957 nAttrStart = rSave.nAttrStart;
4958 nAttrEnd = rSave.nAttrEnd;
4959 bLineEnd = rSave.bLineEnd;
4962 void WW8PLCFxDesc::Save( WW8PLCFxSave1& rSave ) const
4964 if( pPLCFx )
4966 pPLCFx->Save( rSave );
4967 if( pPLCFx->IsSprm() )
4969 WW8PLCFxDesc aD;
4970 aD.nStartPos = nOrigStartPos+nCpOfs;
4971 aD.nCpOfs = rSave.nCpOfs = nCpOfs;
4972 if (!(pPLCFx->SeekPos(aD.nStartPos)))
4974 aD.nEndPos = WW8_CP_MAX;
4975 pPLCFx->SetDirty(true);
4977 pPLCFx->GetSprms(&aD);
4978 pPLCFx->SetDirty(false);
4979 aD.ReduceByOffset();
4980 rSave.nStartCp = aD.nStartPos;
4981 rSave.nPLCFxMemOfs = nOrigSprmsLen - nSprmsLen;
4986 void WW8PLCFxDesc::Restore( const WW8PLCFxSave1& rSave )
4988 if( pPLCFx )
4990 pPLCFx->Restore( rSave );
4991 if( pPLCFx->IsSprm() )
4993 WW8PLCFxDesc aD;
4994 aD.nStartPos = rSave.nStartCp+rSave.nCpOfs;
4995 nCpOfs = aD.nCpOfs = rSave.nCpOfs;
4996 if (!(pPLCFx->SeekPos(aD.nStartPos)))
4998 aD.nEndPos = WW8_CP_MAX;
4999 pPLCFx->SetDirty(true);
5001 pPLCFx->GetSprms(&aD);
5002 pPLCFx->SetDirty(false);
5003 aD.ReduceByOffset();
5004 pMemPos = aD.pMemPos + rSave.nPLCFxMemOfs;
5011 namespace
5013 sal_uInt32 Readcb(SvStream& rSt, ww::WordVersion eVer)
5015 if (eVer <= ww::eWW2)
5017 sal_uInt16 nShort;
5018 rSt >> nShort;
5019 return nShort;
5021 else
5023 sal_uInt32 nLong;
5024 rSt >> nLong;
5025 return nLong;
5030 WW8_CP WW8Fib::GetBaseCp(ManTypes nType) const
5032 WW8_CP nOffset = 0;
5034 switch( nType )
5036 default:
5037 case MAN_MAINTEXT:
5038 break;
5039 case MAN_FTN:
5040 nOffset = ccpText;
5041 break;
5042 case MAN_HDFT:
5043 nOffset = ccpText + ccpFtn;
5044 break;
5046 A subdocument of this kind (MAN_MACRO) probably exists in some defunct
5047 version of MSWord, but now ccpMcr is always 0. If some example that
5048 uses this comes to light, this is the likely calculation required
5050 case MAN_MACRO:
5051 nOffset = ccpText + ccpFtn + ccpHdr;
5052 break;
5055 case MAN_AND:
5056 nOffset = ccpText + ccpFtn + ccpHdr + ccpMcr;
5057 break;
5058 case MAN_EDN:
5059 nOffset = ccpText + ccpFtn + ccpHdr + ccpMcr + ccpAtn;
5060 break;
5061 case MAN_TXBX:
5062 nOffset = ccpText + ccpFtn + ccpHdr + ccpMcr + ccpAtn + ccpEdn;
5063 break;
5064 case MAN_TXBX_HDFT:
5065 nOffset = ccpText + ccpFtn + ccpHdr + ccpMcr + ccpAtn + ccpEdn +
5066 ccpTxbx;
5067 break;
5069 return nOffset;
5072 ww::WordVersion WW8Fib::GetFIBVersion() const
5074 ww::WordVersion eVer = ww::eWW8;
5076 * Word for Windows 2 I think (1.X might work too if anyone has an example.
5077 * Various pages claim that the fileformats of Word 1 and 2 for Windows are
5078 * equivalent to Word for Macintosh 4 and 5. On the other hand
5080 * wIdents for Word for Mac versions...
5081 * 0xFE32 for Word 1
5082 * 0xFE34 for Word 3
5083 * 0xFE37 for Word 4 et 5.
5085 * and this document
5086 * http://cmsdoc.cern.ch/documents/docformat/CMS_CERN_LetterHead.word is
5087 * claimed to be "Word 5 for Mac" by Office etc and has that wIdent, but
5088 * its format isn't the same as that of Word 2 for windows. Nor is it
5089 * the same as that of Word for DOS/PCWord 5
5091 if (wIdent == 0xa5db)
5092 eVer = ww::eWW2;
5093 else
5095 switch (nVersion)
5097 case 6:
5098 eVer = ww::eWW6;
5099 break;
5100 case 7:
5101 eVer = ww::eWW7;
5102 break;
5103 case 8:
5104 eVer = ww::eWW8;
5105 break;
5108 return eVer;
5111 WW8Fib::WW8Fib(SvStream& rSt, sal_uInt8 nWantedVersion, sal_uInt32 nOffset)
5112 : nFibError( 0 )
5114 memset(this, 0, sizeof(*this));
5115 sal_uInt8 aBits1;
5116 sal_uInt8 aBits2;
5117 sal_uInt8 aVer8Bits1; // nur ab WinWord 8 benutzt
5118 rSt.Seek( nOffset );
5120 Wunsch-Nr vermerken, File-Versionsnummer ermitteln
5121 und gegen Wunsch-Nr. checken !
5123 nVersion = nWantedVersion;
5124 rSt >> wIdent;
5125 rSt >> nFib;
5126 rSt >> nProduct;
5127 if( 0 != rSt.GetError() )
5129 sal_Int16 nFibMin;
5130 sal_Int16 nFibMax;
5131 // note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
5132 switch( nVersion )
5134 case 6:
5135 nFibMin = 0x0065; // von 101 WinWord 6.0
5136 // 102 "
5137 // und 103 WinWord 6.0 fuer Macintosh
5138 // 104 "
5139 nFibMax = 0x0069; // bis 105 WinWord 95
5140 break;
5141 case 7:
5142 nFibMin = 0x0069; // von 105 WinWord 95
5143 nFibMax = 0x0069; // bis 105 WinWord 95
5144 break;
5145 case 8:
5146 nFibMin = 0x006A; // von 106 WinWord 97
5147 nFibMax = 0x00c1; // bis 193 WinWord 97 (?)
5148 break;
5149 default:
5150 nFibMin = 0; // Programm-Fehler!
5151 nFibMax = 0;
5152 nFib = 1;
5153 OSL_ENSURE( !this, "Es wurde vergessen, nVersion zu kodieren!" );
5154 break;
5156 if ( (nFib < nFibMin) || (nFib > nFibMax) )
5158 nFibError = ERR_SWG_READ_ERROR; // Error melden
5159 return; // und hopp raus!
5163 ww::WordVersion eVer = GetFIBVersion();
5165 // Hilfs-Varis fuer Ver67:
5166 sal_Int16 pnChpFirst_Ver67=0;
5167 sal_Int16 pnPapFirst_Ver67=0;
5168 sal_Int16 cpnBteChp_Ver67=0;
5169 sal_Int16 cpnBtePap_Ver67=0;
5171 // und auf gehts: FIB einlesen
5172 rSt >> lid;
5173 rSt >> pnNext;
5174 rSt >> aBits1;
5175 rSt >> aBits2;
5176 rSt >> nFibBack;
5177 rSt >> nHash;
5178 rSt >> nKey;
5179 rSt >> envr;
5180 rSt >> aVer8Bits1; // unter Ver67 nur leeres Reservefeld
5181 // Inhalt von aVer8Bits1
5183 // sal_uInt8 fMac :1;
5184 // sal_uInt8 fEmptySpecial :1;
5185 // sal_uInt8 fLoadOverridePage :1;
5186 // sal_uInt8 fFuturesavedUndo :1;
5187 // sal_uInt8 fWord97Saved :1;
5188 // sal_uInt8 :3;
5189 rSt >> chse;
5190 rSt >> chseTables;
5191 rSt >> fcMin;
5192 rSt >> fcMac;
5194 // Einschub fuer WW8 *****************************************************
5195 if (IsEightPlus(eVer))
5197 rSt >> csw;
5199 // Marke: "rgsw" Beginning of the array of shorts
5200 rSt >> wMagicCreated;
5201 rSt >> wMagicRevised;
5202 rSt >> wMagicCreatedPrivate;
5203 rSt >> wMagicRevisedPrivate;
5204 rSt.SeekRel( 9 * sizeof( sal_Int16 ) );
5207 // dies sind die 9 unused Felder:
5208 && (bVer67 || WW8ReadINT16( rSt, pnFbpChpFirst_W6 )) // 1
5209 && (bVer67 || WW8ReadINT16( rSt, pnChpFirst_W6 )) // 2
5210 && (bVer67 || WW8ReadINT16( rSt, cpnBteChp_W6 )) // 3
5211 && (bVer67 || WW8ReadINT16( rSt, pnFbpPapFirst_W6 )) // 4
5212 && (bVer67 || WW8ReadINT16( rSt, pnPapFirst_W6 )) // 5
5213 && (bVer67 || WW8ReadINT16( rSt, cpnBtePap_W6 )) // 6
5214 && (bVer67 || WW8ReadINT16( rSt, pnFbpLvcFirst_W6 )) // 7
5215 && (bVer67 || WW8ReadINT16( rSt, pnLvcFirst_W6 )) // 8
5216 && (bVer67 || WW8ReadINT16( rSt, cpnBteLvc_W6 )) // 9
5218 rSt >> lidFE;
5219 rSt >> clw;
5222 // Ende des Einschubs fuer WW8 *******************************************
5224 // Marke: "rglw" Beginning of the array of longs
5225 rSt >> cbMac;
5227 // 2 Longs uebergehen, da unwichtiger Quatsch
5228 rSt.SeekRel( 2 * sizeof( sal_Int32) );
5230 // weitere 2 Longs nur bei Ver67 ueberspringen
5231 if (IsSevenMinus(eVer))
5232 rSt.SeekRel( 2 * sizeof( sal_Int32) );
5234 rSt >> ccpText;
5235 rSt >> ccpFtn;
5236 rSt >> ccpHdr;
5237 rSt >> ccpMcr;
5238 rSt >> ccpAtn;
5239 rSt >> ccpEdn;
5240 rSt >> ccpTxbx;
5241 rSt >> ccpHdrTxbx;
5243 // weiteres Long nur bei Ver67 ueberspringen
5244 if (IsSevenMinus(eVer))
5245 rSt.SeekRel( 1 * sizeof( sal_Int32) );
5246 else
5248 // Einschub fuer WW8 *****************************************************
5249 rSt >> pnFbpChpFirst;
5250 rSt >> pnChpFirst;
5251 rSt >> cpnBteChp;
5252 rSt >> pnFbpPapFirst;
5253 rSt >> pnPapFirst;
5254 rSt >> cpnBtePap;
5255 rSt >> pnFbpLvcFirst;
5256 rSt >> pnLvcFirst;
5257 rSt >> cpnBteLvc;
5258 rSt >> fcIslandFirst;
5259 rSt >> fcIslandLim;
5260 rSt >> cfclcb;
5263 // Ende des Einschubs fuer WW8 *******************************************
5265 // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
5266 rSt >> fcStshfOrig;
5267 lcbStshfOrig = Readcb(rSt, eVer);
5268 rSt >> fcStshf;
5269 lcbStshf = Readcb(rSt, eVer);
5270 rSt >> fcPlcffndRef;
5271 lcbPlcffndRef = Readcb(rSt, eVer);
5272 rSt >> fcPlcffndTxt;
5273 lcbPlcffndTxt = Readcb(rSt, eVer);
5274 rSt >> fcPlcfandRef;
5275 lcbPlcfandRef = Readcb(rSt, eVer);
5276 rSt >> fcPlcfandTxt;
5277 lcbPlcfandTxt = Readcb(rSt, eVer);
5278 rSt >> fcPlcfsed;
5279 lcbPlcfsed = Readcb(rSt, eVer);
5280 rSt >> fcPlcfpad;
5281 lcbPlcfpad = Readcb(rSt, eVer);
5282 rSt >> fcPlcfphe;
5283 lcbPlcfphe = Readcb(rSt, eVer);
5284 rSt >> fcSttbfglsy;
5285 lcbSttbfglsy = Readcb(rSt, eVer);
5286 rSt >> fcPlcfglsy;
5287 lcbPlcfglsy = Readcb(rSt, eVer);
5288 rSt >> fcPlcfhdd;
5289 lcbPlcfhdd = Readcb(rSt, eVer);
5290 rSt >> fcPlcfbteChpx;
5291 lcbPlcfbteChpx = Readcb(rSt, eVer);
5292 rSt >> fcPlcfbtePapx;
5293 lcbPlcfbtePapx = Readcb(rSt, eVer);
5294 rSt >> fcPlcfsea;
5295 lcbPlcfsea = Readcb(rSt, eVer);
5296 rSt >> fcSttbfffn;
5297 lcbSttbfffn = Readcb(rSt, eVer);
5298 rSt >> fcPlcffldMom;
5299 lcbPlcffldMom = Readcb(rSt, eVer);
5300 rSt >> fcPlcffldHdr;
5301 lcbPlcffldHdr = Readcb(rSt, eVer);
5302 rSt >> fcPlcffldFtn;
5303 lcbPlcffldFtn = Readcb(rSt, eVer);
5304 rSt >> fcPlcffldAtn;
5305 lcbPlcffldAtn = Readcb(rSt, eVer);
5306 rSt >> fcPlcffldMcr;
5307 lcbPlcffldMcr = Readcb(rSt, eVer);
5308 rSt >> fcSttbfbkmk;
5309 lcbSttbfbkmk = Readcb(rSt, eVer);
5310 rSt >> fcPlcfbkf;
5311 lcbPlcfbkf = Readcb(rSt, eVer);
5312 rSt >> fcPlcfbkl;
5313 lcbPlcfbkl = Readcb(rSt, eVer);
5314 rSt >> fcCmds;
5315 lcbCmds = Readcb(rSt, eVer);
5316 rSt >> fcPlcfmcr;
5317 lcbPlcfmcr = Readcb(rSt, eVer);
5318 rSt >> fcSttbfmcr;
5319 lcbSttbfmcr = Readcb(rSt, eVer);
5320 rSt >> fcPrDrvr;
5321 lcbPrDrvr = Readcb(rSt, eVer);
5322 rSt >> fcPrEnvPort;
5323 lcbPrEnvPort = Readcb(rSt, eVer);
5324 rSt >> fcPrEnvLand;
5325 lcbPrEnvLand = Readcb(rSt, eVer);
5326 rSt >> fcWss;
5327 lcbWss = Readcb(rSt, eVer);
5328 rSt >> fcDop;
5329 lcbDop = Readcb(rSt, eVer);
5330 rSt >> fcSttbfAssoc;
5331 lcbSttbfAssoc = Readcb(rSt, eVer);
5332 rSt >> fcClx;
5333 lcbClx = Readcb(rSt, eVer);
5334 rSt >> fcPlcfpgdFtn;
5335 lcbPlcfpgdFtn = Readcb(rSt, eVer);
5336 rSt >> fcAutosaveSource;
5337 lcbAutosaveSource = Readcb(rSt, eVer);
5338 rSt >> fcGrpStAtnOwners;
5339 lcbGrpStAtnOwners = Readcb(rSt, eVer);
5340 rSt >> fcSttbfAtnbkmk;
5341 lcbSttbfAtnbkmk = Readcb(rSt, eVer);
5343 // weiteres short nur bei Ver67 ueberspringen
5344 if (IsSevenMinus(eVer))
5346 rSt.SeekRel( 1*sizeof( sal_Int16) );
5348 // folgende 4 Shorts existieren nur bei Ver67;
5349 rSt >> pnChpFirst_Ver67;
5350 rSt >> pnPapFirst_Ver67;
5351 rSt >> cpnBteChp_Ver67;
5352 rSt >> cpnBtePap_Ver67;
5355 if (eVer > ww::eWW2)
5357 rSt >> fcPlcfdoaMom;
5358 rSt >> lcbPlcfdoaMom;
5359 rSt >> fcPlcfdoaHdr;
5360 rSt >> lcbPlcfdoaHdr;
5361 rSt >> fcPlcfspaMom;
5362 rSt >> lcbPlcfspaMom;
5363 rSt >> fcPlcfspaHdr;
5364 rSt >> lcbPlcfspaHdr;
5366 rSt >> fcPlcfAtnbkf;
5367 rSt >> lcbPlcfAtnbkf;
5368 rSt >> fcPlcfAtnbkl;
5369 rSt >> lcbPlcfAtnbkl;
5370 rSt >> fcPms;
5371 rSt >> lcbPMS;
5372 rSt >> fcFormFldSttbf;
5373 rSt >> lcbFormFldSttbf;
5374 rSt >> fcPlcfendRef;
5375 rSt >> lcbPlcfendRef;
5376 rSt >> fcPlcfendTxt;
5377 rSt >> lcbPlcfendTxt;
5378 rSt >> fcPlcffldEdn;
5379 rSt >> lcbPlcffldEdn;
5380 rSt >> fcPlcfpgdEdn;
5381 rSt >> lcbPlcfpgdEdn;
5382 rSt >> fcDggInfo;
5383 rSt >> lcbDggInfo;
5384 rSt >> fcSttbfRMark;
5385 rSt >> lcbSttbfRMark;
5386 rSt >> fcSttbfCaption;
5387 rSt >> lcbSttbfCaption;
5388 rSt >> fcSttbAutoCaption;
5389 rSt >> lcbSttbAutoCaption;
5390 rSt >> fcPlcfwkb;
5391 rSt >> lcbPlcfwkb;
5392 rSt >> fcPlcfspl;
5393 rSt >> lcbPlcfspl;
5394 rSt >> fcPlcftxbxTxt;
5395 rSt >> lcbPlcftxbxTxt;
5396 rSt >> fcPlcffldTxbx;
5397 rSt >> lcbPlcffldTxbx;
5398 rSt >> fcPlcfHdrtxbxTxt;
5399 rSt >> lcbPlcfHdrtxbxTxt;
5400 rSt >> fcPlcffldHdrTxbx;
5401 rSt >> lcbPlcffldHdrTxbx;
5402 rSt >> fcStwUser;
5403 rSt >> lcbStwUser;
5404 rSt >> fcSttbttmbd;
5405 rSt >> lcbSttbttmbd;
5408 if( 0 == rSt.GetError() )
5410 // Bit-Flags setzen
5411 fDot = aBits1 & 0x01 ;
5412 fGlsy = ( aBits1 & 0x02 ) >> 1;
5413 fComplex = ( aBits1 & 0x04 ) >> 2;
5414 fHasPic = ( aBits1 & 0x08 ) >> 3;
5415 cQuickSaves = ( aBits1 & 0xf0 ) >> 4;
5416 fEncrypted = aBits2 & 0x01 ;
5417 fWhichTblStm= ( aBits2 & 0x02 ) >> 1;
5418 fReadOnlyRecommended = (aBits2 & 0x4) >> 2;
5419 fWriteReservation = (aBits2 & 0x8) >> 3;
5420 fExtChar = ( aBits2 & 0x10 ) >> 4;
5421 // dummy = ( aBits2 & 0x20 ) >> 5;
5422 fFarEast = ( aBits2 & 0x40 ) >> 6; // #i90932#
5423 // dummy = ( aBits2 & 0x80 ) >> 7;
5426 ggfs. Ziel-Varaiblen, aus xxx_Ver67 fuellen
5427 oder Flags setzen
5429 if (IsSevenMinus(eVer))
5431 pnChpFirst = pnChpFirst_Ver67;
5432 pnPapFirst = pnPapFirst_Ver67;
5433 cpnBteChp = cpnBteChp_Ver67;
5434 cpnBtePap = cpnBtePap_Ver67;
5436 else if (IsEightPlus(eVer))
5438 fMac = aVer8Bits1 & 0x01 ;
5439 fEmptySpecial = ( aVer8Bits1 & 0x02 ) >> 1;
5440 fLoadOverridePage = ( aVer8Bits1 & 0x04 ) >> 2;
5441 fFuturesavedUndo = ( aVer8Bits1 & 0x08 ) >> 3;
5442 fWord97Saved = ( aVer8Bits1 & 0x10 ) >> 4;
5443 fWord2000Saved = ( aVer8Bits1 & 0x20 ) >> 5;
5446 speziell fuer WW8:
5447 ermittle die Werte fuer PLCF LST und PLF LFO
5448 und PLCF fuer TextBox-Break-Deskriptoren
5450 long nOldPos = rSt.Tell();
5452 rSt.Seek( 0x02da );
5453 rSt >> fcSttbFnm;
5454 rSt >> lcbSttbFnm;
5455 rSt >> fcPlcfLst;
5456 rSt >> lcbPlcfLst;
5457 rSt >> fcPlfLfo;
5458 rSt >> lcbPlfLfo;
5459 rSt >> fcPlcftxbxBkd;
5460 rSt >> lcbPlcftxbxBkd;
5461 rSt >> fcPlcfHdrtxbxBkd;
5462 rSt >> lcbPlcfHdrtxbxBkd;
5463 if( 0 != rSt.GetError() )
5465 nFibError = ERR_SWG_READ_ERROR;
5468 rSt.Seek( 0x372 ); // fcSttbListNames
5469 rSt >> fcSttbListNames;
5470 rSt >> lcbSttbListNames;
5472 if (cfclcb > 93)
5474 rSt.Seek( 0x382 ); // MagicTables
5475 rSt >> fcPlcfTch;
5476 rSt >> lcbPlcfTch;
5479 if (cfclcb > 113)
5481 rSt.Seek( 0x41A ); // new ATRD
5482 rSt >> fcAtrdExtra;
5483 rSt >> lcbAtrdExtra;
5486 if( 0 != rSt.GetError() )
5487 nFibError = ERR_SWG_READ_ERROR;
5489 rSt.Seek( 0x5bc ); // Actual nFib introduced in Word 2003
5490 rSt >> nFib_actual;
5492 rSt.Seek( nOldPos );
5495 else
5497 nFibError = ERR_SWG_READ_ERROR; // Error melden
5502 WW8Fib::WW8Fib(sal_uInt8 nVer)
5504 memset(this, 0, sizeof(*this));
5505 nVersion = nVer;
5506 if (8 == nVer)
5508 fcMin = 0x800;
5509 wIdent = 0xa5ec;
5510 nFib = 0x0101;
5511 nFibBack = 0xbf;
5512 nProduct = 0x204D;
5514 csw = 0x0e; // muss das sein ???
5515 cfclcb = 0x88; // -""-
5516 clw = 0x16; // -""-
5517 pnFbpChpFirst = pnFbpPapFirst = pnFbpLvcFirst = 0x000fffff;
5518 fExtChar = true;
5519 fWord97Saved = fWord2000Saved = true;
5521 wMagicCreated = 0x6143;
5522 wMagicRevised = 0x6C6F;
5523 wMagicCreatedPrivate = 0x6E61;
5524 wMagicRevisedPrivate = 0x3038;
5526 else
5528 fcMin = 0x300;
5529 wIdent = 0xa5dc;
5530 nFib = nFibBack = 0x65;
5531 nProduct = 0xc02d;
5534 //If nFib is 0x00D9 or greater, then cQuickSaves MUST be 0xF
5535 cQuickSaves = nFib >= 0x00D9 ? 0xF : 0;
5537 // --> #i90932#
5538 lid = 0x409; // LANGUAGE_ENGLISH_US
5540 LanguageType nLang = Application::GetSettings().GetLanguageTag().getLanguageType();
5541 fFarEast = MsLangId::isCJK(nLang);
5542 if (fFarEast)
5543 lidFE = nLang;
5544 else
5545 lidFE = lid;
5547 LanguageTag aLanguageTag( lid );
5548 LocaleDataWrapper aLocaleWrapper( aLanguageTag );
5549 nNumDecimalSep = aLocaleWrapper.getNumDecimalSep()[0];
5552 sal_Unicode WW8Fib::getNumDecimalSep() const
5554 return nNumDecimalSep;
5557 bool WW8Fib::WriteHeader(SvStream& rStrm)
5559 bool bVer8 = 8 == nVersion;
5561 size_t nUnencryptedHdr = bVer8 ? 0x44 : 0x24;
5562 sal_uInt8 *pDataPtr = new sal_uInt8[ nUnencryptedHdr ];
5563 sal_uInt8 *pData = pDataPtr;
5564 memset( pData, 0, nUnencryptedHdr );
5566 sal_uLong nPos = rStrm.Tell();
5567 cbMac = rStrm.Seek( STREAM_SEEK_TO_END );
5568 rStrm.Seek( nPos );
5570 Set_UInt16( pData, wIdent );
5571 Set_UInt16( pData, nFib );
5572 Set_UInt16( pData, nProduct );
5573 Set_UInt16( pData, lid );
5574 Set_UInt16( pData, pnNext );
5576 sal_uInt16 nBits16 = 0;
5577 if( fDot ) nBits16 |= 0x0001;
5578 if( fGlsy) nBits16 |= 0x0002;
5579 if( fComplex ) nBits16 |= 0x0004;
5580 if( fHasPic ) nBits16 |= 0x0008;
5581 nBits16 |= (0xf0 & ( cQuickSaves << 4 ));
5582 if( fEncrypted ) nBits16 |= 0x0100;
5583 if( fWhichTblStm ) nBits16 |= 0x0200;
5585 if (fReadOnlyRecommended)
5586 nBits16 |= 0x0400;
5587 if (fWriteReservation)
5588 nBits16 |= 0x0800;
5590 if( fExtChar ) nBits16 |= 0x1000;
5591 if( fFarEast ) nBits16 |= 0x4000; // #i90932#
5592 if( fObfuscated ) nBits16 |= 0x8000;
5593 Set_UInt16( pData, nBits16 );
5595 Set_UInt16( pData, nFibBack );
5596 Set_UInt16( pData, nHash );
5597 Set_UInt16( pData, nKey );
5598 Set_UInt8( pData, envr );
5600 sal_uInt8 nBits8 = 0;
5601 if( bVer8 )
5603 if( fMac ) nBits8 |= 0x0001;
5604 if( fEmptySpecial ) nBits8 |= 0x0002;
5605 if( fLoadOverridePage ) nBits8 |= 0x0004;
5606 if( fFuturesavedUndo ) nBits8 |= 0x0008;
5607 if( fWord97Saved ) nBits8 |= 0x0010;
5608 if( fWord2000Saved ) nBits8 |= 0x0020;
5610 // unter Ver67 these are only reserved
5611 Set_UInt8( pData, nBits8 );
5613 Set_UInt16( pData, chse );
5614 Set_UInt16( pData, chseTables );
5615 Set_UInt32( pData, fcMin );
5616 Set_UInt32( pData, fcMac );
5618 // Einschub fuer WW8 *****************************************************
5620 // Marke: "rgsw" Beginning of the array of shorts
5621 if( bVer8 )
5623 Set_UInt16( pData, csw );
5624 Set_UInt16( pData, wMagicCreated );
5625 Set_UInt16( pData, wMagicRevised );
5626 Set_UInt16( pData, wMagicCreatedPrivate );
5627 Set_UInt16( pData, wMagicRevisedPrivate );
5628 pData += 9 * sizeof( sal_Int16 );
5629 Set_UInt16( pData, lidFE );
5630 Set_UInt16( pData, clw );
5633 // Ende des Einschubs fuer WW8 *******************************************
5635 // Marke: "rglw" Beginning of the array of longs
5636 Set_UInt32( pData, cbMac );
5638 rStrm.Write( pDataPtr, nUnencryptedHdr );
5639 delete[] pDataPtr;
5640 return 0 == rStrm.GetError();
5643 bool WW8Fib::Write(SvStream& rStrm)
5645 bool bVer8 = 8 == nVersion;
5647 WriteHeader( rStrm );
5649 size_t nUnencryptedHdr = bVer8 ? 0x44 : 0x24;
5651 sal_uInt8 *pDataPtr = new sal_uInt8[ fcMin - nUnencryptedHdr ];
5652 sal_uInt8 *pData = pDataPtr;
5653 memset( pData, 0, fcMin - nUnencryptedHdr );
5655 sal_uLong nPos = rStrm.Tell();
5656 cbMac = rStrm.Seek( STREAM_SEEK_TO_END );
5657 rStrm.Seek( nPos );
5659 // 2 Longs uebergehen, da unwichtiger Quatsch
5660 pData += 2 * sizeof( sal_Int32);
5662 // weitere 2 Longs nur bei Ver67 ueberspringen
5663 if( !bVer8 )
5664 pData += 2 * sizeof( sal_Int32);
5666 Set_UInt32( pData, ccpText );
5667 Set_UInt32( pData, ccpFtn );
5668 Set_UInt32( pData, ccpHdr );
5669 Set_UInt32( pData, ccpMcr );
5670 Set_UInt32( pData, ccpAtn );
5671 Set_UInt32( pData, ccpEdn );
5672 Set_UInt32( pData, ccpTxbx );
5673 Set_UInt32( pData, ccpHdrTxbx );
5675 // weiteres Long nur bei Ver67 ueberspringen
5676 if( !bVer8 )
5677 pData += 1 * sizeof( sal_Int32);
5679 // Einschub fuer WW8 *****************************************************
5680 if( bVer8 )
5682 Set_UInt32( pData, pnFbpChpFirst );
5683 Set_UInt32( pData, pnChpFirst );
5684 Set_UInt32( pData, cpnBteChp );
5685 Set_UInt32( pData, pnFbpPapFirst );
5686 Set_UInt32( pData, pnPapFirst );
5687 Set_UInt32( pData, cpnBtePap );
5688 Set_UInt32( pData, pnFbpLvcFirst );
5689 Set_UInt32( pData, pnLvcFirst );
5690 Set_UInt32( pData, cpnBteLvc );
5691 Set_UInt32( pData, fcIslandFirst );
5692 Set_UInt32( pData, fcIslandLim );
5693 Set_UInt16( pData, cfclcb );
5695 // Ende des Einschubs fuer WW8 *******************************************
5697 // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
5698 Set_UInt32( pData, fcStshfOrig );
5699 Set_UInt32( pData, lcbStshfOrig );
5700 Set_UInt32( pData, fcStshf );
5701 Set_UInt32( pData, lcbStshf );
5702 Set_UInt32( pData, fcPlcffndRef );
5703 Set_UInt32( pData, lcbPlcffndRef );
5704 Set_UInt32( pData, fcPlcffndTxt );
5705 Set_UInt32( pData, lcbPlcffndTxt );
5706 Set_UInt32( pData, fcPlcfandRef );
5707 Set_UInt32( pData, lcbPlcfandRef );
5708 Set_UInt32( pData, fcPlcfandTxt );
5709 Set_UInt32( pData, lcbPlcfandTxt );
5710 Set_UInt32( pData, fcPlcfsed );
5711 Set_UInt32( pData, lcbPlcfsed );
5712 Set_UInt32( pData, fcPlcfpad );
5713 Set_UInt32( pData, lcbPlcfpad );
5714 Set_UInt32( pData, fcPlcfphe );
5715 Set_UInt32( pData, lcbPlcfphe );
5716 Set_UInt32( pData, fcSttbfglsy );
5717 Set_UInt32( pData, lcbSttbfglsy );
5718 Set_UInt32( pData, fcPlcfglsy );
5719 Set_UInt32( pData, lcbPlcfglsy );
5720 Set_UInt32( pData, fcPlcfhdd );
5721 Set_UInt32( pData, lcbPlcfhdd );
5722 Set_UInt32( pData, fcPlcfbteChpx );
5723 Set_UInt32( pData, lcbPlcfbteChpx );
5724 Set_UInt32( pData, fcPlcfbtePapx );
5725 Set_UInt32( pData, lcbPlcfbtePapx );
5726 Set_UInt32( pData, fcPlcfsea );
5727 Set_UInt32( pData, lcbPlcfsea );
5728 Set_UInt32( pData, fcSttbfffn );
5729 Set_UInt32( pData, lcbSttbfffn );
5730 Set_UInt32( pData, fcPlcffldMom );
5731 Set_UInt32( pData, lcbPlcffldMom );
5732 Set_UInt32( pData, fcPlcffldHdr );
5733 Set_UInt32( pData, lcbPlcffldHdr );
5734 Set_UInt32( pData, fcPlcffldFtn );
5735 Set_UInt32( pData, lcbPlcffldFtn );
5736 Set_UInt32( pData, fcPlcffldAtn );
5737 Set_UInt32( pData, lcbPlcffldAtn );
5738 Set_UInt32( pData, fcPlcffldMcr );
5739 Set_UInt32( pData, lcbPlcffldMcr );
5740 Set_UInt32( pData, fcSttbfbkmk );
5741 Set_UInt32( pData, lcbSttbfbkmk );
5742 Set_UInt32( pData, fcPlcfbkf );
5743 Set_UInt32( pData, lcbPlcfbkf );
5744 Set_UInt32( pData, fcPlcfbkl );
5745 Set_UInt32( pData, lcbPlcfbkl );
5746 Set_UInt32( pData, fcCmds );
5747 Set_UInt32( pData, lcbCmds );
5748 Set_UInt32( pData, fcPlcfmcr );
5749 Set_UInt32( pData, lcbPlcfmcr );
5750 Set_UInt32( pData, fcSttbfmcr );
5751 Set_UInt32( pData, lcbSttbfmcr );
5752 Set_UInt32( pData, fcPrDrvr );
5753 Set_UInt32( pData, lcbPrDrvr );
5754 Set_UInt32( pData, fcPrEnvPort );
5755 Set_UInt32( pData, lcbPrEnvPort );
5756 Set_UInt32( pData, fcPrEnvLand );
5757 Set_UInt32( pData, lcbPrEnvLand );
5758 Set_UInt32( pData, fcWss );
5759 Set_UInt32( pData, lcbWss );
5760 Set_UInt32( pData, fcDop );
5761 Set_UInt32( pData, lcbDop );
5762 Set_UInt32( pData, fcSttbfAssoc );
5763 Set_UInt32( pData, lcbSttbfAssoc );
5764 Set_UInt32( pData, fcClx );
5765 Set_UInt32( pData, lcbClx );
5766 Set_UInt32( pData, fcPlcfpgdFtn );
5767 Set_UInt32( pData, lcbPlcfpgdFtn );
5768 Set_UInt32( pData, fcAutosaveSource );
5769 Set_UInt32( pData, lcbAutosaveSource );
5770 Set_UInt32( pData, fcGrpStAtnOwners );
5771 Set_UInt32( pData, lcbGrpStAtnOwners );
5772 Set_UInt32( pData, fcSttbfAtnbkmk );
5773 Set_UInt32( pData, lcbSttbfAtnbkmk );
5775 // weiteres short nur bei Ver67 ueberspringen
5776 if( !bVer8 )
5778 pData += 1*sizeof( sal_Int16);
5779 Set_UInt16( pData, (sal_uInt16)pnChpFirst );
5780 Set_UInt16( pData, (sal_uInt16)pnPapFirst );
5781 Set_UInt16( pData, (sal_uInt16)cpnBteChp );
5782 Set_UInt16( pData, (sal_uInt16)cpnBtePap );
5785 Set_UInt32( pData, fcPlcfdoaMom ); // nur bei Ver67, in Ver8 unused
5786 Set_UInt32( pData, lcbPlcfdoaMom ); // nur bei Ver67, in Ver8 unused
5787 Set_UInt32( pData, fcPlcfdoaHdr ); // nur bei Ver67, in Ver8 unused
5788 Set_UInt32( pData, lcbPlcfdoaHdr ); // nur bei Ver67, in Ver8 unused
5790 Set_UInt32( pData, fcPlcfspaMom ); // in Ver67 leere Reserve
5791 Set_UInt32( pData, lcbPlcfspaMom ); // in Ver67 leere Reserve
5792 Set_UInt32( pData, fcPlcfspaHdr ); // in Ver67 leere Reserve
5793 Set_UInt32( pData, lcbPlcfspaHdr ); // in Ver67 leere Reserve
5795 Set_UInt32( pData, fcPlcfAtnbkf );
5796 Set_UInt32( pData, lcbPlcfAtnbkf );
5797 Set_UInt32( pData, fcPlcfAtnbkl );
5798 Set_UInt32( pData, lcbPlcfAtnbkl );
5799 Set_UInt32( pData, fcPms );
5800 Set_UInt32( pData, lcbPMS );
5801 Set_UInt32( pData, fcFormFldSttbf );
5802 Set_UInt32( pData, lcbFormFldSttbf );
5803 Set_UInt32( pData, fcPlcfendRef );
5804 Set_UInt32( pData, lcbPlcfendRef );
5805 Set_UInt32( pData, fcPlcfendTxt );
5806 Set_UInt32( pData, lcbPlcfendTxt );
5807 Set_UInt32( pData, fcPlcffldEdn );
5808 Set_UInt32( pData, lcbPlcffldEdn );
5809 Set_UInt32( pData, fcPlcfpgdEdn );
5810 Set_UInt32( pData, lcbPlcfpgdEdn );
5811 Set_UInt32( pData, fcDggInfo ); // in Ver67 leere Reserve
5812 Set_UInt32( pData, lcbDggInfo ); // in Ver67 leere Reserve
5813 Set_UInt32( pData, fcSttbfRMark );
5814 Set_UInt32( pData, lcbSttbfRMark );
5815 Set_UInt32( pData, fcSttbfCaption );
5816 Set_UInt32( pData, lcbSttbfCaption );
5817 Set_UInt32( pData, fcSttbAutoCaption );
5818 Set_UInt32( pData, lcbSttbAutoCaption );
5819 Set_UInt32( pData, fcPlcfwkb );
5820 Set_UInt32( pData, lcbPlcfwkb );
5821 Set_UInt32( pData, fcPlcfspl ); // in Ver67 leere Reserve
5822 Set_UInt32( pData, lcbPlcfspl ); // in Ver67 leere Reserve
5823 Set_UInt32( pData, fcPlcftxbxTxt );
5824 Set_UInt32( pData, lcbPlcftxbxTxt );
5825 Set_UInt32( pData, fcPlcffldTxbx );
5826 Set_UInt32( pData, lcbPlcffldTxbx );
5827 Set_UInt32( pData, fcPlcfHdrtxbxTxt );
5828 Set_UInt32( pData, lcbPlcfHdrtxbxTxt );
5829 Set_UInt32( pData, fcPlcffldHdrTxbx );
5830 Set_UInt32( pData, lcbPlcffldHdrTxbx );
5832 if( bVer8 )
5834 pData += 0x2da - 0x27a; // Pos + Offset (fcPlcfLst - fcStwUser)
5835 Set_UInt32( pData, fcSttbFnm);
5836 Set_UInt32( pData, lcbSttbFnm);
5837 Set_UInt32( pData, fcPlcfLst );
5838 Set_UInt32( pData, lcbPlcfLst );
5839 Set_UInt32( pData, fcPlfLfo );
5840 Set_UInt32( pData, lcbPlfLfo );
5841 Set_UInt32( pData, fcPlcftxbxBkd );
5842 Set_UInt32( pData, lcbPlcftxbxBkd );
5843 Set_UInt32( pData, fcPlcfHdrtxbxBkd );
5844 Set_UInt32( pData, lcbPlcfHdrtxbxBkd );
5846 pData += 0x372 - 0x302; // Pos + Offset (fcSttbListNames - fcDocUndo)
5847 Set_UInt32( pData, fcSttbListNames );
5848 Set_UInt32( pData, lcbSttbListNames );
5850 pData += 0x382 - 0x37A;
5851 Set_UInt32( pData, fcPlcfTch );
5852 Set_UInt32( pData, lcbPlcfTch );
5854 pData += 0x3FA - 0x38A;
5855 Set_UInt16( pData, (sal_uInt16)0x0002);
5856 Set_UInt16( pData, (sal_uInt16)0x00D9);
5858 pData += 0x41A - 0x3FE;
5859 Set_UInt32( pData, fcAtrdExtra );
5860 Set_UInt32( pData, lcbAtrdExtra );
5862 pData += 0x4DA - 0x422;
5863 Set_UInt32( pData, fcHplxsdr );
5864 Set_UInt32( pData, 0);
5867 rStrm.Write( pDataPtr, fcMin - nUnencryptedHdr );
5868 delete[] pDataPtr;
5869 return 0 == rStrm.GetError();
5872 rtl_TextEncoding WW8Fib::GetFIBCharset(sal_uInt16 chs)
5874 OSL_ENSURE(chs <= 0x100, "overflowed winword charset set");
5875 rtl_TextEncoding eCharSet =
5876 (0x0100 == chs)
5877 ? RTL_TEXTENCODING_APPLE_ROMAN
5878 : rtl_getTextEncodingFromWindowsCharset( static_cast<sal_uInt8>(chs) );
5879 return eCharSet;
5882 WW8Style::WW8Style(SvStream& rStream, WW8Fib& rFibPara)
5883 : rFib(rFibPara), rSt(rStream), cstd(0), cbSTDBaseInFile(0),
5884 stiMaxWhenSaved(0), istdMaxFixedWhenSaved(0), nVerBuiltInNamesWhenSaved(0),
5885 ftcAsci(0), ftcFE(0), ftcOther(0), ftcBi(0)
5887 if (!checkSeek(rSt, rFib.fcStshf))
5888 return;
5890 sal_uInt16 cbStshi = 0; // 2 bytes size of the following STSHI structure
5891 sal_uInt32 nRemaining = rFib.lcbStshf;
5892 const sal_uInt32 nMinValidStshi = 4;
5894 if (rFib.GetFIBVersion() <= ww::eWW2)
5896 cbStshi = 0;
5897 cstd = 256;
5899 else
5901 if (rFib.nFib < 67) // old Version ? (need to find this again to fix)
5902 cbStshi = nMinValidStshi;
5903 else // new version
5905 if (nRemaining < sizeof(cbStshi))
5906 return;
5907 // lies die Laenge der in der Datei gespeicherten Struktur
5908 rSt >> cbStshi;
5909 nRemaining-=2;
5913 cbStshi = std::min(static_cast<sal_uInt32>(cbStshi), nRemaining);
5914 if (cbStshi < nMinValidStshi)
5915 return;
5917 sal_uInt16 nRead = cbStshi;
5920 sal_uInt16 a16Bit;
5922 if( 2 > nRead ) break;
5923 rSt >> cstd;
5925 if( 4 > nRead ) break;
5926 rSt >> cbSTDBaseInFile;
5928 if( 6 > nRead ) break;
5929 rSt >> a16Bit;
5930 fStdStylenamesWritten = a16Bit & 0x0001;
5932 if( 8 > nRead ) break;
5933 rSt >> stiMaxWhenSaved;
5935 if( 10 > nRead ) break;
5936 rSt >> istdMaxFixedWhenSaved;
5938 if( 12 > nRead ) break;
5939 rSt >> nVerBuiltInNamesWhenSaved;
5941 if( 14 > nRead ) break;
5942 rSt >> ftcAsci;
5944 if( 16 > nRead ) break;
5945 rSt >> ftcFE;
5947 if ( 18 > nRead ) break;
5948 rSt >> ftcOther;
5950 ftcBi = ftcOther;
5952 if ( 20 > nRead ) break;
5953 rSt >> ftcBi;
5955 // ggfs. den Rest ueberlesen
5956 if( 20 < nRead )
5957 rSt.SeekRel( nRead-20 );
5959 while( !this ); // Trick: obiger Block wird genau einmal durchlaufen
5960 // und kann vorzeitig per "break" verlassen werden.
5962 nRemaining -= cbStshi;
5964 //There will be stshi.cstd (cbSTD, STD) pairs in the file following the
5965 //STSHI. Note that styles can be empty, i.e. cbSTD == 0
5966 const sal_uInt32 nMinRecordSize = sizeof(sal_uInt16);
5967 sal_uInt16 nMaxPossibleRecords = nRemaining/nMinRecordSize;
5969 OSL_ENSURE(cstd <= nMaxPossibleRecords,
5970 "allegedly more styles that available data\n");
5971 cstd = std::min(cstd, nMaxPossibleRecords);
5974 // Read1STDFixed() liest ein Style ein. Wenn der Style vollstaendig vorhanden
5975 // ist, d.h. kein leerer Slot, dann wird Speicher alloziert und ein Pointer auf
5976 // die ( evtl. mit Nullen aufgefuellten ) STD geliefert. Ist es ein leerer
5977 // Slot, dann wird ein Nullpointer zurueckgeliefert.
5978 WW8_STD* WW8Style::Read1STDFixed( short& rSkip, short* pcbStd )
5980 WW8_STD* pStd = 0;
5982 sal_uInt16 cbStd(0);
5983 rSt >> cbStd; // lies Laenge
5985 sal_uInt16 nRead = cbSTDBaseInFile;
5986 if( cbStd >= cbSTDBaseInFile )
5988 // Fixed part vollst. vorhanden
5990 // read fixed part of STD
5991 pStd = new WW8_STD;
5992 memset( pStd, 0, sizeof( *pStd ) );
5996 sal_uInt16 a16Bit;
5998 if( 2 > nRead ) break;
5999 a16Bit = 0;
6000 rSt >> a16Bit;
6001 pStd->sti = a16Bit & 0x0fff ;
6002 pStd->fScratch = 0 != ( a16Bit & 0x1000 );
6003 pStd->fInvalHeight = 0 != ( a16Bit & 0x2000 );
6004 pStd->fHasUpe = 0 != ( a16Bit & 0x4000 );
6005 pStd->fMassCopy = 0 != ( a16Bit & 0x8000 );
6007 if( 4 > nRead ) break;
6008 a16Bit = 0;
6009 rSt >> a16Bit;
6010 pStd->sgc = a16Bit & 0x000f ;
6011 pStd->istdBase = ( a16Bit & 0xfff0 ) >> 4;
6013 if( 6 > nRead ) break;
6014 a16Bit = 0;
6015 rSt >> a16Bit;
6016 pStd->cupx = a16Bit & 0x000f ;
6017 pStd->istdNext = ( a16Bit & 0xfff0 ) >> 4;
6019 if( 8 > nRead ) break;
6020 a16Bit = 0;
6021 rSt >> pStd->bchUpe;
6023 // ab Ver8 sollten diese beiden Felder dazukommen:
6024 if(10 > nRead ) break;
6025 a16Bit = 0;
6026 rSt >> a16Bit;
6027 pStd->fAutoRedef = a16Bit & 0x0001 ;
6028 pStd->fHidden = ( a16Bit & 0x0002 ) >> 1;
6030 // man kann nie wissen: vorsichtshalber ueberlesen
6031 // wir eventuelle Fuellsel, die noch zum BASE-Part gehoeren...
6032 if( 10 < nRead )
6033 rSt.SeekRel( nRead-10 );
6035 while( !this ); // Trick: obiger Block wird genau einmal durchlaufen
6036 // und kann vorzeitig per "break" verlassen werden.
6038 if( (0 != rSt.GetError()) || !nRead )
6039 DELETEZ( pStd ); // per NULL den Error melden
6041 rSkip = cbStd - cbSTDBaseInFile;
6043 else
6044 { // Fixed part zu kurz
6045 if( cbStd )
6046 rSt.SeekRel( cbStd ); // ueberlies Reste
6047 rSkip = 0;
6049 if( pcbStd )
6050 *pcbStd = cbStd;
6051 return pStd;
6054 WW8_STD* WW8Style::Read1Style( short& rSkip, String* pString, short* pcbStd )
6056 // Attention: MacWord-Documents have their Stylenames
6057 // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
6059 WW8_STD* pStd = Read1STDFixed( rSkip, pcbStd ); // lese STD
6061 // String gewuenscht ?
6062 if( pString )
6063 { // echter Style ?
6064 if ( pStd )
6066 switch( rFib.nVersion )
6068 case 6:
6069 case 7:
6070 // lies Pascal-String
6071 *pString = read_uInt8_BeltAndBracesString(rSt, RTL_TEXTENCODING_MS_1252);
6072 // leading len and trailing zero --> 2
6073 rSkip -= 2+ pString->Len();
6074 break;
6075 case 8:
6076 // handle Unicode-String with leading length short and
6077 // trailing zero
6078 if (TestBeltAndBraces<sal_Unicode>(rSt))
6080 *pString = read_uInt16_BeltAndBracesString(rSt);
6081 rSkip -= (pString->Len() + 2) * 2;
6083 else
6086 #i8114#
6087 This is supposed to be impossible, its just supposed
6088 to be 16 bit count followed by the string and ending
6089 in a 0 short. But "Lotus SmartSuite Product: Word Pro"
6090 is creating invalid style names in ww7- format. So we
6091 use the belt and braces of the ms strings to see if
6092 they are not corrupt. If they are then we try them as
6093 8bit ones
6095 *pString = read_uInt8_BeltAndBracesString(rSt,RTL_TEXTENCODING_MS_1252);
6096 // leading len and trailing zero --> 2
6097 rSkip -= 2+ pString->Len();
6099 break;
6100 default:
6101 OSL_ENSURE(!this, "Es wurde vergessen, nVersion zu kodieren!");
6102 break;
6105 else
6106 *pString = aEmptyStr; // Kann keinen Namen liefern
6108 return pStd;
6115 struct WW8_FFN_Ver6 : public WW8_FFN_BASE
6117 // ab Ver6
6118 sal_Char szFfn[65]; // 0x6 bzw. 0x40 ab Ver8 zero terminated string that
6119 // records name of font.
6120 // Maximal size of szFfn is 65 characters.
6121 // Vorsicht: Dieses Array kann auch kleiner sein!!!
6122 // Possibly followed by a second sz which records the
6123 // name of an alternate font to use if the first named
6124 // font does not exist on this system.
6126 struct WW8_FFN_Ver8 : public WW8_FFN_BASE
6128 // ab Ver8 sind folgende beiden Felder eingeschoben,
6129 // werden von uns ignoriert.
6130 sal_Char panose[ 10 ]; // 0x6 PANOSE
6131 sal_Char fs[ 24 ]; // 0x10 FONTSIGNATURE
6133 // ab Ver8 als Unicode
6134 sal_uInt16 szFfn[65]; // 0x6 bzw. 0x40 ab Ver8 zero terminated string that
6135 // records name of font.
6136 // Maximal size of szFfn is 65 characters.
6137 // Vorsicht: Dieses Array kann auch kleiner sein!!!
6138 // Possibly followed by a second sz which records the
6139 // name of an alternate font to use if the first named
6140 // font does not exist on this system.
6143 // #i43762# check font name for illegal characters
6144 static void lcl_checkFontname( String& sString )
6146 // for efficiency, we'd like to use String methods as far as possible.
6147 // Hence, we will:
6148 // 1) convert all invalid chars to \u0001
6149 // 2) then erase all \u0001 chars (if any were found), and
6150 // 3) erase leading/trailing ';', in case a font name was
6151 // completely removed
6153 // convert all invalid chars to \u0001
6154 sal_Unicode* pBuffer = sString.GetBufferAccess();
6155 xub_StrLen nLen = sString.Len();
6156 bool bFound = false;
6157 for( xub_StrLen n = 0; n < nLen; n++ )
6159 if( pBuffer[n] < sal_Unicode( 0x20 ) )
6161 pBuffer[n] = sal_Unicode( 1 );
6162 bFound = true;
6165 sString.ReleaseBufferAccess();
6167 // if anything was found, remove \u0001 + leading/trailing ';'
6168 if( bFound )
6170 sString = comphelper::string::remove(sString, 1);
6171 sString = comphelper::string::strip(sString, ';');
6175 namespace
6177 sal_uInt16 calcMaxFonts(sal_uInt8 *p, sal_Int32 nFFn)
6179 // Figure out the max number of fonts defined here
6180 sal_uInt16 nMax = 0;
6181 sal_Int32 nRemaining = nFFn;
6182 while (nRemaining)
6184 //p[0] is cbFfnM1, the alleged total length of FFN - 1.
6185 //i.e. length after cbFfnM1
6186 sal_uInt16 cbFfnM1 = *p++;
6187 --nRemaining;
6189 if (cbFfnM1 > nRemaining)
6190 break;
6192 nMax++;
6193 nRemaining -= cbFfnM1;
6194 p += cbFfnM1;
6196 return nMax;
6200 WW8Fonts::WW8Fonts( SvStream& rSt, WW8Fib& rFib )
6201 : pFontA(0), nMax(0)
6203 // Attention: MacWord-Documents have their Fontnames
6204 // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
6205 if( rFib.lcbSttbfffn <= 2 )
6207 OSL_ENSURE( !this, "Fonttabelle kaputt! (rFib.lcbSttbfffn < 2)" );
6208 return;
6211 if (!checkSeek(rSt, rFib.fcSttbfffn))
6212 return;
6214 sal_Int32 nFFn = rFib.lcbSttbfffn - 2;
6216 // allocate Font Array
6217 sal_uInt8* pA = new sal_uInt8[nFFn];
6218 memset(pA, 0, nFFn);
6220 ww::WordVersion eVersion = rFib.GetFIBVersion();
6222 if( eVersion >= ww::eWW8 )
6224 // bVer8: read the count of strings in nMax
6225 rSt >> nMax;
6228 // Ver8: skip undefined uint16
6229 // Ver67: skip the herein stored total byte of structure
6230 // - we already got that information in rFib.lcbSttbfffn
6231 rSt.SeekRel( 2 );
6233 // read all font information
6234 nFFn = rSt.Read(pA, nFFn);
6235 sal_uInt16 nCalcMax = calcMaxFonts(pA, nFFn);
6237 if (eVersion < ww::eWW8)
6238 nMax = nCalcMax;
6239 else
6241 //newer versions include purportive count of fonts, so take min of that
6242 //and calced max
6243 nMax = std::min(nMax, nCalcMax);
6246 if( nMax )
6248 // allocate Index Array
6249 pFontA = new WW8_FFN[ nMax ];
6250 WW8_FFN* p = pFontA;
6252 if( eVersion <= ww::eWW2 )
6254 WW8_FFN_BASE* pVer2 = (WW8_FFN_BASE*)pA;
6255 for(sal_uInt16 i=0; i<nMax; ++i, ++p)
6257 p->cbFfnM1 = pVer2->cbFfnM1;
6259 p->prg = 0;
6260 p->fTrueType = 0;
6261 p->ff = 0;
6263 p->wWeight = ( *(((sal_uInt8*)pVer2) + 1) );
6264 p->chs = ( *(((sal_uInt8*)pVer2) + 2) );
6266 #i8726# 7- seems to encode the name in the same encoding as
6267 the font, e.g load the doc in 97 and save to see the unicode
6268 ver of the asian fontnames in that example to confirm.
6270 rtl_TextEncoding eEnc = WW8Fib::GetFIBCharset(p->chs);
6271 if ((eEnc == RTL_TEXTENCODING_SYMBOL) || (eEnc == RTL_TEXTENCODING_DONTKNOW))
6272 eEnc = RTL_TEXTENCODING_MS_1252;
6274 p->sFontname = String ( (((const sal_Char*)pVer2) + 1 + 2), eEnc);
6275 pVer2 = (WW8_FFN_BASE*)( ((sal_uInt8*)pVer2) + pVer2->cbFfnM1 + 1 );
6278 else if( eVersion < ww::eWW8 )
6280 WW8_FFN_Ver6* pVer6 = (WW8_FFN_Ver6*)pA;
6281 sal_uInt8 c2;
6282 for(sal_uInt16 i=0; i<nMax; ++i, ++p)
6284 p->cbFfnM1 = pVer6->cbFfnM1;
6285 c2 = *(((sal_uInt8*)pVer6) + 1);
6287 p->prg = c2 & 0x02;
6288 p->fTrueType = (c2 & 0x04) >> 2;
6289 // ein Reserve-Bit ueberspringen
6290 p->ff = (c2 & 0x70) >> 4;
6292 p->wWeight = SVBT16ToShort( *(SVBT16*)&pVer6->wWeight );
6293 p->chs = pVer6->chs;
6294 p->ibszAlt = pVer6->ibszAlt;
6296 #i8726# 7- seems to encode the name in the same encoding as
6297 the font, e.g load the doc in 97 and save to see the unicode
6298 ver of the asian fontnames in that example to confirm.
6300 rtl_TextEncoding eEnc = WW8Fib::GetFIBCharset(p->chs);
6301 if ((eEnc == RTL_TEXTENCODING_SYMBOL) || (eEnc == RTL_TEXTENCODING_DONTKNOW))
6302 eEnc = RTL_TEXTENCODING_MS_1252;
6303 p->sFontname = String(pVer6->szFfn, eEnc);
6304 const sal_uInt16 maxStrSize = sizeof (pVer6->szFfn) / sizeof (pVer6->szFfn[0]);
6305 if (p->ibszAlt && p->ibszAlt < maxStrSize) //don't start after end of string
6307 p->sFontname.Append(';');
6308 p->sFontname += String(pVer6->szFfn+p->ibszAlt, eEnc);
6310 else
6312 //#i18369# if its a symbol font set Symbol as fallback
6313 if (
6314 RTL_TEXTENCODING_SYMBOL == WW8Fib::GetFIBCharset(p->chs)
6315 && !p->sFontname.EqualsAscii("Symbol")
6318 p->sFontname.AppendAscii(";Symbol");
6321 pVer6 = (WW8_FFN_Ver6*)( ((sal_uInt8*)pVer6) + pVer6->cbFfnM1 + 1 );
6324 else
6326 //count of bytes in minimum FontFamilyInformation payload
6327 const sal_uInt8 cbMinFFNPayload = 41;
6328 sal_uInt16 nValidFonts = 0;
6329 sal_Int32 nRemainingFFn = nFFn;
6330 sal_uInt8* pRaw = pA;
6331 for (sal_uInt16 i=0; i < nMax && nRemainingFFn; ++i, ++p)
6333 //pRaw[0] is cbFfnM1, the alleged total length of FFN - 1
6334 //i.e. length after cbFfnM1
6335 sal_uInt8 cbFfnM1 = *pRaw++;
6336 --nRemainingFFn;
6338 if (cbFfnM1 > nRemainingFFn)
6339 break;
6341 if (cbFfnM1 < cbMinFFNPayload)
6342 break;
6344 p->cbFfnM1 = cbFfnM1;
6346 sal_uInt8 *pVer8 = pRaw;
6348 sal_uInt8 c2 = *pVer8++;
6349 --cbFfnM1;
6351 p->prg = c2 & 0x02;
6352 p->fTrueType = (c2 & 0x04) >> 2;
6353 // ein Reserve-Bit ueberspringen
6354 p->ff = (c2 & 0x70) >> 4;
6356 p->wWeight = SVBT16ToShort(*(SVBT16*)pVer8);
6357 pVer8+=2;
6358 cbFfnM1-=2;
6360 p->chs = *pVer8++;
6361 --cbFfnM1;
6363 p->ibszAlt = *pVer8++;
6364 --cbFfnM1;
6366 pVer8 += 10; //PANOSE
6367 cbFfnM1-=10;
6368 pVer8 += 24; //FONTSIGNATURE
6369 cbFfnM1-=24;
6371 OSL_ASSERT(cbFfnM1 >= 2);
6373 sal_uInt8 nMaxNullTerminatedPossible = cbFfnM1/2 - 1;
6374 sal_Unicode *pPrimary = reinterpret_cast<sal_Unicode*>(pVer8);
6375 pPrimary[nMaxNullTerminatedPossible] = 0;
6376 #ifdef OSL_BIGENDIAN
6377 swapEndian(pPrimary);
6378 #endif
6379 p->sFontname = pPrimary;
6380 if (p->ibszAlt && p->ibszAlt < nMaxNullTerminatedPossible)
6382 p->sFontname.Append(';');
6383 sal_Unicode *pSecondary = pPrimary + p->ibszAlt;
6384 #ifdef OSL_BIGENDIAN
6385 swapEndian(pSecondary);
6386 #endif
6387 p->sFontname.Append(pSecondary);
6390 // #i43762# check font name for illegal characters
6391 lcl_checkFontname( p->sFontname );
6393 // Zeiger auf Ursprungsarray einen Font nach hinten setzen
6394 pRaw += p->cbFfnM1;
6395 nRemainingFFn -= p->cbFfnM1;
6396 ++nValidFonts;
6398 OSL_ENSURE(nMax == nValidFonts, "Font count differs with availability");
6399 nMax = std::min(nMax, nValidFonts);
6402 delete[] pA;
6405 const WW8_FFN* WW8Fonts::GetFont( sal_uInt16 nNum ) const
6407 if( !pFontA || nNum >= nMax )
6408 return 0;
6410 return &pFontA[ nNum ];
6418 // Suche zu einem Header / Footer den Index in der WW-Liste von Headern / Footern
6420 // Pferdefuesse bei WinWord6 und -7:
6421 // 1) Am Anfang des Einlesens muss WWPLCF_HdFt mit Fib und Dop konstruiert werden
6422 // 2) Der Haupttext muss sequentiell ueber alle Sections gelesen werden
6423 // 3) Fuer jedes vorkommende Header / Footer - Attribut des Haupttextes
6424 // ( Darf pro Section maximal eins sein ) muss UpdateIndex() genau einmal
6425 // mit dem Parameter des Attributes gerufen werden. Dieser Aufruf muss *nach*
6426 // dem letzten Aufruf von GetTextPos() passieren.
6427 // 4) GetTextPos() darf mit genau einem der obenstehen WW_... aufgerufen werden
6428 // ( nicht verodern ! )
6429 // -> dann liefert GetTextPos() vielleicht auch ein richtiges Ergebnis
6431 WW8PLCF_HdFt::WW8PLCF_HdFt( SvStream* pSt, WW8Fib& rFib, WW8Dop& rDop )
6432 : aPLCF(*pSt, rFib.fcPlcfhdd , rFib.lcbPlcfhdd , 0)
6434 nIdxOffset = 0;
6437 cmc 23/02/2000: This dop.grpfIhdt has a bit set for each special
6438 footnote *and endnote!!* separator,continuation separator, and
6439 continuation notice entry, the documentation does not mention the
6440 endnote separators, the documentation also gets the index numbers
6441 backwards when specifiying which bits to test. The bottom six bits
6442 of this value must be tested and skipped over. Each section's
6443 grpfIhdt is then tested for the existence of the appropriate headers
6444 and footers, at the end of each section the nIdxOffset must be updated
6445 to point to the beginning of the next section's group of headers and
6446 footers in this PLCF, UpdateIndex does that task.
6448 for( sal_uInt8 nI = 0x1; nI <= 0x20; nI <<= 1 )
6449 if( nI & rDop.grpfIhdt ) // Bit gesetzt ?
6450 nIdxOffset++;
6452 nTextOfs = rFib.ccpText + rFib.ccpFtn; // Groesse des Haupttextes
6453 // und der Fussnoten
6456 bool WW8PLCF_HdFt::GetTextPos(sal_uInt8 grpfIhdt, sal_uInt8 nWhich, WW8_CP& rStart,
6457 long& rLen)
6459 sal_uInt8 nI = 0x01;
6460 short nIdx = nIdxOffset;
6461 while (true)
6463 if( nI & nWhich )
6464 break; // found
6465 if( grpfIhdt & nI )
6466 nIdx++; // uninteresting Header / Footer
6467 nI <<= 1; // text next bit
6468 if( nI > 0x20 )
6469 return false; // not found
6471 // nIdx ist HdFt-Index
6472 WW8_CP nEnd;
6473 void* pData;
6475 aPLCF.SetIdx( nIdx ); // Lookup suitable CP
6476 aPLCF.Get( rStart, nEnd, pData );
6477 rLen = nEnd - rStart;
6478 aPLCF.advance();
6480 return true;
6483 bool WW8PLCF_HdFt::GetTextPosExact(short nIdx, WW8_CP& rStart, long& rLen)
6485 WW8_CP nEnd;
6486 void* pData;
6488 aPLCF.SetIdx( nIdx ); // Lookup suitable CP
6489 aPLCF.Get( rStart, nEnd, pData );
6490 rLen = nEnd - rStart;
6491 return true;
6494 void WW8PLCF_HdFt::UpdateIndex( sal_uInt8 grpfIhdt )
6496 // Caution: Description is not correct
6497 for( sal_uInt8 nI = 0x01; nI <= 0x20; nI <<= 1 )
6498 if( nI & grpfIhdt )
6499 nIdxOffset++;
6503 // WW8Dop
6506 WW8Dop::WW8Dop(SvStream& rSt, sal_Int16 nFib, sal_Int32 nPos, sal_uInt32 nSize) : bUseThaiLineBreakingRules(false)
6508 memset( &nDataStart, 0, (&nDataEnd - &nDataStart) );
6509 fDontUseHTMLAutoSpacing = true; //default
6510 fAcetateShowAtn = true; //default
6511 const sal_uInt32 nMaxDopSize = 0x268;
6512 sal_uInt8* pDataPtr = new sal_uInt8[ nMaxDopSize ];
6513 sal_uInt8* pData = pDataPtr;
6515 sal_uInt32 nRead = nMaxDopSize < nSize ? nMaxDopSize : nSize;
6516 rSt.Seek( nPos );
6517 if (2 > nSize || nRead != rSt.Read(pData, nRead))
6518 nDopError = ERR_SWG_READ_ERROR; // Error melden
6519 else
6521 if (nMaxDopSize > nRead)
6522 memset( pData + nRead, 0, nMaxDopSize - nRead );
6524 // dann mal die Daten auswerten
6525 sal_uInt32 a32Bit;
6526 sal_uInt16 a16Bit;
6527 sal_uInt8 a8Bit;
6529 a16Bit = Get_UShort( pData ); // 0 0x00
6530 fFacingPages = 0 != ( a16Bit & 0x0001 ) ;
6531 fWidowControl = 0 != ( a16Bit & 0x0002 ) ;
6532 fPMHMainDoc = 0 != ( a16Bit & 0x0004 ) ;
6533 grfSuppression = ( a16Bit & 0x0018 ) >> 3;
6534 fpc = ( a16Bit & 0x0060 ) >> 5;
6535 grpfIhdt = ( a16Bit & 0xff00 ) >> 8;
6537 a16Bit = Get_UShort( pData ); // 2 0x02
6538 rncFtn = a16Bit & 0x0003 ;
6539 nFtn = ( a16Bit & ~0x0003 ) >> 2 ;
6541 a8Bit = Get_Byte( pData ); // 4 0x04
6542 fOutlineDirtySave = 0 != ( a8Bit & 0x01 );
6544 a8Bit = Get_Byte( pData ); // 5 0x05
6545 fOnlyMacPics = 0 != ( a8Bit & 0x01 );
6546 fOnlyWinPics = 0 != ( a8Bit & 0x02 );
6547 fLabelDoc = 0 != ( a8Bit & 0x04 );
6548 fHyphCapitals = 0 != ( a8Bit & 0x08 );
6549 fAutoHyphen = 0 != ( a8Bit & 0x10 );
6550 fFormNoFields = 0 != ( a8Bit & 0x20 );
6551 fLinkStyles = 0 != ( a8Bit & 0x40 );
6552 fRevMarking = 0 != ( a8Bit & 0x80 );
6554 a8Bit = Get_Byte( pData ); // 6 0x06
6555 fBackup = 0 != ( a8Bit & 0x01 );
6556 fExactCWords = 0 != ( a8Bit & 0x02 );
6557 fPagHidden = 0 != ( a8Bit & 0x04 );
6558 fPagResults = 0 != ( a8Bit & 0x08 );
6559 fLockAtn = 0 != ( a8Bit & 0x10 );
6560 fMirrorMargins = 0 != ( a8Bit & 0x20 );
6561 fReadOnlyRecommended = 0 != ( a8Bit & 0x40 );
6562 fDfltTrueType = 0 != ( a8Bit & 0x80 );
6564 a8Bit = Get_Byte( pData ); // 7 0x07
6565 fPagSuppressTopSpacing = 0 != ( a8Bit & 0x01 );
6566 fProtEnabled = 0 != ( a8Bit & 0x02 );
6567 fDispFormFldSel = 0 != ( a8Bit & 0x04 );
6568 fRMView = 0 != ( a8Bit & 0x08 );
6569 fRMPrint = 0 != ( a8Bit & 0x10 );
6570 fWriteReservation = 0 != ( a8Bit & 0x20 );
6571 fLockRev = 0 != ( a8Bit & 0x40 );
6572 fEmbedFonts = 0 != ( a8Bit & 0x80 );
6575 a8Bit = Get_Byte( pData ); // 8 0x08
6576 copts_fNoTabForInd = 0 != ( a8Bit & 0x01 );
6577 copts_fNoSpaceRaiseLower = 0 != ( a8Bit & 0x02 );
6578 copts_fSupressSpbfAfterPgBrk = 0 != ( a8Bit & 0x04 );
6579 copts_fWrapTrailSpaces = 0 != ( a8Bit & 0x08 );
6580 copts_fMapPrintTextColor = 0 != ( a8Bit & 0x10 );
6581 copts_fNoColumnBalance = 0 != ( a8Bit & 0x20 );
6582 copts_fConvMailMergeEsc = 0 != ( a8Bit & 0x40 );
6583 copts_fSupressTopSpacing = 0 != ( a8Bit & 0x80 );
6585 a8Bit = Get_Byte( pData ); // 9 0x09
6586 copts_fOrigWordTableRules = 0 != ( a8Bit & 0x01 );
6587 copts_fTransparentMetafiles = 0 != ( a8Bit & 0x02 );
6588 copts_fShowBreaksInFrames = 0 != ( a8Bit & 0x04 );
6589 copts_fSwapBordersFacingPgs = 0 != ( a8Bit & 0x08 );
6590 copts_fExpShRtn = 0 != ( a8Bit & 0x20 ); // #i56856#
6592 dxaTab = Get_Short( pData ); // 10 0x0a
6593 wSpare = Get_UShort( pData ); // 12 0x0c
6594 dxaHotZ = Get_UShort( pData ); // 14 0x0e
6595 cConsecHypLim = Get_UShort( pData ); // 16 0x10
6596 wSpare2 = Get_UShort( pData ); // 18 0x12
6597 dttmCreated = Get_Long( pData ); // 20 0x14
6598 dttmRevised = Get_Long( pData ); // 24 0x18
6599 dttmLastPrint = Get_Long( pData ); // 28 0x1c
6600 nRevision = Get_Short( pData ); // 32 0x20
6601 tmEdited = Get_Long( pData ); // 34 0x22
6602 cWords = Get_Long( pData ); // 38 0x26
6603 cCh = Get_Long( pData ); // 42 0x2a
6604 cPg = Get_Short( pData ); // 46 0x2e
6605 cParas = Get_Long( pData ); // 48 0x30
6607 a16Bit = Get_UShort( pData ); // 52 0x34
6608 rncEdn = a16Bit & 0x0003 ;
6609 nEdn = ( a16Bit & ~0x0003 ) >> 2;
6611 a16Bit = Get_UShort( pData ); // 54 0x36
6612 epc = a16Bit & 0x0003 ;
6613 nfcFtnRef = ( a16Bit & 0x003c ) >> 2;
6614 nfcEdnRef = ( a16Bit & 0x03c0 ) >> 6;
6615 fPrintFormData = 0 != ( a16Bit & 0x0400 );
6616 fSaveFormData = 0 != ( a16Bit & 0x0800 );
6617 fShadeFormData = 0 != ( a16Bit & 0x1000 );
6618 fWCFtnEdn = 0 != ( a16Bit & 0x8000 );
6620 cLines = Get_Long( pData ); // 56 0x38
6621 cWordsFtnEnd = Get_Long( pData ); // 60 0x3c
6622 cChFtnEdn = Get_Long( pData ); // 64 0x40
6623 cPgFtnEdn = Get_Short( pData ); // 68 0x44
6624 cParasFtnEdn = Get_Long( pData ); // 70 0x46
6625 cLinesFtnEdn = Get_Long( pData ); // 74 0x4a
6626 lKeyProtDoc = Get_Long( pData ); // 78 0x4e
6628 a16Bit = Get_UShort( pData ); // 82 0x52
6629 wvkSaved = a16Bit & 0x0007 ;
6630 wScaleSaved = ( a16Bit & 0x0ff8 ) >> 3 ;
6631 zkSaved = ( a16Bit & 0x3000 ) >> 12;
6632 fRotateFontW6 = ( a16Bit & 0x4000 ) >> 14;
6633 iGutterPos = ( a16Bit & 0x8000 ) >> 15;
6635 bei nFib >= 103 gehts weiter:
6637 if (nFib >= 103) // Word 6/32bit, 95, 97, 2000, 2002, 2003, 2007
6639 a32Bit = Get_ULong( pData ); // 84 0x54
6640 SetCompatabilityOptions(a32Bit);
6643 //#i22436#, for all WW7- documents
6644 if (nFib <= 104) // Word 95
6645 fUsePrinterMetrics = 1;
6648 bei nFib > 105 gehts weiter:
6650 if (nFib > 105) // Word 97, 2000, 2002, 2003, 2007
6652 adt = Get_Short( pData ); // 88 0x58
6654 doptypography.ReadFromMem(pData); // 90 0x5a
6656 memcpy( &dogrid, pData, sizeof( WW8_DOGRID )); // 400 0x190
6657 pData += sizeof( WW8_DOGRID );
6659 a16Bit = Get_UShort( pData ); // 410 0x19a
6660 // die untersten 9 Bit sind uninteressant
6661 fHtmlDoc = ( a16Bit & 0x0200 ) >> 9 ;
6662 fSnapBorder = ( a16Bit & 0x0800 ) >> 11 ;
6663 fIncludeHeader = ( a16Bit & 0x1000 ) >> 12 ;
6664 fIncludeFooter = ( a16Bit & 0x2000 ) >> 13 ;
6665 fForcePageSizePag = ( a16Bit & 0x4000 ) >> 14 ;
6666 fMinFontSizePag = ( a16Bit & 0x8000 ) >> 15 ;
6668 a16Bit = Get_UShort( pData ); // 412 0x19c
6669 fHaveVersions = 0 != ( a16Bit & 0x0001 );
6670 fAutoVersion = 0 != ( a16Bit & 0x0002 );
6672 pData += 12; // 414 0x19e
6674 cChWS = Get_Long( pData ); // 426 0x1aa
6675 cChWSFtnEdn = Get_Long( pData ); // 430 0x1ae
6676 grfDocEvents = Get_Long( pData ); // 434 0x1b2
6678 pData += 4+30+8; // 438 0x1b6; 442 0x1ba; 472 0x1d8; 476 0x1dc
6680 cDBC = Get_Long( pData ); // 480 0x1e0
6681 cDBCFtnEdn = Get_Long( pData ); // 484 0x1e4
6683 pData += 1 * sizeof( sal_Int32); // 488 0x1e8
6685 nfcFtnRef = Get_Short( pData ); // 492 0x1ec
6686 nfcEdnRef = Get_Short( pData ); // 494 0x1ee
6687 hpsZoonFontPag = Get_Short( pData ); // 496 0x1f0
6688 dywDispPag = Get_Short( pData ); // 498 0x1f2
6690 if (nRead >= 516)
6692 //500 -> 508, Appear to be repeated here in 2000+
6693 pData += 8; // 500 0x1f4
6694 a32Bit = Get_Long( pData ); // 508 0x1fc
6695 SetCompatabilityOptions(a32Bit);
6696 a32Bit = Get_Long( pData ); // 512 0x200
6698 // i#78591#
6699 SetCompatabilityOptions2(a32Bit);
6701 if (nRead >= 550)
6703 pData += 32;
6704 a16Bit = Get_UShort( pData );
6705 fDoNotEmbedSystemFont = ( a16Bit & 0x0001 );
6706 fWordCompat = ( a16Bit & 0x0002 ) >> 1;
6707 fLiveRecover = ( a16Bit & 0x0004 ) >> 2;
6708 fEmbedFactoids = ( a16Bit & 0x0008 ) >> 3;
6709 fFactoidXML = ( a16Bit & 0x00010 ) >> 4;
6710 fFactoidAllDone = ( a16Bit & 0x0020 ) >> 5;
6711 fFolioPrint = ( a16Bit & 0x0040 ) >> 6;
6712 fReverseFolio = ( a16Bit & 0x0080 ) >> 7;
6713 iTextLineEnding = ( a16Bit & 0x0700 ) >> 8;
6714 fHideFcc = ( a16Bit & 0x0800 ) >> 11;
6715 fAcetateShowMarkup = ( a16Bit & 0x1000 ) >> 12;
6716 fAcetateShowAtn = ( a16Bit & 0x2000 ) >> 13;
6717 fAcetateShowInsDel = ( a16Bit & 0x4000 ) >> 14;
6718 fAcetateShowProps = ( a16Bit & 0x8000 ) >> 15;
6720 if (nRead >= 600)
6722 pData += 48;
6723 a16Bit = Get_Short(pData);
6724 fUseBackGroundInAllmodes = (a16Bit & 0x0080) >> 7;
6728 delete[] pDataPtr;
6731 WW8Dop::WW8Dop() : bUseThaiLineBreakingRules(false)
6733 // first set everything to a default of 0
6734 memset( &nDataStart, 0, (&nDataEnd - &nDataStart) );
6736 fWidowControl = 1;
6737 fpc = 1;
6738 nFtn = 1;
6739 fOutlineDirtySave = 1;
6740 fHyphCapitals = 1;
6741 fBackup = 1;
6742 fPagHidden = 1;
6743 fPagResults = 1;
6744 fDfltTrueType = 1;
6747 Writer acts like this all the time at the moment, ideally we need an
6748 option for these two as well to import word docs that are not like
6749 this by default
6751 fNoLeading = 1;
6752 fUsePrinterMetrics = 1;
6754 fRMView = 1;
6755 fRMPrint = 1;
6756 dxaTab = 0x2d0;
6757 dxaHotZ = 0x168;
6758 nRevision = 1;
6759 nEdn = 1;
6761 epc = 3;
6762 nfcEdnRef = 2;
6763 fShadeFormData = 1;
6765 wvkSaved = 2;
6766 wScaleSaved = 100;
6767 zkSaved = 0;
6769 lvl = 9;
6770 fIncludeHeader = 1;
6771 fIncludeFooter = 1;
6773 cChWS = /**!!**/ 0;
6774 cChWSFtnEdn = /**!!**/ 0;
6776 cDBC = /**!!**/ 0;
6777 cDBCFtnEdn = /**!!**/ 0;
6779 fAcetateShowAtn = true;
6782 void WW8Dop::SetCompatabilityOptions(sal_uInt32 a32Bit)
6784 fNoTabForInd = ( a32Bit & 0x00000001 ) ;
6785 fNoSpaceRaiseLower = ( a32Bit & 0x00000002 ) >> 1 ;
6786 fSupressSpbfAfterPageBreak = ( a32Bit & 0x00000004 ) >> 2 ;
6787 fWrapTrailSpaces = ( a32Bit & 0x00000008 ) >> 3 ;
6788 fMapPrintTextColor = ( a32Bit & 0x00000010 ) >> 4 ;
6789 fNoColumnBalance = ( a32Bit & 0x00000020 ) >> 5 ;
6790 fConvMailMergeEsc = ( a32Bit & 0x00000040 ) >> 6 ;
6791 fSupressTopSpacing = ( a32Bit & 0x00000080 ) >> 7 ;
6792 fOrigWordTableRules = ( a32Bit & 0x00000100 ) >> 8 ;
6793 fTransparentMetafiles = ( a32Bit & 0x00000200 ) >> 9 ;
6794 fShowBreaksInFrames = ( a32Bit & 0x00000400 ) >> 10 ;
6795 fSwapBordersFacingPgs = ( a32Bit & 0x00000800 ) >> 11 ;
6796 fCompatabilityOptions_Unknown1_13 = ( a32Bit & 0x00001000 ) >> 12 ;
6797 fExpShRtn = ( a32Bit & 0x00002000 ) >> 13 ; // #i56856#
6798 fCompatabilityOptions_Unknown1_15 = ( a32Bit & 0x00004000 ) >> 14 ;
6799 fCompatabilityOptions_Unknown1_16 = ( a32Bit & 0x00008000 ) >> 15 ;
6800 fSuppressTopSpacingMac5 = ( a32Bit & 0x00010000 ) >> 16 ;
6801 fTruncDxaExpand = ( a32Bit & 0x00020000 ) >> 17 ;
6802 fPrintBodyBeforeHdr = ( a32Bit & 0x00040000 ) >> 18 ;
6803 fNoLeading = ( a32Bit & 0x00080000 ) >> 19 ;
6804 fCompatabilityOptions_Unknown1_21 = ( a32Bit & 0x00100000 ) >> 20 ;
6805 fMWSmallCaps = ( a32Bit & 0x00200000 ) >> 21 ;
6806 fCompatabilityOptions_Unknown1_23 = ( a32Bit & 0x00400000 ) >> 22 ;
6807 fCompatabilityOptions_Unknown1_24 = ( a32Bit & 0x00800800 ) >> 23 ;
6808 fCompatabilityOptions_Unknown1_25 = ( a32Bit & 0x01000000 ) >> 24 ;
6809 fCompatabilityOptions_Unknown1_26 = ( a32Bit & 0x02000000 ) >> 25 ;
6810 fCompatabilityOptions_Unknown1_27 = ( a32Bit & 0x04000000 ) >> 26 ;
6811 fCompatabilityOptions_Unknown1_28 = ( a32Bit & 0x08000000 ) >> 27 ;
6812 fCompatabilityOptions_Unknown1_29 = ( a32Bit & 0x10000000 ) >> 28 ;
6813 fCompatabilityOptions_Unknown1_30 = ( a32Bit & 0x20000000 ) >> 29 ;
6814 fCompatabilityOptions_Unknown1_31 = ( a32Bit & 0x40000000 ) >> 30 ;
6816 fUsePrinterMetrics = ( a32Bit & 0x80000000 ) >> 31 ;
6819 sal_uInt32 WW8Dop::GetCompatabilityOptions() const
6821 sal_uInt32 a32Bit = 0;
6822 if (fNoTabForInd) a32Bit |= 0x00000001;
6823 if (fNoSpaceRaiseLower) a32Bit |= 0x00000002;
6824 if (fSupressSpbfAfterPageBreak) a32Bit |= 0x00000004;
6825 if (fWrapTrailSpaces) a32Bit |= 0x00000008;
6826 if (fMapPrintTextColor) a32Bit |= 0x00000010;
6827 if (fNoColumnBalance) a32Bit |= 0x00000020;
6828 if (fConvMailMergeEsc) a32Bit |= 0x00000040;
6829 if (fSupressTopSpacing) a32Bit |= 0x00000080;
6830 if (fOrigWordTableRules) a32Bit |= 0x00000100;
6831 if (fTransparentMetafiles) a32Bit |= 0x00000200;
6832 if (fShowBreaksInFrames) a32Bit |= 0x00000400;
6833 if (fSwapBordersFacingPgs) a32Bit |= 0x00000800;
6834 if (fCompatabilityOptions_Unknown1_13) a32Bit |= 0x00001000;
6835 if (fExpShRtn) a32Bit |= 0x00002000; // #i56856#
6836 if (fCompatabilityOptions_Unknown1_15) a32Bit |= 0x00004000;
6837 if (fCompatabilityOptions_Unknown1_16) a32Bit |= 0x00008000;
6838 if (fSuppressTopSpacingMac5) a32Bit |= 0x00010000;
6839 if (fTruncDxaExpand) a32Bit |= 0x00020000;
6840 if (fPrintBodyBeforeHdr) a32Bit |= 0x00040000;
6841 if (fNoLeading) a32Bit |= 0x00080000;
6842 if (fCompatabilityOptions_Unknown1_21) a32Bit |= 0x00100000;
6843 if (fMWSmallCaps) a32Bit |= 0x00200000;
6844 if (fCompatabilityOptions_Unknown1_23) a32Bit |= 0x00400000;
6845 if (fCompatabilityOptions_Unknown1_24) a32Bit |= 0x00800000;
6846 if (fCompatabilityOptions_Unknown1_25) a32Bit |= 0x01000000;
6847 if (fCompatabilityOptions_Unknown1_26) a32Bit |= 0x02000000;
6848 if (fCompatabilityOptions_Unknown1_27) a32Bit |= 0x04000000;
6849 if (fCompatabilityOptions_Unknown1_28) a32Bit |= 0x08000000;
6850 if (fCompatabilityOptions_Unknown1_29) a32Bit |= 0x10000000;
6851 if (fCompatabilityOptions_Unknown1_30) a32Bit |= 0x20000000;
6852 if (fCompatabilityOptions_Unknown1_31) a32Bit |= 0x40000000;
6853 if (fUsePrinterMetrics) a32Bit |= 0x80000000;
6854 return a32Bit;
6857 // i#78591#
6858 void WW8Dop::SetCompatabilityOptions2(sal_uInt32 a32Bit)
6860 fCompatabilityOptions_Unknown2_1 = ( a32Bit & 0x00000001 );
6861 fCompatabilityOptions_Unknown2_2 = ( a32Bit & 0x00000002 ) >> 1 ;
6862 fDontUseHTMLAutoSpacing = ( a32Bit & 0x00000004 ) >> 2 ;
6863 fCompatabilityOptions_Unknown2_4 = ( a32Bit & 0x00000008 ) >> 3 ;
6864 fCompatabilityOptions_Unknown2_5 = ( a32Bit & 0x00000010 ) >> 4 ;
6865 fCompatabilityOptions_Unknown2_6 = ( a32Bit & 0x00000020 ) >> 5 ;
6866 fCompatabilityOptions_Unknown2_7 = ( a32Bit & 0x00000040 ) >> 6 ;
6867 fCompatabilityOptions_Unknown2_8 = ( a32Bit & 0x00000080 ) >> 7 ;
6868 fCompatabilityOptions_Unknown2_9 = ( a32Bit & 0x00000100 ) >> 8 ;
6869 fCompatabilityOptions_Unknown2_10 = ( a32Bit & 0x00000200 ) >> 9 ;
6870 fCompatabilityOptions_Unknown2_11 = ( a32Bit & 0x00000400 ) >> 10 ;
6871 fCompatabilityOptions_Unknown2_12 = ( a32Bit & 0x00000800 ) >> 11 ;
6872 fCompatabilityOptions_Unknown2_13 = ( a32Bit & 0x00001000 ) >> 12 ;
6873 fCompatabilityOptions_Unknown2_14 = ( a32Bit & 0x00002000 ) >> 13 ;
6874 fCompatabilityOptions_Unknown2_15 = ( a32Bit & 0x00004000 ) >> 14 ;
6875 fCompatabilityOptions_Unknown2_16 = ( a32Bit & 0x00008000 ) >> 15 ;
6876 fCompatabilityOptions_Unknown2_17 = ( a32Bit & 0x00010000 ) >> 16 ;
6877 fCompatabilityOptions_Unknown2_18 = ( a32Bit & 0x00020000 ) >> 17 ;
6878 fCompatabilityOptions_Unknown2_19 = ( a32Bit & 0x00040000 ) >> 18 ;
6879 fCompatabilityOptions_Unknown2_20 = ( a32Bit & 0x00080000 ) >> 19 ;
6880 fCompatabilityOptions_Unknown2_21 = ( a32Bit & 0x00100000 ) >> 20 ;
6881 fCompatabilityOptions_Unknown2_22 = ( a32Bit & 0x00200000 ) >> 21 ;
6882 fCompatabilityOptions_Unknown2_23 = ( a32Bit & 0x00400000 ) >> 22 ;
6883 fCompatabilityOptions_Unknown2_24 = ( a32Bit & 0x00800800 ) >> 23 ;
6884 fCompatabilityOptions_Unknown2_25 = ( a32Bit & 0x01000800 ) >> 24 ;
6885 fCompatabilityOptions_Unknown2_26 = ( a32Bit & 0x02000800 ) >> 25 ;
6886 fCompatabilityOptions_Unknown2_27 = ( a32Bit & 0x04000800 ) >> 26 ;
6887 fCompatabilityOptions_Unknown2_28 = ( a32Bit & 0x08000800 ) >> 27 ;
6888 fCompatabilityOptions_Unknown2_29 = ( a32Bit & 0x10000800 ) >> 28 ;
6889 fCompatabilityOptions_Unknown2_30 = ( a32Bit & 0x20000800 ) >> 29 ;
6890 fCompatabilityOptions_Unknown2_31 = ( a32Bit & 0x40000800 ) >> 30 ;
6891 fCompatabilityOptions_Unknown2_32 = ( a32Bit & 0x80000000 ) >> 31 ;
6894 sal_uInt32 WW8Dop::GetCompatabilityOptions2() const
6896 sal_uInt32 a32Bit = 0;
6897 if (fCompatabilityOptions_Unknown2_1) a32Bit |= 0x00000001;
6898 if (fCompatabilityOptions_Unknown2_2) a32Bit |= 0x00000002;
6899 if (fDontUseHTMLAutoSpacing) a32Bit |= 0x00000004;
6900 if (fCompatabilityOptions_Unknown2_4) a32Bit |= 0x00000008;
6901 if (fCompatabilityOptions_Unknown2_5) a32Bit |= 0x00000010;
6902 if (fCompatabilityOptions_Unknown2_6) a32Bit |= 0x00000020;
6903 if (fCompatabilityOptions_Unknown2_7) a32Bit |= 0x00000040;
6904 if (fCompatabilityOptions_Unknown2_8) a32Bit |= 0x00000080;
6905 if (fCompatabilityOptions_Unknown2_9) a32Bit |= 0x00000100;
6906 if (fCompatabilityOptions_Unknown2_10) a32Bit |= 0x00000200;
6907 if (fCompatabilityOptions_Unknown2_11) a32Bit |= 0x00000400;
6908 if (fCompatabilityOptions_Unknown2_12) a32Bit |= 0x00000800;
6909 if (fCompatabilityOptions_Unknown2_13) a32Bit |= 0x00001000;
6910 //#i42909# set thai "line breaking rules" compatibility option
6911 // pflin, wonder whether bUseThaiLineBreakingRules is correct
6912 // when importing word document.
6913 if (bUseThaiLineBreakingRules) a32Bit |= 0x00002000;
6914 else if (fCompatabilityOptions_Unknown2_14) a32Bit |= 0x00002000;
6915 if (fCompatabilityOptions_Unknown2_15) a32Bit |= 0x00004000;
6916 if (fCompatabilityOptions_Unknown2_16) a32Bit |= 0x00008000;
6917 if (fCompatabilityOptions_Unknown2_17) a32Bit |= 0x00010000;
6918 if (fCompatabilityOptions_Unknown2_18) a32Bit |= 0x00020000;
6919 if (fCompatabilityOptions_Unknown2_19) a32Bit |= 0x00040000;
6920 if (fCompatabilityOptions_Unknown2_20) a32Bit |= 0x00080000;
6921 if (fCompatabilityOptions_Unknown2_21) a32Bit |= 0x00100000;
6922 if (fCompatabilityOptions_Unknown2_22) a32Bit |= 0x00200000;
6923 if (fCompatabilityOptions_Unknown2_23) a32Bit |= 0x00400000;
6924 if (fCompatabilityOptions_Unknown2_24) a32Bit |= 0x00800000;
6925 if (fCompatabilityOptions_Unknown2_25) a32Bit |= 0x01000000;
6926 if (fCompatabilityOptions_Unknown2_26) a32Bit |= 0x02000000;
6927 if (fCompatabilityOptions_Unknown2_27) a32Bit |= 0x04000000;
6928 if (fCompatabilityOptions_Unknown2_28) a32Bit |= 0x08000000;
6929 if (fCompatabilityOptions_Unknown2_29) a32Bit |= 0x10000000;
6930 if (fCompatabilityOptions_Unknown2_30) a32Bit |= 0x20000000;
6931 if (fCompatabilityOptions_Unknown2_31) a32Bit |= 0x40000000;
6932 if (fCompatabilityOptions_Unknown2_32) a32Bit |= 0x80000000;
6933 return a32Bit;
6936 bool WW8Dop::Write(SvStream& rStrm, WW8Fib& rFib) const
6938 const int nMaxDopLen = 610;
6939 sal_uInt32 nLen = 8 == rFib.nVersion ? nMaxDopLen : 84;
6940 rFib.fcDop = rStrm.Tell();
6941 rFib.lcbDop = nLen;
6943 sal_uInt8 aData[ nMaxDopLen ];
6944 memset( aData, 0, nMaxDopLen );
6945 sal_uInt8* pData = aData;
6947 // dann mal die Daten auswerten
6948 sal_uInt16 a16Bit;
6949 sal_uInt8 a8Bit;
6951 a16Bit = 0; // 0 0x00
6952 if (fFacingPages)
6953 a16Bit |= 0x0001;
6954 if (fWidowControl)
6955 a16Bit |= 0x0002;
6956 if (fPMHMainDoc)
6957 a16Bit |= 0x0004;
6958 a16Bit |= ( 0x0018 & (grfSuppression << 3));
6959 a16Bit |= ( 0x0060 & (fpc << 5));
6960 a16Bit |= ( 0xff00 & (grpfIhdt << 8));
6961 Set_UInt16( pData, a16Bit );
6963 a16Bit = 0; // 2 0x02
6964 a16Bit |= ( 0x0003 & rncFtn );
6965 a16Bit |= ( ~0x0003 & (nFtn << 2));
6966 Set_UInt16( pData, a16Bit );
6968 a8Bit = 0; // 4 0x04
6969 if( fOutlineDirtySave ) a8Bit |= 0x01;
6970 Set_UInt8( pData, a8Bit );
6972 a8Bit = 0; // 5 0x05
6973 if( fOnlyMacPics ) a8Bit |= 0x01;
6974 if( fOnlyWinPics ) a8Bit |= 0x02;
6975 if( fLabelDoc ) a8Bit |= 0x04;
6976 if( fHyphCapitals ) a8Bit |= 0x08;
6977 if( fAutoHyphen ) a8Bit |= 0x10;
6978 if( fFormNoFields ) a8Bit |= 0x20;
6979 if( fLinkStyles ) a8Bit |= 0x40;
6980 if( fRevMarking ) a8Bit |= 0x80;
6981 Set_UInt8( pData, a8Bit );
6983 a8Bit = 0; // 6 0x06
6984 if( fBackup ) a8Bit |= 0x01;
6985 if( fExactCWords ) a8Bit |= 0x02;
6986 if( fPagHidden ) a8Bit |= 0x04;
6987 if( fPagResults ) a8Bit |= 0x08;
6988 if( fLockAtn ) a8Bit |= 0x10;
6989 if( fMirrorMargins ) a8Bit |= 0x20;
6990 if( fReadOnlyRecommended ) a8Bit |= 0x40;
6991 if( fDfltTrueType ) a8Bit |= 0x80;
6992 Set_UInt8( pData, a8Bit );
6994 a8Bit = 0; // 7 0x07
6995 if( fPagSuppressTopSpacing ) a8Bit |= 0x01;
6996 if( fProtEnabled ) a8Bit |= 0x02;
6997 if( fDispFormFldSel ) a8Bit |= 0x04;
6998 if( fRMView ) a8Bit |= 0x08;
6999 if( fRMPrint ) a8Bit |= 0x10;
7000 if( fWriteReservation ) a8Bit |= 0x20;
7001 if( fLockRev ) a8Bit |= 0x40;
7002 if( fEmbedFonts ) a8Bit |= 0x80;
7003 Set_UInt8( pData, a8Bit );
7006 a8Bit = 0; // 8 0x08
7007 if( copts_fNoTabForInd ) a8Bit |= 0x01;
7008 if( copts_fNoSpaceRaiseLower ) a8Bit |= 0x02;
7009 if( copts_fSupressSpbfAfterPgBrk ) a8Bit |= 0x04;
7010 if( copts_fWrapTrailSpaces ) a8Bit |= 0x08;
7011 if( copts_fMapPrintTextColor ) a8Bit |= 0x10;
7012 if( copts_fNoColumnBalance ) a8Bit |= 0x20;
7013 if( copts_fConvMailMergeEsc ) a8Bit |= 0x40;
7014 if( copts_fSupressTopSpacing ) a8Bit |= 0x80;
7015 Set_UInt8( pData, a8Bit );
7017 a8Bit = 0; // 9 0x09
7018 if( copts_fOrigWordTableRules ) a8Bit |= 0x01;
7019 if( copts_fTransparentMetafiles ) a8Bit |= 0x02;
7020 if( copts_fShowBreaksInFrames ) a8Bit |= 0x04;
7021 if( copts_fSwapBordersFacingPgs ) a8Bit |= 0x08;
7022 if( copts_fExpShRtn ) a8Bit |= 0x20; // #i56856#
7023 Set_UInt8( pData, a8Bit );
7025 Set_UInt16( pData, dxaTab ); // 10 0x0a
7026 Set_UInt16( pData, wSpare ); // 12 0x0c
7027 Set_UInt16( pData, dxaHotZ ); // 14 0x0e
7028 Set_UInt16( pData, cConsecHypLim ); // 16 0x10
7029 Set_UInt16( pData, wSpare2 ); // 18 0x12
7030 Set_UInt32( pData, dttmCreated ); // 20 0x14
7031 Set_UInt32( pData, dttmRevised ); // 24 0x18
7032 Set_UInt32( pData, dttmLastPrint ); // 28 0x1c
7033 Set_UInt16( pData, nRevision ); // 32 0x20
7034 Set_UInt32( pData, tmEdited ); // 34 0x22
7035 Set_UInt32( pData, cWords ); // 38 0x26
7036 Set_UInt32( pData, cCh ); // 42 0x2a
7037 Set_UInt16( pData, cPg ); // 46 0x2e
7038 Set_UInt32( pData, cParas ); // 48 0x30
7040 a16Bit = 0; // 52 0x34
7041 a16Bit |= ( 0x0003 & rncEdn );
7042 a16Bit |= (~0x0003 & ( nEdn << 2));
7043 Set_UInt16( pData, a16Bit );
7045 a16Bit = 0; // 54 0x36
7046 a16Bit |= (0x0003 & epc );
7047 a16Bit |= (0x003c & (nfcFtnRef << 2));
7048 a16Bit |= (0x03c0 & (nfcEdnRef << 6));
7049 if( fPrintFormData ) a16Bit |= 0x0400;
7050 if( fSaveFormData ) a16Bit |= 0x0800;
7051 if( fShadeFormData ) a16Bit |= 0x1000;
7052 if( fWCFtnEdn ) a16Bit |= 0x8000;
7053 Set_UInt16( pData, a16Bit );
7055 Set_UInt32( pData, cLines ); // 56 0x38
7056 Set_UInt32( pData, cWordsFtnEnd ); // 60 0x3c
7057 Set_UInt32( pData, cChFtnEdn ); // 64 0x40
7058 Set_UInt16( pData, cPgFtnEdn ); // 68 0x44
7059 Set_UInt32( pData, cParasFtnEdn ); // 70 0x46
7060 Set_UInt32( pData, cLinesFtnEdn ); // 74 0x4a
7061 Set_UInt32( pData, lKeyProtDoc ); // 78 0x4e
7063 a16Bit = 0; // 82 0x52
7064 if (wvkSaved)
7065 a16Bit |= 0x0007;
7066 a16Bit |= (0x0ff8 & (wScaleSaved << 3));
7067 a16Bit |= (0x3000 & (zkSaved << 12));
7068 Set_UInt16( pData, a16Bit );
7070 if( 8 == rFib.nVersion )
7072 Set_UInt32(pData, GetCompatabilityOptions()); // 84 0x54
7074 Set_UInt16( pData, adt ); // 88 0x58
7076 doptypography.WriteToMem(pData); // 400 0x190
7078 memcpy( pData, &dogrid, sizeof( WW8_DOGRID ));
7079 pData += sizeof( WW8_DOGRID );
7081 a16Bit = 0x12; // lvl auf 9 setzen // 410 0x19a
7082 if( fHtmlDoc ) a16Bit |= 0x0200;
7083 if( fSnapBorder ) a16Bit |= 0x0800;
7084 if( fIncludeHeader ) a16Bit |= 0x1000;
7085 if( fIncludeFooter ) a16Bit |= 0x2000;
7086 if( fForcePageSizePag ) a16Bit |= 0x4000;
7087 if( fMinFontSizePag ) a16Bit |= 0x8000;
7088 Set_UInt16( pData, a16Bit );
7090 a16Bit = 0; // 412 0x19c
7091 if( fHaveVersions ) a16Bit |= 0x0001;
7092 if( fAutoVersion ) a16Bit |= 0x0002;
7093 Set_UInt16( pData, a16Bit );
7095 pData += 12; // 414 0x19e
7097 Set_UInt32( pData, cChWS ); // 426 0x1aa
7098 Set_UInt32( pData, cChWSFtnEdn ); // 430 0x1ae
7099 Set_UInt32( pData, grfDocEvents ); // 434 0x1b2
7101 pData += 4+30+8; // 438 0x1b6; 442 0x1ba; 472 0x1d8; 476 0x1dc
7103 Set_UInt32( pData, cDBC ); // 480 0x1e0
7104 Set_UInt32( pData, cDBCFtnEdn ); // 484 0x1e4
7106 pData += 1 * sizeof( sal_Int32); // 488 0x1e8
7108 Set_UInt16( pData, nfcFtnRef ); // 492 0x1ec
7109 Set_UInt16( pData, nfcEdnRef ); // 494 0x1ee
7110 Set_UInt16( pData, hpsZoonFontPag ); // 496 0x1f0
7111 Set_UInt16( pData, dywDispPag ); // 498 0x1f2
7113 //500 -> 508, Appear to be repeated here in 2000+
7114 pData += 8;
7115 Set_UInt32(pData, GetCompatabilityOptions());
7116 Set_UInt32(pData, GetCompatabilityOptions2());
7117 pData += 32;
7119 a16Bit = 0;
7120 if (fAcetateShowMarkup)
7121 a16Bit |= 0x1000;
7122 //Word XP at least requires fAcetateShowMarkup to honour fAcetateShowAtn
7123 if (fAcetateShowAtn)
7125 a16Bit |= 0x1000;
7126 a16Bit |= 0x2000;
7128 Set_UInt16(pData, a16Bit);
7130 pData += 48;
7131 a16Bit = 0x0080;
7132 Set_UInt16(pData, a16Bit);
7134 rStrm.Write( aData, nLen );
7135 return 0 == rStrm.GetError();
7138 void WW8DopTypography::ReadFromMem(sal_uInt8 *&pData)
7140 sal_uInt16 a16Bit = Get_UShort(pData);
7141 fKerningPunct = (a16Bit & 0x0001);
7142 iJustification = (a16Bit & 0x0006) >> 1;
7143 iLevelOfKinsoku = (a16Bit & 0x0018) >> 3;
7144 f2on1 = (a16Bit & 0x0020) >> 5;
7145 reserved1 = (a16Bit & 0x03C0) >> 6;
7146 reserved2 = (a16Bit & 0xFC00) >> 10;
7148 cchFollowingPunct = Get_Short(pData);
7149 cchLeadingPunct = Get_Short(pData);
7151 sal_Int16 i;
7152 for (i=0; i < nMaxFollowing; ++i)
7153 rgxchFPunct[i] = Get_Short(pData);
7154 for (i=0; i < nMaxLeading; ++i)
7155 rgxchLPunct[i] = Get_Short(pData);
7157 if (cchFollowingPunct >= 0 && cchFollowingPunct < nMaxFollowing)
7158 rgxchFPunct[cchFollowingPunct]=0;
7159 else
7160 rgxchFPunct[nMaxFollowing - 1]=0;
7162 if (cchLeadingPunct >= 0 && cchLeadingPunct < nMaxLeading)
7163 rgxchLPunct[cchLeadingPunct]=0;
7164 else
7165 rgxchLPunct[nMaxLeading - 1]=0;
7169 void WW8DopTypography::WriteToMem(sal_uInt8 *&pData) const
7171 sal_uInt16 a16Bit = fKerningPunct;
7172 a16Bit |= (iJustification << 1) & 0x0006;
7173 a16Bit |= (iLevelOfKinsoku << 3) & 0x0018;
7174 a16Bit |= (f2on1 << 5) & 0x002;
7175 a16Bit |= (reserved1 << 6) & 0x03C0;
7176 a16Bit |= (reserved2 << 10) & 0xFC00;
7177 Set_UInt16(pData,a16Bit);
7179 Set_UInt16(pData,cchFollowingPunct);
7180 Set_UInt16(pData,cchLeadingPunct);
7182 sal_Int16 i;
7183 for (i=0; i < nMaxFollowing; ++i)
7184 Set_UInt16(pData,rgxchFPunct[i]);
7185 for (i=0; i < nMaxLeading; ++i)
7186 Set_UInt16(pData,rgxchLPunct[i]);
7189 sal_uInt16 WW8DopTypography::GetConvertedLang() const
7191 sal_uInt16 nLang;
7192 //I have assumed peoples republic/taiwan == simplified/traditional
7194 //This isn't a documented issue, so we might have it all wrong,
7195 //i.e. i.e. whats with the powers of two ?
7198 One example of 3 for reserved1 which was really Japanese, perhaps last bit
7199 is for some other use ?, or redundant. If more examples trigger the assert
7200 we might be able to figure it out.
7202 switch(reserved1 & 0xE)
7204 case 2: //Japan
7205 nLang = LANGUAGE_JAPANESE;
7206 break;
7207 case 4: //Chinese (Peoples Republic)
7208 nLang = LANGUAGE_CHINESE_SIMPLIFIED;
7209 break;
7210 case 6: //Korean
7211 nLang = LANGUAGE_KOREAN;
7212 break;
7213 case 8: //Chinese (Taiwan)
7214 nLang = LANGUAGE_CHINESE_TRADITIONAL;
7215 break;
7216 default:
7217 OSL_ENSURE(!this, "Unknown MS Asian Typography language, report");
7218 nLang = LANGUAGE_CHINESE;
7219 break;
7220 case 0:
7221 //And here we have the possibility that it says 2, but its really
7222 //a bug and only japanese level 2 has been selected after a custom
7223 //version was chosen on last save!
7224 nLang = LANGUAGE_JAPANESE;
7225 break;
7227 return nLang;
7231 // Sprms
7233 sal_uInt16 wwSprmParser::GetSprmTailLen(sal_uInt16 nId, const sal_uInt8* pSprm)
7234 const
7236 SprmInfo aSprm = GetSprmInfo(nId);
7237 sal_uInt16 nL = 0; // number of Bytes to read
7239 //sprmPChgTabs
7240 switch( nId )
7242 case 23:
7243 case 0xC615:
7244 if( pSprm[1 + mnDelta] != 255 )
7245 nL = static_cast< sal_uInt16 >(pSprm[1 + mnDelta] + aSprm.nLen);
7246 else
7248 sal_uInt8 nDel = pSprm[2 + mnDelta];
7249 sal_uInt8 nIns = pSprm[3 + mnDelta + 4 * nDel];
7251 nL = 2 + 4 * nDel + 3 * nIns;
7253 break;
7254 case 0xD608:
7255 nL = SVBT16ToShort( &pSprm[1 + mnDelta] );
7256 break;
7257 default:
7258 switch (aSprm.nVari)
7260 case L_FIX:
7261 nL = aSprm.nLen; // Excl. Token
7262 break;
7263 case L_VAR:
7264 // Variable 1-Byte Length?
7265 // Excl. Token + Var-Lengthbyte
7266 nL = static_cast< sal_uInt16 >(pSprm[1 + mnDelta] + aSprm.nLen);
7267 break;
7268 case L_VAR2:
7269 // Variable 2-Byte Length?
7270 // Excl. Token + Var-Lengthbyte
7271 nL = static_cast< sal_uInt16 >(SVBT16ToShort( &pSprm[1 + mnDelta] ) + aSprm.nLen - 1);
7272 break;
7273 default:
7274 OSL_ENSURE(!this, "Unknown sprm varient");
7275 break;
7277 break;
7279 return nL;
7282 // one or two bytes at the beginning at the sprm id
7283 sal_uInt16 wwSprmParser::GetSprmId(const sal_uInt8* pSp) const
7285 ASSERT_RET_ON_FAIL(pSp, "Why GetSprmId with pSp of 0", 0);
7287 sal_uInt16 nId = 0;
7289 if (ww::IsSevenMinus(meVersion))
7291 nId = *pSp;
7292 if (0x0100 < nId)
7293 nId = 0;
7295 else
7297 nId = SVBT16ToShort(pSp);
7298 if (0x0800 > nId)
7299 nId = 0;
7302 return nId;
7305 // with tokens and length byte
7306 sal_uInt16 wwSprmParser::GetSprmSize(sal_uInt16 nId, const sal_uInt8* pSprm) const
7308 return GetSprmTailLen(nId, pSprm) + 1 + mnDelta + SprmDataOfs(nId);
7311 sal_uInt8 wwSprmParser::SprmDataOfs(sal_uInt16 nId) const
7313 return GetSprmInfo(nId).nVari;
7316 sal_uInt16 wwSprmParser::DistanceToData(sal_uInt16 nId) const
7318 return 1 + mnDelta + SprmDataOfs(nId);
7321 sal_uInt8* wwSprmParser::findSprmData(sal_uInt16 nId, sal_uInt8* pSprms,
7322 sal_uInt16 nLen) const
7324 while (nLen >= MinSprmLen())
7326 sal_uInt16 nAktId = GetSprmId(pSprms);
7327 // gib Zeiger auf Daten
7328 sal_uInt16 nSize = GetSprmSize(nAktId, pSprms);
7330 bool bValid = nSize <= nLen;
7332 SAL_WARN_IF(!bValid, "sw.ww8",
7333 "sprm 0x" << std::hex << nAktId << std::dec << " longer than remaining bytes, " <<
7334 nSize << " vs " << nLen << "doc or parser is wrong");
7336 if (nAktId == nId && bValid) // Sprm found
7337 return pSprms + DistanceToData(nId);
7339 //Clip to available size if wrong
7340 nSize = std::min(nSize, nLen);
7341 pSprms += nSize;
7342 nLen -= nSize;
7344 // Sprm not found
7345 return 0;
7348 SEPr::SEPr() :
7349 bkc(2), fTitlePage(0), fAutoPgn(0), nfcPgn(0), fUnlocked(0), cnsPgn(0),
7350 fPgnRestart(0), fEndNote(1), lnc(0), grpfIhdt(0), nLnnMod(0), dxaLnn(0),
7351 dxaPgn(720), dyaPgn(720), fLBetween(0), vjc(0), dmBinFirst(0),
7352 dmBinOther(0), dmPaperReq(0), fPropRMark(0), ibstPropRMark(0),
7353 dttmPropRMark(0), dxtCharSpace(0), dyaLinePitch(0), clm(0), reserved1(0),
7354 dmOrientPage(0), iHeadingPgn(0), pgnStart(1), lnnMin(0), wTextFlow(0),
7355 reserved2(0), pgbApplyTo(0), pgbPageDepth(0), pgbOffsetFrom(0),
7356 xaPage(lLetterWidth), yaPage(lLetterHeight), xaPageNUp(lLetterWidth), yaPageNUp(lLetterHeight),
7357 dxaLeft(1800), dxaRight(1800), dyaTop(1440), dyaBottom(1440), dzaGutter(0),
7358 dyaHdrTop(720), dyaHdrBottom(720), ccolM1(0), fEvenlySpaced(1),
7359 reserved3(0), fBiDi(0), fFacingCol(0), fRTLGutter(0), fRTLAlignment(0),
7360 dxaColumns(720), dxaColumnWidth(0), dmOrientFirst(0), fLayout(0),
7361 reserved4(0)
7363 memset(rgdxaColumnWidthSpacing, 0, sizeof(rgdxaColumnWidthSpacing));
7366 bool checkSeek(SvStream &rSt, sal_uInt32 nOffset)
7368 return (rSt.Seek(nOffset) == static_cast<sal_Size>(nOffset));
7371 bool checkRead(SvStream &rSt, void *pDest, sal_uInt32 nLength)
7373 return (rSt.Read(pDest, nLength) == static_cast<sal_Size>(nLength));
7376 #ifdef OSL_BIGENDIAN
7377 void swapEndian(sal_Unicode *pString)
7379 for (sal_Unicode *pWork = pString; *pWork; ++pWork)
7380 *pWork = OSL_SWAPWORD(*pWork);
7382 #endif
7384 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */