1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include "ww8scan.hxx"
29 #include <i18nlangtag/mslangid.hxx>
30 #include "sprmids.hxx"
31 #include <rtl/tencinfo.h>
32 #include <sal/macros.h>
33 #include <sal/log.hxx>
34 #include <osl/diagnose.h>
38 #include <comphelper/string.hxx>
39 #include <unotools/localedatawrapper.hxx>
40 #include <i18nlangtag/lang.h>
41 #include <o3tl/safeint.hxx>
42 #include <tools/stream.hxx>
44 #include <vcl/settings.hxx>
45 #include <vcl/svapp.hxx>
47 #ifdef DEBUGSPRMREADER
51 using namespace ::com::sun::star::lang
;
56 winword strings are typically Belt and Braces strings preceded with a
57 pascal style count, and ending with a c style 0 terminator. 16bit chars
58 and count for ww8+ and 8bit chars and count for ww7-. The count and 0
59 can be checked for integrity to catch errors (e.g. lotus created
60 documents) where in error 8bit strings are used instead of 16bits
61 strings for style names.
63 bool TestBeltAndBraces(SvStream
& rStrm
)
66 sal_uInt32 nOldPos
= rStrm
.Tell();
68 rStrm
.ReadUInt16( nBelt
);
69 nBelt
*= sizeof(sal_Unicode
);
70 if (rStrm
.good() && (rStrm
.remainingSize() >= (nBelt
+ sizeof(sal_Unicode
))))
75 sal_Unicode
cBraces(0);
76 rStrm
.ReadUtf16( cBraces
);
77 if (rStrm
.good() && cBraces
== 0)
86 const wwSprmSearcher
*wwSprmParser::GetWW2SprmSearcher()
90 static const SprmInfoRow aSprms
[] =
92 { 0, { 0, L_FIX
} }, // "Default-sprm", will be skipped
93 { 2, { 1, L_FIX
} }, // "sprmPIstd", pap.istd (style code)
94 { 3, { 0, L_VAR
} }, // "sprmPIstdPermute pap.istd permutation
95 { 4, { 1, L_FIX
} }, // "sprmPIncLv1" pap.istddifference
96 { 5, { 1, L_FIX
} }, // "sprmPJc" pap.jc (justification)
97 { 6, { 1, L_FIX
} }, // "sprmPFSideBySide" pap.fSideBySide
98 { 7, { 1, L_FIX
} }, // "sprmPFKeep" pap.fKeep
99 { 8, { 1, L_FIX
} }, // "sprmPFKeepFollow " pap.fKeepFollow
100 { 9, { 1, L_FIX
} }, // "sprmPPageBreakBefore" pap.fPageBreakBefore
101 { 10, { 1, L_FIX
} }, // "sprmPBrcl" pap.brcl
102 { 11, { 1, L_FIX
} }, // "sprmPBrcp" pap.brcp
103 { 12, { 1, L_FIX
} }, // "sprmPNfcSeqNumb" pap.nfcSeqNumb
104 { 13, { 1, L_FIX
} }, // "sprmPNoSeqNumb" pap.nnSeqNumb
105 { 14, { 1, L_FIX
} }, // "sprmPFNoLineNumb" pap.fNoLnn
106 { 15, { 0, L_VAR
} }, // "?sprmPChgTabsPapx" pap.itbdMac, ...
107 { 16, { 2, L_FIX
} }, // "sprmPDxaRight" pap.dxaRight
108 { 17, { 2, L_FIX
} }, // "sprmPDxaLeft" pap.dxaLeft
109 { 18, { 2, L_FIX
} }, // "sprmPNest" pap.dxaLeft
110 { 19, { 2, L_FIX
} }, // "sprmPDxaLeft1" pap.dxaLeft1
111 { 20, { 2, L_FIX
} }, // "sprmPDyaLine" pap.lspd an LSPD
112 { 21, { 2, L_FIX
} }, // "sprmPDyaBefore" pap.dyaBefore
113 { 22, { 2, L_FIX
} }, // "sprmPDyaAfter" pap.dyaAfter
114 { 23, { 0, L_VAR
} }, // "?sprmPChgTabs" pap.itbdMac, pap.rgdxaTab, ...
115 { 24, { 1, L_FIX
} }, // "sprmPFInTable" pap.fInTable
116 { 25, { 1, L_FIX
} }, // "sprmPTtp" pap.fTtp
117 { 26, { 2, L_FIX
} }, // "sprmPDxaAbs" pap.dxaAbs
118 { 27, { 2, L_FIX
} }, // "sprmPDyaAbs" pap.dyaAbs
119 { 28, { 2, L_FIX
} }, // "sprmPDxaWidth" pap.dxaWidth
120 { 29, { 1, L_FIX
} }, // "sprmPPc" pap.pcHorz, pap.pcVert
121 { 30, { 2, L_FIX
} }, // "sprmPBrcTop10" pap.brcTop BRC10
122 { 31, { 2, L_FIX
} }, // "sprmPBrcLeft10" pap.brcLeft BRC10
123 { 32, { 2, L_FIX
} }, // "sprmPBrcBottom10" pap.brcBottom BRC10
124 { 33, { 2, L_FIX
} }, // "sprmPBrcRight10" pap.brcRight BRC10
125 { 34, { 2, L_FIX
} }, // "sprmPBrcBetween10" pap.brcBetween BRC10
126 { 35, { 2, L_FIX
} }, // "sprmPBrcBar10" pap.brcBar BRC10
127 { 36, { 2, L_FIX
} }, // "sprmPFromText10" pap.dxaFromText dxa
128 { 37, { 1, L_FIX
} }, // "sprmPWr" pap.wr wr
129 { 38, { 2, L_FIX
} }, // "sprmPBrcTop" pap.brcTop BRC
130 { 39, { 2, L_FIX
} }, // "sprmPBrcLeft" pap.brcLeft BRC
131 { 40, { 2, L_FIX
} }, // "sprmPBrcBottom" pap.brcBottom BRC
132 { 41, { 2, L_FIX
} }, // "sprmPBrcRight" pap.brcRight BRC
133 { 42, { 2, L_FIX
} }, // "sprmPBrcBetween" pap.brcBetween BRC
134 { 43, { 2, L_FIX
} }, // "sprmPBrcBar" pap.brcBar BRC word
135 { 44, { 1, L_FIX
} }, // "sprmPFNoAutoHyph" pap.fNoAutoHyph
136 { 45, { 2, L_FIX
} }, // "sprmPWHeightAbs" pap.wHeightAbs w
137 { 46, { 2, L_FIX
} }, // "sprmPDcs" pap.dcs DCS
138 { 47, { 2, L_FIX
} }, // "sprmPShd" pap.shd SHD
139 { 48, { 2, L_FIX
} }, // "sprmPDyaFromText" pap.dyaFromText dya
140 { 49, { 2, L_FIX
} }, // "sprmPDxaFromText" pap.dxaFromText dxa
141 { 50, { 1, L_FIX
} }, // "sprmPFBiDi" pap.fBiDi 0 or 1 byte
142 { 51, { 1, L_FIX
} }, // "sprmPFWidowControl" pap.fWidowControl 0 or 1 byte
143 { 52, { 0, L_FIX
} }, // "?sprmPRuler 52"
144 { 53, { 1, L_FIX
} }, // "sprmCFStrikeRM" chp.fRMarkDel 1 or 0 bit
145 { 54, { 1, L_FIX
} }, // "sprmCFRMark" chp.fRMark 1 or 0 bit
146 { 55, { 1, L_FIX
} }, // "sprmCFFieldVanish" chp.fFieldVanish 1 or 0 bit
147 { 57, { 0, L_VAR
} }, // "sprmCDefault" whole CHP
148 { 58, { 0, L_FIX
} }, // "sprmCPlain" whole CHP
149 { 60, { 1, L_FIX
} }, // "sprmCFBold" chp.fBold 0,1, 128, or 129
150 { 61, { 1, L_FIX
} }, // "sprmCFItalic" chp.fItalic 0,1, 128, or 129
151 { 62, { 1, L_FIX
} }, // "sprmCFStrike" chp.fStrike 0,1, 128, or 129
152 { 63, { 1, L_FIX
} }, // "sprmCFOutline" chp.fOutline 0,1, 128, or 129
153 { 64, { 1, L_FIX
} }, // "sprmCFShadow" chp.fShadow 0,1, 128, or 129
154 { 65, { 1, L_FIX
} }, // "sprmCFSmallCaps" chp.fSmallCaps 0,1, 128, or 129
155 { 66, { 1, L_FIX
} }, // "sprmCFCaps" chp.fCaps 0,1, 128, or 129
156 { 67, { 1, L_FIX
} }, // "sprmCFVanish" chp.fVanish 0,1, 128, or 129
157 { 68, { 2, L_FIX
} }, // "sprmCFtc" chp.ftc ftc word
158 { 69, { 1, L_FIX
} }, // "sprmCKul" chp.kul kul byte
159 { 70, { 3, L_FIX
} }, // "sprmCSizePos" chp.hps, chp.hpsPos
160 { 71, { 2, L_FIX
} }, // "sprmCDxaSpace" chp.dxaSpace dxa
161 { 72, { 2, L_FIX
} }, // "sprmCLid" chp.lid LID
162 { 73, { 1, L_FIX
} }, // "sprmCIco" chp.ico ico byte
163 { 74, { 1, L_FIX
} }, // "sprmCHps" chp.hps hps !word!
164 { 75, { 1, L_FIX
} }, // "sprmCHpsInc" chp.hps
165 { 76, { 1, L_FIX
} }, // "sprmCHpsPos" chp.hpsPos hps !word!
166 { 77, { 1, L_FIX
} }, // "sprmCHpsPosAdj" chp.hpsPos hps
167 { 78, { 0, L_VAR
} }, // "?sprmCMajority" chp.fBold, chp.fItalic, ...
168 { 80, { 1, L_FIX
} }, // "sprmCFBoldBi" chp.fBoldBi
169 { 81, { 1, L_FIX
} }, // "sprmCFItalicBi" chp.fItalicBi
170 { 82, { 2, L_FIX
} }, // "sprmCFtcBi" chp.ftcBi
171 { 83, { 2, L_FIX
} }, // "sprmClidBi" chp.lidBi
172 { 84, { 1, L_FIX
} }, // "sprmCIcoBi" chp.icoBi
173 { 85, { 1, L_FIX
} }, // "sprmCHpsBi" chp.hpsBi
174 { 86, { 1, L_FIX
} }, // "sprmCFBiDi" chp.fBiDi
175 { 87, { 1, L_FIX
} }, // "sprmCFDiacColor" chp.fDiacUSico
176 { 94, { 1, L_FIX
} }, // "sprmPicBrcl" pic.brcl brcl (see PIC definition)
177 { 95, {12, L_VAR
} }, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
178 { 96, { 2, L_FIX
} }, // "sprmPicBrcTop" pic.brcTop BRC word
179 { 97, { 2, L_FIX
} }, // "sprmPicBrcLeft" pic.brcLeft BRC word
180 { 98, { 2, L_FIX
} }, // "sprmPicBrcBottom" pic.brcBottom BRC word
181 { 99, { 2, L_FIX
} }, // "sprmPicBrcRight" pic.brcRight BRC word
182 {112, { 1, L_FIX
} }, // "sprmSFRTLGutter", set to one if gutter is on
183 {114, { 1, L_FIX
} }, // "sprmSFBiDi" ;;;
184 {115, { 2, L_FIX
} }, // "sprmSDmBinFirst" sep.dmBinFirst word
185 {116, { 2, L_FIX
} }, // "sprmSDmBinOther" sep.dmBinOther word
186 {117, { 1, L_FIX
} }, // "sprmSBkc" sep.bkc bkc byte
187 {118, { 1, L_FIX
} }, // "sprmSFTitlePage" sep.fTitlePage 0 or 1 byte
188 {119, { 2, L_FIX
} }, // "sprmSCcolumns" sep.ccolM1 # of cols - 1 word
189 {120, { 2, L_FIX
} }, // "sprmSDxaColumns" sep.dxaColumns dxa word
190 {121, { 1, L_FIX
} }, // "sprmSFAutoPgn" sep.fAutoPgn obsolete byte
191 {122, { 1, L_FIX
} }, // "sprmSNfcPgn" sep.nfcPgn nfc byte
192 {123, { 2, L_FIX
} }, // "sprmSDyaPgn" sep.dyaPgn dya short
193 {124, { 2, L_FIX
} }, // "sprmSDxaPgn" sep.dxaPgn dya short
194 {125, { 1, L_FIX
} }, // "sprmSFPgnRestart" sep.fPgnRestart 0 or 1 byte
195 {126, { 1, L_FIX
} }, // "sprmSFEndnote" sep.fEndnote 0 or 1 byte
196 {127, { 1, L_FIX
} }, // "sprmSLnc" sep.lnc lnc byte
197 {128, { 1, L_FIX
} }, // "sprmSGprfIhdt" sep.grpfIhdt grpfihdt
198 {129, { 2, L_FIX
} }, // "sprmSNLnnMod" sep.nLnnMod non-neg int. word
199 {130, { 2, L_FIX
} }, // "sprmSDxaLnn" sep.dxaLnn dxa word
200 {131, { 2, L_FIX
} }, // "sprmSDyaHdrTop" sep.dyaHdrTop dya word
201 {132, { 2, L_FIX
} }, // "sprmSDyaHdrBottom" sep.dyaHdrBottom dya word
202 {133, { 1, L_FIX
} }, // "sprmSLBetween" sep.fLBetween 0 or 1 byte
203 {134, { 1, L_FIX
} }, // "sprmSVjc" sep.vjc vjc byte
204 {135, { 2, L_FIX
} }, // "sprmSLnnMin" sep.lnnMin lnn word
205 {136, { 2, L_FIX
} }, // "sprmSPgnStart" sep.pgnStart pgn word
206 {137, { 1, L_FIX
} }, // "sprmSBOrientation" sep.dmOrientPage dm byte
207 {138, { 1, L_FIX
} }, // "sprmSFFacingCol" ;;;
208 {139, { 2, L_FIX
} }, // "sprmSXaPage" sep.xaPage xa word
209 {140, { 2, L_FIX
} }, // "sprmSYaPage" sep.yaPage ya word
210 {141, { 2, L_FIX
} }, // "sprmSDxaLeft" sep.dxaLeft dxa word
211 {142, { 2, L_FIX
} }, // "sprmSDxaRight" sep.dxaRight dxa word
212 {143, { 2, L_FIX
} }, // "sprmSDyaTop" sep.dyaTop dya word
213 {144, { 2, L_FIX
} }, // "sprmSDyaBottom" sep.dyaBottom dya word
214 {145, { 2, L_FIX
} }, // "sprmSDzaGutter" sep.dzaGutter dza word
215 {146, { 2, L_FIX
} }, // "sprmTJc" tap.jc jc (low order byte is significant)
216 {147, { 2, L_FIX
} }, // "sprmTDxaLeft" tap.rgdxaCenter dxa word
217 {148, { 2, L_FIX
} }, // "sprmTDxaGapHalf" tap.dxaGapHalf, tap.rgdxaCenter
218 {149, { 1, L_FIX
} }, // "sprmTFBiDi" ;;;
219 {152, { 0, L_VAR2
} },// "sprmTDefTable10" tap.rgdxaCenter, tap.rgtc complex
220 {153, { 2, L_FIX
} }, // "sprmTDyaRowHeight" tap.dyaRowHeight dya word
221 {154, { 0, L_VAR2
} },// "sprmTDefTable" tap.rgtc complex
222 {155, { 1, L_VAR
} }, // "sprmTDefTableShd" tap.rgshd complex
223 {157, { 5, L_FIX
} }, // "sprmTSetBrc" tap.rgtc[].rgbrc complex 5 bytes
224 {158, { 4, L_FIX
} }, // "sprmTInsert" tap.rgdxaCenter,tap.rgtc complex
225 {159, { 2, L_FIX
} }, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc complex
226 {160, { 4, L_FIX
} }, // "sprmTDxaCol" tap.rgdxaCenter complex
227 {161, { 2, L_FIX
} }, // "sprmTMerge" tap.fFirstMerged, tap.fMerged complex
228 {162, { 2, L_FIX
} }, // "sprmTSplit" tap.fFirstMerged, tap.fMerged complex
229 {163, { 5, L_FIX
} }, // "sprmTSetBrc10" tap.rgtc[].rgbrc complex 5 bytes
230 {164, { 4, L_FIX
} }, // "sprmTSetShd", tap.rgshd complex 4 bytes
233 static wwSprmSearcher
aSprmSrch(aSprms
, SAL_N_ELEMENTS(aSprms
));
237 const wwSprmSearcher
*wwSprmParser::GetWW6SprmSearcher(const WW8Fib
& rFib
)
241 static const SprmInfoRow aSprms
[] =
243 { 0, { 0, L_FIX
} }, // "Default-sprm", is skipped
244 {NS_sprm::v6::sprmPIstd
, { 2, L_FIX
} }, // pap.istd (style code)
245 {NS_sprm::v6::sprmPIstdPermute
, { 3, L_VAR
} }, // pap.istd permutation
246 {NS_sprm::v6::sprmPIncLv1
, { 1, L_FIX
} }, // pap.istddifference
247 {NS_sprm::v6::sprmPJc
, { 1, L_FIX
} }, // pap.jc (justification)
248 {NS_sprm::v6::sprmPFSideBySide
, { 1, L_FIX
} }, // pap.fSideBySide
249 {NS_sprm::v6::sprmPFKeep
, { 1, L_FIX
} }, // pap.fKeep
250 {NS_sprm::v6::sprmPFKeepFollow
, { 1, L_FIX
} }, // pap.fKeepFollow
251 {NS_sprm::v6::sprmPPageBreakBefore
, { 1, L_FIX
} }, // pap.fPageBreakBefore
252 {NS_sprm::v6::sprmPBrcl
, { 1, L_FIX
} }, // pap.brcl
253 {NS_sprm::v6::sprmPBrcp
, { 1, L_FIX
} }, // pap.brcp
254 {NS_sprm::v6::sprmPAnld
, { 0, L_VAR
} }, // pap.anld (ANLD structure)
255 {NS_sprm::v6::sprmPNLvlAnm
, { 1, L_FIX
} }, // pap.nLvlAnm nn
256 {NS_sprm::v6::sprmPFNoLineNumb
, { 1, L_FIX
} }, // pap.fNoLnn
257 {NS_sprm::v6::sprmPChgTabsPapx
, { 0, L_VAR
} }, // pap.itbdMac, ...
258 {NS_sprm::v6::sprmPDxaRight
, { 2, L_FIX
} }, // pap.dxaRight
259 {NS_sprm::v6::sprmPDxaLeft
, { 2, L_FIX
} }, // pap.dxaLeft
260 {NS_sprm::v6::sprmPNest
, { 2, L_FIX
} }, // pap.dxaLeft
261 {NS_sprm::v6::sprmPDxaLeft1
, { 2, L_FIX
} }, // pap.dxaLeft1
262 {NS_sprm::v6::sprmPDyaLine
, { 4, L_FIX
} }, // pap.lspd an LSPD
263 {NS_sprm::v6::sprmPDyaBefore
, { 2, L_FIX
} }, // pap.dyaBefore
264 {NS_sprm::v6::sprmPDyaAfter
, { 2, L_FIX
} }, // pap.dyaAfter
265 {NS_sprm::v6::sprmPChgTabs
, { 0, L_VAR
} }, // pap.itbdMac, pap.rgdxaTab, ...
266 {NS_sprm::v6::sprmPFInTable
, { 1, L_FIX
} }, // pap.fInTable
267 {NS_sprm::v6::sprmPTtp
, { 1, L_FIX
} }, // pap.fTtp
268 {NS_sprm::v6::sprmPDxaAbs
, { 2, L_FIX
} }, // pap.dxaAbs
269 {NS_sprm::v6::sprmPDyaAbs
, { 2, L_FIX
} }, // pap.dyaAbs
270 {NS_sprm::v6::sprmPDxaWidth
, { 2, L_FIX
} }, // pap.dxaWidth
271 {NS_sprm::v6::sprmPPc
, { 1, L_FIX
} }, // pap.pcHorz, pap.pcVert
272 {NS_sprm::v6::sprmPBrcTop10
, { 2, L_FIX
} }, // pap.brcTop BRC10
273 {NS_sprm::v6::sprmPBrcLeft10
, { 2, L_FIX
} }, // pap.brcLeft BRC10
274 {NS_sprm::v6::sprmPBrcBottom10
, { 2, L_FIX
} }, // pap.brcBottom BRC10
275 {NS_sprm::v6::sprmPBrcRight10
, { 2, L_FIX
} }, // pap.brcRight BRC10
276 {NS_sprm::v6::sprmPBrcBetween10
, { 2, L_FIX
} }, // pap.brcBetween BRC10
277 {NS_sprm::v6::sprmPBrcBar10
, { 2, L_FIX
} }, // pap.brcBar BRC10
278 {NS_sprm::v6::sprmPFromText10
, { 2, L_FIX
} }, // pap.dxaFromText dxa
279 {NS_sprm::v6::sprmPWr
, { 1, L_FIX
} }, // pap.wr wr
280 {NS_sprm::v6::sprmPBrcTop
, { 2, L_FIX
} }, // pap.brcTop BRC
281 {NS_sprm::v6::sprmPBrcLeft
, { 2, L_FIX
} }, // pap.brcLeft BRC
282 {NS_sprm::v6::sprmPBrcBottom
, { 2, L_FIX
} }, // pap.brcBottom BRC
283 {NS_sprm::v6::sprmPBrcRight
, { 2, L_FIX
} }, // pap.brcRight BRC
284 {NS_sprm::v6::sprmPBrcBetween
, { 2, L_FIX
} }, // pap.brcBetween BRC
285 {NS_sprm::v6::sprmPBrcBar
, { 2, L_FIX
} }, // pap.brcBar BRC word
286 {NS_sprm::v6::sprmPFNoAutoHyph
, { 1, L_FIX
} }, // pap.fNoAutoHyph
287 {NS_sprm::v6::sprmPWHeightAbs
, { 2, L_FIX
} }, // pap.wHeightAbs w
288 {NS_sprm::v6::sprmPDcs
, { 2, L_FIX
} }, // pap.dcs DCS
289 {NS_sprm::v6::sprmPShd
, { 2, L_FIX
} }, // pap.shd SHD
290 {NS_sprm::v6::sprmPDyaFromText
, { 2, L_FIX
} }, // pap.dyaFromText dya
291 {NS_sprm::v6::sprmPDxaFromText
, { 2, L_FIX
} }, // pap.dxaFromText dxa
292 {NS_sprm::v6::sprmPFLocked
, { 1, L_FIX
} }, // pap.fLocked 0 or 1 byte
293 {NS_sprm::v6::sprmPFWidowControl
, { 1, L_FIX
} }, // pap.fWidowControl 0 or 1 byte
294 {NS_sprm::v6::sprmPRuler
, { 0, L_FIX
} },
295 { 64, { 0, L_VAR
} }, // rtl property ?
296 {NS_sprm::v6::sprmCFStrikeRM
, { 1, L_FIX
} }, // chp.fRMarkDel 1 or 0 bit
297 {NS_sprm::v6::sprmCFRMark
, { 1, L_FIX
} }, // chp.fRMark 1 or 0 bit
298 {NS_sprm::v6::sprmCFFldVanish
, { 1, L_FIX
} }, // chp.fFieldVanish 1 or 0 bit
299 {NS_sprm::v6::sprmCPicLocation
, { 0, L_VAR
} }, // chp.fcPic and chp.fSpec
300 {NS_sprm::v6::sprmCIbstRMark
, { 2, L_FIX
} }, // chp.ibstRMark index into sttbRMark
301 {NS_sprm::v6::sprmCDttmRMark
, { 4, L_FIX
} }, // chp.dttm DTTM long
302 {NS_sprm::v6::sprmCFData
, { 1, L_FIX
} }, // chp.fData 1 or 0 bit
303 {NS_sprm::v6::sprmCRMReason
, { 2, L_FIX
} }, // chp.idslRMReason an index to a table
304 {NS_sprm::v6::sprmCChse
, { 3, L_FIX
} }, // chp.fChsDiff and chp.chse
305 {NS_sprm::v6::sprmCSymbol
, { 0, L_VAR
} }, // chp.fSpec, chp.chSym and chp.ftcSym
306 {NS_sprm::v6::sprmCFOle2
, { 1, L_FIX
} }, // chp.fOle2 1 or 0 bit
307 { 77, { 0, L_VAR
} }, // unknown
308 { 79, { 0, L_VAR
} }, // unknown
309 {NS_sprm::v6::sprmCIstd
, { 2, L_FIX
} }, // chp.istd istd, see stylesheet definition
310 {NS_sprm::v6::sprmCIstdPermute
, { 0, L_VAR
} }, // chp.istd permutation vector
311 {NS_sprm::v6::sprmCDefault
, { 0, L_VAR
} }, // whole CHP
312 {NS_sprm::v6::sprmCPlain
, { 0, L_FIX
} }, // whole CHP
313 {NS_sprm::v6::sprmCFBold
, { 1, L_FIX
} }, // chp.fBold 0,1, 128, or 129
314 {NS_sprm::v6::sprmCFItalic
, { 1, L_FIX
} }, // chp.fItalic 0,1, 128, or 129
315 {NS_sprm::v6::sprmCFStrike
, { 1, L_FIX
} }, // chp.fStrike 0,1, 128, or 129
316 {NS_sprm::v6::sprmCFOutline
, { 1, L_FIX
} }, // chp.fOutline 0,1, 128, or 129
317 {NS_sprm::v6::sprmCFShadow
, { 1, L_FIX
} }, // chp.fShadow 0,1, 128, or 129
318 {NS_sprm::v6::sprmCFSmallCaps
, { 1, L_FIX
} }, // chp.fSmallCaps 0,1, 128, or 129
319 {NS_sprm::v6::sprmCFCaps
, { 1, L_FIX
} }, // chp.fCaps 0,1, 128, or 129
320 {NS_sprm::v6::sprmCFVanish
, { 1, L_FIX
} }, // chp.fVanish 0,1, 128, or 129
321 {NS_sprm::v6::sprmCFtc
, { 2, L_FIX
} }, // chp.ftc ftc word
322 {NS_sprm::v6::sprmCKul
, { 1, L_FIX
} }, // chp.kul kul byte
323 {NS_sprm::v6::sprmCSizePos
, { 3, L_FIX
} }, // chp.hps, chp.hpsPos
324 {NS_sprm::v6::sprmCDxaSpace
, { 2, L_FIX
} }, // chp.dxaSpace dxa
325 {NS_sprm::v6::sprmCLid
, { 2, L_FIX
} }, // chp.lid LID
326 {NS_sprm::v6::sprmCIco
, { 1, L_FIX
} }, // chp.ico ico byte
327 {NS_sprm::v6::sprmCHps
, { 2, L_FIX
} }, // chp.hps hps !word!
328 {NS_sprm::v6::sprmCHpsInc
, { 1, L_FIX
} }, // chp.hps
329 {NS_sprm::v6::sprmCHpsPos
, { 2, L_FIX
} }, // chp.hpsPos hps !word!
330 {NS_sprm::v6::sprmCHpsPosAdj
, { 1, L_FIX
} }, // chp.hpsPos hps
331 {NS_sprm::v6::sprmCMajority
, { 0, L_VAR
} }, // chp.fBold, chp.fItalic, ...
332 {NS_sprm::v6::sprmCIss
, { 1, L_FIX
} }, // chp.iss iss
333 {NS_sprm::v6::sprmCHpsNew50
, { 0, L_VAR
} }, // chp.hps hps variable width
334 {NS_sprm::v6::sprmCHpsInc1
, { 0, L_VAR
} }, // chp.hps complex
335 {NS_sprm::v6::sprmCHpsKern
, { 2, L_FIX
} }, // chp.hpsKern hps
336 {NS_sprm::v6::sprmCMajority50
, { 0, L_VAR
} }, // chp.fBold, chp.fItalic, ...
337 {NS_sprm::v6::sprmCHpsMul
, { 2, L_FIX
} }, // chp.hps percentage to grow hps
338 {NS_sprm::v6::sprmCCondHyhen
, { 2, L_FIX
} }, // chp.ysri ysri
339 {111, { 0, L_VAR
} }, // sprmCFBoldBi or font code
340 {112, { 0, L_VAR
} }, // sprmCFItalicBi or font code
341 {113, { 0, L_VAR
} }, // ww7 rtl font
342 {114, { 0, L_VAR
} }, // ww7 lid
343 {115, { 0, L_VAR
} }, // ww7 CJK font
344 {116, { 0, L_VAR
} }, // ww7 fontsize
345 {NS_sprm::v6::sprmCFSpec
, { 1, L_FIX
} }, // chp.fSpec 1 or 0 bit
346 {NS_sprm::v6::sprmCFObj
, { 1, L_FIX
} }, // chp.fObj 1 or 0 bit
347 {NS_sprm::v6::sprmPicBrcl
, { 1, L_FIX
} }, // pic.brcl brcl (see PIC definition)
348 {NS_sprm::v6::sprmPicScale
, {12, L_VAR
} }, // pic.mx, pic.my, pic.dxaCropleft,
349 {NS_sprm::v6::sprmPicBrcTop
, { 2, L_FIX
} }, // pic.brcTop BRC word
350 {NS_sprm::v6::sprmPicBrcLeft
, { 2, L_FIX
} }, // pic.brcLeft BRC word
351 {NS_sprm::v6::sprmPicBrcBottom
, { 2, L_FIX
} }, // pic.brcBottom BRC word
352 {NS_sprm::v6::sprmPicBrcRight
, { 2, L_FIX
} }, // pic.brcRight BRC word
353 {NS_sprm::v6::sprmSScnsPgn
, { 1, L_FIX
} }, // sep.cnsPgn cns byte
354 {NS_sprm::v6::sprmSiHeadingPgn
, { 1, L_FIX
} }, // sep.iHeadingPgn
355 {NS_sprm::v6::sprmSOlstAnm
, { 0, L_VAR
} }, // sep.olstAnm OLST variable length
356 {NS_sprm::v6::sprmSDxaColWidth
, { 3, L_FIX
} }, // sep.rgdxaColWidthSpacing complex
357 {NS_sprm::v6::sprmSDxaColSpacing
, { 3, L_FIX
} }, // sep.rgdxaColWidthSpacing
358 {NS_sprm::v6::sprmSFEvenlySpaced
, { 1, L_FIX
} }, // sep.fEvenlySpaced 1 or 0
359 {NS_sprm::v6::sprmSFProtected
, { 1, L_FIX
} }, // sep.fUnlocked 1 or 0 byte
360 {NS_sprm::v6::sprmSDmBinFirst
, { 2, L_FIX
} }, // sep.dmBinFirst word
361 {NS_sprm::v6::sprmSDmBinOther
, { 2, L_FIX
} }, // sep.dmBinOther word
362 {NS_sprm::v6::sprmSBkc
, { 1, L_FIX
} }, // sep.bkc bkc byte
363 {NS_sprm::v6::sprmSFTitlePage
, { 1, L_FIX
} }, // sep.fTitlePage 0 or 1 byte
364 {NS_sprm::v6::sprmSCcolumns
, { 2, L_FIX
} }, // sep.ccolM1 # of cols - 1 word
365 {NS_sprm::v6::sprmSDxaColumns
, { 2, L_FIX
} }, // sep.dxaColumns dxa word
366 {NS_sprm::v6::sprmSFAutoPgn
, { 1, L_FIX
} }, // sep.fAutoPgn obsolete byte
367 {NS_sprm::v6::sprmSNfcPgn
, { 1, L_FIX
} }, // sep.nfcPgn nfc byte
368 {NS_sprm::v6::sprmSDyaPgn
, { 2, L_FIX
} }, // sep.dyaPgn dya short
369 {NS_sprm::v6::sprmSDxaPgn
, { 2, L_FIX
} }, // sep.dxaPgn dya short
370 {NS_sprm::v6::sprmSFPgnRestart
, { 1, L_FIX
} }, // sep.fPgnRestart 0 or 1 byte
371 {NS_sprm::v6::sprmSFEndnote
, { 1, L_FIX
} }, // sep.fEndnote 0 or 1 byte
372 {NS_sprm::v6::sprmSLnc
, { 1, L_FIX
} }, // sep.lnc lnc byte
373 {NS_sprm::v6::sprmSGprfIhdt
, { 1, L_FIX
} }, // sep.grpfIhdt grpfihdt
374 {NS_sprm::v6::sprmSNLnnMod
, { 2, L_FIX
} }, // sep.nLnnMod non-neg int. word
375 {NS_sprm::v6::sprmSDxaLnn
, { 2, L_FIX
} }, // sep.dxaLnn dxa word
376 {NS_sprm::v6::sprmSDyaHdrTop
, { 2, L_FIX
} }, // sep.dyaHdrTop dya word
377 {NS_sprm::v6::sprmSDyaHdrBottom
, { 2, L_FIX
} }, // sep.dyaHdrBottom dya word
378 {NS_sprm::v6::sprmSLBetween
, { 1, L_FIX
} }, // sep.fLBetween 0 or 1 byte
379 {NS_sprm::v6::sprmSVjc
, { 1, L_FIX
} }, // sep.vjc vjc byte
380 {NS_sprm::v6::sprmSLnnMin
, { 2, L_FIX
} }, // sep.lnnMin lnn word
381 {NS_sprm::v6::sprmSPgnStart
, { 2, L_FIX
} }, // sep.pgnStart pgn word
382 {NS_sprm::v6::sprmSBOrientation
, { 1, L_FIX
} }, // sep.dmOrientPage dm byte
383 {NS_sprm::v6::sprmSBCustomize
, { 0, L_FIX
} },
384 {NS_sprm::v6::sprmSXaPage
, { 2, L_FIX
} }, // sep.xaPage xa word
385 {NS_sprm::v6::sprmSYaPage
, { 2, L_FIX
} }, // sep.yaPage ya word
386 {NS_sprm::v6::sprmSDxaLeft
, { 2, L_FIX
} }, // sep.dxaLeft dxa word
387 {NS_sprm::v6::sprmSDxaRight
, { 2, L_FIX
} }, // sep.dxaRight dxa word
388 {NS_sprm::v6::sprmSDyaTop
, { 2, L_FIX
} }, // sep.dyaTop dya word
389 {NS_sprm::v6::sprmSDyaBottom
, { 2, L_FIX
} }, // sep.dyaBottom dya word
390 {NS_sprm::v6::sprmSDzaGutter
, { 2, L_FIX
} }, // sep.dzaGutter dza word
391 {NS_sprm::v6::sprmSDMPaperReq
, { 2, L_FIX
} }, // sep.dmPaperReq dm word
392 {179, { 0, L_VAR
} }, // rtl property ?
393 {181, { 0, L_VAR
} }, // rtl property ?
394 {NS_sprm::v6::sprmTJc
, { 2, L_FIX
} }, // tap.jc jc (low order byte is significant)
395 {NS_sprm::v6::sprmTDxaLeft
, { 2, L_FIX
} }, // tap.rgdxaCenter dxa word
396 {NS_sprm::v6::sprmTDxaGapHalf
, { 2, L_FIX
} }, // tap.dxaGapHalf, tap.rgdxaCenter
397 {NS_sprm::v6::sprmTFCantSplit
, { 1, L_FIX
} }, // tap.fCantSplit 1 or 0 byte
398 {NS_sprm::v6::sprmTTableHeader
, { 1, L_FIX
} }, // tap.fTableHeader 1 or 0 byte
399 {NS_sprm::v6::sprmTTableBorders
, {12, L_FIX
} }, // tap.rgbrcTable complex 12 bytes
400 {NS_sprm::v6::sprmTDefTable10
, { 0, L_VAR2
} }, // tap.rgdxaCenter, tap.rgtc complex
401 {NS_sprm::v6::sprmTDyaRowHeight
, { 2, L_FIX
} }, // tap.dyaRowHeight dya word
402 {NS_sprm::v6::sprmTDefTable
, { 0, L_VAR2
} }, // tap.rgtc complex
403 {NS_sprm::v6::sprmTDefTableShd
, { 1, L_VAR
} }, // tap.rgshd complex
404 {NS_sprm::v6::sprmTTlp
, { 4, L_FIX
} }, // tap.tlp TLP 4 bytes
405 {NS_sprm::v6::sprmTSetBrc
, { 5, L_FIX
} }, // tap.rgtc[].rgbrc complex 5 bytes
406 {NS_sprm::v6::sprmTInsert
, { 4, L_FIX
} }, // tap.rgdxaCenter,tap.rgtc complex
407 {NS_sprm::v6::sprmTDelete
, { 2, L_FIX
} }, // tap.rgdxaCenter, tap.rgtc complex
408 {NS_sprm::v6::sprmTDxaCol
, { 4, L_FIX
} }, // tap.rgdxaCenter complex
409 {NS_sprm::v6::sprmTMerge
, { 2, L_FIX
} }, // tap.fFirstMerged, tap.fMerged complex
410 {NS_sprm::v6::sprmTSplit
, { 2, L_FIX
} }, // tap.fFirstMerged, tap.fMerged complex
411 {NS_sprm::v6::sprmTSetBrc10
, { 5, L_FIX
} }, // tap.rgtc[].rgbrc complex 5 bytes
412 {NS_sprm::v6::sprmTSetShd
, { 4, L_FIX
} }, // tap.rgshd complex 4 bytes
413 {207, { 0, L_VAR
} } // rtl property ?
416 if (rFib
.m_wIdent
>= 0xa697 && rFib
.m_wIdent
<= 0xa699)
418 //see Read_AmbiguousSPRM for this oddity
419 static wwSprmSearcher
aSprmSrch(aSprms
, SAL_N_ELEMENTS(aSprms
), true);
423 static wwSprmSearcher
aSprmSrch(aSprms
, SAL_N_ELEMENTS(aSprms
));
427 void wwSprmSearcher::patchCJKVariant()
429 for (sal_uInt16 nId
= 111; nId
<= 113; ++nId
)
431 SprmInfo
& amb1
= map_
[nId
];
433 amb1
.nVari
= wwSprmParser::L_FIX
;
437 template <class Sprm
> static constexpr SprmInfoRow
InfoRow()
439 return { Sprm::val
, { Sprm::len
, Sprm::varlen
? wwSprmParser::L_VAR
: wwSprmParser::L_FIX
} };
442 const wwSprmSearcher
*wwSprmParser::GetWW8SprmSearcher()
446 static const SprmInfoRow aSprms
[] =
448 { 0, { 0, L_FIX
} }, // "Default-sprm"/ is skipped
449 InfoRow
<NS_sprm::PIstd
>(), // pap.istd;istd (style code);short;
450 InfoRow
<NS_sprm::PIstdPermute
>(), // pap.istd;permutation vector
451 InfoRow
<NS_sprm::PIncLvl
>(), // pap.istd, pap.lvl;difference
452 // between istd of base PAP and istd of PAP to be
454 InfoRow
<NS_sprm::PJc80
>(), // pap.jc;jc (justification);byte;
455 {NS_sprm::LN_PFSideBySide
, { 1, L_FIX
} }, // "sprmPFSideBySide" pap.fSideBySide;0 or 1;byte;
456 InfoRow
<NS_sprm::PFKeep
>(), // pap.fKeep;0 or 1;byte;
457 InfoRow
<NS_sprm::PFKeepFollow
>(), // pap.fKeepFollow;0 or 1;byte;
458 InfoRow
<NS_sprm::PFPageBreakBefore
>(), // pap.fPageBreakBefore;
460 {NS_sprm::LN_PBrcl
, { 1, L_FIX
} }, // "sprmPBrcl" pap.brcl;brcl;byte;
461 {NS_sprm::LN_PBrcp
, { 1, L_FIX
} }, // "sprmPBrcp" pap.brcp;brcp;byte;
462 InfoRow
<NS_sprm::PIlvl
>(), // pap.ilvl;ilvl;byte;
463 InfoRow
<NS_sprm::PIlfo
>(), // pap.ilfo;ilfo (list index) ;short;
464 InfoRow
<NS_sprm::PFNoLineNumb
>(), // pap.fNoLnn;0 or 1;byte;
465 InfoRow
<NS_sprm::PChgTabsPapx
>(), // pap.itbdMac, pap.rgdxaTab,
467 InfoRow
<NS_sprm::PDxaRight80
>(), // pap.dxaRight;dxa;word;
468 InfoRow
<NS_sprm::PDxaLeft80
>(), // pap.dxaLeft;dxa;word;
469 InfoRow
<NS_sprm::PNest80
>(), // pap.dxaLeft;dxa
470 InfoRow
<NS_sprm::PDxaLeft180
>(), // pap.dxaLeft1;dxa;word;
471 InfoRow
<NS_sprm::PDyaLine
>(), // pap.lspd;an LSPD, a long word
472 // structure consisting of a short of dyaLine
473 // followed by a short of fMultLinespace
474 InfoRow
<NS_sprm::PDyaBefore
>(), // pap.dyaBefore;dya;word;
475 InfoRow
<NS_sprm::PDyaAfter
>(), // pap.dyaAfter;dya;word;
476 InfoRow
<NS_sprm::PChgTabs
>(), // pap.itbdMac, pap.rgdxaTab,
478 InfoRow
<NS_sprm::PFInTable
>(), // pap.fInTable;0 or 1;byte;
479 InfoRow
<NS_sprm::PFTtp
>(), // pap.fTtp;0 or 1;byte;
480 InfoRow
<NS_sprm::PDxaAbs
>(), // pap.dxaAbs;dxa;word;
481 InfoRow
<NS_sprm::PDyaAbs
>(), // pap.dyaAbs;dya;word;
482 InfoRow
<NS_sprm::PDxaWidth
>(), // pap.dxaWidth;dxa;word;
483 InfoRow
<NS_sprm::PPc
>(), // pap.pcHorz, pap.pcVert;complex
484 {NS_sprm::LN_PBrcTop10
, { 2, L_FIX
} }, // "sprmPBrcTop10" pap.brcTop;BRC10;word;
485 {NS_sprm::LN_PBrcLeft10
, { 2, L_FIX
} }, // "sprmPBrcLeft10" pap.brcLeft;BRC10;word;
486 {NS_sprm::LN_PBrcBottom10
, { 2, L_FIX
} }, // "sprmPBrcBottom10" pap.brcBottom;BRC10;word;
487 {NS_sprm::LN_PBrcRight10
, { 2, L_FIX
} }, // "sprmPBrcRight10" pap.brcRight;BRC10;word;
488 {NS_sprm::LN_PBrcBetween10
, { 2, L_FIX
} }, // "sprmPBrcBetween10" pap.brcBetween;BRC10;word;
489 {NS_sprm::LN_PBrcBar10
, { 2, L_FIX
} }, // "sprmPBrcBar10" pap.brcBar;BRC10;word;
490 {NS_sprm::LN_PDxaFromText10
, { 2, L_FIX
} }, // "sprmPDxaFromText10" pap.dxaFromText;dxa;word;
491 InfoRow
<NS_sprm::PWr
>(), // pap.wr;wr
492 InfoRow
<NS_sprm::PBrcTop80
>(), // pap.brcTop;BRC;long;
493 InfoRow
<NS_sprm::PBrcLeft80
>(), // pap.brcLeft;BRC;long;
494 InfoRow
<NS_sprm::PBrcBottom80
>(), // pap.brcBottom;BRC;long;
495 InfoRow
<NS_sprm::PBrcRight80
>(), // pap.brcRight;BRC;long;
496 InfoRow
<NS_sprm::PBrcBetween80
>(), // pap.brcBetween;BRC;long;
497 InfoRow
<NS_sprm::PBrcBar80
>(), // pap.brcBar;BRC;long;
498 InfoRow
<NS_sprm::PFNoAutoHyph
>(), // pap.fNoAutoHyph;0 or 1;byte;
499 InfoRow
<NS_sprm::PWHeightAbs
>(), // pap.wHeightAbs;w;word;
500 InfoRow
<NS_sprm::PDcs
>(), // pap.dcs;DCS;short;
501 InfoRow
<NS_sprm::PShd80
>(), // pap.shd;SHD;word;
502 InfoRow
<NS_sprm::PDyaFromText
>(), // pap.dyaFromText;dya;word;
503 InfoRow
<NS_sprm::PDxaFromText
>(), // pap.dxaFromText;dxa;word;
504 InfoRow
<NS_sprm::PFLocked
>(), // pap.fLocked;0 or 1;byte;
505 InfoRow
<NS_sprm::PFWidowControl
>(), // pap.fWidowControl;0 or 1
506 {NS_sprm::LN_PRuler
, { 0, L_VAR
} }, // "sprmPRuler" ;;variable length;
507 InfoRow
<NS_sprm::PFKinsoku
>(), // pap.fKinsoku;0 or 1;byte;
508 InfoRow
<NS_sprm::PFWordWrap
>(), // pap.fWordWrap;0 or 1;byte;
509 InfoRow
<NS_sprm::PFOverflowPunct
>(), // pap.fOverflowPunct;0 or 1
510 InfoRow
<NS_sprm::PFTopLinePunct
>(), // pap.fTopLinePunct;0 or 1
511 InfoRow
<NS_sprm::PFAutoSpaceDE
>(), // pap.fAutoSpaceDE;0 or 1
512 InfoRow
<NS_sprm::PFAutoSpaceDN
>(), // pap.fAutoSpaceDN;0 or 1
513 InfoRow
<NS_sprm::PWAlignFont
>(), // pap.wAlignFont;iFa
514 InfoRow
<NS_sprm::PFrameTextFlow
>(), // pap.fVertical pap.fBackward
515 // pap.fRotateFont;complex
516 {NS_sprm::LN_PISnapBaseLine
, { 1, L_FIX
} }, // "sprmPISnapBaseLine" obsolete: not applicable in
517 // Word97 and later versions;
518 {NS_sprm::LN_PAnld
, { 0, L_VAR
} }, // "sprmPAnld" pap.anld;;variable length;
519 {NS_sprm::LN_PPropRMark
, { 0, L_VAR
} }, // "sprmPPropRMark" pap.fPropRMark;complex
520 InfoRow
<NS_sprm::POutLvl
>(), // pap.lvl;has no effect if pap.istd
522 InfoRow
<NS_sprm::PFBiDi
>(), // ;;byte;
523 InfoRow
<NS_sprm::PFNumRMIns
>(), // pap.fNumRMIns;1 or 0;bit;
524 {NS_sprm::LN_PCrLf
, { 1, L_FIX
} }, // "sprmPCrLf" ;;byte;
525 InfoRow
<NS_sprm::PNumRM
>(), // pap.numrm;;variable length;
526 {NS_sprm::LN_PHugePapx
, { 4, L_FIX
} }, // "sprmPHugePapx" fc in the data stream to locate
528 InfoRow
<NS_sprm::PHugePapx
>(), // fc in the data stream to locate
530 InfoRow
<NS_sprm::PFUsePgsuSettings
>(), // pap.fUsePgsuSettings;
532 InfoRow
<NS_sprm::PFAdjustRight
>(), // pap.fAdjustRight;1 or 0;byte;
533 InfoRow
<NS_sprm::CFRMarkDel
>(), // chp.fRMarkDel;1 or 0;bit;
534 InfoRow
<NS_sprm::CFRMarkIns
>(), // chp.fRMark;1 or 0;bit;
535 InfoRow
<NS_sprm::CFFldVanish
>(), // chp.fFieldVanish;1 or 0;bit;
536 InfoRow
<NS_sprm::CPicLocation
>(), // chp.fcPic and chp.fSpec;
537 InfoRow
<NS_sprm::CIbstRMark
>(), // chp.ibstRMark;index into
539 InfoRow
<NS_sprm::CDttmRMark
>(), // chp.dttmRMark;DTTM;long;
540 InfoRow
<NS_sprm::CFData
>(), // chp.fData;1 or 0;bit;
541 InfoRow
<NS_sprm::CIdslRMark
>(), // chp.idslRMReason;an index to a
542 // table of strings defined in Word 6.0
543 // executables;short;
544 {NS_sprm::LN_CChs
, { 1, L_FIX
} }, // "sprmCChs" chp.fChsDiff and chp.chse;
545 InfoRow
<NS_sprm::CSymbol
>(), // chp.fSpec, chp.xchSym and
547 InfoRow
<NS_sprm::CFOle2
>(), // chp.fOle2;1 or 0;bit;
548 {NS_sprm::LN_CIdCharType
, { 0, L_FIX
} }, // "sprmCIdCharType" obsolete: not applicable in
549 // Word97 and later versions;
550 InfoRow
<NS_sprm::CHighlight
>(), // chp.fHighlight,
551 // chp.icoHighlight;ico (fHighlight is set to 1 iff
553 {NS_sprm::LN_CObjLocation
, { 4, L_FIX
} }, // "sprmCObjLocation" chp.fcObj;FC;long;
554 {NS_sprm::LN_CFFtcAsciSymb
, { 0, L_FIX
} }, // "sprmCFFtcAsciSymb" ;;;
555 InfoRow
<NS_sprm::CIstd
>(), // chp.istd;istd, see stylesheet def
556 InfoRow
<NS_sprm::CIstdPermute
>(), // chp.istd;permutation vector
557 {NS_sprm::LN_CDefault
, { 0, L_VAR
} }, // "sprmCDefault" whole CHP;none;variable length;
558 InfoRow
<NS_sprm::CPlain
>(), // whole CHP;none;0;
559 InfoRow
<NS_sprm::CKcd
>(), // ;;;
560 InfoRow
<NS_sprm::CFBold
>(), // chp.fBold;0,1, 128, or 129
561 InfoRow
<NS_sprm::CFItalic
>(), // chp.fItalic;0,1, 128, or 129
562 InfoRow
<NS_sprm::CFStrike
>(), // chp.fStrike;0,1, 128, or 129
563 InfoRow
<NS_sprm::CFOutline
>(), // chp.fOutline;0,1, 128, or 129
564 InfoRow
<NS_sprm::CFShadow
>(), // chp.fShadow;0,1, 128, or 129
565 InfoRow
<NS_sprm::CFSmallCaps
>(), // chp.fSmallCaps;0,1, 128, or 129
566 InfoRow
<NS_sprm::CFCaps
>(), // chp.fCaps;0,1, 128, or 129
567 InfoRow
<NS_sprm::CFVanish
>(), // chp.fVanish;0,1, 128, or 129
568 {NS_sprm::LN_CFtcDefault
, { 2, L_FIX
} }, // "sprmCFtcDefault" ;ftc, only used internally
569 InfoRow
<NS_sprm::CKul
>(), // chp.kul;kul;byte;
570 {NS_sprm::LN_CSizePos
, { 3, L_FIX
} }, // "sprmCSizePos" chp.hps, chp.hpsPos;3 bytes;
571 InfoRow
<NS_sprm::CDxaSpace
>(), // chp.dxaSpace;dxa;word;
572 {NS_sprm::LN_CLid
, { 2, L_FIX
} }, // "sprmCLid" ;only used internally never stored
573 InfoRow
<NS_sprm::CIco
>(), // chp.ico;ico;byte;
574 InfoRow
<NS_sprm::CHps
>(), // chp.hps;hps
575 {NS_sprm::LN_CHpsInc
, { 1, L_FIX
} }, // "sprmCHpsInc" chp.hps;
576 InfoRow
<NS_sprm::CHpsPos
>(), // chp.hpsPos;hps;short; (doc wrong)
577 {NS_sprm::LN_CHpsPosAdj
, { 1, L_FIX
} }, // "sprmCHpsPosAdj" chp.hpsPos;hps
578 InfoRow
<NS_sprm::CMajority
>(), // chp.fBold, chp.fItalic,
579 // chp.fSmallCaps, chp.fVanish, chp.fStrike,
580 // chp.fCaps, chp.rgftc, chp.hps, chp.hpsPos,
581 // chp.kul, chp.dxaSpace, chp.ico,
582 // chp.rglid;complex;variable length, length byte
583 // plus size of following grpprl;
584 InfoRow
<NS_sprm::CIss
>(), // chp.iss;iss;byte;
585 {NS_sprm::LN_CHpsNew50
, { 0, L_VAR
} }, // "sprmCHpsNew50" chp.hps;hps;variable width
586 {NS_sprm::LN_CHpsInc1
, { 0, L_VAR
} }, // "sprmCHpsInc1" chp.hps;complex
587 InfoRow
<NS_sprm::CHpsKern
>(), // chp.hpsKern;hps;short;
588 {NS_sprm::LN_CMajority50
, { 2, L_FIX
} }, // "sprmCMajority50" chp.fBold, chp.fItalic,
589 // chp.fSmallCaps, chp.fVanish, chp.fStrike,
590 // chp.fCaps, chp.ftc, chp.hps, chp.hpsPos, chp.kul,
591 // chp.dxaSpace, chp.ico,;complex
592 {NS_sprm::LN_CHpsMul
, { 2, L_FIX
} }, // "sprmCHpsMul" chp.hps;percentage to grow hps
593 InfoRow
<NS_sprm::CHresi
>(), // chp.ysri;ysri;short;
594 InfoRow
<NS_sprm::CRgFtc0
>(), // chp.rgftc[0];ftc for ASCII text
595 InfoRow
<NS_sprm::CRgFtc1
>(), // chp.rgftc[1];ftc for Far East text
596 InfoRow
<NS_sprm::CRgFtc2
>(), // chp.rgftc[2];ftc for non-FE text
597 InfoRow
<NS_sprm::CCharScale
>(),
598 InfoRow
<NS_sprm::CFDStrike
>(), // chp.fDStrike;;byte;
599 InfoRow
<NS_sprm::CFImprint
>(), // chp.fImprint;1 or 0;bit;
600 InfoRow
<NS_sprm::CFSpec
>(), // chp.fSpec ;1 or 0;bit;
601 InfoRow
<NS_sprm::CFObj
>(), // chp.fObj;1 or 0;bit;
602 InfoRow
<NS_sprm::CPropRMark90
>(), // chp.fPropRMark,
603 // chp.ibstPropRMark, chp.dttmPropRMark;Complex
604 InfoRow
<NS_sprm::CFEmboss
>(), // chp.fEmboss;1 or 0;bit;
605 InfoRow
<NS_sprm::CSfxText
>(), // chp.sfxtText;text animation;byte;
606 InfoRow
<NS_sprm::CFBiDi
>(), // ;;;
607 {NS_sprm::LN_CFDiacColor
, { 1, L_FIX
} }, // "sprmCFDiacColor" ;;;
608 InfoRow
<NS_sprm::CFBoldBi
>(), // ;;;
609 InfoRow
<NS_sprm::CFItalicBi
>(), // ;;;
610 InfoRow
<NS_sprm::CFtcBi
>(),
611 InfoRow
<NS_sprm::CLidBi
>(), // ;;;
612 InfoRow
<NS_sprm::CIcoBi
>(), // ;;;
613 InfoRow
<NS_sprm::CHpsBi
>(), // ;;;
614 InfoRow
<NS_sprm::CDispFldRMark
>(), // chp.fDispFieldRMark,
615 // chp.ibstDispFieldRMark, chp.dttmDispFieldRMark ;
616 InfoRow
<NS_sprm::CIbstRMarkDel
>(), // chp.ibstRMarkDel;index into
618 InfoRow
<NS_sprm::CDttmRMarkDel
>(), // chp.dttmRMarkDel;DTTM;long;
619 InfoRow
<NS_sprm::CBrc80
>(), // chp.brc;BRC;long;
620 InfoRow
<NS_sprm::CShd80
>(), // chp.shd;SHD;short;
621 InfoRow
<NS_sprm::CIdslRMarkDel
>(), // chp.idslRMReasonDel;an index
622 // to a table of strings defined in Word 6.0
623 // executables;short;
624 InfoRow
<NS_sprm::CFUsePgsuSettings
>(),
625 // chp.fUsePgsuSettings;1 or 0
626 {NS_sprm::LN_CCpg
, { 2, L_FIX
} }, // "sprmCCpg" ;;word;
627 InfoRow
<NS_sprm::CRgLid0_80
>(), // chp.rglid[0];LID: for non-FE text
628 InfoRow
<NS_sprm::CRgLid1_80
>(), // chp.rglid[1];LID: for Far East text
629 InfoRow
<NS_sprm::CIdctHint
>(), // chp.idctHint;IDCT:
630 {NS_sprm::LN_PicBrcl
, { 1, L_FIX
} }, // "sprmPicBrcl" pic.brcl;brcl (see PIC definition)
631 {NS_sprm::LN_PicScale
, { 0, L_VAR
} }, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
632 // pic.dyaCropTop pic.dxaCropRight,
633 // pic.dyaCropBottom;Complex
634 InfoRow
<NS_sprm::PicBrcTop80
>(), // pic.brcTop;BRC;long;
635 InfoRow
<NS_sprm::PicBrcLeft80
>(), // pic.brcLeft;BRC;long;
636 InfoRow
<NS_sprm::PicBrcBottom80
>(), // pic.brcBottom;BRC;long;
637 InfoRow
<NS_sprm::PicBrcRight80
>(), // pic.brcRight;BRC;long;
638 InfoRow
<NS_sprm::ScnsPgn
>(), // sep.cnsPgn;cns;byte;
639 InfoRow
<NS_sprm::SiHeadingPgn
>(), // sep.iHeadingPgn;heading number
641 {NS_sprm::LN_SOlstAnm
, { 0, L_VAR
} }, // "sprmSOlstAnm" sep.olstAnm;OLST;variable length;
642 InfoRow
<NS_sprm::SDxaColWidth
>(), // sep.rgdxaColWidthSpacing;
643 InfoRow
<NS_sprm::SDxaColSpacing
>(), // sep.rgdxaColWidthSpacing;
645 InfoRow
<NS_sprm::SFEvenlySpaced
>(), // sep.fEvenlySpaced;1 or 0
646 InfoRow
<NS_sprm::SFProtected
>(), // sep.fUnlocked;1 or 0;byte;
647 InfoRow
<NS_sprm::SDmBinFirst
>(), // sep.dmBinFirst;;word;
648 InfoRow
<NS_sprm::SDmBinOther
>(), // sep.dmBinOther;;word;
649 InfoRow
<NS_sprm::SBkc
>(), // sep.bkc;bkc;byte;
650 InfoRow
<NS_sprm::SFTitlePage
>(), // sep.fTitlePage;0 or 1;byte;
651 InfoRow
<NS_sprm::SCcolumns
>(), // sep.ccolM1;# of cols - 1;word;
652 InfoRow
<NS_sprm::SDxaColumns
>(), // sep.dxaColumns;dxa;word;
653 {NS_sprm::LN_SFAutoPgn
, { 1, L_FIX
} }, // "sprmSFAutoPgn" sep.fAutoPgn;obsolete;byte;
654 InfoRow
<NS_sprm::SNfcPgn
>(), // sep.nfcPgn;nfc;byte;
655 {NS_sprm::LN_SDyaPgn
, { 2, L_FIX
} }, // "sprmSDyaPgn" sep.dyaPgn;dya;short;
656 {NS_sprm::LN_SDxaPgn
, { 2, L_FIX
} }, // "sprmSDxaPgn" sep.dxaPgn;dya;short;
657 InfoRow
<NS_sprm::SFPgnRestart
>(), // sep.fPgnRestart;0 or 1;byte;
658 InfoRow
<NS_sprm::SFEndnote
>(), // sep.fEndnote;0 or 1;byte;
659 InfoRow
<NS_sprm::SLnc
>(), // sep.lnc;lnc;byte;
660 {NS_sprm::LN_SGprfIhdt
, { 1, L_FIX
} }, // "sprmSGprfIhdt" sep.grpfIhdt;grpfihdt
661 InfoRow
<NS_sprm::SNLnnMod
>(), // sep.nLnnMod;non-neg int.;word;
662 InfoRow
<NS_sprm::SDxaLnn
>(), // sep.dxaLnn;dxa;word;
663 InfoRow
<NS_sprm::SDyaHdrTop
>(), // sep.dyaHdrTop;dya;word;
664 InfoRow
<NS_sprm::SDyaHdrBottom
>(), // sep.dyaHdrBottom;dya;word;
665 InfoRow
<NS_sprm::SLBetween
>(), // sep.fLBetween;0 or 1;byte;
666 InfoRow
<NS_sprm::SVjc
>(), // sep.vjc;vjc;byte;
667 InfoRow
<NS_sprm::SLnnMin
>(), // sep.lnnMin;lnn;word;
668 InfoRow
<NS_sprm::SPgnStart97
>(), // sep.pgnStart;pgn;word;
669 InfoRow
<NS_sprm::SBOrientation
>(), // sep.dmOrientPage;dm;byte;
670 {NS_sprm::LN_SBCustomize
, { 1, L_FIX
} }, // "sprmSBCustomize" ;;;
671 InfoRow
<NS_sprm::SXaPage
>(), // sep.xaPage;xa;word;
672 InfoRow
<NS_sprm::SYaPage
>(), // sep.yaPage;ya;word;
673 InfoRow
<NS_sprm::SDxaLeft
>(), // sep.dxaLeft;dxa;word;
674 InfoRow
<NS_sprm::SDxaRight
>(), // sep.dxaRight;dxa;word;
675 InfoRow
<NS_sprm::SDyaTop
>(), // sep.dyaTop;dya;word;
676 InfoRow
<NS_sprm::SDyaBottom
>(), // sep.dyaBottom;dya;word;
677 InfoRow
<NS_sprm::SDzaGutter
>(), // sep.dzaGutter;dza;word;
678 InfoRow
<NS_sprm::SDmPaperReq
>(), // sep.dmPaperReq;dm;word;
679 {NS_sprm::LN_SPropRMark
, { 0, L_VAR
} }, // "sprmSPropRMark" sep.fPropRMark,
680 // sep.ibstPropRMark, sep.dttmPropRMark ;complex
681 InfoRow
<NS_sprm::SFBiDi
>(), // ;;;
682 {NS_sprm::LN_SFFacingCol
, { 1, L_FIX
} }, // "sprmSFFacingCol" ;;;
683 InfoRow
<NS_sprm::SFRTLGutter
>(), //, set to one if gutter is on
685 InfoRow
<NS_sprm::SBrcTop80
>(), // sep.brcTop;BRC;long;
686 InfoRow
<NS_sprm::SBrcLeft80
>(), // sep.brcLeft;BRC;long;
687 InfoRow
<NS_sprm::SBrcBottom80
>(), // sep.brcBottom;BRC;long;
688 InfoRow
<NS_sprm::SBrcRight80
>(), // sep.brcRight;BRC;long;
689 InfoRow
<NS_sprm::SPgbProp
>(), // sep.pgbProp;;word;
690 InfoRow
<NS_sprm::SDxtCharSpace
>(), // sep.dxtCharSpace;dxt;long;
691 InfoRow
<NS_sprm::SDyaLinePitch
>(),
692 // sep.dyaLinePitch;dya; WRONG:long; RIGHT:short; !
693 InfoRow
<NS_sprm::SClm
>(), // ;;;
694 InfoRow
<NS_sprm::STextFlow
>(), // sep.wTextFlow;complex
695 InfoRow
<NS_sprm::TJc90
>(), // tap.jc;jc;word (low order byte is
697 InfoRow
<NS_sprm::TDxaLeft
>(), // tap.rgdxaCenter
698 InfoRow
<NS_sprm::TDxaGapHalf
>(), // tap.dxaGapHalf,
700 InfoRow
<NS_sprm::TFCantSplit90
>(), // tap.fCantSplit90;1 or 0;byte;
701 InfoRow
<NS_sprm::TTableHeader
>(), // tap.fTableHeader;1 or 0;byte;
702 InfoRow
<NS_sprm::TFCantSplit
>(), // tap.fCantSplit;1 or 0;byte;
703 InfoRow
<NS_sprm::TTableBorders80
>(), // tap.rgbrcTable;complex
704 {NS_sprm::LN_TDefTable10
, { 0, L_VAR2
} }, // "sprmTDefTable10" tap.rgdxaCenter,
706 InfoRow
<NS_sprm::TDyaRowHeight
>(), // tap.dyaRowHeight;dya;word;
707 {NS_sprm::LN_TDefTable
, { 0, L_VAR2
} }, // "sprmTDefTable" tap.rgtc;complex
708 InfoRow
<NS_sprm::TDefTableShd80
>(), // tap.rgshd;complex
709 InfoRow
<NS_sprm::TTlp
>(), // tap.tlp;TLP;4 bytes;
710 InfoRow
<NS_sprm::TFBiDi
>(), // ;;;
711 {NS_sprm::LN_THTMLProps
, { 1, L_FIX
} }, // "sprmTHTMLProps" ;;;
712 InfoRow
<NS_sprm::TSetBrc80
>(), // tap.rgtc[].rgbrc;complex
713 InfoRow
<NS_sprm::TInsert
>(), // tap.rgdxaCenter, tap.rgtc;complex
714 InfoRow
<NS_sprm::TDelete
>(), // tap.rgdxaCenter, tap.rgtc;complex
715 InfoRow
<NS_sprm::TDxaCol
>(), // tap.rgdxaCenter;complex
716 InfoRow
<NS_sprm::TMerge
>(), // tap.fFirstMerged, tap.fMerged;
717 InfoRow
<NS_sprm::TSplit
>(), // tap.fFirstMerged, tap.fMerged;
718 {NS_sprm::LN_TSetBrc10
, { 0, L_VAR
} }, // "sprmTSetBrc10" tap.rgtc[].rgbrc;complex
719 {NS_sprm::LN_TSetShd80
, { 0, L_VAR
} }, // "sprmTSetShd80" tap.rgshd;complex
720 {NS_sprm::LN_TSetShdOdd80
, { 0, L_VAR
} }, // "sprmTSetShdOdd80" tap.rgshd;complex
721 InfoRow
<NS_sprm::TTextFlow
>(), // tap.rgtc[].fVerticaltap,
722 // rgtc[].fBackwardtap, rgtc[].fRotateFont;0 or 10
724 {NS_sprm::LN_TDiagLine
, { 1, L_FIX
} }, // "sprmTDiagLine" ;;;
725 InfoRow
<NS_sprm::TVertMerge
>(), // tap.rgtc[].vertMerge
726 InfoRow
<NS_sprm::TVertAlign
>(), // tap.rgtc[].vertAlign
727 InfoRow
<NS_sprm::CFELayout
>(),
728 InfoRow
<NS_sprm::PItap
>(), // undocumented
729 InfoRow
<NS_sprm::TTableWidth
>(), // undocumented
730 InfoRow
<NS_sprm::TDefTableShd
>(),
731 InfoRow
<NS_sprm::TTableBorders
>(),
732 InfoRow
<NS_sprm::TBrcTopCv
>(), // undocumented
733 InfoRow
<NS_sprm::TBrcLeftCv
>(), // undocumented
734 InfoRow
<NS_sprm::TBrcBottomCv
>(), // undocumented
735 InfoRow
<NS_sprm::TBrcRightCv
>(), // undocumented
736 InfoRow
<NS_sprm::TCellPadding
>(), // undocumented
737 InfoRow
<NS_sprm::TCellPaddingDefault
>(), // undocumented
738 {0xD238, { 0, L_VAR
} }, // undocumented sep
739 InfoRow
<NS_sprm::PBrcTop
>(),
740 InfoRow
<NS_sprm::PBrcLeft
>(),
741 InfoRow
<NS_sprm::PBrcBottom
>(),
742 InfoRow
<NS_sprm::PBrcRight
>(),
743 InfoRow
<NS_sprm::PBrcBetween
>(),
744 InfoRow
<NS_sprm::TWidthIndent
>(), // undocumented
745 InfoRow
<NS_sprm::CRgLid0
>(), // chp.rglid[0];LID: for non-FE text
746 InfoRow
<NS_sprm::CRgLid1
>(), // chp.rglid[1];LID: for Far East text
747 {0x6463, { 4, L_FIX
} }, // undocumented
748 InfoRow
<NS_sprm::PJc
>(), // undoc, must be asian version of "sprmPJc"
749 InfoRow
<NS_sprm::PDxaRight
>(), // undoc, must be asian version of "sprmPDxaRight"
750 InfoRow
<NS_sprm::PDxaLeft
>(), // undoc, must be asian version of "sprmPDxaLeft"
751 InfoRow
<NS_sprm::PDxaLeft1
>(), // undoc, must be asian version of "sprmPDxaLeft1"
752 InfoRow
<NS_sprm::TFAutofit
>(), // undocumented
753 InfoRow
<NS_sprm::TPc
>(), // undocumented
754 InfoRow
<NS_sprm::SRsid
>(), // undocumented, sep, perhaps related to textgrids ?
755 InfoRow
<NS_sprm::SFpc
>(), // undocumented, sep
756 InfoRow
<NS_sprm::PFInnerTableCell
>(), // undocumented, subtable "sprmPFInTable" equiv ?
757 InfoRow
<NS_sprm::PFInnerTtp
>(), // undocumented, subtable "sprmPFTtp" equiv ?
758 InfoRow
<NS_sprm::TDxaAbs
>(), // undocumented
759 InfoRow
<NS_sprm::TDyaAbs
>(), // undocumented
760 InfoRow
<NS_sprm::TDxaFromText
>(), // undocumented
761 InfoRow
<NS_sprm::CRsidProp
>(), // undocumented
762 InfoRow
<NS_sprm::CRsidText
>(), // undocumented
763 InfoRow
<NS_sprm::CCv
>(), // text colour
764 InfoRow
<NS_sprm::PShd
>(), // undocumented, para back colour
765 InfoRow
<NS_sprm::PRsid
>(), // undocumented
766 InfoRow
<NS_sprm::PTableProps
>(), // undocumented
767 InfoRow
<NS_sprm::TWidthBefore
>(), // undocumented
768 InfoRow
<NS_sprm::TSetShdTable
>(), // undocumented, something to do with colour.
769 InfoRow
<NS_sprm::TDefTableShdRaw
>(), // undocumented, something to do with colour.
770 InfoRow
<NS_sprm::CShd
>(), // text backcolour
771 InfoRow
<NS_sprm::SRncFtn
>(), // undocumented, sep
772 InfoRow
<NS_sprm::PFDyaBeforeAuto
>(), // undocumented, para autobefore
773 InfoRow
<NS_sprm::PFDyaAfterAuto
>(), // undocumented, para autoafter
774 // "sprmPFContextualSpacing", don't add space between para of the same style
775 InfoRow
<NS_sprm::PFContextualSpacing
>(),
778 static wwSprmSearcher
aSprmSrch(aSprms
, SAL_N_ELEMENTS(aSprms
));
782 wwSprmParser::wwSprmParser(const WW8Fib
& rFib
) : meVersion(rFib
.GetFIBVersion())
784 OSL_ENSURE((meVersion
>= ww::eWW1
&& 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(rFib
);
794 mpKnownSprms
= GetWW8SprmSearcher();
797 SprmInfo
wwSprmParser::GetSprmInfo(sal_uInt16 nId
) const
799 const SprmInfo
* pFound
= mpKnownSprms
->search(nId
);
800 if (pFound
!= nullptr)
805 OSL_ENSURE(ww::IsEightPlus(meVersion
),
806 "Unknown ww7- sprm, dangerous, report to development");
808 //All the unknown ww7 sprms appear to be variable (which makes sense)
809 SprmInfo aSrch
= { 0, L_VAR
};
810 if (ww::IsEightPlus(meVersion
)) //We can recover perfectly in this case
844 static sal_uInt8
Get_Byte( sal_uInt8
*& p
)
851 static sal_uInt16
Get_UShort( sal_uInt8
*& p
)
853 const sal_uInt16 n
= SVBT16ToUInt16( *reinterpret_cast<SVBT16
*>(p
) );
858 static sal_Int16
Get_Short( sal_uInt8
*& p
)
860 return Get_UShort(p
);
863 static sal_uInt32
Get_ULong( sal_uInt8
*& p
)
865 sal_uInt32 n
= SVBT32ToUInt32( *reinterpret_cast<SVBT32
*>(p
) );
870 static sal_Int32
Get_Long( sal_uInt8
*& p
)
875 WW8SprmIter::WW8SprmIter(const sal_uInt8
* pSprms_
, sal_Int32 nLen_
,
876 const wwSprmParser
&rParser
)
877 : mrSprmParser(rParser
), m_pSprms( pSprms_
), m_nRemLen( nLen_
)
882 void WW8SprmIter::SetSprms(const sal_uInt8
* pSprms_
, sal_Int32 nLen_
)
889 void WW8SprmIter::advance()
893 sal_uInt16 nSize
= m_nCurrentSize
;
894 if (nSize
> m_nRemLen
)
902 void WW8SprmIter::UpdateMyMembers()
904 bool bValid
= (m_pSprms
&& m_nRemLen
>= mrSprmParser
.MinSprmLen());
908 m_nCurrentId
= mrSprmParser
.GetSprmId(m_pSprms
);
909 m_nCurrentSize
= mrSprmParser
.GetSprmSize(m_nCurrentId
, m_pSprms
, m_nRemLen
);
910 m_pCurrentParams
= m_pSprms
+ mrSprmParser
.DistanceToData(m_nCurrentId
);
911 bValid
= m_nCurrentSize
<= m_nRemLen
;
912 SAL_WARN_IF(!bValid
, "sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong");
918 m_pCurrentParams
= nullptr;
924 SprmResult
WW8SprmIter::FindSprm(sal_uInt16 nId
, bool bFindFirst
, const sal_uInt8
* pNextByteMatch
)
930 if (GetCurrentId() == nId
)
932 sal_Int32 nFixedLen
= mrSprmParser
.DistanceToData(nId
);
933 sal_Int32 nL
= mrSprmParser
.GetSprmSize(nId
, GetSprms(), GetRemLen());
934 SprmResult
aSprmResult(GetCurrentParams(), nL
- nFixedLen
);
935 // typically pNextByteMatch is nullptr and we just return the first match
936 // very occasionally we want one with a specific following byte
937 if ( !pNextByteMatch
|| (aSprmResult
.nRemainingData
>= 1 && *aSprmResult
.pSprm
== *pNextByteMatch
) )
951 // WW8PLCFx_PCDAttrs cling to WW8PLCF_Pcd and therefore do not have their own iterators.
952 // All methods relating to iterators are therefore dummies.
953 WW8PLCFx_PCDAttrs::WW8PLCFx_PCDAttrs(const WW8Fib
& rFib
,
954 WW8PLCFx_PCD
* pPLCFx_PCD
, const WW8ScannerBase
* pBase
)
955 : WW8PLCFx(rFib
, true), m_pPcdI(pPLCFx_PCD
->GetPLCFIter()),
956 m_pPcd(pPLCFx_PCD
), mrGrpprls(pBase
->m_aPieceGrpprls
)
960 sal_uInt32
WW8PLCFx_PCDAttrs::GetIdx() const
965 void WW8PLCFx_PCDAttrs::SetIdx(sal_uInt32
)
969 bool WW8PLCFx_PCDAttrs::SeekPos(WW8_CP
)
974 void WW8PLCFx_PCDAttrs::advance()
978 WW8_CP
WW8PLCFx_PCDAttrs::Where()
980 return m_pPcd
? m_pPcd
->Where() : WW8_CP_MAX
;
983 void WW8PLCFx_PCDAttrs::GetSprms(WW8PLCFxDesc
* p
)
987 p
->bRealLineEnd
= false;
988 if ( !m_pPcdI
|| !m_pPcdI
->Get(p
->nStartPos
, p
->nEndPos
, pData
) )
990 // PLCF fully processed
991 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
992 p
->pMemPos
= nullptr;
997 const sal_uInt16 nPrm
= SVBT16ToUInt16( static_cast<WW8_PCD
*>(pData
)->prm
);
1001 const sal_uInt16 nSprmIdx
= nPrm
>> 1;
1003 if( nSprmIdx
>= mrGrpprls
.size() )
1006 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
1007 p
->pMemPos
= nullptr;
1011 const sal_uInt8
* pSprms
= mrGrpprls
[ nSprmIdx
].get();
1013 p
->nSprmsLen
= SVBT16ToUInt16( pSprms
); // Length
1015 p
->pMemPos
= pSprms
; // Position
1019 // SPRM is stored directly into members var
1021 These are the attr that are in the piece-table instead of in the text!
1024 if (IsSevenMinus(GetFIBVersion()))
1026 m_aShortSprm
[0] = static_cast<sal_uInt8
>( ( nPrm
& 0xfe) >> 1 );
1027 m_aShortSprm
[1] = static_cast<sal_uInt8
>( nPrm
>> 8 );
1028 p
->nSprmsLen
= nPrm
? 2 : 0; // length
1030 // store Position of internal mini storage in Data Pointer
1031 p
->pMemPos
= m_aShortSprm
;
1035 p
->pMemPos
= nullptr;
1037 sal_uInt8 nSprmListIdx
= static_cast<sal_uInt8
>((nPrm
& 0xfe) >> 1);
1040 // process Sprm Id Matching as explained in MS Documentation
1042 // ''Property Modifier(variant 1) (PRM)''
1043 // see file: s62f39.htm
1045 // Since Sprm is 7 bits, rgsprmPrm can hold 0x80 entries.
1046 static const sal_uInt16 aSprmId
[0x80] =
1048 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1049 0x0000,0x0000,0x0000,0x0000,
1050 // sprmPIncLvl, sprmPJc, sprmPFSideBySide, sprmPFKeep
1051 0x2402,0x2403,NS_sprm::LN_PFSideBySide
,0x2405,
1052 // sprmPFKeepFollow, sprmPFPageBreakBefore, sprmPBrcl,
1054 0x2406,0x2407,NS_sprm::LN_PBrcl
,NS_sprm::LN_PBrcp
,
1055 // sprmPIlvl, sprmNoop, sprmPFNoLineNumb, sprmNoop
1056 0x260A,0x0000,0x240C,0x0000,
1057 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1058 0x0000,0x0000,0x0000,0x0000,
1059 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1060 0x0000,0x0000,0x0000,0x0000,
1061 // sprmPFInTable, sprmPFTtp, sprmNoop, sprmNoop
1062 0x2416,0x2417,0x0000,0x0000,
1063 // sprmNoop, sprmPPc, sprmNoop, sprmNoop
1064 0x0000,0x261B,0x0000,0x0000,
1065 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1066 0x0000,0x0000,0x0000,0x0000,
1067 // sprmNoop, sprmPWr, sprmNoop, sprmNoop
1068 0x0000,0x2423,0x0000,0x0000,
1069 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1070 0x0000,0x0000,0x0000,0x0000,
1071 // sprmPFNoAutoHyph, sprmNoop, sprmNoop, sprmNoop
1072 0x242A,0x0000,0x0000,0x0000,
1073 // sprmNoop, sprmNoop, sprmPFLocked, sprmPFWidowControl
1074 0x0000,0x0000,0x2430,0x2431,
1075 // sprmNoop, sprmPFKinsoku, sprmPFWordWrap,
1076 // sprmPFOverflowPunct
1077 0x0000,0x2433,0x2434,0x2435,
1078 // sprmPFTopLinePunct, sprmPFAutoSpaceDE,
1079 // sprmPFAutoSpaceDN, sprmNoop
1080 0x2436,0x2437,0x2438,0x0000,
1081 // sprmNoop, sprmPISnapBaseLine, sprmNoop, sprmNoop
1082 0x0000,NS_sprm::LN_PISnapBaseLine
,0x000,0x0000,
1083 // sprmNoop, sprmCFStrikeRM, sprmCFRMark, sprmCFFieldVanish
1084 0x0000,0x0800,0x0801,0x0802,
1085 // sprmNoop, sprmNoop, sprmNoop, sprmCFData
1086 0x0000,0x0000,0x0000,0x0806,
1087 // sprmNoop, sprmNoop, sprmNoop, sprmCFOle2
1088 0x0000,0x0000,0x0000,0x080A,
1089 // sprmNoop, sprmCHighlight, sprmCFEmboss, sprmCSfxText
1090 0x0000,0x2A0C,0x0858,0x2859,
1091 // sprmNoop, sprmNoop, sprmNoop, sprmCPlain
1092 0x0000,0x0000,0x0000,0x2A33,
1093 // sprmNoop, sprmCFBold, sprmCFItalic, sprmCFStrike
1094 0x0000,0x0835,0x0836,0x0837,
1095 // sprmCFOutline, sprmCFShadow, sprmCFSmallCaps, sprmCFCaps,
1096 0x0838,0x0839,0x083a,0x083b,
1097 // sprmCFVanish, sprmNoop, sprmCKul, sprmNoop,
1098 0x083C,0x0000,0x2A3E,0x0000,
1099 // sprmNoop, sprmNoop, sprmCIco, sprmNoop,
1100 0x0000,0x0000,0x2A42,0x0000,
1101 // sprmCHpsInc, sprmNoop, sprmCHpsPosAdj, sprmNoop,
1102 NS_sprm::LN_CHpsInc
,0x0000,NS_sprm::LN_CHpsPosAdj
,0x0000,
1103 // sprmCIss, sprmNoop, sprmNoop, sprmNoop,
1104 0x2A48,0x0000,0x0000,0x0000,
1105 // sprmNoop, sprmNoop, sprmNoop, sprmNoop,
1106 0x0000,0x0000,0x0000,0x0000,
1107 // sprmNoop, sprmNoop, sprmNoop, sprmCFDStrike,
1108 0x0000,0x0000,0x0000,0x2A53,
1109 // sprmCFImprint, sprmCFSpec, sprmCFObj, sprmPicBrcl,
1110 0x0854,0x0855,0x0856,NS_sprm::LN_PicBrcl
,
1111 // sprmPOutLvl, sprmPFBiDi, sprmNoop, sprmNoop,
1112 0x2640,0x2441,0x0000,0x0000,
1113 // sprmNoop, sprmNoop, sprmPPnbrRMarkNot
1114 0x0000,0x0000,0x0000,0x0000
1117 // find real Sprm Id:
1118 const sal_uInt16 nSprmId
= aSprmId
[ nSprmListIdx
];
1122 // move Sprm Id and Sprm Param to internal mini storage:
1123 m_aShortSprm
[0] = static_cast<sal_uInt8
>( nSprmId
& 0x00ff) ;
1124 m_aShortSprm
[1] = static_cast<sal_uInt8
>( ( nSprmId
& 0xff00) >> 8 );
1125 m_aShortSprm
[2] = static_cast<sal_uInt8
>( nPrm
>> 8 );
1127 // store Sprm Length in member:
1128 p
->nSprmsLen
= nPrm
? 3 : 0;
1130 // store Position of internal mini storage in Data Pointer
1131 p
->pMemPos
= m_aShortSprm
;
1138 WW8PLCFx_PCD::WW8PLCFx_PCD(const WW8Fib
& rFib
, WW8PLCFpcd
* pPLCFpcd
,
1139 WW8_CP nStartCp
, bool bVer67P
)
1140 : WW8PLCFx(rFib
, false), m_nClipStart(-1)
1142 // construct own iterator
1143 m_pPcdI
.reset( new WW8PLCFpcd_Iter(*pPLCFpcd
, nStartCp
) );
1147 WW8PLCFx_PCD::~WW8PLCFx_PCD()
1151 sal_uInt32
WW8PLCFx_PCD::GetIMax() const
1153 return m_pPcdI
? m_pPcdI
->GetIMax() : 0;
1156 sal_uInt32
WW8PLCFx_PCD::GetIdx() const
1158 return m_pPcdI
? m_pPcdI
->GetIdx() : 0;
1161 void WW8PLCFx_PCD::SetIdx(sal_uInt32 nIdx
)
1164 m_pPcdI
->SetIdx( nIdx
);
1167 bool WW8PLCFx_PCD::SeekPos(WW8_CP nCpPos
)
1169 return m_pPcdI
&& m_pPcdI
->SeekPos( nCpPos
);
1172 WW8_CP
WW8PLCFx_PCD::Where()
1174 return m_pPcdI
? m_pPcdI
->Where() : WW8_CP_MAX
;
1177 tools::Long
WW8PLCFx_PCD::GetNoSprms( WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
1182 if ( !m_pPcdI
|| !m_pPcdI
->Get(rStart
, rEnd
, pData
) )
1184 rStart
= rEnd
= WW8_CP_MAX
;
1187 return m_pPcdI
->GetIdx();
1190 void WW8PLCFx_PCD::advance()
1192 OSL_ENSURE(m_pPcdI
, "missing pPcdI");
1197 WW8_FC
WW8PLCFx_PCD::CurrentPieceStartCp2Fc( WW8_CP nCp
)
1199 WW8_CP nCpStart
, nCpEnd
;
1202 if ( !m_pPcdI
->Get(nCpStart
, nCpEnd
, pData
) )
1204 OSL_ENSURE( false, "CurrentPieceStartCp2Fc() with false Cp found (1)" );
1208 OSL_ENSURE( nCp
>= nCpStart
&& nCp
< nCpEnd
,
1209 "AktPieceCp2Fc() with false Cp found (2)" );
1211 if( nCp
< nCpStart
)
1216 bool bIsUnicode
= false;
1217 WW8_FC nFC
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
1219 nFC
= WW8PLCFx_PCD::TransformPieceAddress( nFC
, bIsUnicode
);
1222 bool bFail
= o3tl::checked_sub(nCp
, nCpStart
, nDistance
);
1225 SAL_WARN("sw.ww8", "broken offset, ignoring");
1231 bFail
= o3tl::checked_multiply
<WW8_CP
>(nDistance
, 2, nDistance
);
1234 SAL_WARN("sw.ww8", "broken offset, ignoring");
1240 bFail
= o3tl::checked_add(nFC
, nDistance
, nRet
);
1243 SAL_WARN("sw.ww8", "broken offset, ignoring");
1250 void WW8PLCFx_PCD::CurrentPieceFc2Cp( WW8_CP
& rStartPos
, WW8_CP
& rEndPos
,
1251 const WW8ScannerBase
*pSBase
)
1253 //No point going anywhere with this
1254 if ((rStartPos
== WW8_CP_MAX
) && (rEndPos
== WW8_CP_MAX
))
1257 rStartPos
= pSBase
->WW8Fc2Cp( rStartPos
);
1258 rEndPos
= pSBase
->WW8Fc2Cp( rEndPos
);
1261 WW8_CP
WW8PLCFx_PCD::CurrentPieceStartFc2Cp( WW8_FC nStartPos
)
1263 WW8_CP nCpStart
, nCpEnd
;
1265 if ( !m_pPcdI
->Get( nCpStart
, nCpEnd
, pData
) )
1267 OSL_ENSURE( false, "CurrentPieceStartFc2Cp() - error" );
1270 bool bIsUnicode
= false;
1271 sal_Int32 nFcStart
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
1273 nFcStart
= WW8PLCFx_PCD::TransformPieceAddress( nFcStart
, bIsUnicode
);
1275 sal_Int32 nUnicodeFactor
= bIsUnicode
? 2 : 1;
1277 if( nStartPos
< nFcStart
)
1278 nStartPos
= nFcStart
;
1281 bool bFail
= o3tl::checked_sub(nCpEnd
, nCpStart
, nCpLen
);
1284 SAL_WARN("sw.ww8", "broken offset, ignoring");
1289 bFail
= o3tl::checked_multiply(nCpLen
, nUnicodeFactor
, nCpLenBytes
);
1292 SAL_WARN("sw.ww8", "broken offset, ignoring");
1297 bFail
= o3tl::checked_add(nFcStart
, nCpLenBytes
, nFcLen
);
1300 SAL_WARN("sw.ww8", "broken offset, ignoring");
1305 bFail
= o3tl::checked_add(nFcStart
, nFcLen
, nFcEnd
);
1308 SAL_WARN("sw.ww8", "broken offset, ignoring");
1313 if (nStartPos
>= nFcEnd
)
1314 nStartPos
= nFcEnd
- (1 * nUnicodeFactor
);
1316 WW8_FC nFcDiff
= (nStartPos
- nFcStart
) / nUnicodeFactor
;
1319 bFail
= o3tl::checked_add(nCpStart
, nFcDiff
, nCpRet
);
1322 SAL_WARN("sw.ww8", "broken offset, ignoring");
1329 // Helper routines for all
1331 // Convert BRC from WW6 to WW8 format
1332 WW8_BRC::WW8_BRC(const WW8_BRCVer6
& brcVer6
)
1334 sal_uInt8 _dptLineWidth
= brcVer6
.dxpLineWidth(),
1335 _brcType
= brcVer6
.brcType();
1337 if (_dptLineWidth
> 5) // this signifies dashed(6) or dotted(7) line
1339 _brcType
= _dptLineWidth
;
1342 _dptLineWidth
*= 6; // convert units from 0.75pt to 1/8pt
1344 *this = WW8_BRC(_dptLineWidth
, _brcType
, brcVer6
.ico(), brcVer6
.dxpSpace(),
1345 brcVer6
.fShadow(), false);
1348 // Convert BRC from WW8 to WW9 format
1349 WW8_BRCVer9::WW8_BRCVer9(const WW8_BRC
& brcVer8
)
1351 if (brcVer8
.isNil()) {
1352 UInt32ToSVBT32(0, aBits1
);
1353 UInt32ToSVBT32(0xffffffff, aBits2
);
1357 sal_uInt32 _cv
= brcVer8
.ico() == 0 ? 0xff000000 // "auto" colour
1358 : wwUtility::RGBToBGR(SwWW8ImplReader::GetCol(brcVer8
.ico()));
1359 *this = WW8_BRCVer9(_cv
, brcVer8
.dptLineWidth(), brcVer8
.brcType(),
1360 brcVer8
.dptSpace(), brcVer8
.fShadow(), brcVer8
.fFrame());
1364 short WW8_BRC::DetermineBorderProperties(short *pSpace
) const
1366 WW8_BRCVer9
brcVer9(*this);
1367 return brcVer9
.DetermineBorderProperties(pSpace
);
1370 short WW8_BRCVer9::DetermineBorderProperties(short *pSpace
) const
1373 Word does not factor the width of the border into the width/height
1374 stored in the information for graphic/table/object widths, so we need
1375 to figure out this extra width here and utilize the returned size in
1378 short nMSTotalWidth
;
1380 //Specification in 8ths of a point, 1 Point = 20 Twips, so by 2.5
1381 nMSTotalWidth
= static_cast<short>(dptLineWidth()) * 20 / 8;
1383 //Figure out the real size of the border according to word
1386 //Note that codes over 25 are undocumented, and I can't create
1387 //these 4 here in the wild.
1392 OSL_FAIL("Can't create these from the menus, please report");
1395 case 23: //Only 3pt in the menus, but honours the size setting.
1399 triple line is five times the width of an ordinary line,
1400 except that the smallest 1/4 point size appears to have
1401 exactly the same total border width as a 3/4 point size
1402 ordinary line, i.e. three times the nominal line width. The
1403 second smallest 1/2 point size appears to have exactly the
1404 total border width as a 2 1/4 border, i.e 4.5 times the size.
1406 if (nMSTotalWidth
== 5)
1408 else if (nMSTotalWidth
== 10)
1409 nMSTotalWidth
= nMSTotalWidth
*9/2;
1415 wave, the dimensions appear to be created by the drawing of
1416 the wave, so we have only two possibilities in the menus, 3/4
1417 point is equal to solid 3 point. This calculation seems to
1418 match well to results.
1424 double wave, the dimensions appear to be created by the
1425 drawing of the wave, so we have only one possibilities in the
1426 menus, that of 3/4 point is equal to solid 3 point. This
1427 calculation seems to match well to results.
1429 nMSTotalWidth
+= 45*2;
1434 *pSpace
= static_cast<short>(dptSpace()) * 20; // convert from points to twips
1435 return nMSTotalWidth
;
1439 * WW8Cp2Fc is a good method, a CP always maps to a FC
1440 * WW8Fc2Cp on the other hand is more dubious, a random FC
1441 * may not map to a valid CP. Try and avoid WW8Fc2Cp where
1444 WW8_CP
WW8ScannerBase::WW8Fc2Cp( WW8_FC nFcPos
) const
1446 WW8_CP nFallBackCpEnd
= WW8_CP_MAX
;
1447 if( nFcPos
== WW8_FC_MAX
)
1448 return nFallBackCpEnd
;
1451 if (m_pWw8Fib
->m_nVersion
>= 8)
1454 bIsUnicode
= m_pWw8Fib
->m_fExtChar
;
1456 if( m_pPieceIter
) // Complex File ?
1458 sal_uInt32 nOldPos
= m_pPieceIter
->GetIdx();
1460 for (m_pPieceIter
->SetIdx(0);
1461 m_pPieceIter
->GetIdx() < m_pPieceIter
->GetIMax(); m_pPieceIter
->advance())
1463 WW8_CP nCpStart
, nCpEnd
;
1465 if( !m_pPieceIter
->Get( nCpStart
, nCpEnd
, pData
) )
1466 { // outside PLCFfpcd ?
1467 OSL_ENSURE( false, "PLCFpcd-WW8Fc2Cp() went wrong" );
1470 sal_Int32 nFcStart
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
1471 if (m_pWw8Fib
->m_nVersion
>= 8)
1473 nFcStart
= WW8PLCFx_PCD::TransformPieceAddress( nFcStart
,
1478 bIsUnicode
= m_pWw8Fib
->m_fExtChar
;
1482 if (o3tl::checked_sub(nCpEnd
, nCpStart
, nLen
))
1484 SAL_WARN("sw.ww8", "broken offset, ignoring");
1489 if (o3tl::checked_multiply
<WW8_CP
>(nLen
, 2, nLen
))
1491 SAL_WARN("sw.ww8", "broken offset, ignoring");
1497 If this cp is inside this piece, or it's the last piece and we are
1498 on the very last cp of that piece
1500 if (nFcPos
>= nFcStart
)
1504 if (o3tl::checked_sub(nFcPos
, nFcStart
, nFcDiff
))
1506 SAL_WARN("sw.ww8", "broken offset, ignoring");
1512 if (o3tl::checked_add(nCpStart
, nFcDiff
, nTempCp
))
1514 SAL_WARN("sw.ww8", "broken offset, ignoring");
1518 if (o3tl::checked_add(nFcStart
, nLen
, nFcEnd
))
1520 SAL_WARN("sw.ww8", "broken offset, ignoring");
1523 if (nFcPos
< nFcEnd
)
1525 m_pPieceIter
->SetIdx( nOldPos
);
1528 else if (nFcPos
== nFcEnd
)
1530 //Keep this cp as its on a piece boundary because we might
1531 //need it if tests fail
1532 nFallBackCpEnd
= nTempCp
;
1537 m_pPieceIter
->SetIdx( nOldPos
); // not found
1539 If it was not found, then this is because it has fallen between two
1540 stools, i.e. either it is the last cp/fc of the last piece, or it is
1541 the last cp/fc of a disjoint piece.
1543 return nFallBackCpEnd
;
1547 if (o3tl::checked_sub(nFcPos
, m_pWw8Fib
->m_fcMin
, nFcDiff
))
1549 SAL_WARN("sw.ww8", "broken offset, ignoring");
1555 nFallBackCpEnd
= nFcDiff
;
1557 nFallBackCpEnd
= (nFcDiff
+ 1) / 2;
1559 return nFallBackCpEnd
;
1562 // the fib of WinWord2 has a last entry of cpnBtePap of 2 byte sized type PN at
1564 const int nSmallestPossibleFib
= 326;
1566 WW8_FC
WW8ScannerBase::WW8Cp2Fc(WW8_CP nCpPos
, bool* pIsUnicode
,
1567 WW8_CP
* pNextPieceCp
, bool* pTestFlag
) const
1571 if( WW8_CP_MAX
== nCpPos
)
1576 pIsUnicode
= &bIsUnicode
;
1578 if (m_pWw8Fib
->m_nVersion
>= 8)
1579 *pIsUnicode
= false;
1581 *pIsUnicode
= m_pWw8Fib
->m_fExtChar
;
1589 *pNextPieceCp
= WW8_CP_MAX
;
1591 if( !m_pPieceIter
->SeekPos( nCpPos
) )
1596 OSL_ENSURE( false, "Handed over wrong CP to WW8Cp2Fc()" );
1600 WW8_CP nCpStart
, nCpEnd
;
1602 if( !m_pPieceIter
->Get( nCpStart
, nCpEnd
, pData
) )
1607 OSL_ENSURE( false, "PLCFfpcd-Get went wrong" );
1612 *pNextPieceCp
= nCpEnd
;
1614 nRet
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
1615 if (m_pWw8Fib
->m_nVersion
>= 8)
1616 nRet
= WW8PLCFx_PCD::TransformPieceAddress( nRet
, *pIsUnicode
);
1618 *pIsUnicode
= m_pWw8Fib
->m_fExtChar
;
1621 bool bFail
= o3tl::checked_sub(nCpPos
, nCpStart
, nCpLen
);
1624 SAL_WARN("sw.ww8", "broken offset, ignoring");
1630 bFail
= o3tl::checked_multiply
<WW8_CP
>(nCpLen
, 2, nCpLen
);
1633 SAL_WARN("sw.ww8", "broken offset, ignoring");
1638 bFail
= o3tl::checked_add(nRet
, nCpLen
, nRet
);
1641 SAL_WARN("sw.ww8", "broken offset, ignoring");
1650 const bool bFail
= o3tl::checked_multiply
<WW8_CP
>(nCpPos
, 2, nCpPos
);
1653 SAL_WARN("sw.ww8", "broken offset, ignoring");
1659 const bool bFail
= o3tl::checked_add(m_pWw8Fib
->m_fcMin
, nCpPos
, nRet
);
1662 SAL_WARN("sw.ww8", "broken offset, ignoring");
1666 // the text and the fib share the same stream, if the text is inside the fib
1667 // then it's definitely a bad offset. The smallest FIB supported is that of
1668 // WW2 which is 326 bytes in size
1669 if (nRet
< nSmallestPossibleFib
)
1671 SAL_WARN("sw.ww8", "broken offset, ignoring");
1678 std::unique_ptr
<WW8PLCFpcd
> WW8ScannerBase::OpenPieceTable( SvStream
* pStr
, const WW8Fib
* pWwF
)
1680 if ( ((8 > m_pWw8Fib
->m_nVersion
) && !pWwF
->m_fComplex
) || !pWwF
->m_lcbClx
)
1683 if (pWwF
->m_lcbClx
< 0)
1686 WW8_FC nClxPos
= pWwF
->m_fcClx
;
1688 if (!checkSeek(*pStr
, nClxPos
))
1691 sal_Int32 nClxLen
= pWwF
->m_lcbClx
;
1692 sal_Int32 nLeft
= nClxLen
;
1697 pStr
->ReadUChar( clxt
);
1699 if( 2 == clxt
) // PLCFfpcd ?
1700 break; // PLCFfpcd found
1702 pStr
->ReadUInt16( nLen
);
1705 return nullptr; // gone wrong
1706 if( 1 == clxt
) // clxtGrpprl ?
1708 if (m_aPieceGrpprls
.size() == SHRT_MAX
)
1710 if (nLen
> pStr
->remainingSize())
1712 std::unique_ptr
<sal_uInt8
[]> p(new sal_uInt8
[nLen
+2]); // allocate
1713 ShortToSVBT16(nLen
, p
.get()); // add length
1714 if (!checkRead(*pStr
, p
.get()+2, nLen
)) // read grpprl
1718 m_aPieceGrpprls
.push_back(std::move(p
)); // add to array
1722 nLen
= std::min
<sal_uInt64
>(nLen
, pStr
->remainingSize());
1723 pStr
->Seek(pStr
->Tell() + nLen
); // non-Grpprl left
1727 // read Piece Table PLCF
1728 sal_Int32
nPLCFfLen(0);
1729 if (pWwF
->GetFIBVersion() <= ww::eWW2
)
1731 sal_Int16
nWordTwoLen(0);
1732 pStr
->ReadInt16( nWordTwoLen
);
1733 nPLCFfLen
= nWordTwoLen
;
1736 pStr
->ReadInt32( nPLCFfLen
);
1737 OSL_ENSURE( 65536 > nPLCFfLen
, "PLCFfpcd above 64 k" );
1738 return std::make_unique
<WW8PLCFpcd
>( pStr
, pStr
->Tell(), nPLCFfLen
, 8 );
1741 WW8ScannerBase::WW8ScannerBase( SvStream
* pSt
, SvStream
* pTableSt
,
1742 SvStream
* pDataSt
, WW8Fib
* pWwFib
)
1745 m_pPiecePLCF
= OpenPieceTable( pTableSt
, m_pWw8Fib
); // Complex
1748 m_pPieceIter
.reset(new WW8PLCFpcd_Iter( *m_pPiecePLCF
));
1749 m_pPLCFx_PCD
.reset( new WW8PLCFx_PCD(*pWwFib
, m_pPiecePLCF
.get(), 0,
1750 IsSevenMinus(m_pWw8Fib
->GetFIBVersion())));
1751 m_pPLCFx_PCDAttrs
.reset(new WW8PLCFx_PCDAttrs(*pWwFib
,
1752 m_pPLCFx_PCD
.get(), this));
1756 m_pPieceIter
= nullptr;
1757 m_pPLCFx_PCD
= nullptr;
1758 m_pPLCFx_PCDAttrs
= nullptr;
1761 // pChpPLCF and pPapPLCF may NOT be created before pPLCFx_PCD !!
1762 m_pChpPLCF
.reset(new WW8PLCFx_Cp_FKP( pSt
, pTableSt
, pDataSt
, *this, CHP
)); // CHPX
1763 m_pPapPLCF
.reset(new WW8PLCFx_Cp_FKP( pSt
, pTableSt
, pDataSt
, *this, PAP
)); // PAPX
1765 m_pSepPLCF
.reset(new WW8PLCFx_SEPX( pSt
, pTableSt
, *pWwFib
, 0 )); // SEPX
1768 m_pFootnotePLCF
.reset(new WW8PLCFx_SubDoc( pTableSt
, *pWwFib
, 0,
1769 pWwFib
->m_fcPlcffndRef
, pWwFib
->m_lcbPlcffndRef
, pWwFib
->m_fcPlcffndText
,
1770 pWwFib
->m_lcbPlcffndText
, 2 ));
1772 m_pEdnPLCF
.reset(new WW8PLCFx_SubDoc( pTableSt
, *pWwFib
, 0,
1773 pWwFib
->m_fcPlcfendRef
, pWwFib
->m_lcbPlcfendRef
, pWwFib
->m_fcPlcfendText
,
1774 pWwFib
->m_lcbPlcfendText
, 2 ));
1776 m_pAndPLCF
.reset(new WW8PLCFx_SubDoc( pTableSt
, *pWwFib
, 0,
1777 pWwFib
->m_fcPlcfandRef
, pWwFib
->m_lcbPlcfandRef
, pWwFib
->m_fcPlcfandText
,
1778 pWwFib
->m_lcbPlcfandText
, IsSevenMinus(pWwFib
->GetFIBVersion()) ? 20 : 30));
1781 m_pFieldPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_MAINTEXT
));
1782 // Fields Header / Footer
1783 m_pFieldHdFtPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_HDFT
));
1785 m_pFieldFootnotePLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_FTN
));
1787 m_pFieldEdnPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_EDN
));
1789 m_pFieldAndPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_AND
));
1790 // Fields in Textboxes in Main Text
1791 m_pFieldTxbxPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_TXBX
));
1792 // Fields in Textboxes in Header / Footer
1793 m_pFieldTxbxHdFtPLCF
.reset(new WW8PLCFx_FLD(pTableSt
,*pWwFib
,MAN_TXBX_HDFT
));
1795 // Note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
1796 switch( m_pWw8Fib
->m_nVersion
)
1800 if( pWwFib
->m_fcPlcfdoaMom
&& pWwFib
->m_lcbPlcfdoaMom
)
1802 m_pMainFdoa
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfdoaMom
,
1803 pWwFib
->m_lcbPlcfdoaMom
, 6 ));
1805 if( pWwFib
->m_fcPlcfdoaHdr
&& pWwFib
->m_lcbPlcfdoaHdr
)
1807 m_pHdFtFdoa
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfdoaHdr
,
1808 pWwFib
->m_lcbPlcfdoaHdr
, 6 ));
1812 if( pWwFib
->m_fcPlcfspaMom
&& pWwFib
->m_lcbPlcfspaMom
)
1814 m_pMainFdoa
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfspaMom
,
1815 pWwFib
->m_lcbPlcfspaMom
, 26 ));
1817 if( pWwFib
->m_fcPlcfspaHdr
&& pWwFib
->m_lcbPlcfspaHdr
)
1819 m_pHdFtFdoa
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfspaHdr
,
1820 pWwFib
->m_lcbPlcfspaHdr
, 26 ));
1822 // PLCF for TextBox break-descriptors in the main text
1823 if( pWwFib
->m_fcPlcftxbxBkd
&& pWwFib
->m_lcbPlcftxbxBkd
)
1825 m_pMainTxbxBkd
.reset(new WW8PLCFspecial( pTableSt
,
1826 pWwFib
->m_fcPlcftxbxBkd
, pWwFib
->m_lcbPlcftxbxBkd
, 0));
1828 // PLCF for TextBox break-descriptors in Header/Footer range
1829 if( pWwFib
->m_fcPlcfHdrtxbxBkd
&& pWwFib
->m_lcbPlcfHdrtxbxBkd
)
1831 m_pHdFtTxbxBkd
.reset(new WW8PLCFspecial( pTableSt
,
1832 pWwFib
->m_fcPlcfHdrtxbxBkd
, pWwFib
->m_lcbPlcfHdrtxbxBkd
, 0));
1834 // Sub table cp positions
1835 if (pWwFib
->m_fcPlcfTch
&& pWwFib
->m_lcbPlcfTch
)
1837 m_pMagicTables
.reset(new WW8PLCFspecial( pTableSt
,
1838 pWwFib
->m_fcPlcfTch
, pWwFib
->m_lcbPlcfTch
, 4));
1840 // Sub document cp positions
1841 if (pWwFib
->m_fcPlcfwkb
&& pWwFib
->m_lcbPlcfwkb
)
1843 m_pSubdocs
.reset(new WW8PLCFspecial( pTableSt
,
1844 pWwFib
->m_fcPlcfwkb
, pWwFib
->m_lcbPlcfwkb
, 12));
1847 if (pWwFib
->m_fcAtrdExtra
&& pWwFib
->m_lcbAtrdExtra
)
1849 sal_uInt64
const nOldPos
= pTableSt
->Tell();
1850 if (checkSeek(*pTableSt
, pWwFib
->m_fcAtrdExtra
) && (pTableSt
->remainingSize() >= pWwFib
->m_lcbAtrdExtra
))
1852 m_pExtendedAtrds
.reset( new sal_uInt8
[pWwFib
->m_lcbAtrdExtra
] );
1853 pWwFib
->m_lcbAtrdExtra
= pTableSt
->ReadBytes(m_pExtendedAtrds
.get(), pWwFib
->m_lcbAtrdExtra
);
1856 pWwFib
->m_lcbAtrdExtra
= 0;
1857 pTableSt
->Seek(nOldPos
);
1862 OSL_ENSURE( false, "nVersion not implemented!" );
1866 // PLCF for TextBox stories in main text
1867 sal_uInt32 nLenTxBxS
= (8 > m_pWw8Fib
->m_nVersion
) ? 0 : 22;
1868 if( pWwFib
->m_fcPlcftxbxText
&& pWwFib
->m_lcbPlcftxbxText
)
1870 m_pMainTxbx
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcftxbxText
,
1871 pWwFib
->m_lcbPlcftxbxText
, nLenTxBxS
));
1874 // PLCF for TextBox stories in Header/Footer range
1875 if( pWwFib
->m_fcPlcfHdrtxbxText
&& pWwFib
->m_lcbPlcfHdrtxbxText
)
1877 m_pHdFtTxbx
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfHdrtxbxText
,
1878 pWwFib
->m_lcbPlcfHdrtxbxText
, nLenTxBxS
));
1881 m_pBook
.reset(new WW8PLCFx_Book(pTableSt
, *pWwFib
));
1882 m_pAtnBook
.reset(new WW8PLCFx_AtnBook(pTableSt
, *pWwFib
));
1883 m_pFactoidBook
.reset(new WW8PLCFx_FactoidBook(pTableSt
, *pWwFib
));
1886 WW8ScannerBase::~WW8ScannerBase()
1888 m_aPieceGrpprls
.clear();
1889 m_pPLCFx_PCDAttrs
.reset();
1890 m_pPLCFx_PCD
.reset();
1891 m_pPieceIter
.reset();
1892 m_pPiecePLCF
.reset();
1893 m_pFactoidBook
.reset();
1896 m_pFieldEdnPLCF
.reset();
1897 m_pFieldFootnotePLCF
.reset();
1898 m_pFieldAndPLCF
.reset();
1899 m_pFieldHdFtPLCF
.reset();
1900 m_pFieldPLCF
.reset();
1901 m_pFieldTxbxPLCF
.reset();
1902 m_pFieldTxbxHdFtPLCF
.reset();
1904 m_pFootnotePLCF
.reset();
1909 m_pMainFdoa
.reset();
1910 m_pHdFtFdoa
.reset();
1911 m_pMainTxbx
.reset();
1912 m_pMainTxbxBkd
.reset();
1913 m_pHdFtTxbx
.reset();
1914 m_pHdFtTxbxBkd
.reset();
1915 m_pMagicTables
.reset();
1921 static bool WW8SkipField(WW8PLCFspecial
& rPLCF
)
1926 if (!rPLCF
.Get(nP
, pData
)) // End of PLCFspecial?
1931 if((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) != 0x13 ) // No beginning?
1932 return true; // Do not terminate on error
1934 if( !rPLCF
.Get( nP
, pData
) )
1937 while((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x13 )
1939 // still new (nested) beginnings ?
1940 WW8SkipField( rPLCF
); // nested Field in description
1941 if( !rPLCF
.Get( nP
, pData
) )
1945 if((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x14 )
1948 // Field Separator ?
1951 if( !rPLCF
.Get( nP
, pData
) )
1954 while ((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x13)
1956 // still new (nested) beginnings?
1957 WW8SkipField( rPLCF
); // nested Field in Results
1958 if( !rPLCF
.Get( nP
, pData
) )
1967 static bool WW8GetFieldPara(WW8PLCFspecial
& rPLCF
, WW8FieldDesc
& rF
)
1970 sal_uInt32 nOldIdx
= rPLCF
.GetIdx();
1972 rF
.nLen
= rF
.nId
= rF
.nOpt
= 0;
1973 rF
.bCodeNest
= rF
.bResNest
= false;
1975 if (!rPLCF
.Get(rF
.nSCode
, pData
) || rF
.nSCode
< 0) // end of PLCFspecial?
1980 if (!pData
|| (static_cast<sal_uInt8
*>(pData
)[0] & 0x1f) != 0x13) // No beginning?
1983 rF
.nId
= static_cast<sal_uInt8
*>(pData
)[1];
1985 if( !rPLCF
.Get( rF
.nLCode
, pData
) )
1988 if (rF
.nLCode
< rF
.nSCode
)
1991 rF
.nSRes
= rF
.nLCode
; // Default
1992 rF
.nSCode
++; // without markers
1993 rF
.nLCode
-= rF
.nSCode
; // Pos -> length
1995 while((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x13 )
1997 // still new (nested) beginnings ?
1998 WW8SkipField( rPLCF
); // nested Field in description
1999 rF
.bCodeNest
= true;
2000 if (!rPLCF
.Get(rF
.nSRes
, pData
) || rF
.nSRes
< 0)
2004 if ((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x14 ) // Field Separator?
2008 if (!rPLCF
.Get(rF
.nLRes
, pData
) || rF
.nLRes
< 0)
2011 while((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x13 )
2013 // still new (nested) beginnings ?
2014 WW8SkipField( rPLCF
); // nested Field in results
2016 if (!rPLCF
.Get(rF
.nLRes
, pData
) || rF
.nLRes
< 0)
2020 if (o3tl::checked_sub
<WW8_CP
>(rF
.nLRes
, rF
.nSCode
, nTmp
))
2025 if (o3tl::checked_add
<WW8_CP
>(nTmp
, 2, rF
.nLen
)) // nLRes is still the final position
2030 rF
.nLRes
-= rF
.nSRes
; // now: nLRes = length
2031 if (o3tl::checked_add
<WW8_CP
>(rF
.nSRes
, 1, rF
.nSRes
)) // Endpos including Markers
2038 rF
.nLRes
= 0; // no result found
2040 if (o3tl::checked_sub
<WW8_CP
>(rF
.nSRes
, rF
.nSCode
, nTmp
))
2045 if (o3tl::checked_add
<WW8_CP
>(nTmp
, 2, rF
.nLen
)) // total length
2059 if((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x15 )
2062 // INDEX-Field has set Bit7?
2063 rF
.nOpt
= static_cast<sal_uInt8
*>(pData
)[1]; // yes -> copy flags
2065 rF
.nId
= 0; // no -> Field invalid
2068 rPLCF
.SetIdx( nOldIdx
);
2071 rPLCF
.SetIdx( nOldIdx
);
2075 OUString
read_uInt8_BeltAndBracesString(SvStream
& rStrm
, rtl_TextEncoding eEnc
)
2077 const OUString aRet
= read_uInt8_lenPrefixed_uInt8s_ToOUString(rStrm
, eEnc
);
2078 rStrm
.SeekRel(sizeof(sal_uInt8
)); // skip null-byte at end
2082 OUString
read_uInt16_BeltAndBracesString(SvStream
& rStrm
)
2084 const OUString aRet
= read_uInt16_PascalString(rStrm
);
2085 rStrm
.SeekRel(sizeof(sal_Unicode
)); // skip null-byte at end
2089 sal_Int32
WW8ScannerBase::WW8ReadString( SvStream
& rStrm
, OUString
& rStr
,
2090 WW8_CP nCurrentStartCp
, tools::Long nTotalLen
, rtl_TextEncoding eEnc
) const
2092 // Read in plain text, which can extend over several pieces
2095 if (nCurrentStartCp
< 0 || nTotalLen
< 0)
2098 WW8_CP nBehindTextCp
= nCurrentStartCp
+ nTotalLen
;
2099 WW8_CP nNextPieceCp
= nBehindTextCp
; // Initialization, important for Ver6
2100 tools::Long nTotalRead
= 0;
2103 bool bIsUnicode(false), bPosOk(false);
2104 WW8_FC fcAct
= WW8Cp2Fc(nCurrentStartCp
,&bIsUnicode
,&nNextPieceCp
,&bPosOk
);
2106 // Probably aimed beyond file end, doesn't matter!
2110 bool bValid
= checkSeek(rStrm
, fcAct
);
2114 WW8_CP nEnd
= (nNextPieceCp
< nBehindTextCp
) ? nNextPieceCp
2117 const bool bFail
= o3tl::checked_sub(nEnd
, nCurrentStartCp
, nLen
);
2125 ? read_uInt16s_ToOUString(rStrm
, nLen
)
2126 : read_uInt8s_ToOUString(rStrm
, nLen
, eEnc
);
2129 nCurrentStartCp
+= nLen
;
2130 if ( nTotalRead
!= rStr
.getLength() )
2133 while( nTotalRead
< nTotalLen
);
2135 return rStr
.getLength();
2138 WW8PLCFspecial::WW8PLCFspecial(SvStream
* pSt
, sal_uInt32 nFilePos
,
2139 sal_uInt32 nPLCF
, sal_uInt32 nStruct
)
2140 : m_nIdx(0), m_nStru(nStruct
)
2142 const sal_uInt32 nValidMin
=4;
2144 sal_uInt64
const nOldPos
= pSt
->Tell();
2146 bool bValid
= checkSeek(*pSt
, nFilePos
);
2147 std::size_t nRemainingSize
= pSt
->remainingSize();
2148 if( nRemainingSize
< nValidMin
|| nPLCF
< nValidMin
)
2150 nPLCF
= bValid
? std::min(nRemainingSize
, static_cast<std::size_t>(nPLCF
)) : nValidMin
;
2152 // Pointer to Pos- and Struct-array
2153 m_pPLCF_PosArray
.reset( new sal_Int32
[ ( nPLCF
+ 3 ) / 4 ] );
2154 m_pPLCF_PosArray
[0] = 0;
2156 nPLCF
= bValid
? pSt
->ReadBytes(m_pPLCF_PosArray
.get(), nPLCF
) : nValidMin
;
2158 nPLCF
= std::max(nPLCF
, nValidMin
);
2160 m_nIMax
= ( nPLCF
- 4 ) / ( 4 + nStruct
);
2161 #ifdef OSL_BIGENDIAN
2162 for( m_nIdx
= 0; m_nIdx
<= m_nIMax
; m_nIdx
++ )
2163 m_pPLCF_PosArray
[m_nIdx
] = OSL_SWAPDWORD( m_pPLCF_PosArray
[m_nIdx
] );
2165 #endif // OSL_BIGENDIAN
2166 if( nStruct
) // Pointer to content array
2167 m_pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&m_pPLCF_PosArray
[m_nIMax
+ 1]);
2169 m_pPLCF_Contents
= nullptr; // no content
2174 // WW8PLCFspecial::SeekPos() sets WW8PLCFspecial to position nPos, while also the entry is used
2175 // that begins before nPos and ends after nPos.
2176 // Suitable for normal attributes. However, the beginning of the attribute is not corrected onto
2177 // the position nPos.
2178 bool WW8PLCFspecial::SeekPos(tools::Long nP
)
2180 if( nP
< m_pPLCF_PosArray
[0] )
2183 return false; // Not found: nP less than smallest entry
2186 // Search from beginning?
2187 if ((m_nIdx
< 1) || (nP
< m_pPLCF_PosArray
[m_nIdx
- 1]))
2190 tools::Long nI
= m_nIdx
;
2191 tools::Long nEnd
= m_nIMax
;
2193 for(int n
= (1==m_nIdx
? 1 : 2); n
; --n
)
2195 for( ; nI
<=nEnd
; ++nI
)
2196 { // search with an index that is incremented by 1
2197 if( nP
< m_pPLCF_PosArray
[nI
] )
2199 m_nIdx
= nI
- 1; // nI - 1 is the correct index
2200 return true; // done
2206 m_nIdx
= m_nIMax
; // not found, greater than all entries
2210 // WW8PLCFspecial::SeekPosExact() like SeekPos(), but it is ensured that no attribute is cut,
2211 // i.e. the next given attribute begins at or after nPos.
2212 // Is used for fields and bookmarks.
2213 bool WW8PLCFspecial::SeekPosExact(tools::Long nP
)
2215 if( nP
< m_pPLCF_PosArray
[0] )
2218 return false; // Not found: nP less than smallest entry
2220 // Search from beginning?
2221 if( nP
<=m_pPLCF_PosArray
[m_nIdx
] )
2224 tools::Long nI
= m_nIdx
? m_nIdx
-1 : 0;
2225 tools::Long nEnd
= m_nIMax
;
2227 for(int n
= (0==m_nIdx
? 1 : 2); n
; --n
)
2229 for( ; nI
< nEnd
; ++nI
)
2231 if( nP
<=m_pPLCF_PosArray
[nI
] )
2233 m_nIdx
= nI
; // nI is the correct index
2234 return true; // done
2240 m_nIdx
= m_nIMax
; // Not found, greater than all entries
2244 bool WW8PLCFspecial::Get(WW8_CP
& rPos
, void*& rpValue
) const
2246 return GetData( m_nIdx
, rPos
, rpValue
);
2249 bool WW8PLCFspecial::GetData(tools::Long nInIdx
, WW8_CP
& rPos
, void*& rpValue
) const
2251 if ( nInIdx
>= m_nIMax
)
2256 rPos
= m_pPLCF_PosArray
[nInIdx
];
2257 rpValue
= m_pPLCF_Contents
? static_cast<void*>(&m_pPLCF_Contents
[nInIdx
* m_nStru
]) : nullptr;
2261 // WW8PLCF e.g. for SEPX
2262 // Ctor for *others* than Fkps
2263 // With nStartPos < 0, the first element of PLCFs will be taken
2264 WW8PLCF::WW8PLCF(SvStream
& rSt
, WW8_FC nFilePos
, sal_Int32 nPLCF
, int nStruct
,
2265 WW8_CP nStartPos
) : m_nIdx(0), m_nStru(nStruct
)
2269 SAL_WARN("sw.ww8", "broken WW8PLCF, ignoring");
2273 m_nIMax
= (nPLCF
- 4) / (4 + nStruct
);
2275 ReadPLCF(rSt
, nFilePos
, nPLCF
);
2277 if( nStartPos
>= 0 )
2278 SeekPos( nStartPos
);
2281 // Ctor *only* for Fkps
2282 // The last 2 parameters are needed for PLCF.Chpx and PLCF.Papx.
2283 // If ncpN != 0, then an incomplete PLCF will be completed. This is always required for WW6 with
2284 // lack of resources and for WordPad (W95).
2285 // With nStartPos < 0, the first element of the PLCFs is taken.
2286 WW8PLCF::WW8PLCF(SvStream
& rSt
, WW8_FC nFilePos
, sal_Int32 nPLCF
, int nStruct
,
2287 WW8_CP nStartPos
, sal_Int32 nPN
, sal_Int32 ncpN
): m_nIdx(0),
2292 SAL_WARN("sw.ww8", "broken WW8PLCF, ignoring");
2293 m_nIMax
= SAL_MAX_INT32
;
2296 m_nIMax
= (nPLCF
- 4) / (4 + nStruct
);
2298 if( m_nIMax
>= ncpN
)
2299 ReadPLCF(rSt
, nFilePos
, nPLCF
);
2301 GeneratePLCF(rSt
, nPN
, ncpN
);
2303 if( nStartPos
>= 0 )
2304 SeekPos( nStartPos
);
2307 void WW8PLCF::ReadPLCF(SvStream
& rSt
, WW8_FC nFilePos
, sal_uInt32 nPLCF
)
2309 sal_uInt64
const nOldPos
= rSt
.Tell();
2310 bool bValid
= nPLCF
!= 0 && checkSeek(rSt
, nFilePos
)
2311 && (rSt
.remainingSize() >= nPLCF
);
2315 // Pointer to Pos-array
2316 const size_t nEntries
= (nPLCF
+ 3) / 4;
2317 m_pPLCF_PosArray
.reset(new WW8_CP
[nEntries
]);
2318 bValid
= checkRead(rSt
, m_pPLCF_PosArray
.get(), nPLCF
);
2319 size_t nBytesAllocated
= nEntries
* sizeof(WW8_CP
);
2320 if (bValid
&& nPLCF
!= nBytesAllocated
)
2322 sal_uInt8
* pStartBlock
= reinterpret_cast<sal_uInt8
*>(m_pPLCF_PosArray
.get());
2323 memset(pStartBlock
+ nPLCF
, 0, nBytesAllocated
- nPLCF
);
2329 #ifdef OSL_BIGENDIAN
2330 for( m_nIdx
= 0; m_nIdx
<= m_nIMax
; m_nIdx
++ )
2331 m_pPLCF_PosArray
[m_nIdx
] = OSL_SWAPDWORD( m_pPLCF_PosArray
[m_nIdx
] );
2333 #endif // OSL_BIGENDIAN
2334 // Pointer to content array
2335 m_pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&m_pPLCF_PosArray
[m_nIMax
+ 1]);
2337 TruncToSortedRange();
2340 OSL_ENSURE(bValid
, "Document has corrupt PLCF, ignoring it");
2348 void WW8PLCF::MakeFailedPLCF()
2351 m_pPLCF_PosArray
.reset( new WW8_CP
[2] );
2352 m_pPLCF_PosArray
[0] = m_pPLCF_PosArray
[1] = WW8_CP_MAX
;
2353 m_pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&m_pPLCF_PosArray
[m_nIMax
+ 1]);
2358 sal_Int32
TruncToSortedRange(const sal_Int32
* pPLCF_PosArray
, sal_Int32 nIMax
)
2360 //Docs state that: ... all Plcs ... are sorted in ascending order.
2361 //So ensure that here for broken documents.
2362 for (auto nI
= 0; nI
< nIMax
; ++nI
)
2364 if (pPLCF_PosArray
[nI
] > pPLCF_PosArray
[nI
+1])
2366 SAL_WARN("sw.ww8", "Document has unsorted PLCF, truncated to sorted portion");
2375 void WW8PLCFpcd::TruncToSortedRange()
2377 m_nIMax
= ::TruncToSortedRange(m_pPLCF_PosArray
.get(), m_nIMax
);
2380 void WW8PLCF::TruncToSortedRange()
2382 m_nIMax
= ::TruncToSortedRange(m_pPLCF_PosArray
.get(), m_nIMax
);
2385 void WW8PLCF::GeneratePLCF(SvStream
& rSt
, sal_Int32 nPN
, sal_Int32 ncpN
)
2387 OSL_ENSURE( m_nIMax
< ncpN
, "Pcl.Fkp: Why is PLCF too big?" );
2389 bool failure
= false;
2392 if ((m_nIMax
< 1) || (m_nIMax
> (WW8_CP_MAX
- 4) / (4 + m_nStru
)) || nPN
< 0)
2397 // Check arguments to ShortToSVBT16 in loop below will all be valid:
2399 failure
= o3tl::checked_add(nPN
, ncpN
, nResult
) || nResult
> SAL_MAX_UINT16
;
2404 size_t nSiz
= (4 + m_nStru
) * m_nIMax
+ 4;
2405 size_t nElems
= ( nSiz
+ 3 ) / 4;
2406 m_pPLCF_PosArray
.reset( new WW8_CP
[ nElems
] ); // Pointer to Pos-array
2408 for (sal_Int32 i
= 0; i
< ncpN
&& !failure
; ++i
)
2411 // construct FC entries
2412 // first FC entry of each Fkp
2413 if (!checkSeek(rSt
, (nPN
+ i
) << 9))
2417 rSt
.ReadInt32( nFc
);
2418 m_pPLCF_PosArray
[i
] = nFc
;
2420 failure
= bool(rSt
.GetError());
2430 std::size_t nLastFkpPos
= nPN
+ m_nIMax
- 1;
2431 nLastFkpPos
= nLastFkpPos
<< 9;
2432 // number of FC entries of last Fkp
2433 if (!checkSeek(rSt
, nLastFkpPos
+ 511))
2437 rSt
.ReadUChar( nb
);
2438 // last FC entry of last Fkp
2439 if (!checkSeek(rSt
, nLastFkpPos
+ nb
* 4))
2443 rSt
.ReadInt32( nFc
);
2444 m_pPLCF_PosArray
[m_nIMax
] = nFc
; // end of the last Fkp
2446 failure
= bool(rSt
.GetError());
2452 // Pointer to content array
2453 m_pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&m_pPLCF_PosArray
[m_nIMax
+ 1]);
2454 sal_uInt8
* p
= m_pPLCF_Contents
;
2456 for (sal_Int32 i
= 0; i
< ncpN
; ++i
) // construct PNs
2458 ShortToSVBT16(o3tl::narrowing
<sal_uInt16
>(nPN
+ i
), p
);
2463 SAL_WARN_IF(failure
, "sw.ww8", "Document has corrupt PLCF, ignoring it");
2469 bool WW8PLCF::SeekPos(WW8_CP nPos
)
2473 if( nP
< m_pPLCF_PosArray
[0] )
2476 // not found: nPos less than smallest entry
2480 // Search from beginning?
2481 if ((m_nIdx
< 1) || (nP
< m_pPLCF_PosArray
[m_nIdx
- 1]))
2484 sal_Int32 nI
= m_nIdx
;
2485 sal_Int32 nEnd
= m_nIMax
;
2487 for(int n
= (1==m_nIdx
? 1 : 2); n
; --n
)
2489 for( ; nI
<=nEnd
; ++nI
) // search with an index that is incremented by 1
2491 if( nP
< m_pPLCF_PosArray
[nI
] ) // found position
2493 m_nIdx
= nI
- 1; // nI - 1 is the correct index
2494 return true; // done
2501 m_nIdx
= m_nIMax
; // not found, greater than all entries
2505 bool WW8PLCF::Get(WW8_CP
& rStart
, WW8_CP
& rEnd
, void*& rpValue
) const
2507 if ( m_nIdx
>= m_nIMax
)
2509 rStart
= rEnd
= WW8_CP_MAX
;
2512 rStart
= m_pPLCF_PosArray
[ m_nIdx
];
2513 rEnd
= m_pPLCF_PosArray
[ m_nIdx
+ 1 ];
2514 rpValue
= static_cast<void*>(&m_pPLCF_Contents
[m_nIdx
* m_nStru
]);
2518 WW8_CP
WW8PLCF::Where() const
2520 if ( m_nIdx
>= m_nIMax
)
2523 return m_pPLCF_PosArray
[m_nIdx
];
2526 WW8PLCFpcd::WW8PLCFpcd(SvStream
* pSt
, sal_uInt32 nFilePos
,
2527 sal_uInt32 nPLCF
, sal_uInt32 nStruct
)
2528 : m_nStru( nStruct
)
2530 const sal_uInt32 nValidMin
=4;
2532 sal_uInt64
const nOldPos
= pSt
->Tell();
2534 bool bValid
= checkSeek(*pSt
, nFilePos
);
2535 std::size_t nRemainingSize
= pSt
->remainingSize();
2536 if( nRemainingSize
< nValidMin
|| nPLCF
< nValidMin
)
2538 nPLCF
= bValid
? std::min(nRemainingSize
, static_cast<std::size_t>(nPLCF
)) : nValidMin
;
2540 m_pPLCF_PosArray
.reset( new WW8_CP
[ ( nPLCF
+ 3 ) / 4 ] ); // Pointer to Pos-array
2541 m_pPLCF_PosArray
[0] = 0;
2543 nPLCF
= bValid
? pSt
->ReadBytes(m_pPLCF_PosArray
.get(), nPLCF
) : nValidMin
;
2544 nPLCF
= std::max(nPLCF
, nValidMin
);
2546 m_nIMax
= ( nPLCF
- 4 ) / ( 4 + nStruct
);
2547 #ifdef OSL_BIGENDIAN
2548 for( tools::Long nI
= 0; nI
<= m_nIMax
; nI
++ )
2549 m_pPLCF_PosArray
[nI
] = OSL_SWAPDWORD( m_pPLCF_PosArray
[nI
] );
2550 #endif // OSL_BIGENDIAN
2552 // Pointer to content array
2553 m_pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&m_pPLCF_PosArray
[m_nIMax
+ 1]);
2554 TruncToSortedRange();
2556 pSt
->Seek( nOldPos
);
2559 // If nStartPos < 0, the first element of PLCFs will be taken
2560 WW8PLCFpcd_Iter::WW8PLCFpcd_Iter( WW8PLCFpcd
& rPLCFpcd
, tools::Long nStartPos
)
2561 :m_rPLCF( rPLCFpcd
), m_nIdx( 0 )
2563 if( nStartPos
>= 0 )
2564 SeekPos( nStartPos
);
2567 bool WW8PLCFpcd_Iter::SeekPos(tools::Long nPos
)
2569 tools::Long nP
= nPos
;
2571 if( nP
< m_rPLCF
.m_pPLCF_PosArray
[0] )
2574 return false; // not found: nPos less than smallest entry
2576 // Search from beginning?
2577 if ((m_nIdx
< 1) || (nP
< m_rPLCF
.m_pPLCF_PosArray
[m_nIdx
- 1]))
2580 tools::Long nI
= m_nIdx
;
2581 tools::Long nEnd
= m_rPLCF
.m_nIMax
;
2583 for(int n
= (1==m_nIdx
? 1 : 2); n
; --n
)
2585 for( ; nI
<=nEnd
; ++nI
)
2586 { // search with an index that is incremented by 1
2587 if( nP
< m_rPLCF
.m_pPLCF_PosArray
[nI
] )
2589 m_nIdx
= nI
- 1; // nI - 1 is the correct index
2590 return true; // done
2596 m_nIdx
= m_rPLCF
.m_nIMax
; // not found, greater than all entries
2600 bool WW8PLCFpcd_Iter::Get(WW8_CP
& rStart
, WW8_CP
& rEnd
, void*& rpValue
) const
2602 if( m_nIdx
>= m_rPLCF
.m_nIMax
)
2604 rStart
= rEnd
= WW8_CP_MAX
;
2607 rStart
= m_rPLCF
.m_pPLCF_PosArray
[m_nIdx
];
2608 rEnd
= m_rPLCF
.m_pPLCF_PosArray
[m_nIdx
+ 1];
2609 rpValue
= static_cast<void*>(&m_rPLCF
.m_pPLCF_Contents
[m_nIdx
* m_rPLCF
.m_nStru
]);
2613 sal_Int32
WW8PLCFpcd_Iter::Where() const
2615 if ( m_nIdx
>= m_rPLCF
.m_nIMax
)
2616 return SAL_MAX_INT32
;
2618 return m_rPLCF
.m_pPLCF_PosArray
[m_nIdx
];
2621 bool WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator<
2622 (const WW8PLCFx_Fc_FKP::WW8Fkp::Entry
& rSecond
) const
2624 return (mnFC
< rSecond
.mnFC
);
2627 static bool IsReplaceAllSprm(sal_uInt16 nSpId
)
2629 return (NS_sprm::LN_PHugePapx
== nSpId
|| 0x6646 == nSpId
);
2632 static bool IsExpandableSprm(sal_uInt16 nSpId
)
2634 return 0x646B == nSpId
;
2637 void WW8PLCFx_Fc_FKP::WW8Fkp::FillEntry(WW8PLCFx_Fc_FKP::WW8Fkp::Entry
&rEntry
,
2638 std::size_t nDataOffset
, sal_uInt16 nLen
)
2640 bool bValidPos
= (nDataOffset
< sizeof(maRawData
));
2642 OSL_ENSURE(bValidPos
, "sprm sequence offset is out of range, ignoring");
2650 const sal_uInt16 nAvailableData
= sizeof(maRawData
)-nDataOffset
;
2651 OSL_ENSURE(nLen
<= nAvailableData
, "sprm sequence len is out of range, clipping");
2652 rEntry
.mnLen
= std::min(nLen
, nAvailableData
);
2653 rEntry
.mpData
= maRawData
+ nDataOffset
;
2656 WW8PLCFx_Fc_FKP::WW8Fkp::WW8Fkp(const WW8Fib
& rFib
, SvStream
* pSt
,
2657 SvStream
* pDataSt
, tools::Long _nFilePos
, tools::Long nItemSiz
, ePLCFT ePl
,
2659 : m_nItemSize(nItemSiz
), m_nFilePos(_nFilePos
), mnIdx(0), m_ePLCF(ePl
)
2660 , mnMustRemainCached(0), maSprmParser(rFib
)
2662 memset(maRawData
, 0, 512);
2664 const ww::WordVersion eVersion
= rFib
.GetFIBVersion();
2666 sal_uInt64
const nOldPos
= pSt
->Tell();
2668 bool bCouldSeek
= checkSeek(*pSt
, m_nFilePos
);
2669 bool bCouldRead
= bCouldSeek
&& checkRead(*pSt
, maRawData
, 512);
2671 mnIMax
= bCouldRead
? maRawData
[511] : 0;
2673 sal_uInt8
*pStart
= maRawData
;
2674 // Offset-Location in maRawData
2675 const size_t nRawDataStart
= (mnIMax
+ 1) * 4;
2677 for (mnIdx
= 0; mnIdx
< mnIMax
; ++mnIdx
)
2679 const size_t nRawDataOffset
= nRawDataStart
+ mnIdx
* m_nItemSize
;
2681 //clip to available data, corrupt fkp
2682 if (nRawDataOffset
>= 511)
2688 unsigned int nOfs
= maRawData
[nRawDataOffset
] * 2;
2689 // nOfs in [0..0xff*2=510]
2691 Entry
aEntry(Get_Long(pStart
));
2699 aEntry
.mnLen
= maRawData
[nOfs
];
2702 std::size_t nDataOffset
= nOfs
+ 1;
2704 FillEntry(aEntry
, nDataOffset
, aEntry
.mnLen
);
2706 if (aEntry
.mnLen
&& eVersion
<= ww::eWW2
)
2708 Word2CHPX aChpx
= ReadWord2Chpx(*pSt
, m_nFilePos
+ nOfs
+ 1, static_cast< sal_uInt8
>(aEntry
.mnLen
));
2709 std::vector
<sal_uInt8
> aSprms
= ChpxToSprms(aChpx
);
2710 aEntry
.mnLen
= static_cast< sal_uInt16
>(aSprms
.size());
2713 aEntry
.mpData
= new sal_uInt8
[aEntry
.mnLen
];
2714 memcpy(aEntry
.mpData
, aSprms
.data(), aEntry
.mnLen
);
2715 aEntry
.mbMustDelete
= true;
2722 sal_uInt8 nDelta
= 0;
2724 aEntry
.mnLen
= maRawData
[nOfs
];
2725 if (IsEightPlus(eVersion
) && !aEntry
.mnLen
)
2727 aEntry
.mnLen
= maRawData
[nOfs
+1];
2732 //stylecode, std/istd
2733 if (eVersion
<= ww::eWW2
)
2735 if (aEntry
.mnLen
>= 1)
2737 aEntry
.mnIStd
= *(maRawData
+nOfs
+1+nDelta
);
2738 aEntry
.mnLen
--; //style code
2739 if (aEntry
.mnLen
>= 6)
2741 aEntry
.mnLen
-=6; //PHE
2742 //skip stc, len byte + 6 byte PHE
2743 unsigned int nOffset
= nOfs
+ 8;
2744 if (nOffset
>= 511) //Bad offset
2746 if (aEntry
.mnLen
) //start is ok
2748 if (nOffset
+ aEntry
.mnLen
> 512) //Bad end, clip
2749 aEntry
.mnLen
= 512 - nOffset
;
2750 aEntry
.mpData
= maRawData
+ nOffset
;
2754 aEntry
.mnLen
=0; //Too short
2759 if (aEntry
.mnLen
>= 2)
2761 //len byte + optional extra len byte
2762 std::size_t nDataOffset
= nOfs
+ 1 + nDelta
;
2763 aEntry
.mnIStd
= nDataOffset
<= sizeof(maRawData
)-sizeof(aEntry
.mnIStd
) ?
2764 SVBT16ToUInt16(maRawData
+nDataOffset
) : 0;
2765 aEntry
.mnLen
-=2; //istd
2769 nDataOffset
+= sizeof(aEntry
.mnIStd
);
2771 FillEntry(aEntry
, nDataOffset
, aEntry
.mnLen
);
2775 aEntry
.mnLen
=0; //Too short, ignore
2778 const sal_uInt16 nSpId
= aEntry
.mnLen
2779 ? maSprmParser
.GetSprmId(aEntry
.mpData
) : 0;
2782 If we replace then we throw away the old data, if we
2783 are expanding, then we tack the old data onto the end
2786 const bool bExpand
= IsExpandableSprm(nSpId
);
2787 const sal_uInt8
* pStartData
2788 = aEntry
.mpData
== nullptr ? nullptr : aEntry
.mpData
+ 2;
2789 const sal_uInt8
* pLastValidDataPos
= maRawData
+ 512 - sizeof(sal_uInt32
);
2790 if (pStartData
!= nullptr && pStartData
> pLastValidDataPos
)
2791 pStartData
= nullptr;
2792 if ((IsReplaceAllSprm(nSpId
) || bExpand
) && pStartData
)
2794 sal_uInt32 nCurr
= pDataSt
->Tell();
2795 sal_uInt32 nPos
= SVBT32ToUInt32(pStartData
);
2798 bool bOk
= checkSeek(*pDataSt
, nPos
);
2801 pDataSt
->ReadUInt16( nLen
);
2802 bOk
= nLen
<= pDataSt
->remainingSize();
2807 const sal_uInt16 nOrigLen
= bExpand
? aEntry
.mnLen
: 0;
2808 sal_uInt8
*pOrigData
= bExpand
? aEntry
.mpData
: nullptr;
2810 aEntry
.mnLen
= nLen
;
2812 new sal_uInt8
[aEntry
.mnLen
+ nOrigLen
];
2813 aEntry
.mbMustDelete
= true;
2815 pDataSt
->ReadBytes(aEntry
.mpData
, aEntry
.mnLen
);
2817 pDataSt
->Seek( nCurr
);
2821 memcpy(aEntry
.mpData
+ aEntry
.mnLen
,
2822 pOrigData
, nOrigLen
);
2823 aEntry
.mnLen
= aEntry
.mnLen
+ nOrigLen
;
2830 OSL_FAIL("sweet god, what have you done!");
2835 maEntries
.push_back(aEntry
);
2837 #ifdef DEBUGSPRMREADER
2840 sal_uInt8
* pSprms
= GetLenAndIStdAndSprms( nLen
);
2841 WW8SprmIter
aIter(pSprms
, nLen
, maSprmParser
);
2842 while (aIter
.GetSprms())
2844 fprintf(stderr
, "id is %x\n", aIter
.GetCurrentId());
2851 //one more FC than grrpl entries
2852 maEntries
.emplace_back(Get_Long(pStart
));
2854 //we expect them sorted, but it appears possible for them to arrive unsorted
2855 std::stable_sort(maEntries
.begin(), maEntries
.end());
2865 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::Entry(const Entry
&rEntry
)
2866 : mnFC(rEntry
.mnFC
), mnLen(rEntry
.mnLen
), mnIStd(rEntry
.mnIStd
),
2867 mbMustDelete(rEntry
.mbMustDelete
)
2871 mpData
= new sal_uInt8
[mnLen
];
2872 memcpy(mpData
, rEntry
.mpData
, mnLen
);
2875 mpData
= rEntry
.mpData
;
2878 WW8PLCFx_Fc_FKP::WW8Fkp::Entry
&
2879 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator=(const Entry
&rEntry
)
2881 if (this == &rEntry
)
2888 mnLen
= rEntry
.mnLen
;
2889 mnIStd
= rEntry
.mnIStd
;
2890 mbMustDelete
= rEntry
.mbMustDelete
;
2892 if (rEntry
.mbMustDelete
)
2894 mpData
= new sal_uInt8
[mnLen
];
2895 memcpy(mpData
, rEntry
.mpData
, mnLen
);
2898 mpData
= rEntry
.mpData
;
2903 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::~Entry()
2909 void WW8PLCFx_Fc_FKP::WW8Fkp::Reset(WW8_FC nFc
)
2916 bool WW8PLCFx_Fc_FKP::WW8Fkp::SeekPos(WW8_FC nFc
)
2918 if (nFc
< maEntries
[0].mnFC
)
2921 return false; // not found: nPos less than smallest entry
2924 // Search from beginning?
2925 if ((mnIdx
< 1) || (nFc
< maEntries
[mnIdx
- 1].mnFC
))
2928 sal_uInt8 nI
= mnIdx
;
2929 sal_uInt8 nEnd
= mnIMax
;
2931 for(sal_uInt8 n
= (1==mnIdx
? 1 : 2); n
; --n
)
2933 for( ; nI
<=nEnd
; ++nI
)
2934 { // search with an index that is incremented by 1
2935 if (nFc
< maEntries
[nI
].mnFC
)
2937 mnIdx
= nI
- 1; // nI - 1 is the correct index
2938 return true; // done
2944 mnIdx
= mnIMax
; // not found, greater than all entries
2948 sal_uInt8
* WW8PLCFx_Fc_FKP::WW8Fkp::Get(WW8_FC
& rStart
, WW8_FC
& rEnd
, sal_Int32
& rLen
)
2953 if (mnIdx
>= mnIMax
)
2955 rStart
= WW8_FC_MAX
;
2959 rStart
= maEntries
[mnIdx
].mnFC
;
2960 rEnd
= maEntries
[mnIdx
+ 1].mnFC
;
2962 sal_uInt8
* pSprms
= GetLenAndIStdAndSprms( rLen
);
2966 void WW8PLCFx_Fc_FKP::WW8Fkp::SetIdx(sal_uInt8 nI
)
2974 sal_uInt8
* WW8PLCFx_Fc_FKP::WW8Fkp::GetLenAndIStdAndSprms(sal_Int32
& rLen
) const
2976 rLen
= maEntries
[mnIdx
].mnLen
;
2977 return maEntries
[mnIdx
].mpData
;
2980 SprmResult
WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm( sal_uInt16 nId
, bool bFindFirst
)
2982 if (mnIdx
>= mnIMax
)
2983 return SprmResult();
2986 sal_uInt8
* pSprms
= GetLenAndIStdAndSprms( nLen
);
2988 WW8SprmIter
aIter(pSprms
, nLen
, maSprmParser
);
2989 return aIter
.FindSprm(nId
, bFindFirst
);
2992 void WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm(sal_uInt16 nId
,
2993 std::vector
<SprmResult
> &rResult
)
2995 if (mnIdx
>= mnIMax
)
2999 sal_uInt8
* pSprms
= GetLenAndIStdAndSprms( nLen
);
3001 WW8SprmIter
aIter(pSprms
, nLen
, maSprmParser
);
3003 while(aIter
.GetSprms())
3005 if (aIter
.GetCurrentId() == nId
)
3007 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId
);
3008 sal_Int32 nL
= maSprmParser
.GetSprmSize(nId
, aIter
.GetSprms(), aIter
.GetRemLen());
3009 rResult
.emplace_back(aIter
.GetCurrentParams(), nL
- nFixedLen
);
3015 ww::WordVersion
WW8PLCFx::GetFIBVersion() const
3017 return mrFib
.GetFIBVersion();
3020 void WW8PLCFx::GetSprms( WW8PLCFxDesc
* p
)
3022 OSL_ENSURE( false, "Called wrong GetSprms" );
3023 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
3024 p
->pMemPos
= nullptr;
3026 p
->bRealLineEnd
= false;
3029 tools::Long
WW8PLCFx::GetNoSprms( WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
3031 OSL_ENSURE( false, "Called wrong GetNoSprms" );
3032 rStart
= rEnd
= WW8_CP_MAX
;
3037 // ...Idx2: Default: ignore
3038 sal_uInt32
WW8PLCFx::GetIdx2() const
3043 void WW8PLCFx::SetIdx2(sal_uInt32
)
3054 explicit SamePos(tools::Long nPo
) : mnPo(nPo
) {}
3055 bool operator()(const std::unique_ptr
<WW8PLCFx_Fc_FKP::WW8Fkp
>& pFkp
)
3056 {return mnPo
== pFkp
->GetFilePos();}
3061 bool WW8PLCFx_Fc_FKP::NewFkp()
3063 WW8_CP nPLCFStart
, nPLCFEnd
;
3066 static const int WW8FkpSizeTabVer2
[ PLCF_END
] =
3068 1, 1, 0 /*, 0, 0, 0*/
3070 static const int WW8FkpSizeTabVer6
[ PLCF_END
] =
3072 1, 7, 0 /*, 0, 0, 0*/
3074 static const int WW8FkpSizeTabVer8
[ PLCF_END
] =
3076 1, 13, 0 /*, 0, 0, 0*/
3078 const int* pFkpSizeTab
;
3080 switch (GetFIBVersion())
3084 pFkpSizeTab
= WW8FkpSizeTabVer2
;
3088 pFkpSizeTab
= WW8FkpSizeTabVer6
;
3091 pFkpSizeTab
= WW8FkpSizeTabVer8
;
3095 OSL_ENSURE( false, "nVersion not implemented!" );
3099 if (!m_pPLCF
->Get( nPLCFStart
, nPLCFEnd
, pPage
))
3102 return false; // PLCF completely processed
3105 tools::Long nPo
= SVBT16ToUInt16( static_cast<sal_uInt8
*>(pPage
) );
3106 nPo
<<= 9; // shift as LONG
3108 tools::Long nCurrentFkpFilePos
= m_pFkp
? m_pFkp
->GetFilePos() : -1;
3109 if (nCurrentFkpFilePos
== nPo
)
3110 m_pFkp
->Reset(GetStartFc());
3114 std::find_if(maFkpCache
.begin(), maFkpCache
.end(), SamePos(nPo
));
3115 if (aIter
!= maFkpCache
.end())
3117 m_pFkp
= aIter
->get();
3118 m_pFkp
->Reset(GetStartFc());
3122 m_pFkp
= new WW8Fkp(GetFIB(), m_pFKPStrm
, m_pDataStrm
, nPo
,
3123 pFkpSizeTab
[ m_ePLCF
], m_ePLCF
, GetStartFc());
3124 maFkpCache
.push_back(std::unique_ptr
<WW8Fkp
>(m_pFkp
));
3126 if (maFkpCache
.size() > eMaxCache
)
3128 WW8Fkp
* pCachedFkp
= maFkpCache
.front().get();
3129 if (!pCachedFkp
->IsMustRemainCache())
3131 maFkpCache
.pop_front();
3137 SetStartFc( -1 ); // only the first time
3141 WW8PLCFx_Fc_FKP::WW8PLCFx_Fc_FKP(SvStream
* pSt
, SvStream
* pTableSt
,
3142 SvStream
* pDataSt
, const WW8Fib
& rFib
, ePLCFT ePl
, WW8_FC nStartFcL
)
3143 : WW8PLCFx(rFib
, true), m_pFKPStrm(pSt
), m_pDataStrm(pDataSt
)
3144 , m_pFkp(nullptr), m_ePLCF(ePl
)
3146 SetStartFc(nStartFcL
);
3147 tools::Long nLenStruct
= (8 > rFib
.m_nVersion
) ? 2 : 4;
3150 m_pPLCF
.reset(new WW8PLCF(*pTableSt
, rFib
.m_fcPlcfbteChpx
, rFib
.m_lcbPlcfbteChpx
,
3151 nLenStruct
, GetStartFc(), rFib
.m_pnChpFirst
, rFib
.m_cpnBteChp
));
3155 m_pPLCF
.reset(new WW8PLCF(*pTableSt
, rFib
.m_fcPlcfbtePapx
, rFib
.m_lcbPlcfbtePapx
,
3156 nLenStruct
, GetStartFc(), rFib
.m_pnPapFirst
, rFib
.m_cpnBtePap
));
3160 WW8PLCFx_Fc_FKP::~WW8PLCFx_Fc_FKP()
3164 m_pPCDAttrs
.reset();
3167 sal_uInt32
WW8PLCFx_Fc_FKP::GetIdx() const
3169 sal_uInt32 u
= m_pPLCF
->GetIdx() << 8;
3171 u
|= m_pFkp
->GetIdx();
3175 void WW8PLCFx_Fc_FKP::SetIdx(sal_uInt32 nIdx
)
3177 if( !( nIdx
& 0xffffff00L
) )
3179 m_pPLCF
->SetIdx( nIdx
>> 8 );
3183 { // there was a Fkp
3184 // Set PLCF one position back to retrieve the address of the Fkp
3185 m_pPLCF
->SetIdx( ( nIdx
>> 8 ) - 1 );
3186 if (NewFkp()) // read Fkp again
3188 sal_uInt8 nFkpIdx
= static_cast<sal_uInt8
>(nIdx
& 0xff);
3189 m_pFkp
->SetIdx(nFkpIdx
); // set Fkp-Pos again
3194 bool WW8PLCFx_Fc_FKP::SeekPos(WW8_FC nFcPos
)
3196 // StartPos for next Where()
3197 SetStartFc( nFcPos
);
3199 // find StartPos for next pPLCF->Get()
3200 bool bRet
= m_pPLCF
->SeekPos(nFcPos
);
3202 // make FKP invalid?
3203 WW8_CP nPLCFStart
, nPLCFEnd
;
3205 if( m_pFkp
&& m_pPLCF
->Get( nPLCFStart
, nPLCFEnd
, pPage
) )
3207 tools::Long nPo
= SVBT16ToUInt16( static_cast<sal_uInt8
*>(pPage
) );
3208 nPo
<<= 9; // shift as LONG
3209 if (nPo
!= m_pFkp
->GetFilePos())
3212 m_pFkp
->SeekPos( nFcPos
);
3217 WW8_FC
WW8PLCFx_Fc_FKP::Where()
3219 if( !m_pFkp
&& !NewFkp() )
3221 WW8_FC nP
= m_pFkp
? m_pFkp
->Where() : WW8_FC_MAX
;
3222 if( nP
!= WW8_FC_MAX
)
3225 m_pFkp
= nullptr; // FKP finished -> get new
3226 return Where(); // easiest way: do it recursively
3229 sal_uInt8
* WW8PLCFx_Fc_FKP::GetSprmsAndPos(WW8_FC
& rStart
, WW8_FC
& rEnd
, sal_Int32
& rLen
)
3231 rLen
= 0; // Default
3232 rStart
= rEnd
= WW8_FC_MAX
;
3234 if( !m_pFkp
) // Fkp not there ?
3240 sal_uInt8
* pPos
= m_pFkp
? m_pFkp
->Get( rStart
, rEnd
, rLen
) : nullptr;
3241 if( rStart
== WW8_FC_MAX
) //Not found
3246 void WW8PLCFx_Fc_FKP::advance()
3248 if( !m_pFkp
&& !NewFkp() )
3255 if( m_pFkp
->Where() == WW8_FC_MAX
)
3259 sal_uInt16
WW8PLCFx_Fc_FKP::GetIstd() const
3261 return m_pFkp
? m_pFkp
->GetIstd() : 0xFFFF;
3264 void WW8PLCFx_Fc_FKP::GetPCDSprms( WW8PLCFxDesc
& rDesc
)
3266 rDesc
.pMemPos
= nullptr;
3267 rDesc
.nSprmsLen
= 0;
3272 OSL_FAIL("+Problem: GetPCDSprms: NewFkp necessary (not possible!)" );
3276 m_pPCDAttrs
->GetSprms(&rDesc
);
3280 SprmResult
WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId
, bool bFindFirst
)
3282 // const would be nicer, but for that, NewFkp() would need to be replaced or eliminated
3285 OSL_FAIL( "+Motz: HasSprm: NewFkp needed ( no const possible )" );
3286 // happens in BugDoc 31722
3288 return SprmResult();
3292 return SprmResult();
3294 SprmResult aRes
= m_pFkp
->HasSprm(nId
, bFindFirst
);
3299 GetPCDSprms( aDesc
);
3303 WW8SprmIter
aIter(aDesc
.pMemPos
, aDesc
.nSprmsLen
,
3304 m_pFkp
->GetSprmParser());
3305 aRes
= aIter
.FindSprm(nId
, bFindFirst
);
3312 void WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId
, std::vector
<SprmResult
> &rResult
)
3314 // const would be nicer, but for that, NewFkp() would need to be replaced or eliminated
3317 OSL_FAIL( "+Motz: HasSprm: NewFkp needed ( no const possible )" );
3318 // happens in BugDoc 31722
3326 m_pFkp
->HasSprm(nId
, rResult
);
3329 GetPCDSprms( aDesc
);
3334 const wwSprmParser
&rSprmParser
= m_pFkp
->GetSprmParser();
3335 WW8SprmIter
aIter(aDesc
.pMemPos
, aDesc
.nSprmsLen
, rSprmParser
);
3336 while(aIter
.GetSprms())
3338 if (aIter
.GetCurrentId() == nId
)
3340 sal_Int32 nFixedLen
= rSprmParser
.DistanceToData(nId
);
3341 sal_Int32 nL
= rSprmParser
.GetSprmSize(nId
, aIter
.GetSprms(), aIter
.GetRemLen());
3342 rResult
.emplace_back(aIter
.GetCurrentParams(), nL
- nFixedLen
);
3348 WW8PLCFx_Cp_FKP::WW8PLCFx_Cp_FKP( SvStream
* pSt
, SvStream
* pTableSt
,
3349 SvStream
* pDataSt
, const WW8ScannerBase
& rBase
, ePLCFT ePl
)
3350 : WW8PLCFx_Fc_FKP(pSt
, pTableSt
, pDataSt
, *rBase
.m_pWw8Fib
, ePl
,
3351 rBase
.WW8Cp2Fc(0)), m_rSBase(rBase
), m_nAttrStart(-1), m_nAttrEnd(-1),
3353 m_bComplex( (7 < rBase
.m_pWw8Fib
->m_nVersion
) || rBase
.m_pWw8Fib
->m_fComplex
)
3355 ResetAttrStartEnd();
3357 if (m_rSBase
.m_pPiecePLCF
)
3358 m_pPcd
.reset( new WW8PLCFx_PCD(GetFIB(), rBase
.m_pPiecePLCF
.get(), 0, IsSevenMinus(GetFIBVersion())) );
3361 Make a copy of the piece attributes for so that the calls to HasSprm on a
3362 Fc_FKP will be able to take into account the current piece attributes,
3363 despite the fact that such attributes can only be found through a cp based
3368 m_pPCDAttrs
.reset( m_rSBase
.m_pPLCFx_PCDAttrs
? new WW8PLCFx_PCDAttrs(
3369 *m_rSBase
.m_pWw8Fib
, m_pPcd
.get(), &m_rSBase
) : nullptr);
3372 m_pPieceIter
= m_rSBase
.m_pPieceIter
.get();
3375 WW8PLCFx_Cp_FKP::~WW8PLCFx_Cp_FKP()
3379 void WW8PLCFx_Cp_FKP::ResetAttrStartEnd()
3386 sal_uInt32
WW8PLCFx_Cp_FKP::GetPCDIdx() const
3388 return m_pPcd
? m_pPcd
->GetIdx() : 0;
3391 bool WW8PLCFx_Cp_FKP::SeekPos(WW8_CP nCpPos
)
3393 if( m_pPcd
) // Complex
3395 if( !m_pPcd
->SeekPos( nCpPos
) ) // set piece
3397 if (m_pPCDAttrs
&& !m_pPCDAttrs
->GetIter()->SeekPos(nCpPos
))
3399 return WW8PLCFx_Fc_FKP::SeekPos(m_pPcd
->CurrentPieceStartCp2Fc(nCpPos
));
3401 // NO piece table !!!
3402 return WW8PLCFx_Fc_FKP::SeekPos( m_rSBase
.WW8Cp2Fc(nCpPos
) );
3405 WW8_CP
WW8PLCFx_Cp_FKP::Where()
3407 WW8_FC nFc
= WW8PLCFx_Fc_FKP::Where();
3409 return m_pPcd
->CurrentPieceStartFc2Cp( nFc
); // identify piece
3410 return m_rSBase
.WW8Fc2Cp( nFc
); // NO piece table !!!
3413 void WW8PLCFx_Cp_FKP::GetSprms(WW8PLCFxDesc
* p
)
3415 WW8_CP nOrigCp
= p
->nStartPos
;
3417 if (!GetDirty()) //Normal case
3419 p
->pMemPos
= WW8PLCFx_Fc_FKP::GetSprmsAndPos(p
->nStartPos
, p
->nEndPos
,
3425 For the odd case where we have a location in a fastsaved file which
3426 does not have an entry in the FKP, perhaps its para end is in the next
3427 piece, or perhaps the cp just doesn't exist at all in this document.
3428 AdvSprm doesn't know so it sets the PLCF as dirty and we figure out
3429 in this method what the situation is
3431 It doesn't exist then the piece iterator will not be able to find it.
3432 Otherwise our cool fastsave algorithm can be brought to bear on the
3437 const sal_uInt32 nOldPos
= m_pPieceIter
->GetIdx();
3438 bool bOk
= m_pPieceIter
->SeekPos(nOrigCp
);
3439 m_pPieceIter
->SetIdx(nOldPos
);
3444 if( m_pPcd
) // piece table available
3446 // Init ( no ++ called, yet )
3447 if( (m_nAttrStart
> m_nAttrEnd
) || (m_nAttrStart
== -1) )
3449 p
->bRealLineEnd
= (m_ePLCF
== PAP
);
3451 if ( ((m_ePLCF
== PAP
) || (m_ePLCF
== CHP
)) && (nOrigCp
!= WW8_CP_MAX
) )
3453 bool bIsUnicode
=false;
3455 To find the end of a paragraph for a character in a
3456 complex format file.
3458 It is necessary to know the piece that contains the
3459 character and the FC assigned to the character.
3462 //We set the piece iterator to the piece that contains the
3463 //character, now we have the correct piece for this character
3464 sal_uInt32 nOldPos
= m_pPieceIter
->GetIdx();
3465 p
->nStartPos
= nOrigCp
;
3466 m_pPieceIter
->SeekPos( p
->nStartPos
);
3468 //This is the FC assigned to the character, but we already
3469 //have the result of the next stage, so we can skip this step
3470 //WW8_FC nStartFc = rSBase.WW8Cp2Fc(p->nStartPos, &bIsUnicode);
3473 Using the FC of the character, first search the FKP that
3474 describes the character to find the smallest FC in the rgfc
3475 that is larger than the character FC.
3477 //But the search has already been done, the next largest FC is
3479 WW8_FC nOldEndPos
= p
->nEndPos
;
3482 If the FC found in the FKP is less than or equal to the limit
3483 FC of the piece, the end of the paragraph that contains the
3484 character is at the FKP FC minus 1.
3486 WW8_CP nCpStart
, nCpEnd
;
3487 void* pData
=nullptr;
3488 bool bOk
= m_pPieceIter
->Get(nCpStart
, nCpEnd
, pData
);
3492 m_pPieceIter
->SetIdx(nOldPos
);
3496 WW8_FC nLimitFC
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
3497 WW8_FC nBeginLimitFC
= nLimitFC
;
3498 if (IsEightPlus(GetFIBVersion()))
3501 WW8PLCFx_PCD::TransformPieceAddress(nLimitFC
,
3506 bool bFail
= o3tl::checked_sub(nCpEnd
, nCpStart
, nCpLen
);
3509 SAL_WARN("sw.ww8", "broken offset, ignoring");
3510 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3511 m_pPieceIter
->SetIdx(nOldPos
);
3517 bFail
= o3tl::checked_multiply
<WW8_CP
>(nCpLen
, 2, nCpLen
);
3520 SAL_WARN("sw.ww8", "broken offset, ignoring");
3521 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3522 m_pPieceIter
->SetIdx(nOldPos
);
3527 bFail
= o3tl::checked_add(nBeginLimitFC
, nCpLen
, nLimitFC
);
3530 SAL_WARN("sw.ww8", "broken offset, ignoring");
3531 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3532 m_pPieceIter
->SetIdx(nOldPos
);
3536 if (nOldEndPos
<= nLimitFC
)
3538 bFail
= o3tl::checked_sub(nLimitFC
, nOldEndPos
, nCpLen
);
3541 SAL_WARN("sw.ww8", "broken offset, ignoring");
3542 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3543 m_pPieceIter
->SetIdx(nOldPos
);
3547 nCpLen
/= (bIsUnicode
? 2 : 1);
3549 bFail
= o3tl::checked_sub(nCpEnd
, nCpLen
, p
->nEndPos
);
3552 SAL_WARN("sw.ww8", "broken offset, ignoring");
3553 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3554 m_pPieceIter
->SetIdx(nOldPos
);
3560 p
->nEndPos
= nCpEnd
;
3564 If the FKP FC that was found was greater than the FC
3565 of the end of the piece, scan piece by piece toward
3566 the end of the document until a piece is found that
3567 contains a paragraph end mark.
3571 It's possible to check if a piece contains a paragraph
3572 mark by using the FC of the beginning of the piece to
3573 search in the FKPs for the smallest FC in the FKP rgfc
3574 that is greater than the FC of the beginning of the
3575 piece. If the FC found is less than or equal to the
3576 limit FC of the piece, then the character that ends
3577 the paragraph is the character immediately before the
3581 m_pPieceIter
->advance();
3583 for (;m_pPieceIter
->GetIdx() < m_pPieceIter
->GetIMax();
3584 m_pPieceIter
->advance())
3586 if( !m_pPieceIter
->Get( nCpStart
, nCpEnd
, pData
) )
3588 OSL_ENSURE( false, "piece iter broken!" );
3592 sal_Int32 nFcStart
=SVBT32ToUInt32(static_cast<WW8_PCD
*>(pData
)->fc
);
3594 if (IsEightPlus(GetFIBVersion()))
3597 WW8PLCFx_PCD::TransformPieceAddress(
3598 nFcStart
,bIsUnicode
);
3601 bFail
= o3tl::checked_sub(nCpEnd
, nCpStart
, nCpLen
);
3604 SAL_WARN("sw.ww8", "broken offset, ignoring");
3605 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3611 bFail
= o3tl::checked_multiply
<WW8_CP
>(nCpLen
, 2, nCpLen
);
3614 SAL_WARN("sw.ww8", "broken offset, ignoring");
3615 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3620 bFail
= o3tl::checked_add(nFcStart
, nCpLen
, nLimitFC
);
3623 SAL_WARN("sw.ww8", "broken offset, ignoring");
3624 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3628 //if it doesn't exist, skip it
3629 if (!SeekPos(nCpStart
))
3632 WW8_FC nOne
,nSmallest
;
3633 p
->pMemPos
= WW8PLCFx_Fc_FKP::GetSprmsAndPos(nOne
,
3634 nSmallest
, p
->nSprmsLen
);
3636 if (nSmallest
<= nLimitFC
)
3639 bFail
= o3tl::checked_sub(nLimitFC
, nSmallest
, nCpDiff
);
3642 SAL_WARN("sw.ww8", "broken offset, ignoring");
3643 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3650 bFail
= o3tl::checked_sub(nCpEnd
, nCpDiff
, nEndPos
);
3653 SAL_WARN("sw.ww8", "broken offset, ignoring");
3654 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3658 OSL_ENSURE(nEndPos
>= p
->nStartPos
, "EndPos before StartPos");
3660 if (nEndPos
>= p
->nStartPos
)
3661 p
->nEndPos
= nEndPos
;
3668 m_pPieceIter
->SetIdx( nOldPos
);
3671 WW8PLCFx_PCD::CurrentPieceFc2Cp( p
->nStartPos
, p
->nEndPos
,&m_rSBase
);
3675 p
->nStartPos
= m_nAttrStart
;
3676 p
->nEndPos
= m_nAttrEnd
;
3677 p
->bRealLineEnd
= m_bLineEnd
;
3680 else // NO piece table !!!
3682 p
->nStartPos
= m_rSBase
.WW8Fc2Cp( p
->nStartPos
);
3683 p
->nEndPos
= m_rSBase
.WW8Fc2Cp( p
->nEndPos
);
3684 p
->bRealLineEnd
= m_ePLCF
== PAP
;
3688 void WW8PLCFx_Cp_FKP::advance()
3690 WW8PLCFx_Fc_FKP::advance();
3691 // !pPcd: emergency break
3692 if ( !m_bComplex
|| !m_pPcd
)
3695 if( GetPCDIdx() >= m_pPcd
->GetIMax() ) // End of PLCF
3697 m_nAttrStart
= m_nAttrEnd
= WW8_CP_MAX
;
3701 sal_Int32 nFkpLen
; // Fkp entry
3703 WW8PLCFx_Fc_FKP::GetSprmsAndPos(m_nAttrStart
, m_nAttrEnd
, nFkpLen
);
3705 WW8PLCFx_PCD::CurrentPieceFc2Cp( m_nAttrStart
, m_nAttrEnd
, &m_rSBase
);
3706 m_bLineEnd
= (m_ePLCF
== PAP
);
3709 WW8PLCFx_SEPX::WW8PLCFx_SEPX(SvStream
* pSt
, SvStream
* pTableSt
,
3710 const WW8Fib
& rFib
, WW8_CP nStartCp
)
3711 : WW8PLCFx(rFib
, true), maSprmParser(rFib
),
3712 m_pStrm(pSt
), m_nArrMax(256), m_nSprmSiz(0)
3714 if (rFib
.m_lcbPlcfsed
)
3715 m_pPLCF
.reset( new WW8PLCF(*pTableSt
, rFib
.m_fcPlcfsed
, rFib
.m_lcbPlcfsed
,
3716 GetFIBVersion() <= ww::eWW2
? 6 : 12, nStartCp
) );
3718 m_pSprms
.reset( new sal_uInt8
[m_nArrMax
] ); // maximum length
3721 WW8PLCFx_SEPX::~WW8PLCFx_SEPX()
3725 sal_uInt32
WW8PLCFx_SEPX::GetIdx() const
3727 return m_pPLCF
? m_pPLCF
->GetIdx() : 0;
3730 void WW8PLCFx_SEPX::SetIdx(sal_uInt32 nIdx
)
3732 if( m_pPLCF
) m_pPLCF
->SetIdx( nIdx
);
3735 bool WW8PLCFx_SEPX::SeekPos(WW8_CP nCpPos
)
3737 return m_pPLCF
&& m_pPLCF
->SeekPos( nCpPos
);
3740 WW8_CP
WW8PLCFx_SEPX::Where()
3742 return m_pPLCF
? m_pPLCF
->Where() : 0;
3745 void WW8PLCFx_SEPX::GetSprms(WW8PLCFxDesc
* p
)
3747 if( !m_pPLCF
) return;
3751 p
->bRealLineEnd
= false;
3752 if (!m_pPLCF
->Get( p
->nStartPos
, p
->nEndPos
, pData
))
3754 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
; // PLCF completely processed
3755 p
->pMemPos
= nullptr;
3760 sal_uInt32 nPo
= SVBT32ToUInt32( static_cast<sal_uInt8
*>(pData
)+2 );
3761 if (nPo
== 0xFFFFFFFF || !checkSeek(*m_pStrm
, nPo
))
3763 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
; // Sepx empty
3764 p
->pMemPos
= nullptr;
3770 if (GetFIBVersion() <= ww::eWW2
) // eWW6 ?, docs say yes, but...
3773 m_pStrm
->ReadUChar( nSiz
);
3778 m_pStrm
->ReadUInt16( m_nSprmSiz
);
3781 std::size_t nRemaining
= m_pStrm
->remainingSize();
3782 if (m_nSprmSiz
> nRemaining
)
3783 m_nSprmSiz
= nRemaining
;
3785 if( m_nSprmSiz
> m_nArrMax
)
3787 m_nArrMax
= m_nSprmSiz
; // Get more memory
3788 m_pSprms
.reset( new sal_uInt8
[m_nArrMax
] );
3790 m_nSprmSiz
= m_pStrm
->ReadBytes(m_pSprms
.get(), m_nSprmSiz
); // read Sprms
3792 p
->nSprmsLen
= m_nSprmSiz
;
3793 p
->pMemPos
= m_pSprms
.get(); // return Position
3798 void WW8PLCFx_SEPX::advance()
3804 SprmResult
WW8PLCFx_SEPX::HasSprm(sal_uInt16 nId
) const
3806 return HasSprm(nId
, m_pSprms
.get(), m_nSprmSiz
);
3809 SprmResult
WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId
, const sal_uInt8
* pOtherSprms
,
3810 tools::Long nOtherSprmSiz
) const
3815 WW8SprmIter
aIter(pOtherSprms
, nOtherSprmSiz
, maSprmParser
);
3816 aRet
= aIter
.FindSprm(nId
, /*bFindFirst=*/true);
3821 bool WW8PLCFx_SEPX::Find4Sprms(sal_uInt16 nId1
,sal_uInt16 nId2
,sal_uInt16 nId3
,sal_uInt16 nId4
,
3822 SprmResult
& r1
, SprmResult
& r2
, SprmResult
& r3
, SprmResult
& r4
) const
3827 bool bFound
= false;
3829 sal_uInt8
* pSp
= m_pSprms
.get();
3831 while (i
+ maSprmParser
.MinSprmLen() <= m_nSprmSiz
)
3834 const sal_uInt16 nCurrentId
= maSprmParser
.GetSprmId(pSp
);
3835 sal_Int32 nRemLen
= m_nSprmSiz
- i
;
3836 const sal_Int32 x
= maSprmParser
.GetSprmSize(nCurrentId
, pSp
, nRemLen
);
3837 bool bValid
= x
<= nRemLen
;
3840 SAL_WARN("sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong");
3844 if( nCurrentId
== nId1
)
3846 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId1
);
3847 r1
= SprmResult(pSp
+ nFixedLen
, x
- nFixedLen
);
3849 else if( nCurrentId
== nId2
)
3851 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId2
);
3852 r2
= SprmResult(pSp
+ nFixedLen
, x
- nFixedLen
);
3854 else if( nCurrentId
== nId3
)
3856 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId3
);
3857 r3
= SprmResult(pSp
+ nFixedLen
, x
- nFixedLen
);
3859 else if( nCurrentId
== nId4
)
3861 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId4
);
3862 r4
= SprmResult(pSp
+ nFixedLen
, x
- nFixedLen
);
3867 // increment pointer so that it points to next SPRM
3874 SprmResult
WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId
, sal_uInt8 n2nd
) const
3879 WW8SprmIter
aIter(m_pSprms
.get(), m_nSprmSiz
, maSprmParser
);
3880 aRet
= aIter
.FindSprm(nId
, /*bFindFirst=*/true, &n2nd
);
3885 WW8PLCFx_SubDoc::WW8PLCFx_SubDoc(SvStream
* pSt
, const WW8Fib
& rFib
,
3886 WW8_CP nStartCp
, tools::Long nFcRef
, tools::Long nLenRef
, tools::Long nFcText
, tools::Long nLenText
,
3887 tools::Long nStruct
)
3888 : WW8PLCFx(rFib
, true)
3890 if( nLenRef
&& nLenText
)
3892 m_pRef
.reset(new WW8PLCF(*pSt
, nFcRef
, nLenRef
, nStruct
, nStartCp
));
3893 m_pText
.reset(new WW8PLCF(*pSt
, nFcText
, nLenText
, 0, nStartCp
));
3897 WW8PLCFx_SubDoc::~WW8PLCFx_SubDoc()
3903 sal_uInt32
WW8PLCFx_SubDoc::GetIdx() const
3905 // Probably pText ... no need for it
3907 return ( m_pRef
->GetIdx() << 16 | m_pText
->GetIdx() );
3911 void WW8PLCFx_SubDoc::SetIdx(sal_uInt32 nIdx
)
3915 m_pRef
->SetIdx( nIdx
>> 16 );
3916 // Probably pText ... no need for it
3917 m_pText
->SetIdx( nIdx
& 0xFFFF );
3921 bool WW8PLCFx_SubDoc::SeekPos( WW8_CP nCpPos
)
3923 return m_pRef
&& m_pRef
->SeekPos( nCpPos
);
3926 WW8_CP
WW8PLCFx_SubDoc::Where()
3928 return m_pRef
? m_pRef
->Where() : WW8_CP_MAX
;
3931 void WW8PLCFx_SubDoc::GetSprms(WW8PLCFxDesc
* p
)
3933 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
3934 p
->pMemPos
= nullptr;
3936 p
->bRealLineEnd
= false;
3941 sal_uInt32 nNr
= m_pRef
->GetIdx();
3945 if (!m_pRef
->Get(p
->nStartPos
, nFoo
, pData
))
3947 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
3951 if (o3tl::checked_add
<WW8_CP
>(p
->nStartPos
, 1, p
->nEndPos
))
3953 SAL_WARN("sw.ww8", "broken offset, ignoring");
3954 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
3961 m_pText
->SetIdx(nNr
);
3963 if (!m_pText
->Get(p
->nCp2OrIdx
, p
->nSprmsLen
, pData
))
3965 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
3970 if (p
->nCp2OrIdx
< 0 || p
->nCp2OrIdx
> p
->nSprmsLen
)
3972 SAL_WARN("sw.ww8", "Document has invalid Cp or Idx, ignoring it");
3973 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
3978 p
->nSprmsLen
-= p
->nCp2OrIdx
;
3981 void WW8PLCFx_SubDoc::advance()
3983 if (m_pRef
&& m_pText
)
3991 WW8PLCFx_FLD::WW8PLCFx_FLD( SvStream
* pSt
, const WW8Fib
& rMyFib
, short nType
)
3992 : WW8PLCFx(rMyFib
, true), m_rFib(rMyFib
)
4000 nFc
= m_rFib
.m_fcPlcffldHdr
;
4001 nLen
= m_rFib
.m_lcbPlcffldHdr
;
4004 nFc
= m_rFib
.m_fcPlcffldFootnote
;
4005 nLen
= m_rFib
.m_lcbPlcffldFootnote
;
4008 nFc
= m_rFib
.m_fcPlcffldEdn
;
4009 nLen
= m_rFib
.m_lcbPlcffldEdn
;
4012 nFc
= m_rFib
.m_fcPlcffldAtn
;
4013 nLen
= m_rFib
.m_lcbPlcffldAtn
;
4016 nFc
= m_rFib
.m_fcPlcffldTxbx
;
4017 nLen
= m_rFib
.m_lcbPlcffldTxbx
;
4020 nFc
= m_rFib
.m_fcPlcffldHdrTxbx
;
4021 nLen
= m_rFib
.m_lcbPlcffldHdrTxbx
;
4024 nFc
= m_rFib
.m_fcPlcffldMom
;
4025 nLen
= m_rFib
.m_lcbPlcffldMom
;
4030 m_pPLCF
.reset( new WW8PLCFspecial( pSt
, nFc
, nLen
, 2 ) );
4033 WW8PLCFx_FLD::~WW8PLCFx_FLD()
4037 sal_uInt32
WW8PLCFx_FLD::GetIdx() const
4039 return m_pPLCF
? m_pPLCF
->GetIdx() : 0;
4042 void WW8PLCFx_FLD::SetIdx(sal_uInt32 nIdx
)
4045 m_pPLCF
->SetIdx( nIdx
);
4048 bool WW8PLCFx_FLD::SeekPos(WW8_CP nCpPos
)
4050 return m_pPLCF
&& m_pPLCF
->SeekPosExact( nCpPos
);
4053 WW8_CP
WW8PLCFx_FLD::Where()
4055 return m_pPLCF
? m_pPLCF
->Where() : WW8_CP_MAX
;
4058 bool WW8PLCFx_FLD::StartPosIsFieldStart()
4062 return m_pPLCF
&& m_pPLCF
->Get(nTest
, pData
) && ((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f) == 0x13);
4065 bool WW8PLCFx_FLD::EndPosIsFieldEnd(WW8_CP
& nCP
)
4071 tools::Long n
= m_pPLCF
->GetIdx();
4077 if ( m_pPLCF
->Get(nTest
, pData
) && ((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f) == 0x15) )
4089 void WW8PLCFx_FLD::GetSprms(WW8PLCFxDesc
* p
)
4091 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
4092 p
->pMemPos
= nullptr;
4094 p
->bRealLineEnd
= false;
4098 p
->nStartPos
= WW8_CP_MAX
; // there are no fields
4102 tools::Long n
= m_pPLCF
->GetIdx();
4106 if (!m_pPLCF
->Get(nP
, pData
)) // end of PLCFspecial?
4108 p
->nStartPos
= WW8_CP_MAX
; // PLCF completely processed
4115 if (!m_pPLCF
->Get(nP
, pData
)) // end of PLCFspecial?
4117 p
->nStartPos
= WW8_CP_MAX
; // PLCF completely processed
4125 p
->nCp2OrIdx
= m_pPLCF
->GetIdx();
4128 void WW8PLCFx_FLD::advance()
4130 SAL_WARN_IF(!m_pPLCF
, "sw.ww8", "Call without PLCFspecial field");
4136 bool WW8PLCFx_FLD::GetPara(tools::Long nIdx
, WW8FieldDesc
& rF
)
4138 SAL_WARN_IF(!m_pPLCF
, "sw.ww8", "Call without PLCFspecial field");
4142 tools::Long n
= m_pPLCF
->GetIdx();
4143 m_pPLCF
->SetIdx(nIdx
);
4145 bool bOk
= WW8GetFieldPara(*m_pPLCF
, rF
);
4152 void WW8ReadSTTBF(bool bVer8
, SvStream
& rStrm
, sal_uInt32 nStart
, sal_Int32 nLen
,
4153 sal_uInt16 nExtraLen
, rtl_TextEncoding eCS
, std::vector
<OUString
> &rArray
,
4154 std::vector
<ww::bytes
>* pExtraArray
, std::vector
<OUString
>* pValueArray
)
4156 if (nLen
==0) // Handle Empty STTBF
4159 sal_uInt64
const nOldPos
= rStrm
.Tell();
4160 if (checkSeek(rStrm
, nStart
))
4162 sal_uInt16
nLen2(0);
4163 rStrm
.ReadUInt16( nLen2
); // bVer67: total length of structure
4164 // bVer8 : count of strings
4168 sal_uInt16
nStrings(0);
4169 bool bUnicode
= (0xFFFF == nLen2
);
4171 rStrm
.ReadUInt16( nStrings
);
4175 rStrm
.ReadUInt16( nExtraLen
);
4177 const size_t nMinStringLen
= bUnicode
? sizeof(sal_uInt16
) : sizeof(sal_uInt8
);
4178 const size_t nMinRecordSize
= nExtraLen
+ nMinStringLen
;
4179 assert(nMinRecordSize
!= 0 && "impossible to be zero");
4180 const size_t nMaxPossibleStrings
= rStrm
.remainingSize() / nMinRecordSize
;
4181 if (nStrings
> nMaxPossibleStrings
)
4183 SAL_WARN("sw.ww8", "STTBF claims " << nStrings
<< " entries, but only " << nMaxPossibleStrings
<< " are possible");
4184 nStrings
= nMaxPossibleStrings
;
4187 if (nExtraLen
&& nStrings
)
4189 const size_t nMaxExtraLen
= (rStrm
.remainingSize() - (nStrings
* nMinStringLen
)) / nStrings
;
4190 if (nExtraLen
> nMaxExtraLen
)
4192 SAL_WARN("sw.ww8", "STTBF claims " << nMaxExtraLen
<< " extra len, but only " << nMaxExtraLen
<< " are possible");
4193 nExtraLen
= nMaxExtraLen
;
4197 for (sal_uInt16 i
=0; i
< nStrings
; ++i
)
4200 rArray
.push_back(read_uInt16_PascalString(rStrm
));
4203 OString aTmp
= read_uInt8_lenPrefixed_uInt8s_ToOString(rStrm
);
4204 rArray
.push_back(OStringToOUString(aTmp
, eCS
));
4207 // Skip the extra data
4212 ww::bytes
extraData(nExtraLen
);
4213 rStrm
.ReadBytes(extraData
.data(), nExtraLen
);
4214 pExtraArray
->push_back(extraData
);
4217 rStrm
.SeekRel( nExtraLen
);
4220 // read the value of the document variables, if requested.
4223 for (sal_uInt16 i
=0; i
< nStrings
; ++i
)
4226 pValueArray
->push_back(read_uInt16_PascalString(rStrm
));
4229 OString aTmp
= read_uInt8_lenPrefixed_uInt8s_ToOString(rStrm
);
4230 pValueArray
->push_back(OStringToOUString(aTmp
, eCS
));
4239 OSL_ENSURE(nLen2
== nLen
,
4240 "Fib length and read length are different");
4241 if (nLen
> SAL_MAX_UINT16
)
4242 nLen
= SAL_MAX_UINT16
;
4245 nLen2
= o3tl::narrowing
<sal_uInt16
>(nLen
);
4247 sal_uLong nRead
= 0;
4248 for( nLen2
-= 2; nRead
< nLen2
; )
4250 sal_uInt8
nBChar(0);
4251 rStrm
.ReadUChar( nBChar
);
4255 OString aTmp
= read_uInt8s_ToOString(rStrm
, nBChar
);
4256 nRead
+= aTmp
.getLength();
4257 rArray
.push_back(OStringToOUString(aTmp
, eCS
));
4260 rArray
.emplace_back();
4262 // Skip the extra data (for bVer67 versions this must come from
4263 // external knowledge)
4268 ww::bytes
extraData(nExtraLen
);
4269 rStrm
.ReadBytes(extraData
.data(), nExtraLen
);
4270 pExtraArray
->push_back(extraData
);
4273 rStrm
.SeekRel( nExtraLen
);
4279 rStrm
.Seek(nOldPos
);
4282 WW8PLCFx_Book::WW8PLCFx_Book(SvStream
* pTableSt
, const WW8Fib
& rFib
)
4283 : WW8PLCFx(rFib
, false), m_nIsEnd(0), m_nBookmarkId(1)
4285 if( !rFib
.m_fcPlcfbkf
|| !rFib
.m_lcbPlcfbkf
|| !rFib
.m_fcPlcfbkl
||
4286 !rFib
.m_lcbPlcfbkl
|| !rFib
.m_fcSttbfbkmk
|| !rFib
.m_lcbSttbfbkmk
)
4292 m_pBook
[0].reset( new WW8PLCFspecial(pTableSt
,rFib
.m_fcPlcfbkf
,rFib
.m_lcbPlcfbkf
,4) );
4294 m_pBook
[1].reset( new WW8PLCFspecial(pTableSt
,rFib
.m_fcPlcfbkl
,rFib
.m_lcbPlcfbkl
,0) );
4296 rtl_TextEncoding eStructChrSet
= WW8Fib::GetFIBCharset(rFib
.m_chseTables
, rFib
.m_lid
);
4298 WW8ReadSTTBF( (7 < rFib
.m_nVersion
), *pTableSt
, rFib
.m_fcSttbfbkmk
,
4299 rFib
.m_lcbSttbfbkmk
, 0, eStructChrSet
, m_aBookNames
);
4301 m_nIMax
= m_aBookNames
.size();
4303 if( m_pBook
[0]->GetIMax() < m_nIMax
) // Count of Bookmarks
4304 m_nIMax
= m_pBook
[0]->GetIMax();
4305 if( m_pBook
[1]->GetIMax() < m_nIMax
)
4306 m_nIMax
= m_pBook
[1]->GetIMax();
4307 m_aStatus
.resize(m_nIMax
);
4311 WW8PLCFx_Book::~WW8PLCFx_Book()
4315 sal_uInt32
WW8PLCFx_Book::GetIdx() const
4317 return m_nIMax
? m_pBook
[0]->GetIdx() : 0;
4320 void WW8PLCFx_Book::SetIdx(sal_uInt32 nI
)
4323 m_pBook
[0]->SetIdx( nI
);
4326 sal_uInt32
WW8PLCFx_Book::GetIdx2() const
4328 return m_nIMax
? ( m_pBook
[1]->GetIdx() | ( m_nIsEnd
? 0x80000000 : 0 ) ) : 0;
4331 void WW8PLCFx_Book::SetIdx2(sal_uInt32 nI
)
4335 m_pBook
[1]->SetIdx( nI
& 0x7fffffff );
4336 m_nIsEnd
= o3tl::narrowing
<sal_uInt16
>( ( nI
>> 31 ) & 1 ); // 0 or 1
4340 bool WW8PLCFx_Book::SeekPos(WW8_CP nCpPos
)
4345 bool bOk
= m_pBook
[0]->SeekPosExact( nCpPos
);
4346 bOk
&= m_pBook
[1]->SeekPosExact( nCpPos
);
4352 WW8_CP
WW8PLCFx_Book::Where()
4354 return m_pBook
[m_nIsEnd
]->Where();
4357 tools::Long
WW8PLCFx_Book::GetNoSprms( WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
4363 if (!m_pBook
[0] || !m_pBook
[1] || !m_nIMax
|| (m_pBook
[m_nIsEnd
]->GetIdx()) >= m_nIMax
)
4365 rStart
= rEnd
= WW8_CP_MAX
;
4369 (void)m_pBook
[m_nIsEnd
]->Get( rStart
, pData
); // query position
4370 return m_pBook
[m_nIsEnd
]->GetIdx();
4373 // The operator ++ has a pitfall: If 2 bookmarks adjoin each other,
4374 // we should first go to the end of the first one
4375 // and then to the beginning of the second one.
4376 // But if 2 bookmarks with the length of 0 lie on top of each other,
4377 // we *must* first find the start and end of each bookmark.
4381 // is not solved yet.
4382 // Because I must jump back and forth in the start- and end-indices then.
4383 // This would require one more index or bitfield to remember
4384 // the already processed bookmarks.
4386 void WW8PLCFx_Book::advance()
4388 if( !(m_pBook
[0] && m_pBook
[1] && m_nIMax
) )
4391 (*m_pBook
[m_nIsEnd
]).advance();
4393 sal_uLong l0
= m_pBook
[0]->Where();
4394 sal_uLong l1
= m_pBook
[1]->Where();
4401 const void * p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx());
4402 tools::Long nPairFor
= (p
== nullptr) ? 0 : SVBT16ToUInt16(*static_cast<SVBT16
const *>(p
));
4403 if (nPairFor
== m_pBook
[1]->GetIdx())
4406 m_nIsEnd
= m_nIsEnd
? 0 : 1;
4410 tools::Long
WW8PLCFx_Book::GetLen() const
4414 OSL_ENSURE( false, "Incorrect call (1) of PLCF_Book::GetLen()" );
4419 if( !m_pBook
[0]->Get( nStartPos
, p
) )
4421 OSL_ENSURE( false, "Incorrect call (2) of PLCF_Book::GetLen()" );
4424 const sal_uInt16 nEndIdx
= SVBT16ToUInt16( *static_cast<SVBT16
*>(p
) );
4425 tools::Long nNum
= m_pBook
[1]->GetPos( nEndIdx
);
4430 void WW8PLCFx_Book::SetStatus(sal_uInt16 nIndex
, eBookStatus eStat
)
4432 SAL_WARN_IF(nIndex
>= m_nIMax
, "sw.ww8",
4433 "bookmark index " << nIndex
<< " invalid");
4434 eBookStatus eStatus
= m_aStatus
.at(nIndex
);
4435 m_aStatus
[nIndex
] = static_cast<eBookStatus
>(eStatus
| eStat
);
4438 eBookStatus
WW8PLCFx_Book::GetStatus() const
4440 if (m_aStatus
.empty())
4442 tools::Long nEndIdx
= GetHandle();
4443 return ( nEndIdx
< m_nIMax
) ? m_aStatus
[nEndIdx
] : BOOK_NORMAL
;
4446 tools::Long
WW8PLCFx_Book::GetHandle() const
4448 if( !m_pBook
[0] || !m_pBook
[1] )
4452 return m_pBook
[1]->GetIdx();
4455 if (const void* p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx()))
4456 return SVBT16ToUInt16( *static_cast<SVBT16
const *>(p
) );
4462 OUString
WW8PLCFx_Book::GetBookmark(tools::Long nStart
,tools::Long nEnd
, sal_uInt16
&nIndex
)
4464 bool bFound
= false;
4466 if (m_pBook
[0] && m_pBook
[1])
4468 WW8_CP nStartCurrent
, nEndCurrent
;
4469 while (sal::static_int_cast
<decltype(m_aBookNames
)::size_type
>(i
) < m_aBookNames
.size())
4474 if( m_pBook
[0]->GetData( i
, nStartCurrent
, p
) && p
)
4475 nEndIdx
= SVBT16ToUInt16( *static_cast<SVBT16
*>(p
) );
4478 OSL_ENSURE( false, "Bookmark-EndIdx not readable" );
4482 nEndCurrent
= m_pBook
[1]->GetPos( nEndIdx
);
4484 if ((nStartCurrent
>= nStart
) && (nEndCurrent
<= nEnd
))
4493 return bFound
? m_aBookNames
[i
] : OUString();
4496 OUString
WW8PLCFx_Book::GetUniqueBookmarkName(const OUString
&rSuggestedName
)
4498 OUString
aRet(rSuggestedName
.isEmpty() ? OUString("Unnamed") : rSuggestedName
);
4500 while (i
< m_aBookNames
.size())
4502 if (aRet
== m_aBookNames
[i
])
4504 sal_Int32 len
= aRet
.getLength();
4505 sal_Int32 p
= len
- 1;
4506 while (p
> 0 && aRet
[p
] >= '0' && aRet
[p
] <= '9')
4508 aRet
= aRet
.subView(0, p
+1) + OUString::number(m_nBookmarkId
++);
4509 i
= 0; // start search from beginning
4517 void WW8PLCFx_Book::MapName(OUString
& rName
)
4519 if( !m_pBook
[0] || !m_pBook
[1] )
4523 while (i
< m_aBookNames
.size())
4525 if (rName
.equalsIgnoreAsciiCase(m_aBookNames
[i
]))
4527 rName
= m_aBookNames
[i
];
4534 const OUString
* WW8PLCFx_Book::GetName() const
4536 const OUString
*pRet
= nullptr;
4537 if (!m_nIsEnd
&& (m_pBook
[0]->GetIdx() < m_nIMax
))
4538 pRet
= &(m_aBookNames
[m_pBook
[0]->GetIdx()]);
4542 WW8PLCFx_AtnBook::WW8PLCFx_AtnBook(SvStream
* pTableSt
, const WW8Fib
& rFib
)
4543 : WW8PLCFx(rFib
, /*bSprm=*/false),
4546 if (!rFib
.m_fcPlcfAtnbkf
|| !rFib
.m_lcbPlcfAtnbkf
|| !rFib
.m_fcPlcfAtnbkl
|| !rFib
.m_lcbPlcfAtnbkl
)
4552 m_pBook
[0].reset( new WW8PLCFspecial(pTableSt
, rFib
.m_fcPlcfAtnbkf
, rFib
.m_lcbPlcfAtnbkf
, 4) );
4553 m_pBook
[1].reset( new WW8PLCFspecial(pTableSt
, rFib
.m_fcPlcfAtnbkl
, rFib
.m_lcbPlcfAtnbkl
, 0) );
4555 m_nIMax
= m_pBook
[0]->GetIMax();
4556 if (m_pBook
[1]->GetIMax() < m_nIMax
)
4557 m_nIMax
= m_pBook
[1]->GetIMax();
4561 WW8PLCFx_AtnBook::~WW8PLCFx_AtnBook()
4565 sal_uInt32
WW8PLCFx_AtnBook::GetIdx() const
4567 return m_nIMax
? m_pBook
[0]->GetIdx() : 0;
4570 void WW8PLCFx_AtnBook::SetIdx(sal_uInt32 nI
)
4573 m_pBook
[0]->SetIdx( nI
);
4576 sal_uInt32
WW8PLCFx_AtnBook::GetIdx2() const
4579 return m_pBook
[1]->GetIdx() | ( m_bIsEnd
? 0x80000000 : 0 );
4584 void WW8PLCFx_AtnBook::SetIdx2(sal_uInt32 nI
)
4588 m_pBook
[1]->SetIdx( nI
& 0x7fffffff );
4589 m_bIsEnd
= static_cast<bool>(( nI
>> 31 ) & 1);
4593 bool WW8PLCFx_AtnBook::SeekPos(WW8_CP nCpPos
)
4598 bool bOk
= m_pBook
[0]->SeekPosExact(nCpPos
);
4599 bOk
&= m_pBook
[1]->SeekPosExact(nCpPos
);
4605 WW8_CP
WW8PLCFx_AtnBook::Where()
4607 return m_pBook
[static_cast<int>(m_bIsEnd
)]->Where();
4610 tools::Long
WW8PLCFx_AtnBook::GetNoSprms( WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
4616 if (!m_pBook
[0] || !m_pBook
[1] || !m_nIMax
|| (m_pBook
[static_cast<int>(m_bIsEnd
)]->GetIdx()) >= m_nIMax
)
4618 rStart
= rEnd
= WW8_CP_MAX
;
4622 (void)m_pBook
[static_cast<int>(m_bIsEnd
)]->Get(rStart
, pData
);
4623 return m_pBook
[static_cast<int>(m_bIsEnd
)]->GetIdx();
4626 void WW8PLCFx_AtnBook::advance()
4628 if( !(m_pBook
[0] && m_pBook
[1] && m_nIMax
) )
4631 (*m_pBook
[static_cast<int>(m_bIsEnd
)]).advance();
4633 sal_uLong l0
= m_pBook
[0]->Where();
4634 sal_uLong l1
= m_pBook
[1]->Where();
4641 const void * p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx());
4642 tools::Long nPairFor
= (p
== nullptr) ? 0 : SVBT16ToUInt16(*static_cast<SVBT16
const *>(p
));
4643 if (nPairFor
== m_pBook
[1]->GetIdx())
4646 m_bIsEnd
= !m_bIsEnd
;
4650 tools::Long
WW8PLCFx_AtnBook::getHandle() const
4652 if (!m_pBook
[0] || !m_pBook
[1])
4656 return m_pBook
[1]->GetIdx();
4659 if (const void* p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx()))
4660 return SVBT16ToUInt16(*static_cast<const SVBT16
*>(p
));
4666 bool WW8PLCFx_AtnBook::getIsEnd() const
4671 WW8PLCFx_FactoidBook::WW8PLCFx_FactoidBook(SvStream
* pTableSt
, const WW8Fib
& rFib
)
4672 : WW8PLCFx(rFib
, /*bSprm=*/false),
4675 if (!rFib
.m_fcPlcfBkfFactoid
|| !rFib
.m_lcbPlcfBkfFactoid
|| !rFib
.m_fcPlcfBklFactoid
|| !rFib
.m_lcbPlcfBklFactoid
)
4681 m_pBook
[0].reset(new WW8PLCFspecial(pTableSt
, rFib
.m_fcPlcfBkfFactoid
, rFib
.m_lcbPlcfBkfFactoid
, 6));
4682 m_pBook
[1].reset(new WW8PLCFspecial(pTableSt
, rFib
.m_fcPlcfBklFactoid
, rFib
.m_lcbPlcfBklFactoid
, 4));
4684 m_nIMax
= m_pBook
[0]->GetIMax();
4685 if (m_pBook
[1]->GetIMax() < m_nIMax
)
4686 m_nIMax
= m_pBook
[1]->GetIMax();
4690 WW8PLCFx_FactoidBook::~WW8PLCFx_FactoidBook()
4694 sal_uInt32
WW8PLCFx_FactoidBook::GetIdx() const
4696 return m_nIMax
? m_pBook
[0]->GetIdx() : 0;
4699 void WW8PLCFx_FactoidBook::SetIdx(sal_uInt32 nI
)
4702 m_pBook
[0]->SetIdx(nI
);
4705 sal_uInt32
WW8PLCFx_FactoidBook::GetIdx2() const
4708 return m_pBook
[1]->GetIdx() | (m_bIsEnd
? 0x80000000 : 0);
4713 void WW8PLCFx_FactoidBook::SetIdx2(sal_uInt32 nI
)
4717 m_pBook
[1]->SetIdx(nI
& 0x7fffffff);
4718 m_bIsEnd
= static_cast<bool>((nI
>> 31) & 1);
4722 bool WW8PLCFx_FactoidBook::SeekPos(WW8_CP nCpPos
)
4727 bool bOk
= m_pBook
[0]->SeekPosExact(nCpPos
);
4728 bOk
&= m_pBook
[1]->SeekPosExact(nCpPos
);
4734 WW8_CP
WW8PLCFx_FactoidBook::Where()
4736 return m_pBook
[static_cast<int>(m_bIsEnd
)]->Where();
4739 tools::Long
WW8PLCFx_FactoidBook::GetNoSprms(WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
4745 if (!m_pBook
[0] || !m_pBook
[1] || !m_nIMax
|| (m_pBook
[static_cast<int>(m_bIsEnd
)]->GetIdx()) >= m_nIMax
)
4747 rStart
= rEnd
= WW8_CP_MAX
;
4751 (void)m_pBook
[static_cast<int>(m_bIsEnd
)]->Get(rStart
, pData
);
4752 return m_pBook
[static_cast<int>(m_bIsEnd
)]->GetIdx();
4755 void WW8PLCFx_FactoidBook::advance()
4757 if (!(m_pBook
[0] && m_pBook
[1] && m_nIMax
))
4760 (*m_pBook
[static_cast<int>(m_bIsEnd
)]).advance();
4762 sal_uLong l0
= m_pBook
[0]->Where();
4763 sal_uLong l1
= m_pBook
[1]->Where();
4770 const void * p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx());
4771 tools::Long nPairFor
= (p
== nullptr) ? 0 : SVBT16ToUInt16(*static_cast<SVBT16
const *>(p
));
4772 if (nPairFor
== m_pBook
[1]->GetIdx())
4775 m_bIsEnd
= !m_bIsEnd
;
4779 tools::Long
WW8PLCFx_FactoidBook::getHandle() const
4781 if (!m_pBook
[0] || !m_pBook
[1])
4785 return m_pBook
[1]->GetIdx();
4788 if (const void* p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx()))
4789 return SVBT16ToUInt16(*static_cast<const SVBT16
*>(p
));
4795 bool WW8PLCFx_FactoidBook::getIsEnd() const
4800 // In the end of a paragraph in WW6 the attribute extends after the <CR>.
4801 // This will be reset by one character to be used with SW,
4802 // if we don't expect trouble thereby.
4803 void WW8PLCFMan::AdjustEnds( WW8PLCFxDesc
& rDesc
)
4805 // might be necessary to do this for pChp and/or pSep as well,
4806 // but its definitely the case for paragraphs that EndPos > StartPos
4807 // for a well formed paragraph as those always have a paragraph
4809 if (&rDesc
== m_pPap
&& rDesc
.bRealLineEnd
)
4811 if (rDesc
.nStartPos
== rDesc
.nEndPos
&& rDesc
.nEndPos
!= WW8_CP_MAX
)
4813 SAL_WARN("sw.ww8", "WW8PLCFxDesc End same as Start, abandoning to avoid looping");
4814 rDesc
.nEndPos
= WW8_CP_MAX
;
4818 //Store old end position for supercool new property finder that uses
4819 //cp instead of fc's as nature intended
4820 rDesc
.nOrigEndPos
= rDesc
.nEndPos
;
4821 rDesc
.nOrigStartPos
= rDesc
.nStartPos
;
4824 Normally given ^XXX{para end}^ we don't actually insert a para end
4825 character into the document, so we clip the para end property one to the
4826 left to make the para properties end when the paragraph text does. In a
4827 drawing textbox we actually do insert a para end character, so we don't
4828 clip it. Making the para end properties end after the para end char.
4830 if (GetDoingDrawTextBox())
4833 if ( (&rDesc
== m_pPap
) && rDesc
.bRealLineEnd
)
4835 if ( m_pPap
->nEndPos
!= WW8_CP_MAX
) // Para adjust
4837 m_nLineEnd
= m_pPap
->nEndPos
;// nLineEnd points *after* the <CR>
4838 m_pPap
->nEndPos
--; // shorten paragraph end by one character
4840 // Is there already a sep end, which points to the current paragraph end?
4841 // Then we also must shorten by one character
4842 if( m_pSep
->nEndPos
== m_nLineEnd
)
4846 else if (&rDesc
== m_pSep
)
4848 // Sep Adjust if end Char-Attr == paragraph end ...
4849 if( (rDesc
.nEndPos
== m_nLineEnd
) && (rDesc
.nEndPos
> rDesc
.nStartPos
) )
4850 rDesc
.nEndPos
--; // ... then shorten by one character
4854 void WW8PLCFxDesc::ReduceByOffset()
4856 SAL_WARN_IF(WW8_CP_MAX
!= nStartPos
&& nStartPos
> nEndPos
, "sw.ww8",
4857 "End " << nEndPos
<< " before Start " << nStartPos
);
4859 if( nStartPos
!= WW8_CP_MAX
)
4863 Force the property change to happen at the beginning of this
4864 subdocument, same as in GetNewNoSprms, except that the target type is
4865 attributes attached to a piece that might span subdocument boundaries
4867 if (nCpOfs
> nStartPos
)
4870 nStartPos
-= nCpOfs
;
4872 if (nEndPos
!= WW8_CP_MAX
)
4874 if (nCpOfs
> nEndPos
)
4876 SAL_WARN("sw.ww8", "broken subdocument piece entry");
4877 nEndPos
= WW8_CP_MAX
;
4884 void WW8PLCFMan::GetNewSprms( WW8PLCFxDesc
& rDesc
)
4886 rDesc
.pPLCFx
->GetSprms(&rDesc
);
4887 rDesc
.ReduceByOffset();
4889 rDesc
.bFirstSprm
= true;
4890 AdjustEnds( rDesc
);
4891 rDesc
.nOrigSprmsLen
= rDesc
.nSprmsLen
;
4894 void WW8PLCFMan::GetNewNoSprms( WW8PLCFxDesc
& rDesc
)
4896 rDesc
.nCp2OrIdx
= rDesc
.pPLCFx
->GetNoSprms(rDesc
.nStartPos
, rDesc
.nEndPos
,
4899 SAL_WARN_IF(WW8_CP_MAX
!= rDesc
.nStartPos
&& rDesc
.nStartPos
> rDesc
.nEndPos
, "sw.ww8",
4900 "End " << rDesc
.nEndPos
<< " before Start " << rDesc
.nStartPos
);
4902 rDesc
.ReduceByOffset();
4904 rDesc
.bFirstSprm
= true;
4905 rDesc
.nOrigSprmsLen
= rDesc
.nSprmsLen
;
4908 sal_uInt16
WW8PLCFMan::GetId(const WW8PLCFxDesc
* p
) const
4910 sal_uInt16 nId
= 0; // Id = 0 for empty attributes
4914 else if (p
== m_pFootnote
)
4916 else if (p
== m_pEdn
)
4918 else if (p
== m_pAnd
)
4920 else if (p
->nSprmsLen
>= maSprmParser
.MinSprmLen())
4921 nId
= maSprmParser
.GetSprmId(p
->pMemPos
);
4926 WW8PLCFMan::WW8PLCFMan(const WW8ScannerBase
* pBase
, ManTypes nType
, tools::Long nStartCp
,
4927 bool bDoingDrawTextBox
)
4928 : maSprmParser(*pBase
->m_pWw8Fib
),
4929 m_nLineEnd(WW8_CP_MAX
),
4930 mbDoingDrawTextBox(bDoingDrawTextBox
)
4932 m_pWwFib
= pBase
->m_pWw8Fib
;
4936 if( MAN_MAINTEXT
== nType
)
4938 // search order of the attributes
4939 m_nPLCF
= MAN_PLCF_COUNT
;
4940 m_pField
= &m_aD
[0];
4943 m_pFootnote
= &m_aD
[3];
4946 m_pPcd
= pBase
->m_pPLCFx_PCD
? &m_aD
[5] : nullptr;
4947 //pPcdA index == pPcd index + 1
4948 m_pPcdA
= pBase
->m_pPLCFx_PCDAttrs
? &m_aD
[6] : nullptr;
4953 m_pAtnBkm
= &m_aD
[10];
4954 m_pFactoidBkm
= &m_aD
[11];
4956 m_pSep
->pPLCFx
= pBase
->m_pSepPLCF
.get();
4957 m_pFootnote
->pPLCFx
= pBase
->m_pFootnotePLCF
.get();
4958 m_pEdn
->pPLCFx
= pBase
->m_pEdnPLCF
.get();
4959 m_pBkm
->pPLCFx
= pBase
->m_pBook
.get();
4960 m_pAnd
->pPLCFx
= pBase
->m_pAndPLCF
.get();
4961 m_pAtnBkm
->pPLCFx
= pBase
->m_pAtnBook
.get();
4962 m_pFactoidBkm
->pPLCFx
= pBase
->m_pFactoidBook
.get();
4967 // search order of the attributes
4969 m_pField
= &m_aD
[0];
4970 m_pBkm
= pBase
->m_pBook
? &m_aD
[1] : nullptr;
4972 m_pPcd
= pBase
->m_pPLCFx_PCD
? &m_aD
[2] : nullptr;
4973 //pPcdA index == pPcd index + 1
4974 m_pPcdA
= pBase
->m_pPLCFx_PCDAttrs
? &m_aD
[3] : nullptr;
4978 m_pSep
= &m_aD
[6]; // Dummy
4980 m_pAnd
= m_pAtnBkm
= m_pFactoidBkm
= m_pFootnote
= m_pEdn
= nullptr; // not used at SpezText
4983 m_pChp
->pPLCFx
= pBase
->m_pChpPLCF
.get();
4984 m_pPap
->pPLCFx
= pBase
->m_pPapPLCF
.get();
4986 m_pPcd
->pPLCFx
= pBase
->m_pPLCFx_PCD
.get();
4988 m_pPcdA
->pPLCFx
= pBase
->m_pPLCFx_PCDAttrs
.get();
4990 m_pBkm
->pPLCFx
= pBase
->m_pBook
.get();
4992 m_pMagicTables
= pBase
->m_pMagicTables
.get();
4993 m_pSubdocs
= pBase
->m_pSubdocs
.get();
4994 m_pExtendedAtrds
= pBase
->m_pExtendedAtrds
.get();
4996 switch( nType
) // field initialization
4999 m_pField
->pPLCFx
= pBase
->m_pFieldHdFtPLCF
.get();
5000 m_pFdoa
= pBase
->m_pHdFtFdoa
.get();
5001 m_pTxbx
= pBase
->m_pHdFtTxbx
.get();
5002 m_pTxbxBkd
= pBase
->m_pHdFtTxbxBkd
.get();
5005 m_pField
->pPLCFx
= pBase
->m_pFieldFootnotePLCF
.get();
5006 m_pFdoa
= m_pTxbx
= m_pTxbxBkd
= nullptr;
5009 m_pField
->pPLCFx
= pBase
->m_pFieldEdnPLCF
.get();
5010 m_pFdoa
= m_pTxbx
= m_pTxbxBkd
= nullptr;
5013 m_pField
->pPLCFx
= pBase
->m_pFieldAndPLCF
.get();
5014 m_pFdoa
= m_pTxbx
= m_pTxbxBkd
= nullptr;
5017 m_pField
->pPLCFx
= pBase
->m_pFieldTxbxPLCF
.get();
5018 m_pTxbx
= pBase
->m_pMainTxbx
.get();
5019 m_pTxbxBkd
= pBase
->m_pMainTxbxBkd
.get();
5023 m_pField
->pPLCFx
= pBase
->m_pFieldTxbxHdFtPLCF
.get();
5024 m_pTxbx
= pBase
->m_pHdFtTxbx
.get();
5025 m_pTxbxBkd
= pBase
->m_pHdFtTxbxBkd
.get();
5029 m_pField
->pPLCFx
= pBase
->m_pFieldPLCF
.get();
5030 m_pFdoa
= pBase
->m_pMainFdoa
.get();
5031 m_pTxbx
= pBase
->m_pMainTxbx
.get();
5032 m_pTxbxBkd
= pBase
->m_pMainTxbxBkd
.get();
5037 m_pWwFib
->GetBaseCp(nType
, &cp
); //TODO: check return value
5040 if( nStartCp
|| m_nCpO
)
5041 SeekPos( nStartCp
); // adjust PLCFe at text StartPos
5043 // initialization to the member vars Low-Level
5044 GetChpPLCF()->ResetAttrStartEnd();
5045 GetPapPLCF()->ResetAttrStartEnd();
5046 for( sal_uInt16 i
=0; i
< m_nPLCF
; ++i
)
5048 WW8PLCFxDesc
* p
= &m_aD
[i
];
5052 For subdocuments we modify the cp of properties to be relative to
5053 the beginning of subdocuments, we should also do the same for
5054 piecetable changes, and piecetable properties, otherwise a piece
5055 change that happens in a subdocument is lost.
5057 p
->nCpOfs
= ( p
== m_pChp
|| p
== m_pPap
|| p
== m_pBkm
|| p
== m_pPcd
||
5058 p
== m_pPcdA
) ? m_nCpO
: 0;
5061 p
->bFirstSprm
= false;
5062 p
->xIdStack
.reset();
5064 if ((p
== m_pChp
) || (p
== m_pPap
))
5065 p
->nStartPos
= p
->nEndPos
= nStartCp
;
5067 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
5070 // initialization to the member vars High-Level
5071 for( sal_uInt16 i
=0; i
<m_nPLCF
; ++i
){
5072 WW8PLCFxDesc
* p
= &m_aD
[i
];
5076 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
5080 if( p
->pPLCFx
->IsSprm() )
5082 // Careful: nEndPos must be
5083 p
->xIdStack
.emplace();
5084 if ((p
== m_pChp
) || (p
== m_pPap
))
5086 WW8_CP nTemp
= p
->nEndPos
+p
->nCpOfs
;
5087 p
->pMemPos
= nullptr;
5089 p
->nStartPos
= nTemp
;
5090 if (!(*p
->pPLCFx
).SeekPos(p
->nStartPos
))
5091 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
5096 GetNewSprms( *p
); // initialized at all PLCFs
5098 else if( p
->pPLCFx
)
5099 GetNewNoSprms( *p
);
5103 WW8PLCFMan::~WW8PLCFMan()
5105 for( sal_uInt16 i
=0; i
<m_nPLCF
; i
++)
5106 m_aD
[i
].xIdStack
.reset();
5109 // 0. which attr class,
5110 // 1. if it's an attr start,
5111 // 2. CP, where is next attr change
5112 sal_uInt16
WW8PLCFMan::WhereIdx(bool *const pbStart
, WW8_CP
*const pPos
) const
5114 OSL_ENSURE(m_nPLCF
,"What the hell");
5115 WW8_CP nNext
= WW8_CP_MAX
; // search order:
5116 sal_uInt16 nNextIdx
= m_nPLCF
;// first ending found ( CHP, PAP, ( SEP ) ),
5117 bool bStart
= true; // now find beginnings ( ( SEP ), PAP, CHP )
5118 const WW8PLCFxDesc
* pD
;
5119 for (sal_uInt16 i
=0; i
< m_nPLCF
; ++i
)
5124 if( (pD
->nEndPos
< nNext
) && (pD
->nStartPos
== WW8_CP_MAX
) )
5126 // otherwise start = end
5127 nNext
= pD
->nEndPos
;
5133 for (sal_uInt16 i
=m_nPLCF
; i
> 0; --i
)
5136 if (pD
!= m_pPcdA
&& pD
->nStartPos
< nNext
)
5138 nNext
= pD
->nStartPos
;
5150 // gives the CP pos of the next attr change
5151 WW8_CP
WW8PLCFMan::Where() const
5154 WhereIdx(nullptr, &l
);
5158 void WW8PLCFMan::SeekPos( tools::Long nNewCp
)
5160 m_pChp
->pPLCFx
->SeekPos( nNewCp
+ m_nCpO
); // create new attr
5161 m_pPap
->pPLCFx
->SeekPos( nNewCp
+ m_nCpO
);
5162 m_pField
->pPLCFx
->SeekPos( nNewCp
);
5164 m_pPcd
->pPLCFx
->SeekPos( nNewCp
+ m_nCpO
);
5166 m_pBkm
->pPLCFx
->SeekPos( nNewCp
+ m_nCpO
);
5169 void WW8PLCFMan::SaveAllPLCFx( WW8PLCFxSaveAll
& rSave
) const
5173 m_pPcd
->Save( rSave
.aS
[n
++] );
5175 m_pPcdA
->Save( rSave
.aS
[n
++] );
5177 for(sal_uInt16 i
=0; i
<m_nPLCF
; ++i
)
5178 if( m_pPcd
!= &m_aD
[i
] && m_pPcdA
!= &m_aD
[i
] )
5179 m_aD
[i
].Save( rSave
.aS
[n
++] );
5182 void WW8PLCFMan::RestoreAllPLCFx( const WW8PLCFxSaveAll
& rSave
)
5186 m_pPcd
->Restore( rSave
.aS
[n
++] );
5188 m_pPcdA
->Restore( rSave
.aS
[n
++] );
5190 for(sal_uInt16 i
=0; i
<m_nPLCF
; ++i
)
5191 if( m_pPcd
!= &m_aD
[i
] && m_pPcdA
!= &m_aD
[i
] )
5192 m_aD
[i
].Restore( rSave
.aS
[n
++] );
5197 bool IsSizeLegal(tools::Long nSprmLen
, sal_Int32 nSprmsLen
)
5199 if (nSprmLen
> nSprmsLen
)
5201 SAL_WARN("sw.ww8", "Short sprm, len " << nSprmLen
<< " claimed, max possible is " << nSprmsLen
);
5208 bool WW8PLCFMan::IsSprmLegalForCategory(sal_uInt16 nSprmId
, short nIdx
) const
5210 const WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5211 if (p
!= m_pSep
) // just check sep for now
5215 ww::WordVersion eVersion
= maSprmParser
.GetFIBVersion();
5216 if (eVersion
<= ww::eWW2
)
5217 bRet
= nSprmId
>= 112 && nSprmId
<= 145;
5218 else if (eVersion
< ww::eWW8
)
5219 bRet
= nSprmId
>= NS_sprm::v6::sprmSScnsPgn
&& nSprmId
<= NS_sprm::v6::sprmSDMPaperReq
;
5223 Sprm bits: 10-12 sgc sprm group; type of sprm (PAP, CHP, etc)
5225 sgc value type of sprm
5232 auto nSGC
= ((nSprmId
& 0x1C00) >> 10);
5236 SAL_INFO("sw.ww8", "sprm, id " << nSprmId
<< " wrong category for section properties");
5240 void WW8PLCFMan::GetSprmStart( short nIdx
, WW8PLCFManResult
* pRes
) const
5242 memset( pRes
, 0, sizeof( WW8PLCFManResult
) );
5248 const WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5250 // first Sprm in a Group
5254 pRes
->nFlags
|= MAN_MASK_NEW_PAP
;
5255 else if( p
== m_pSep
)
5256 pRes
->nFlags
|= MAN_MASK_NEW_SEP
;
5258 pRes
->pMemPos
= p
->pMemPos
;
5259 pRes
->nSprmId
= GetId(p
);
5260 pRes
->nCp2OrIdx
= p
->nCp2OrIdx
;
5261 if ((p
== m_pFootnote
) || (p
== m_pEdn
) || (p
== m_pAnd
))
5262 pRes
->nMemLen
= p
->nSprmsLen
;
5263 else if (p
->nSprmsLen
>= maSprmParser
.MinSprmLen()) //normal
5265 // Length of actual sprm
5266 pRes
->nMemLen
= maSprmParser
.GetSprmSize(pRes
->nSprmId
, pRes
->pMemPos
, p
->nSprmsLen
);
5267 if (!IsSizeLegal(pRes
->nMemLen
, p
->nSprmsLen
) || !IsSprmLegalForCategory(pRes
->nSprmId
, nIdx
))
5274 void WW8PLCFMan::GetSprmEnd( short nIdx
, WW8PLCFManResult
* pRes
) const
5276 memset( pRes
, 0, sizeof( WW8PLCFManResult
) );
5278 const WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5280 if (!(p
->xIdStack
->empty()))
5281 pRes
->nSprmId
= p
->xIdStack
->top(); // get end position
5284 OSL_ENSURE( false, "No Id on the Stack" );
5289 void WW8PLCFMan::GetNoSprmStart( short nIdx
, WW8PLCFManResult
* pRes
) const
5291 const WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5293 pRes
->nCpPos
= p
->nStartPos
;
5294 pRes
->nMemLen
= p
->nSprmsLen
;
5295 pRes
->nCp2OrIdx
= p
->nCp2OrIdx
;
5298 pRes
->nSprmId
= eFLD
;
5299 else if( p
== m_pFootnote
)
5300 pRes
->nSprmId
= eFTN
;
5301 else if( p
== m_pEdn
)
5302 pRes
->nSprmId
= eEDN
;
5303 else if( p
== m_pBkm
)
5304 pRes
->nSprmId
= eBKN
;
5305 else if (p
== m_pAtnBkm
)
5306 pRes
->nSprmId
= eATNBKN
;
5307 else if (p
== m_pFactoidBkm
)
5308 pRes
->nSprmId
= eFACTOIDBKN
;
5309 else if( p
== m_pAnd
)
5310 pRes
->nSprmId
= eAND
;
5311 else if( p
== m_pPcd
)
5313 //We slave the piece table attributes to the piece table, the piece
5314 //table attribute iterator contains the sprms for this piece.
5315 GetSprmStart( nIdx
+1, pRes
);
5318 pRes
->nSprmId
= 0; // default: not found
5321 void WW8PLCFMan::GetNoSprmEnd( short nIdx
, WW8PLCFManResult
* pRes
) const
5323 pRes
->nMemLen
= -1; // end tag
5325 if( &m_aD
[nIdx
] == m_pBkm
)
5326 pRes
->nSprmId
= eBKN
;
5327 else if (&m_aD
[nIdx
] == m_pAtnBkm
)
5328 pRes
->nSprmId
= eATNBKN
;
5329 else if (&m_aD
[nIdx
] == m_pFactoidBkm
)
5330 pRes
->nSprmId
= eFACTOIDBKN
;
5331 else if( &m_aD
[nIdx
] == m_pPcd
)
5333 //We slave the piece table attributes to the piece table, the piece
5334 //table attribute iterator contains the sprms for this piece.
5335 GetSprmEnd( nIdx
+1, pRes
);
5341 void WW8PLCFMan::TransferOpenSprms(std::stack
<sal_uInt16
> &rStack
)
5343 for (sal_uInt16 i
= 0; i
< m_nPLCF
; ++i
)
5345 WW8PLCFxDesc
* p
= &m_aD
[i
];
5346 if (!p
|| !p
->xIdStack
)
5348 while (!p
->xIdStack
->empty())
5350 rStack
.push(p
->xIdStack
->top());
5356 void WW8PLCFMan::AdvSprm(short nIdx
, bool bStart
)
5358 WW8PLCFxDesc
* p
= &m_aD
[nIdx
]; // determine sprm class(!)
5360 p
->bFirstSprm
= false;
5363 const sal_uInt16 nLastId
= GetId(p
);
5365 const sal_uInt16 nLastAttribStarted
= IsSprmLegalForCategory(nLastId
, nIdx
) ? nLastId
: 0;
5367 p
->xIdStack
->push(nLastAttribStarted
); // remember Id for attribute end
5371 Check, if we have to process more sprm(s).
5375 // Length of last sprm
5376 const sal_Int32 nSprmL
= maSprmParser
.GetSprmSize(nLastId
, p
->pMemPos
, p
->nSprmsLen
);
5378 // Reduce length of all sprms by length of last sprm
5379 p
->nSprmsLen
-= nSprmL
;
5381 // pos of next possible sprm
5382 if (p
->nSprmsLen
< maSprmParser
.MinSprmLen())
5384 // preventively set to 0, because the end follows!
5385 p
->pMemPos
= nullptr;
5389 p
->pMemPos
+= nSprmL
;
5394 if (p
->nSprmsLen
< maSprmParser
.MinSprmLen())
5395 p
->nStartPos
= WW8_CP_MAX
; // the ending follows
5399 if (!(p
->xIdStack
->empty()))
5401 if (p
->xIdStack
->empty())
5403 if ( (p
== m_pChp
) || (p
== m_pPap
) )
5405 p
->pMemPos
= nullptr;
5407 p
->nStartPos
= p
->nOrigEndPos
+p
->nCpOfs
;
5410 On failed seek we have run out of sprms, probably. But if it's
5411 a fastsaved file (has pPcd) then we may be just in a sprm free
5412 gap between pieces that have them, so set dirty flag in sprm
5413 finder to consider than.
5415 if (!(*p
->pPLCFx
).SeekPos(p
->nStartPos
))
5417 p
->nEndPos
= WW8_CP_MAX
;
5418 p
->pPLCFx
->SetDirty(true);
5420 if (!p
->pPLCFx
->GetDirty() || m_pPcd
)
5422 p
->pPLCFx
->SetDirty(false);
5426 To get the character and paragraph properties you first get
5427 the pap and chp and then apply the fastsaved pPcd properties
5428 to the range. If a pap or chp starts inside the pPcd range
5429 then we must bring the current pPcd range to a halt so as to
5430 end those sprms, then the pap/chp will be processed, and then
5431 we must force a restart of the pPcd on that pap/chp starting
5432 boundary. Doing that effectively means that the pPcd sprms will
5433 be applied to the new range. Not doing it means that the pPcd
5434 sprms will only be applied to the first pap/chp set of
5435 properties contained in the pap/chp range.
5437 So we bring the pPcd to a halt on this location here, by
5438 settings its end to the current start, then store the starting
5439 position of the current range to clipstart. The pPcd sprms
5440 will end as normal (albeit earlier than originally expected),
5441 and the existence of a clipstart will force the pPcd iterator
5442 to reread the current set of sprms instead of advancing to its
5443 next set. Then the clipstart will be set as the starting
5444 position which will force them to be applied directly after
5447 if (m_pPcd
&& ((p
->nStartPos
> m_pPcd
->nStartPos
) ||
5448 (m_pPcd
->nStartPos
== WW8_CP_MAX
)) &&
5449 (m_pPcd
->nEndPos
!= p
->nStartPos
))
5451 m_pPcd
->nEndPos
= p
->nStartPos
;
5452 static_cast<WW8PLCFx_PCD
*>(m_pPcd
->pPLCFx
)->SetClipStart(
5459 p
->pPLCFx
->advance(); // next Group of Sprms
5460 p
->pMemPos
= nullptr; // !!!
5464 SAL_WARN_IF(p
->nStartPos
> p
->nEndPos
, "sw.ww8",
5465 "End " << p
->nEndPos
<< " before Start " << p
->nStartPos
);
5470 void WW8PLCFMan::AdvNoSprm(short nIdx
, bool bStart
)
5473 For the case of a piece table we slave the piece table attribute iterator
5474 to the piece table and access it through that only. They are two separate
5475 structures, but act together as one logical one. The attributes only go
5476 to the next entry when the piece changes
5478 WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5482 AdvSprm(nIdx
+1,bStart
);
5484 p
->nStartPos
= m_aD
[nIdx
+1].nStartPos
;
5487 if (m_aD
[nIdx
+1].xIdStack
->empty())
5489 WW8PLCFx_PCD
*pTemp
= static_cast<WW8PLCFx_PCD
*>(m_pPcd
->pPLCFx
);
5492 As per normal, go on to the next set of properties, i.e. we
5493 have traversed over to the next piece. With a clipstart set
5494 we are being told to reread the current piece sprms so as to
5495 reapply them to a new chp or pap range.
5497 if (pTemp
->GetClipStart() == -1)
5498 p
->pPLCFx
->advance();
5499 p
->pMemPos
= nullptr;
5501 GetNewSprms( m_aD
[nIdx
+1] );
5502 GetNewNoSprms( *p
);
5503 if (pTemp
->GetClipStart() != -1)
5506 #i2325#, now we will force our starting position to the
5507 clipping start so as to force the application of these
5508 sprms after the current pap/chp sprms so as to apply the
5509 fastsave sprms to the current range.
5511 p
->nStartPos
= pTemp
->GetClipStart();
5512 pTemp
->SetClipStart(-1);
5518 { // NoSprm without end
5519 p
->pPLCFx
->advance();
5520 p
->pMemPos
= nullptr; // MemPos invalid
5522 GetNewNoSprms( *p
);
5526 void WW8PLCFMan::advance()
5529 const sal_uInt16 nIdx
= WhereIdx(&bStart
);
5532 WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5534 p
->bFirstSprm
= true; // Default
5536 if( p
->pPLCFx
->IsSprm() )
5537 AdvSprm( nIdx
, bStart
);
5539 AdvNoSprm( nIdx
, bStart
);
5543 // return true for the beginning of an attribute or error,
5544 // false for the end of an attribute
5545 // remaining return values are delivered to the caller from WW8PclxManResults.
5546 bool WW8PLCFMan::Get(WW8PLCFManResult
* pRes
) const
5548 memset( pRes
, 0, sizeof( WW8PLCFManResult
) );
5550 const sal_uInt16 nIdx
= WhereIdx(&bStart
);
5552 if( nIdx
>= m_nPLCF
)
5554 OSL_ENSURE( false, "Position not found" );
5558 if( m_aD
[nIdx
].pPLCFx
->IsSprm() )
5562 GetSprmStart( nIdx
, pRes
);
5567 GetSprmEnd( nIdx
, pRes
);
5575 GetNoSprmStart( nIdx
, pRes
);
5580 GetNoSprmEnd( nIdx
, pRes
);
5586 sal_uInt16
WW8PLCFMan::GetColl() const
5588 if( m_pPap
->pPLCFx
)
5589 return m_pPap
->pPLCFx
->GetIstd();
5592 OSL_ENSURE( false, "GetColl without PLCF_Pap" );
5597 WW8PLCFx_FLD
* WW8PLCFMan::GetField() const
5599 return static_cast<WW8PLCFx_FLD
*>(m_pField
->pPLCFx
);
5602 SprmResult
WW8PLCFMan::HasParaSprm( sal_uInt16 nId
) const
5604 return static_cast<WW8PLCFx_Cp_FKP
*>(m_pPap
->pPLCFx
)->HasSprm( nId
);
5607 SprmResult
WW8PLCFMan::HasCharSprm( sal_uInt16 nId
) const
5609 return static_cast<WW8PLCFx_Cp_FKP
*>(m_pChp
->pPLCFx
)->HasSprm( nId
);
5612 void WW8PLCFMan::HasCharSprm(sal_uInt16 nId
,
5613 std::vector
<SprmResult
> &rResult
) const
5615 static_cast<WW8PLCFx_Cp_FKP
*>(m_pChp
->pPLCFx
)->HasSprm(nId
, rResult
);
5618 void WW8PLCFx::Save( WW8PLCFxSave1
& rSave
) const
5620 rSave
.nPLCFxPos
= GetIdx();
5621 rSave
.nPLCFxPos2
= GetIdx2();
5622 rSave
.nPLCFxMemOfs
= 0;
5623 rSave
.nStartFC
= GetStartFc();
5626 void WW8PLCFx::Restore( const WW8PLCFxSave1
& rSave
)
5628 SetIdx( rSave
.nPLCFxPos
);
5629 SetIdx2( rSave
.nPLCFxPos2
);
5630 SetStartFc( rSave
.nStartFC
);
5633 sal_uInt32
WW8PLCFx_Cp_FKP::GetIdx2() const
5638 void WW8PLCFx_Cp_FKP::SetIdx2(sal_uInt32 nIdx
)
5641 m_pPcd
->SetIdx( nIdx
);
5644 void WW8PLCFx_Cp_FKP::Save( WW8PLCFxSave1
& rSave
) const
5647 m_pFkp
->IncMustRemainCache();
5648 WW8PLCFx::Save( rSave
);
5650 rSave
.nAttrStart
= m_nAttrStart
;
5651 rSave
.nAttrEnd
= m_nAttrEnd
;
5652 rSave
.bLineEnd
= m_bLineEnd
;
5655 void WW8PLCFx_Cp_FKP::Restore( const WW8PLCFxSave1
& rSave
)
5657 WW8PLCFx::Restore( rSave
);
5659 m_nAttrStart
= rSave
.nAttrStart
;
5660 m_nAttrEnd
= rSave
.nAttrEnd
;
5661 m_bLineEnd
= rSave
.bLineEnd
;
5664 m_pFkp
->DecMustRemainCache();
5667 void WW8PLCFxDesc::Save( WW8PLCFxSave1
& rSave
) const
5672 pPLCFx
->Save( rSave
);
5673 if( !pPLCFx
->IsSprm() )
5677 aD
.nStartPos
= nOrigStartPos
+nCpOfs
;
5678 aD
.nCpOfs
= rSave
.nCpOfs
= nCpOfs
;
5679 if (!(pPLCFx
->SeekPos(aD
.nStartPos
)))
5681 aD
.nEndPos
= WW8_CP_MAX
;
5682 pPLCFx
->SetDirty(true);
5684 pPLCFx
->GetSprms(&aD
);
5685 pPLCFx
->SetDirty(false);
5686 aD
.ReduceByOffset();
5687 rSave
.nStartCp
= aD
.nStartPos
;
5688 rSave
.nPLCFxMemOfs
= nOrigSprmsLen
- nSprmsLen
;
5691 void WW8PLCFxDesc::Restore( const WW8PLCFxSave1
& rSave
)
5696 pPLCFx
->Restore( rSave
);
5697 if( !pPLCFx
->IsSprm() )
5701 aD
.nStartPos
= rSave
.nStartCp
+rSave
.nCpOfs
;
5702 nCpOfs
= aD
.nCpOfs
= rSave
.nCpOfs
;
5703 if (!(pPLCFx
->SeekPos(aD
.nStartPos
)))
5705 aD
.nEndPos
= WW8_CP_MAX
;
5706 pPLCFx
->SetDirty(true);
5708 pPLCFx
->GetSprms(&aD
);
5709 pPLCFx
->SetDirty(false);
5710 aD
.ReduceByOffset();
5712 if (nOrigSprmsLen
> aD
.nSprmsLen
)
5714 //two entries exist for the same offset, cut and run
5715 SAL_WARN("sw.ww8", "restored properties don't match saved properties, bailing out");
5721 nSprmsLen
= nOrigSprmsLen
- rSave
.nPLCFxMemOfs
;
5722 pMemPos
= aD
.pMemPos
== nullptr ? nullptr : aD
.pMemPos
+ rSave
.nPLCFxMemOfs
;
5728 sal_uInt32
Readcb(SvStream
& rSt
, ww::WordVersion eVer
)
5730 if (eVer
<= ww::eWW2
)
5732 sal_uInt16
nShort(0);
5733 rSt
.ReadUInt16(nShort
);
5738 sal_uInt32
nLong(0);
5739 rSt
.ReadUInt32(nLong
);
5745 bool WW8Fib::GetBaseCp(ManTypes nType
, WW8_CP
* cp
) const
5747 assert(cp
!= nullptr);
5753 if (m_ccpTxbx
< 0) {
5756 nOffset
= m_ccpTxbx
;
5759 if (m_ccpEdn
< 0 || m_ccpEdn
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5762 nOffset
+= m_ccpEdn
;
5765 if (m_ccpAtn
< 0 || m_ccpAtn
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5768 nOffset
+= m_ccpAtn
;
5771 if (m_ccpMcr
< 0 || m_ccpMcr
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5774 nOffset
+= m_ccpMcr
;
5778 A subdocument of this kind (MAN_MACRO) probably exists in some defunct
5779 version of MSWord, but now ccpMcr is always 0. If some example that
5780 uses this comes to light, this is the likely calculation required
5784 if (m_ccpHdr
< 0 || m_ccpHdr
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5787 nOffset
+= m_ccpHdr
;
5790 if (m_ccpFootnote
< 0 || m_ccpFootnote
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5793 nOffset
+= m_ccpFootnote
;
5796 if (m_ccpText
< 0 || m_ccpText
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5799 nOffset
+= m_ccpText
;
5808 ww::WordVersion
WW8Fib::GetFIBVersion() const
5810 ww::WordVersion eVer
= ww::eWW8
;
5812 * Word for Windows 2 I think (1.X might work too if anyone has an example.
5814 * 0xA59B for Word 1 for Windows
5815 * 0xA59C for Word 1 for OS/2 "PM Word"
5817 * Various pages claim that the fileformats of Word 1 and 2 for Windows are
5818 * equivalent to Word for Macintosh 4 and 5. On the other hand
5820 * wIdents for Word for Mac versions...
5823 * 0xFE37 for Word 4 et 5.
5826 * http://cmsdoc.cern.ch/documents/docformat/CMS_CERN_LetterHead.word is
5827 * claimed to be "Word 5 for Mac" by Office etc and has that wIdent, but
5828 * its format isn't the same as that of Word 2 for windows. Nor is it
5829 * the same as that of Word for DOS/PCWord 5
5831 if (m_wIdent
== 0xa59b || m_wIdent
== 0xa59c)
5833 else if (m_wIdent
== 0xa5db)
5853 WW8Fib::WW8Fib(SvStream
& rSt
, sal_uInt8 nWantedVersion
, sal_uInt32 nOffset
):
5854 m_fDot(false), m_fGlsy(false), m_fComplex(false), m_fHasPic(false), m_cQuickSaves(0),
5855 m_fEncrypted(false), m_fWhichTableStm(false), m_fReadOnlyRecommended(false),
5856 m_fWriteReservation(false), m_fExtChar(false), m_fFarEast(false), m_fObfuscated(false),
5857 m_fMac(false), m_fEmptySpecial(false), m_fLoadOverridePage(false), m_fFuturesavedUndo(false),
5858 m_fWord97Saved(false), m_fWord2000Saved(false)
5859 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
5860 // above bit-field member initializations can be moved to the class definition
5862 // See [MS-DOC] 2.5.15 "How to read the FIB".
5863 rSt
.Seek( nOffset
);
5865 note desired number, identify file version number
5866 and check against desired number!
5868 m_nVersion
= nWantedVersion
;
5869 rSt
.ReadUInt16( m_wIdent
);
5870 rSt
.ReadUInt16( m_nFib
);
5871 rSt
.ReadUInt16( m_nProduct
);
5872 if( ERRCODE_NONE
!= rSt
.GetError() )
5876 // note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
5877 switch( m_nVersion
)
5880 nFibMin
= 0x0065; // from 101 WinWord 6.0
5882 // and 103 WinWord 6.0 for Macintosh
5884 nFibMax
= 0x0069; // to 105 WinWord 95
5887 nFibMin
= 0x0069; // from 105 WinWord 95
5888 nFibMax
= 0x0069; // to 105 WinWord 95
5891 nFibMin
= 0x006A; // from 106 WinWord 97
5892 nFibMax
= 0x00c1; // to 193 WinWord 97 (?)
5895 nFibMin
= 0; // program error!
5898 OSL_ENSURE( false, "nVersion not implemented!" );
5901 if ( (m_nFib
< nFibMin
) || (m_nFib
> nFibMax
) )
5903 m_nFibError
= ERR_SWG_READ_ERROR
; // report error
5908 ww::WordVersion eVer
= GetFIBVersion();
5910 // helper vars for Ver67:
5911 sal_Int16 pnChpFirst_Ver67
=0;
5912 sal_Int16 pnPapFirst_Ver67
=0;
5913 sal_Int16 cpnBteChp_Ver67
=0;
5914 sal_Int16 cpnBtePap_Ver67
=0;
5917 sal_uInt16 nTmpLid
= 0;
5918 rSt
.ReadUInt16(nTmpLid
);
5919 m_lid
= LanguageType(nTmpLid
);
5920 rSt
.ReadInt16( m_pnNext
);
5921 sal_uInt8
aBits1(0);
5922 rSt
.ReadUChar( aBits1
);
5923 sal_uInt8
aBits2(0);
5924 rSt
.ReadUChar( aBits2
);
5925 rSt
.ReadUInt16( m_nFibBack
);
5926 rSt
.ReadUInt16( m_nHash
);
5927 rSt
.ReadUInt16( m_nKey
);
5928 rSt
.ReadUChar( m_envr
);
5929 sal_uInt8
aVer8Bits1(0); // only used starting with WinWord 8
5930 rSt
.ReadUChar( aVer8Bits1
); // only have an empty reserve field under Ver67
5931 // content from aVer8Bits1
5933 // sal_uInt8 fMac :1;
5934 // sal_uInt8 fEmptySpecial :1;
5935 // sal_uInt8 fLoadOverridePage :1;
5936 // sal_uInt8 fFuturesavedUndo :1;
5937 // sal_uInt8 fWord97Saved :1;
5939 rSt
.ReadUInt16( m_chse
);
5940 rSt
.ReadUInt16( m_chseTables
);
5941 rSt
.ReadInt32( m_fcMin
);
5942 rSt
.ReadInt32( m_fcMac
);
5944 // insertion for WW8
5945 if (IsEightPlus(eVer
))
5947 rSt
.ReadUInt16( m_csw
);
5949 // Marke: "rgsw" Beginning of the array of shorts
5950 rSt
.ReadUInt16( m_wMagicCreated
);
5951 rSt
.ReadUInt16( m_wMagicRevised
);
5952 rSt
.ReadUInt16( m_wMagicCreatedPrivate
);
5953 rSt
.ReadUInt16( m_wMagicRevisedPrivate
);
5954 rSt
.SeekRel( 9 * sizeof( sal_Int16
) );
5957 // these are the 9 unused fields:
5958 && (bVer67 || WW8ReadINT16( rSt, pnFbpChpFirst_W6 )) // 1
5959 && (bVer67 || WW8ReadINT16( rSt, pnChpFirst_W6 )) // 2
5960 && (bVer67 || WW8ReadINT16( rSt, cpnBteChp_W6 )) // 3
5961 && (bVer67 || WW8ReadINT16( rSt, pnFbpPapFirst_W6 )) // 4
5962 && (bVer67 || WW8ReadINT16( rSt, pnPapFirst_W6 )) // 5
5963 && (bVer67 || WW8ReadINT16( rSt, cpnBtePap_W6 )) // 6
5964 && (bVer67 || WW8ReadINT16( rSt, pnFbpLvcFirst_W6 )) // 7
5965 && (bVer67 || WW8ReadINT16( rSt, pnLvcFirst_W6 )) // 8
5966 && (bVer67 || WW8ReadINT16( rSt, cpnBteLvc_W6 )) // 9
5968 sal_uInt16 nTmpFE
= 0;
5969 rSt
.ReadUInt16(nTmpFE
);
5970 m_lidFE
= LanguageType(nTmpFE
);
5971 rSt
.ReadUInt16( m_clw
);
5974 // end of the insertion for WW8
5976 // Marke: "rglw" Beginning of the array of longs
5977 rSt
.ReadInt32( m_cbMac
);
5979 // ignore 2 longs, because they are unimportant
5980 rSt
.SeekRel( 2 * sizeof( sal_Int32
) );
5982 // skipping 2 more longs only at Ver67
5983 if (IsSevenMinus(eVer
))
5984 rSt
.SeekRel( 2 * sizeof( sal_Int32
) );
5986 rSt
.ReadInt32( m_ccpText
);
5987 rSt
.ReadInt32( m_ccpFootnote
);
5988 rSt
.ReadInt32( m_ccpHdr
);
5989 rSt
.ReadInt32( m_ccpMcr
);
5990 rSt
.ReadInt32( m_ccpAtn
);
5991 rSt
.ReadInt32( m_ccpEdn
);
5992 rSt
.ReadInt32( m_ccpTxbx
);
5993 rSt
.ReadInt32( m_ccpHdrTxbx
);
5995 // only skip one more long at Ver67
5996 if (IsSevenMinus(eVer
))
5997 rSt
.SeekRel( 1 * sizeof( sal_Int32
) );
6000 // insertion for WW8
6001 rSt
.ReadInt32( m_pnFbpChpFirst
);
6002 rSt
.ReadInt32( m_pnChpFirst
);
6003 rSt
.ReadInt32( m_cpnBteChp
);
6004 rSt
.ReadInt32( m_pnFbpPapFirst
);
6005 rSt
.ReadInt32( m_pnPapFirst
);
6006 rSt
.ReadInt32( m_cpnBtePap
);
6007 rSt
.ReadInt32( m_pnFbpLvcFirst
);
6008 rSt
.ReadInt32( m_pnLvcFirst
);
6009 rSt
.ReadInt32( m_cpnBteLvc
);
6010 rSt
.ReadInt32( m_fcIslandFirst
);
6011 rSt
.ReadInt32( m_fcIslandLim
);
6012 rSt
.ReadUInt16( m_cfclcb
);
6014 // Read cswNew to find out if nFib should be ignored.
6015 sal_uInt32 nPos
= rSt
.Tell();
6016 rSt
.SeekRel(m_cfclcb
* 8);
6017 if (rSt
.good() && rSt
.remainingSize() >= 2)
6019 rSt
.ReadUInt16(m_cswNew
);
6024 // end of the insertion for WW8
6026 // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
6027 rSt
.ReadInt32( m_fcStshfOrig
);
6028 m_lcbStshfOrig
= Readcb(rSt
, eVer
);
6029 rSt
.ReadInt32( m_fcStshf
);
6030 m_lcbStshf
= Readcb(rSt
, eVer
);
6031 rSt
.ReadInt32( m_fcPlcffndRef
);
6032 m_lcbPlcffndRef
= Readcb(rSt
, eVer
);
6033 rSt
.ReadInt32( m_fcPlcffndText
);
6034 m_lcbPlcffndText
= Readcb(rSt
, eVer
);
6035 rSt
.ReadInt32( m_fcPlcfandRef
);
6036 m_lcbPlcfandRef
= Readcb(rSt
, eVer
);
6037 rSt
.ReadInt32( m_fcPlcfandText
);
6038 m_lcbPlcfandText
= Readcb(rSt
, eVer
);
6039 rSt
.ReadInt32( m_fcPlcfsed
);
6040 m_lcbPlcfsed
= Readcb(rSt
, eVer
);
6041 rSt
.ReadInt32( m_fcPlcfpad
);
6042 m_lcbPlcfpad
= Readcb(rSt
, eVer
);
6043 rSt
.ReadInt32( m_fcPlcfphe
);
6044 m_lcbPlcfphe
= Readcb(rSt
, eVer
);
6045 rSt
.ReadInt32( m_fcSttbfglsy
);
6046 m_lcbSttbfglsy
= Readcb(rSt
, eVer
);
6047 rSt
.ReadInt32( m_fcPlcfglsy
);
6048 m_lcbPlcfglsy
= Readcb(rSt
, eVer
);
6049 rSt
.ReadInt32( m_fcPlcfhdd
);
6050 m_lcbPlcfhdd
= Readcb(rSt
, eVer
);
6051 rSt
.ReadInt32( m_fcPlcfbteChpx
);
6052 m_lcbPlcfbteChpx
= Readcb(rSt
, eVer
);
6053 rSt
.ReadInt32( m_fcPlcfbtePapx
);
6054 m_lcbPlcfbtePapx
= Readcb(rSt
, eVer
);
6055 rSt
.ReadInt32( m_fcPlcfsea
);
6056 m_lcbPlcfsea
= Readcb(rSt
, eVer
);
6057 rSt
.ReadInt32( m_fcSttbfffn
);
6058 m_lcbSttbfffn
= Readcb(rSt
, eVer
);
6059 rSt
.ReadInt32( m_fcPlcffldMom
);
6060 m_lcbPlcffldMom
= Readcb(rSt
, eVer
);
6061 rSt
.ReadInt32( m_fcPlcffldHdr
);
6062 m_lcbPlcffldHdr
= Readcb(rSt
, eVer
);
6063 rSt
.ReadInt32( m_fcPlcffldFootnote
);
6064 m_lcbPlcffldFootnote
= Readcb(rSt
, eVer
);
6065 rSt
.ReadInt32( m_fcPlcffldAtn
);
6066 m_lcbPlcffldAtn
= Readcb(rSt
, eVer
);
6067 rSt
.ReadInt32( m_fcPlcffldMcr
);
6068 m_lcbPlcffldMcr
= Readcb(rSt
, eVer
);
6069 rSt
.ReadInt32( m_fcSttbfbkmk
);
6070 m_lcbSttbfbkmk
= Readcb(rSt
, eVer
);
6071 rSt
.ReadInt32( m_fcPlcfbkf
);
6072 m_lcbPlcfbkf
= Readcb(rSt
, eVer
);
6073 rSt
.ReadInt32( m_fcPlcfbkl
);
6074 m_lcbPlcfbkl
= Readcb(rSt
, eVer
);
6075 rSt
.ReadInt32( m_fcCmds
);
6076 m_lcbCmds
= Readcb(rSt
, eVer
);
6077 rSt
.ReadInt32( m_fcPlcfmcr
);
6078 m_lcbPlcfmcr
= Readcb(rSt
, eVer
);
6079 rSt
.ReadInt32( m_fcSttbfmcr
);
6080 m_lcbSttbfmcr
= Readcb(rSt
, eVer
);
6081 if (eVer
>= ww::eWW2
)
6083 rSt
.ReadInt32( m_fcPrDrvr
);
6084 m_lcbPrDrvr
= Readcb(rSt
, eVer
);
6085 rSt
.ReadInt32( m_fcPrEnvPort
);
6086 m_lcbPrEnvPort
= Readcb(rSt
, eVer
);
6087 rSt
.ReadInt32( m_fcPrEnvLand
);
6088 m_lcbPrEnvLand
= Readcb(rSt
, eVer
);
6092 rSt
.ReadInt32( m_fcPrEnvPort
);
6093 m_lcbPrEnvPort
= Readcb(rSt
, eVer
);
6095 rSt
.ReadInt32( m_fcWss
);
6096 m_lcbWss
= Readcb(rSt
, eVer
);
6097 rSt
.ReadInt32( m_fcDop
);
6098 m_lcbDop
= Readcb(rSt
, eVer
);
6099 rSt
.ReadInt32( m_fcSttbfAssoc
);
6100 m_lcbSttbfAssoc
= Readcb(rSt
, eVer
);
6101 rSt
.ReadInt32( m_fcClx
);
6102 m_lcbClx
= Readcb(rSt
, eVer
);
6103 rSt
.ReadInt32( m_fcPlcfpgdFootnote
);
6104 m_lcbPlcfpgdFootnote
= Readcb(rSt
, eVer
);
6105 rSt
.ReadInt32( m_fcAutosaveSource
);
6106 m_lcbAutosaveSource
= Readcb(rSt
, eVer
);
6107 rSt
.ReadInt32( m_fcGrpStAtnOwners
);
6108 m_lcbGrpStAtnOwners
= Readcb(rSt
, eVer
);
6109 rSt
.ReadInt32( m_fcSttbfAtnbkmk
);
6110 m_lcbSttbfAtnbkmk
= Readcb(rSt
, eVer
);
6112 // only skip more shot at Ver67
6113 if (IsSevenMinus(eVer
))
6115 if (eVer
== ww::eWW1
)
6116 rSt
.SeekRel(1*sizeof(sal_Int32
));
6117 rSt
.SeekRel(1*sizeof(sal_Int16
));
6119 if (eVer
>= ww::eWW2
)
6121 rSt
.ReadInt16(pnChpFirst_Ver67
);
6122 rSt
.ReadInt16(pnPapFirst_Ver67
);
6124 rSt
.ReadInt16(cpnBteChp_Ver67
);
6125 rSt
.ReadInt16(cpnBtePap_Ver67
);
6128 if (eVer
> ww::eWW2
)
6130 rSt
.ReadInt32( m_fcPlcfdoaMom
);
6131 rSt
.ReadInt32( m_lcbPlcfdoaMom
);
6132 rSt
.ReadInt32( m_fcPlcfdoaHdr
);
6133 rSt
.ReadInt32( m_lcbPlcfdoaHdr
);
6134 rSt
.ReadInt32( m_fcPlcfspaMom
);
6135 rSt
.ReadInt32( m_lcbPlcfspaMom
);
6136 rSt
.ReadInt32( m_fcPlcfspaHdr
);
6137 rSt
.ReadInt32( m_lcbPlcfspaHdr
);
6139 rSt
.ReadInt32( m_fcPlcfAtnbkf
);
6140 rSt
.ReadInt32( m_lcbPlcfAtnbkf
);
6141 rSt
.ReadInt32( m_fcPlcfAtnbkl
);
6142 rSt
.ReadInt32( m_lcbPlcfAtnbkl
);
6143 rSt
.ReadInt32( m_fcPms
);
6144 rSt
.ReadInt32( m_lcbPMS
);
6145 rSt
.ReadInt32( m_fcFormFieldSttbf
);
6146 rSt
.ReadInt32( m_lcbFormFieldSttbf
);
6147 rSt
.ReadInt32( m_fcPlcfendRef
);
6148 rSt
.ReadInt32( m_lcbPlcfendRef
);
6149 rSt
.ReadInt32( m_fcPlcfendText
);
6150 rSt
.ReadInt32( m_lcbPlcfendText
);
6151 rSt
.ReadInt32( m_fcPlcffldEdn
);
6152 rSt
.ReadInt32( m_lcbPlcffldEdn
);
6153 rSt
.ReadInt32( m_fcPlcfpgdEdn
);
6154 rSt
.ReadInt32( m_lcbPlcfpgdEdn
);
6155 rSt
.ReadInt32( m_fcDggInfo
);
6156 rSt
.ReadInt32( m_lcbDggInfo
);
6157 rSt
.ReadInt32( m_fcSttbfRMark
);
6158 rSt
.ReadInt32( m_lcbSttbfRMark
);
6159 rSt
.ReadInt32( m_fcSttbfCaption
);
6160 rSt
.ReadInt32( m_lcbSttbfCaption
);
6161 rSt
.ReadInt32( m_fcSttbAutoCaption
);
6162 rSt
.ReadInt32( m_lcbSttbAutoCaption
);
6163 rSt
.ReadInt32( m_fcPlcfwkb
);
6164 rSt
.ReadInt32( m_lcbPlcfwkb
);
6165 rSt
.ReadInt32( m_fcPlcfspl
);
6166 rSt
.ReadInt32( m_lcbPlcfspl
);
6167 rSt
.ReadInt32( m_fcPlcftxbxText
);
6168 rSt
.ReadInt32( m_lcbPlcftxbxText
);
6169 rSt
.ReadInt32( m_fcPlcffldTxbx
);
6170 rSt
.ReadInt32( m_lcbPlcffldTxbx
);
6171 rSt
.ReadInt32( m_fcPlcfHdrtxbxText
);
6172 rSt
.ReadInt32( m_lcbPlcfHdrtxbxText
);
6173 rSt
.ReadInt32( m_fcPlcffldHdrTxbx
);
6174 rSt
.ReadInt32( m_lcbPlcffldHdrTxbx
);
6175 rSt
.ReadInt32( m_fcStwUser
);
6176 rSt
.ReadUInt32( m_lcbStwUser
);
6177 rSt
.ReadInt32( m_fcSttbttmbd
);
6178 rSt
.ReadUInt32( m_lcbSttbttmbd
);
6181 if( ERRCODE_NONE
== rSt
.GetError() )
6184 m_fDot
= aBits1
& 0x01 ;
6185 m_fGlsy
= ( aBits1
& 0x02 ) >> 1;
6186 m_fComplex
= ( aBits1
& 0x04 ) >> 2;
6187 m_fHasPic
= ( aBits1
& 0x08 ) >> 3;
6188 m_cQuickSaves
= ( aBits1
& 0xf0 ) >> 4;
6189 m_fEncrypted
= aBits2
& 0x01 ;
6190 m_fWhichTableStm
= ( aBits2
& 0x02 ) >> 1;
6191 m_fReadOnlyRecommended
= (aBits2
& 0x4) >> 2;
6192 m_fWriteReservation
= (aBits2
& 0x8) >> 3;
6193 m_fExtChar
= ( aBits2
& 0x10 ) >> 4;
6194 // dummy = ( aBits2 & 0x20 ) >> 5;
6195 m_fFarEast
= ( aBits2
& 0x40 ) >> 6; // #i90932#
6196 // dummy = ( aBits2 & 0x80 ) >> 7;
6199 p.r.n. fill targeted variable with xxx_Ver67
6202 if (IsSevenMinus(eVer
))
6204 m_pnChpFirst
= pnChpFirst_Ver67
;
6205 m_pnPapFirst
= pnPapFirst_Ver67
;
6206 m_cpnBteChp
= cpnBteChp_Ver67
;
6207 m_cpnBtePap
= cpnBtePap_Ver67
;
6209 else if (IsEightPlus(eVer
))
6211 m_fMac
= aVer8Bits1
& 0x01 ;
6212 m_fEmptySpecial
= ( aVer8Bits1
& 0x02 ) >> 1;
6213 m_fLoadOverridePage
= ( aVer8Bits1
& 0x04 ) >> 2;
6214 m_fFuturesavedUndo
= ( aVer8Bits1
& 0x08 ) >> 3;
6215 m_fWord97Saved
= ( aVer8Bits1
& 0x10 ) >> 4;
6216 m_fWord2000Saved
= ( aVer8Bits1
& 0x20 ) >> 5;
6220 identify the values for PLCF and PLF LFO
6221 and PLCF for the textbox break descriptors
6223 sal_uInt64 nOldPos
= rSt
.Tell();
6226 rSt
.ReadInt32( m_fcSttbFnm
);
6227 rSt
.ReadInt32( m_lcbSttbFnm
);
6228 rSt
.ReadInt32( m_fcPlcfLst
);
6229 rSt
.ReadInt32( m_lcbPlcfLst
);
6230 rSt
.ReadInt32( m_fcPlfLfo
);
6231 rSt
.ReadInt32( m_lcbPlfLfo
);
6232 rSt
.ReadInt32( m_fcPlcftxbxBkd
);
6233 rSt
.ReadInt32( m_lcbPlcftxbxBkd
);
6234 rSt
.ReadInt32( m_fcPlcfHdrtxbxBkd
);
6235 rSt
.ReadInt32( m_lcbPlcfHdrtxbxBkd
);
6236 if( ERRCODE_NONE
!= rSt
.GetError() )
6238 m_nFibError
= ERR_SWG_READ_ERROR
;
6241 rSt
.Seek( 0x372 ); // fcSttbListNames
6242 rSt
.ReadInt32( m_fcSttbListNames
);
6243 rSt
.ReadInt32( m_lcbSttbListNames
);
6247 rSt
.Seek( 0x382 ); // MagicTables
6248 rSt
.ReadInt32( m_fcPlcfTch
);
6249 rSt
.ReadInt32( m_lcbPlcfTch
);
6254 rSt
.Seek( 0x41A ); // new ATRD
6255 rSt
.ReadInt32( m_fcAtrdExtra
);
6256 rSt
.ReadUInt32( m_lcbAtrdExtra
);
6259 // Factoid bookmarks
6263 rSt
.ReadInt32(m_fcPlcfBkfFactoid
);
6264 rSt
.ReadUInt32(m_lcbPlcfBkfFactoid
);
6267 rSt
.ReadInt32(m_fcPlcfBklFactoid
);
6268 rSt
.ReadUInt32(m_lcbPlcfBklFactoid
);
6271 rSt
.ReadInt32(m_fcFactoidData
);
6272 rSt
.ReadUInt32(m_lcbFactoidData
);
6275 if( ERRCODE_NONE
!= rSt
.GetError() )
6276 m_nFibError
= ERR_SWG_READ_ERROR
;
6278 rSt
.Seek( 0x5bc ); // Actual nFib introduced in Word 2003
6279 rSt
.ReadUInt16( m_nFib_actual
);
6281 rSt
.Seek( nOldPos
);
6286 m_nFibError
= ERR_SWG_READ_ERROR
; // report error
6290 WW8Fib::WW8Fib(sal_uInt8 nVer
, bool bDot
):
6291 m_nVersion(nVer
), m_fDot(false), m_fGlsy(false), m_fComplex(false), m_fHasPic(false), m_cQuickSaves(0),
6292 m_fEncrypted(false), m_fWhichTableStm(false), m_fReadOnlyRecommended(false),
6293 m_fWriteReservation(false), m_fExtChar(false), m_fFarEast(false), m_fObfuscated(false),
6294 m_fMac(false), m_fEmptySpecial(false), m_fLoadOverridePage(false), m_fFuturesavedUndo(false),
6295 m_fWord97Saved(false), m_fWord2000Saved(false)
6296 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
6297 // above bit-field member initializations can be moved to the class definition
6305 m_nProduct
= 0x204D;
6308 m_csw
= 0x0e; // Is this really necessary???
6309 m_cfclcb
= 0x88; // -""-
6310 m_clw
= 0x16; // -""-
6311 m_pnFbpChpFirst
= m_pnFbpPapFirst
= m_pnFbpLvcFirst
= 0x000fffff;
6313 m_fWord97Saved
= m_fWord2000Saved
= true;
6315 // Just a fancy way to write 'Caolan80'.
6316 m_wMagicCreated
= 0x6143;
6317 m_wMagicRevised
= 0x6C6F;
6318 m_wMagicCreatedPrivate
= 0x6E61;
6319 m_wMagicRevisedPrivate
= 0x3038;
6325 m_nFib
= m_nFibBack
= 0x65;
6326 m_nProduct
= 0xc02d;
6329 //If nFib is 0x00D9 or greater, then cQuickSaves MUST be 0xF
6330 m_cQuickSaves
= m_nFib
>= 0x00D9 ? 0xF : 0;
6333 m_lid
= LanguageType(0x409); // LANGUAGE_ENGLISH_US
6335 LanguageType nLang
= Application::GetSettings().GetLanguageTag().getLanguageType();
6336 m_fFarEast
= MsLangId::isCJK(nLang
);
6342 LanguageTag
aLanguageTag( m_lid
);
6343 LocaleDataWrapper
aLocaleWrapper( std::move(aLanguageTag
) );
6344 m_nNumDecimalSep
= aLocaleWrapper
.getNumDecimalSep()[0];
6348 void WW8Fib::WriteHeader(SvStream
& rStrm
)
6350 bool bVer8
= 8 == m_nVersion
;
6352 size_t nUnencryptedHdr
= bVer8
? 0x44 : 0x24;
6353 std::unique_ptr
<sal_uInt8
[]> pDataPtr( new sal_uInt8
[ nUnencryptedHdr
] );
6354 sal_uInt8
*pData
= pDataPtr
.get();
6355 memset( pData
, 0, nUnencryptedHdr
);
6357 m_cbMac
= rStrm
.TellEnd();
6359 Set_UInt16( pData
, m_wIdent
);
6360 Set_UInt16( pData
, m_nFib
);
6361 Set_UInt16( pData
, m_nProduct
);
6362 Set_UInt16( pData
, static_cast<sal_uInt16
>(m_lid
) );
6363 Set_UInt16( pData
, m_pnNext
);
6365 sal_uInt16 nBits16
= 0;
6366 if( m_fDot
) nBits16
|= 0x0001;
6367 if( m_fGlsy
) nBits16
|= 0x0002;
6368 if( m_fComplex
) nBits16
|= 0x0004;
6369 if( m_fHasPic
) nBits16
|= 0x0008;
6370 nBits16
|= (0xf0 & ( m_cQuickSaves
<< 4 ));
6371 if( m_fEncrypted
) nBits16
|= 0x0100;
6372 if( m_fWhichTableStm
) nBits16
|= 0x0200;
6374 if (m_fReadOnlyRecommended
)
6376 if (m_fWriteReservation
)
6379 if( m_fExtChar
) nBits16
|= 0x1000;
6380 if( m_fFarEast
) nBits16
|= 0x4000; // #i90932#
6381 if( m_fObfuscated
) nBits16
|= 0x8000;
6382 Set_UInt16( pData
, nBits16
);
6384 Set_UInt16( pData
, m_nFibBack
);
6385 Set_UInt16( pData
, m_nHash
);
6386 Set_UInt16( pData
, m_nKey
);
6387 Set_UInt8( pData
, m_envr
);
6389 sal_uInt8 nBits8
= 0;
6392 if( m_fMac
) nBits8
|= 0x0001;
6393 if( m_fEmptySpecial
) nBits8
|= 0x0002;
6394 if( m_fLoadOverridePage
) nBits8
|= 0x0004;
6395 if( m_fFuturesavedUndo
) nBits8
|= 0x0008;
6396 if( m_fWord97Saved
) nBits8
|= 0x0010;
6397 if( m_fWord2000Saved
) nBits8
|= 0x0020;
6399 // under Ver67 these are only reserved
6400 Set_UInt8( pData
, nBits8
);
6402 Set_UInt16( pData
, m_chse
);
6403 Set_UInt16( pData
, m_chseTables
);
6404 Set_UInt32( pData
, m_fcMin
);
6405 Set_UInt32( pData
, m_fcMac
);
6407 // insertion for WW8
6409 // Marke: "rgsw" Beginning of the array of shorts
6412 Set_UInt16( pData
, m_csw
);
6413 Set_UInt16( pData
, m_wMagicCreated
);
6414 Set_UInt16( pData
, m_wMagicRevised
);
6415 Set_UInt16( pData
, m_wMagicCreatedPrivate
);
6416 Set_UInt16( pData
, m_wMagicRevisedPrivate
);
6417 pData
+= 9 * sizeof( sal_Int16
);
6418 Set_UInt16( pData
, static_cast<sal_uInt16
>(m_lidFE
) );
6419 Set_UInt16( pData
, m_clw
);
6422 // end of the insertion for WW8
6424 // Marke: "rglw" Beginning of the array of longs
6425 Set_UInt32( pData
, m_cbMac
);
6427 rStrm
.WriteBytes(pDataPtr
.get(), nUnencryptedHdr
);
6430 void WW8Fib::Write(SvStream
& rStrm
)
6432 bool bVer8
= 8 == m_nVersion
;
6434 WriteHeader( rStrm
);
6436 size_t nUnencryptedHdr
= bVer8
? 0x44 : 0x24;
6438 std::unique_ptr
<sal_uInt8
[]> pDataPtr( new sal_uInt8
[ m_fcMin
- nUnencryptedHdr
] );
6439 sal_uInt8
*pData
= pDataPtr
.get();
6440 memset( pData
, 0, m_fcMin
- nUnencryptedHdr
);
6442 m_cbMac
= rStrm
.TellEnd();
6444 // ignore 2 longs, because they are unimportant
6445 pData
+= 2 * sizeof( sal_Int32
);
6447 // skipping 2 more longs only at Ver67
6449 pData
+= 2 * sizeof( sal_Int32
);
6451 Set_UInt32( pData
, m_ccpText
);
6452 Set_UInt32( pData
, m_ccpFootnote
);
6453 Set_UInt32( pData
, m_ccpHdr
);
6454 Set_UInt32( pData
, m_ccpMcr
);
6455 Set_UInt32( pData
, m_ccpAtn
);
6456 Set_UInt32( pData
, m_ccpEdn
);
6457 Set_UInt32( pData
, m_ccpTxbx
);
6458 Set_UInt32( pData
, m_ccpHdrTxbx
);
6460 // only skip one more long at Ver67
6462 pData
+= 1 * sizeof( sal_Int32
);
6464 // insertion for WW8
6467 Set_UInt32( pData
, m_pnFbpChpFirst
);
6468 Set_UInt32( pData
, m_pnChpFirst
);
6469 Set_UInt32( pData
, m_cpnBteChp
);
6470 Set_UInt32( pData
, m_pnFbpPapFirst
);
6471 Set_UInt32( pData
, m_pnPapFirst
);
6472 Set_UInt32( pData
, m_cpnBtePap
);
6473 Set_UInt32( pData
, m_pnFbpLvcFirst
);
6474 Set_UInt32( pData
, m_pnLvcFirst
);
6475 Set_UInt32( pData
, m_cpnBteLvc
);
6476 Set_UInt32( pData
, m_fcIslandFirst
);
6477 Set_UInt32( pData
, m_fcIslandLim
);
6478 Set_UInt16( pData
, m_cfclcb
);
6480 // end of the insertion for WW8
6482 // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
6483 Set_UInt32( pData
, m_fcStshfOrig
);
6484 Set_UInt32( pData
, m_lcbStshfOrig
);
6485 Set_UInt32( pData
, m_fcStshf
);
6486 Set_UInt32( pData
, m_lcbStshf
);
6487 Set_UInt32( pData
, m_fcPlcffndRef
);
6488 Set_UInt32( pData
, m_lcbPlcffndRef
);
6489 Set_UInt32( pData
, m_fcPlcffndText
);
6490 Set_UInt32( pData
, m_lcbPlcffndText
);
6491 Set_UInt32( pData
, m_fcPlcfandRef
);
6492 Set_UInt32( pData
, m_lcbPlcfandRef
);
6493 Set_UInt32( pData
, m_fcPlcfandText
);
6494 Set_UInt32( pData
, m_lcbPlcfandText
);
6495 Set_UInt32( pData
, m_fcPlcfsed
);
6496 Set_UInt32( pData
, m_lcbPlcfsed
);
6497 Set_UInt32( pData
, m_fcPlcfpad
);
6498 Set_UInt32( pData
, m_lcbPlcfpad
);
6499 Set_UInt32( pData
, m_fcPlcfphe
);
6500 Set_UInt32( pData
, m_lcbPlcfphe
);
6501 Set_UInt32( pData
, m_fcSttbfglsy
);
6502 Set_UInt32( pData
, m_lcbSttbfglsy
);
6503 Set_UInt32( pData
, m_fcPlcfglsy
);
6504 Set_UInt32( pData
, m_lcbPlcfglsy
);
6505 Set_UInt32( pData
, m_fcPlcfhdd
);
6506 Set_UInt32( pData
, m_lcbPlcfhdd
);
6507 Set_UInt32( pData
, m_fcPlcfbteChpx
);
6508 Set_UInt32( pData
, m_lcbPlcfbteChpx
);
6509 Set_UInt32( pData
, m_fcPlcfbtePapx
);
6510 Set_UInt32( pData
, m_lcbPlcfbtePapx
);
6511 Set_UInt32( pData
, m_fcPlcfsea
);
6512 Set_UInt32( pData
, m_lcbPlcfsea
);
6513 Set_UInt32( pData
, m_fcSttbfffn
);
6514 Set_UInt32( pData
, m_lcbSttbfffn
);
6515 Set_UInt32( pData
, m_fcPlcffldMom
);
6516 Set_UInt32( pData
, m_lcbPlcffldMom
);
6517 Set_UInt32( pData
, m_fcPlcffldHdr
);
6518 Set_UInt32( pData
, m_lcbPlcffldHdr
);
6519 Set_UInt32( pData
, m_fcPlcffldFootnote
);
6520 Set_UInt32( pData
, m_lcbPlcffldFootnote
);
6521 Set_UInt32( pData
, m_fcPlcffldAtn
);
6522 Set_UInt32( pData
, m_lcbPlcffldAtn
);
6523 Set_UInt32( pData
, m_fcPlcffldMcr
);
6524 Set_UInt32( pData
, m_lcbPlcffldMcr
);
6525 Set_UInt32( pData
, m_fcSttbfbkmk
);
6526 Set_UInt32( pData
, m_lcbSttbfbkmk
);
6527 Set_UInt32( pData
, m_fcPlcfbkf
);
6528 Set_UInt32( pData
, m_lcbPlcfbkf
);
6529 Set_UInt32( pData
, m_fcPlcfbkl
);
6530 Set_UInt32( pData
, m_lcbPlcfbkl
);
6531 Set_UInt32( pData
, m_fcCmds
);
6532 Set_UInt32( pData
, m_lcbCmds
);
6533 Set_UInt32( pData
, m_fcPlcfmcr
);
6534 Set_UInt32( pData
, m_lcbPlcfmcr
);
6535 Set_UInt32( pData
, m_fcSttbfmcr
);
6536 Set_UInt32( pData
, m_lcbSttbfmcr
);
6537 Set_UInt32( pData
, m_fcPrDrvr
);
6538 Set_UInt32( pData
, m_lcbPrDrvr
);
6539 Set_UInt32( pData
, m_fcPrEnvPort
);
6540 Set_UInt32( pData
, m_lcbPrEnvPort
);
6541 Set_UInt32( pData
, m_fcPrEnvLand
);
6542 Set_UInt32( pData
, m_lcbPrEnvLand
);
6543 Set_UInt32( pData
, m_fcWss
);
6544 Set_UInt32( pData
, m_lcbWss
);
6545 Set_UInt32( pData
, m_fcDop
);
6546 Set_UInt32( pData
, m_lcbDop
);
6547 Set_UInt32( pData
, m_fcSttbfAssoc
);
6548 Set_UInt32( pData
, m_lcbSttbfAssoc
);
6549 Set_UInt32( pData
, m_fcClx
);
6550 Set_UInt32( pData
, m_lcbClx
);
6551 Set_UInt32( pData
, m_fcPlcfpgdFootnote
);
6552 Set_UInt32( pData
, m_lcbPlcfpgdFootnote
);
6553 Set_UInt32( pData
, m_fcAutosaveSource
);
6554 Set_UInt32( pData
, m_lcbAutosaveSource
);
6555 Set_UInt32( pData
, m_fcGrpStAtnOwners
);
6556 Set_UInt32( pData
, m_lcbGrpStAtnOwners
);
6557 Set_UInt32( pData
, m_fcSttbfAtnbkmk
);
6558 Set_UInt32( pData
, m_lcbSttbfAtnbkmk
);
6560 // only skip one more short at Ver67
6563 pData
+= 1*sizeof( sal_Int16
);
6564 Set_UInt16( pData
, o3tl::narrowing
<sal_uInt16
>(m_pnChpFirst
) );
6565 Set_UInt16( pData
, o3tl::narrowing
<sal_uInt16
>(m_pnPapFirst
) );
6566 Set_UInt16( pData
, o3tl::narrowing
<sal_uInt16
>(m_cpnBteChp
) );
6567 Set_UInt16( pData
, o3tl::narrowing
<sal_uInt16
>(m_cpnBtePap
) );
6570 Set_UInt32( pData
, m_fcPlcfdoaMom
); // only at Ver67, in Ver8 unused
6571 Set_UInt32( pData
, m_lcbPlcfdoaMom
); // only at Ver67, in Ver8 unused
6572 Set_UInt32( pData
, m_fcPlcfdoaHdr
); // only at Ver67, in Ver8 unused
6573 Set_UInt32( pData
, m_lcbPlcfdoaHdr
); // only at Ver67, in Ver8 unused
6575 Set_UInt32( pData
, m_fcPlcfspaMom
); // in Ver67 empty reserve
6576 Set_UInt32( pData
, m_lcbPlcfspaMom
); // in Ver67 empty reserve
6577 Set_UInt32( pData
, m_fcPlcfspaHdr
); // in Ver67 empty reserve
6578 Set_UInt32( pData
, m_lcbPlcfspaHdr
); // in Ver67 empty reserve
6580 Set_UInt32( pData
, m_fcPlcfAtnbkf
);
6581 Set_UInt32( pData
, m_lcbPlcfAtnbkf
);
6582 Set_UInt32( pData
, m_fcPlcfAtnbkl
);
6583 Set_UInt32( pData
, m_lcbPlcfAtnbkl
);
6584 Set_UInt32( pData
, m_fcPms
);
6585 Set_UInt32( pData
, m_lcbPMS
);
6586 Set_UInt32( pData
, m_fcFormFieldSttbf
);
6587 Set_UInt32( pData
, m_lcbFormFieldSttbf
);
6588 Set_UInt32( pData
, m_fcPlcfendRef
);
6589 Set_UInt32( pData
, m_lcbPlcfendRef
);
6590 Set_UInt32( pData
, m_fcPlcfendText
);
6591 Set_UInt32( pData
, m_lcbPlcfendText
);
6592 Set_UInt32( pData
, m_fcPlcffldEdn
);
6593 Set_UInt32( pData
, m_lcbPlcffldEdn
);
6594 Set_UInt32( pData
, m_fcPlcfpgdEdn
);
6595 Set_UInt32( pData
, m_lcbPlcfpgdEdn
);
6596 Set_UInt32( pData
, m_fcDggInfo
); // in Ver67 empty reserve
6597 Set_UInt32( pData
, m_lcbDggInfo
); // in Ver67 empty reserve
6598 Set_UInt32( pData
, m_fcSttbfRMark
);
6599 Set_UInt32( pData
, m_lcbSttbfRMark
);
6600 Set_UInt32( pData
, m_fcSttbfCaption
);
6601 Set_UInt32( pData
, m_lcbSttbfCaption
);
6602 Set_UInt32( pData
, m_fcSttbAutoCaption
);
6603 Set_UInt32( pData
, m_lcbSttbAutoCaption
);
6604 Set_UInt32( pData
, m_fcPlcfwkb
);
6605 Set_UInt32( pData
, m_lcbPlcfwkb
);
6606 Set_UInt32( pData
, m_fcPlcfspl
); // in Ver67 empty reserve
6607 Set_UInt32( pData
, m_lcbPlcfspl
); // in Ver67 empty reserve
6608 Set_UInt32( pData
, m_fcPlcftxbxText
);
6609 Set_UInt32( pData
, m_lcbPlcftxbxText
);
6610 Set_UInt32( pData
, m_fcPlcffldTxbx
);
6611 Set_UInt32( pData
, m_lcbPlcffldTxbx
);
6612 Set_UInt32( pData
, m_fcPlcfHdrtxbxText
);
6613 Set_UInt32( pData
, m_lcbPlcfHdrtxbxText
);
6614 Set_UInt32( pData
, m_fcPlcffldHdrTxbx
);
6615 Set_UInt32( pData
, m_lcbPlcffldHdrTxbx
);
6619 pData
+= 0x2da - 0x27a; // Pos + Offset (fcPlcfLst - fcStwUser)
6620 Set_UInt32( pData
, m_fcSttbFnm
);
6621 Set_UInt32( pData
, m_lcbSttbFnm
);
6622 Set_UInt32( pData
, m_fcPlcfLst
);
6623 Set_UInt32( pData
, m_lcbPlcfLst
);
6624 Set_UInt32( pData
, m_fcPlfLfo
);
6625 Set_UInt32( pData
, m_lcbPlfLfo
);
6626 Set_UInt32( pData
, m_fcPlcftxbxBkd
);
6627 Set_UInt32( pData
, m_lcbPlcftxbxBkd
);
6628 Set_UInt32( pData
, m_fcPlcfHdrtxbxBkd
);
6629 Set_UInt32( pData
, m_lcbPlcfHdrtxbxBkd
);
6631 pData
+= 0x372 - 0x302; // Pos + Offset (fcSttbListNames - fcDocUndo)
6632 Set_UInt32( pData
, m_fcSttbListNames
);
6633 Set_UInt32( pData
, m_lcbSttbListNames
);
6635 pData
+= 0x382 - 0x37A;
6636 Set_UInt32( pData
, m_fcPlcfTch
);
6637 Set_UInt32( pData
, m_lcbPlcfTch
);
6639 pData
+= 0x3FA - 0x38A;
6640 Set_UInt16( pData
, sal_uInt16(0x0002));
6641 Set_UInt16( pData
, sal_uInt16(0x00D9));
6643 pData
+= 0x41A - 0x3FE;
6644 Set_UInt32( pData
, m_fcAtrdExtra
);
6645 Set_UInt32( pData
, m_lcbAtrdExtra
);
6647 pData
+= 0x42a - 0x422;
6648 Set_UInt32(pData
, m_fcSttbfBkmkFactoid
);
6649 Set_UInt32(pData
, m_lcbSttbfBkmkFactoid
);
6650 Set_UInt32(pData
, m_fcPlcfBkfFactoid
);
6651 Set_UInt32(pData
, m_lcbPlcfBkfFactoid
);
6653 pData
+= 0x442 - 0x43A;
6654 Set_UInt32(pData
, m_fcPlcfBklFactoid
);
6655 Set_UInt32(pData
, m_lcbPlcfBklFactoid
);
6656 Set_UInt32(pData
, m_fcFactoidData
);
6657 Set_UInt32(pData
, m_lcbFactoidData
);
6659 pData
+= 0x4BA - 0x452;
6660 Set_UInt32(pData
, m_fcPlcffactoid
);
6661 Set_UInt32(pData
, m_lcbPlcffactoid
);
6663 pData
+= 0x4DA - 0x4c2;
6664 Set_UInt32( pData
, m_fcHplxsdr
);
6665 Set_UInt32( pData
, 0);
6668 rStrm
.WriteBytes(pDataPtr
.get(), m_fcMin
- nUnencryptedHdr
);
6671 rtl_TextEncoding
WW8Fib::GetFIBCharset(sal_uInt16 chs
, LanguageType nLidLocale
)
6673 OSL_ENSURE(chs
<= 0x100, "overflowed winword charset set");
6675 return RTL_TEXTENCODING_APPLE_ROMAN
;
6676 if (chs
== 0 && static_cast<sal_uInt16
>(nLidLocale
) >= 999)
6680 language stamp -- localized version In pre-WinWord 2.0 files this
6681 value was the nLocale. If value is < 999, then it is the nLocale,
6682 otherwise it is the lid.
6684 css::lang::Locale
aLocale(LanguageTag::convertToLocale(nLidLocale
));
6685 return msfilter::util::getBestTextEncodingFromLocale(aLocale
);
6687 return rtl_getTextEncodingFromWindowsCharset(static_cast<sal_uInt8
>(chs
));
6690 MSOFactoidType::MSOFactoidType()
6695 namespace MSOPBString
6697 static OUString
Read(SvStream
& rStream
)
6702 rStream
.ReadUInt16(nBuf
);
6703 sal_uInt16 nCch
= nBuf
& 0x7fff; // Bits 1..15.
6704 bool bAnsiString
= (nBuf
& (1 << 15)) >> 15; // 16th bit.
6706 aRet
= OStringToOUString(read_uInt8s_ToOString(rStream
, nCch
), RTL_TEXTENCODING_ASCII_US
);
6708 aRet
= read_uInt16s_ToOUString(rStream
, nCch
);
6713 static void Write(std::u16string_view aString
, SvStream
& rStream
)
6715 sal_uInt16 nBuf
= 0;
6716 nBuf
|= sal_Int32(aString
.size()); // cch, 0..14th bits.
6717 nBuf
|= 0x8000; // fAnsiString, 15th bit.
6718 rStream
.WriteUInt16(nBuf
);
6719 SwWW8Writer::WriteString8(rStream
, aString
, false, RTL_TEXTENCODING_ASCII_US
);
6723 void MSOFactoidType::Read(SvStream
& rStream
)
6725 sal_uInt32
cbFactoid(0);
6726 rStream
.ReadUInt32(cbFactoid
);
6727 rStream
.ReadUInt32(m_nId
);
6728 m_aUri
= MSOPBString::Read(rStream
);
6729 m_aTag
= MSOPBString::Read(rStream
);
6730 MSOPBString::Read(rStream
); // rgbDownloadURL
6733 void MSOFactoidType::Write(WW8Export
& rExport
)
6735 SvStream
& rStream
= *rExport
.m_pTableStrm
;
6737 SvMemoryStream aStream
;
6738 aStream
.WriteUInt32(m_nId
); // id
6739 MSOPBString::Write(m_aUri
, aStream
);
6740 MSOPBString::Write(m_aTag
, aStream
);
6741 MSOPBString::Write(u
"", aStream
); // rgbDownloadURL
6742 rStream
.WriteUInt32(aStream
.Tell());
6744 rStream
.WriteStream(aStream
);
6747 void MSOPropertyBagStore::Read(SvStream
& rStream
)
6749 sal_uInt32
cFactoidType(0);
6750 rStream
.ReadUInt32(cFactoidType
);
6751 for (sal_uInt32 i
= 0; i
< cFactoidType
&& rStream
.good(); ++i
)
6753 MSOFactoidType aFactoidType
;
6754 aFactoidType
.Read(rStream
);
6755 m_aFactoidTypes
.push_back(aFactoidType
);
6757 sal_uInt16
cbHdr(0);
6758 rStream
.ReadUInt16(cbHdr
);
6759 SAL_WARN_IF(cbHdr
!= 0xc, "sw.ww8", "MSOPropertyBagStore::Read: unexpected cbHdr");
6761 rStream
.ReadUInt16(nVer
);
6762 SAL_WARN_IF(nVer
!= 0x0100, "sw.ww8", "MSOPropertyBagStore::Read: unexpected nVer");
6763 rStream
.SeekRel(4); // cfactoid
6764 sal_uInt32
nCste(0);
6765 rStream
.ReadUInt32(nCste
);
6767 //each string has a 2 byte len record at the start
6768 const size_t nMaxPossibleRecords
= rStream
.remainingSize() / sizeof(sal_uInt16
);
6769 if (nCste
> nMaxPossibleRecords
)
6771 SAL_WARN("sw.ww8", nCste
<< " records claimed, but max possible is " << nMaxPossibleRecords
);
6772 nCste
= nMaxPossibleRecords
;
6775 for (sal_uInt32 i
= 0; i
< nCste
; ++i
)
6777 OUString aString
= MSOPBString::Read(rStream
);
6778 m_aStringTable
.push_back(aString
);
6782 void MSOPropertyBagStore::Write(WW8Export
& rExport
)
6784 SvStream
& rStream
= *rExport
.m_pTableStrm
;
6785 rStream
.WriteUInt32(m_aFactoidTypes
.size()); // cFactoidType
6786 for (MSOFactoidType
& rType
: m_aFactoidTypes
)
6787 rType
.Write(rExport
);
6788 rStream
.WriteUInt16(0xc); // cbHdr
6789 rStream
.WriteUInt16(0x0100); // sVer
6790 rStream
.WriteUInt32(0); // cfactoid
6791 rStream
.WriteUInt32(m_aStringTable
.size()); // cste
6792 for (const OUString
& rString
: m_aStringTable
)
6793 MSOPBString::Write(rString
, rStream
);
6796 MSOProperty::MSOProperty()
6802 void MSOProperty::Read(SvStream
& rStream
)
6804 rStream
.ReadUInt32(m_nKey
);
6805 rStream
.ReadUInt32(m_nValue
);
6808 void MSOProperty::Write(SvStream
& rStream
)
6810 rStream
.WriteUInt32(m_nKey
);
6811 rStream
.WriteUInt32(m_nValue
);
6814 MSOPropertyBag::MSOPropertyBag()
6819 bool MSOPropertyBag::Read(SvStream
& rStream
)
6821 rStream
.ReadUInt16(m_nId
);
6822 sal_uInt16
cProp(0);
6823 rStream
.ReadUInt16(cProp
);
6824 if (!rStream
.good())
6826 rStream
.SeekRel(2); // cbUnknown
6827 //each MSOProperty is 8 bytes in size
6828 const size_t nMaxPossibleRecords
= rStream
.remainingSize() / 8;
6829 if (cProp
> nMaxPossibleRecords
)
6831 SAL_WARN("sw.ww8", cProp
<< " records claimed, but max possible is " << nMaxPossibleRecords
);
6832 cProp
= nMaxPossibleRecords
;
6834 for (sal_uInt16 i
= 0; i
< cProp
&& rStream
.good(); ++i
)
6836 MSOProperty aProperty
;
6837 aProperty
.Read(rStream
);
6838 m_aProperties
.push_back(aProperty
);
6840 return rStream
.good();
6843 void MSOPropertyBag::Write(WW8Export
& rExport
)
6845 SvStream
& rStream
= *rExport
.m_pTableStrm
;
6846 rStream
.WriteUInt16(m_nId
);
6847 rStream
.WriteUInt16(m_aProperties
.size());
6848 rStream
.WriteUInt16(0); // cbUnknown
6849 for (MSOProperty
& rProperty
: m_aProperties
)
6850 rProperty
.Write(rStream
);
6853 void WW8SmartTagData::Read(SvStream
& rStream
, WW8_FC fcFactoidData
, sal_uInt32 lcbFactoidData
)
6855 sal_uInt64 nOldPosition
= rStream
.Tell();
6856 if (!checkSeek(rStream
, fcFactoidData
))
6859 m_aPropBagStore
.Read(rStream
);
6860 while (rStream
.good() && rStream
.Tell() < fcFactoidData
+ lcbFactoidData
)
6862 MSOPropertyBag aPropertyBag
;
6863 if (!aPropertyBag
.Read(rStream
))
6865 m_aPropBags
.push_back(aPropertyBag
);
6868 rStream
.Seek(nOldPosition
);
6871 void WW8SmartTagData::Write(WW8Export
& rExport
)
6873 m_aPropBagStore
.Write(rExport
);
6874 for (MSOPropertyBag
& rPropertyBag
: m_aPropBags
)
6875 rPropertyBag
.Write(rExport
);
6878 WW8Style::WW8Style(SvStream
& rStream
, WW8Fib
& rFibPara
)
6879 : m_rFib(rFibPara
), m_rStream(rStream
), m_cstd(0), m_cbSTDBaseInFile(0), m_fStdStylenamesWritten(0)
6880 , m_stiMaxWhenSaved(0), m_istdMaxFixedWhenSaved(0), m_nVerBuiltInNamesWhenSaved(0)
6881 , m_ftcAsci(0), m_ftcFE(0), m_ftcOther(0), m_ftcBi(0)
6883 if (!checkSeek(m_rStream
, m_rFib
.m_fcStshf
))
6886 sal_uInt16 cbStshi
= 0; // 2 bytes size of the following STSHI structure
6887 sal_uInt32 nRemaining
= m_rFib
.m_lcbStshf
;
6888 const sal_uInt32 nMinValidStshi
= 4;
6890 if (m_rFib
.GetFIBVersion() <= ww::eWW2
)
6897 if (m_rFib
.m_nFib
< 67) // old Version ? (need to find this again to fix)
6898 cbStshi
= nMinValidStshi
;
6901 if (nRemaining
< sizeof(cbStshi
))
6903 // reads the length of the structure in the file
6904 m_rStream
.ReadUInt16( cbStshi
);
6909 cbStshi
= std::min(static_cast<sal_uInt32
>(cbStshi
), nRemaining
);
6910 if (cbStshi
< nMinValidStshi
)
6913 const sal_uInt16 nRead
= cbStshi
;
6916 m_rStream
.ReadUInt16( m_cstd
);
6918 m_rStream
.ReadUInt16( m_cbSTDBaseInFile
);
6920 if( 6 > nRead
) break;
6923 m_rStream
.ReadUInt16( a16Bit
);
6924 m_fStdStylenamesWritten
= a16Bit
& 0x0001;
6926 if( 8 > nRead
) break;
6927 m_rStream
.ReadUInt16( m_stiMaxWhenSaved
);
6929 if( 10 > nRead
) break;
6930 m_rStream
.ReadUInt16( m_istdMaxFixedWhenSaved
);
6932 if( 12 > nRead
) break;
6933 m_rStream
.ReadUInt16( m_nVerBuiltInNamesWhenSaved
);
6935 if( 14 > nRead
) break;
6936 m_rStream
.ReadUInt16( m_ftcAsci
);
6938 if( 16 > nRead
) break;
6939 m_rStream
.ReadUInt16( m_ftcFE
);
6941 if ( 18 > nRead
) break;
6942 m_rStream
.ReadUInt16( m_ftcOther
);
6944 m_ftcBi
= m_ftcOther
;
6946 if ( 20 > nRead
) break;
6947 m_rStream
.ReadUInt16( m_ftcBi
);
6949 // p.r.n. ignore the rest
6951 m_rStream
.SeekRel( nRead
-20 );
6953 while( false ); // trick: the block above will be passed through exactly one time
6954 // and that's why we can early exit with "break".
6956 nRemaining
-= cbStshi
;
6958 //There will be stshi.cstd (cbSTD, STD) pairs in the file following the
6959 //STSHI. Note that styles can be empty, i.e. cbSTD == 0
6960 const sal_uInt32 nMinRecordSize
= sizeof(sal_uInt16
);
6961 const sal_uInt16 nMaxPossibleRecords
= nRemaining
/nMinRecordSize
;
6963 OSL_ENSURE(m_cstd
<= nMaxPossibleRecords
,
6964 "allegedly more styles that available data");
6965 m_cstd
= o3tl::sanitizing_min(m_cstd
, nMaxPossibleRecords
);
6968 // Read1STDFixed() reads a style. If the style is completely existent,
6969 // so it has no empty slot, we should allocate memory and a pointer should
6970 // reference to STD (perhaps filled with 0). If the slot is empty,
6971 // it will return a null pointer.
6972 std::unique_ptr
<WW8_STD
> WW8Style::Read1STDFixed(sal_uInt16
& rSkip
)
6974 if (m_rStream
.remainingSize() < 2)
6980 std::unique_ptr
<WW8_STD
> pStd
;
6982 sal_uInt16
cbStd(0);
6983 m_rStream
.ReadUInt16(cbStd
); // read length
6985 const sal_uInt16 nRead
= m_cbSTDBaseInFile
;
6986 if( cbStd
>= m_cbSTDBaseInFile
)
6988 // Fixed part completely available
6990 // read fixed part of STD
6991 pStd
.reset(new WW8_STD
);
6992 memset( pStd
.get(), 0, sizeof( *pStd
) );
6996 if( 2 > nRead
) break;
6998 sal_uInt16 a16Bit
= 0;
6999 m_rStream
.ReadUInt16( a16Bit
);
7000 pStd
->sti
= a16Bit
& 0x0fff ;
7001 pStd
->fScratch
= sal_uInt16(0 != ( a16Bit
& 0x1000 ));
7002 pStd
->fInvalHeight
= sal_uInt16(0 != ( a16Bit
& 0x2000 ));
7003 pStd
->fHasUpe
= sal_uInt16(0 != ( a16Bit
& 0x4000 ));
7004 pStd
->fMassCopy
= sal_uInt16(0 != ( a16Bit
& 0x8000 ));
7006 if( 4 > nRead
) break;
7008 m_rStream
.ReadUInt16( a16Bit
);
7009 pStd
->sgc
= a16Bit
& 0x000f ;
7010 pStd
->istdBase
= ( a16Bit
& 0xfff0 ) >> 4;
7012 if( 6 > nRead
) break;
7014 m_rStream
.ReadUInt16( a16Bit
);
7015 pStd
->cupx
= a16Bit
& 0x000f ;
7016 pStd
->istdNext
= ( a16Bit
& 0xfff0 ) >> 4;
7018 if( 8 > nRead
) break;
7019 m_rStream
.ReadUInt16( pStd
->bchUpe
);
7021 // from Ver8 this two fields should be added:
7022 if(10 > nRead
) break;
7024 m_rStream
.ReadUInt16( a16Bit
);
7025 pStd
->fAutoRedef
= a16Bit
& 0x0001 ;
7026 pStd
->fHidden
= ( a16Bit
& 0x0002 ) >> 1;
7027 // You never know: cautionary skipped
7030 auto nSkip
= std::min
<sal_uInt64
>(nRead
- 10, m_rStream
.remainingSize());
7031 m_rStream
.Seek(m_rStream
.Tell() + nSkip
);
7034 while( false ); // trick: the block above will passed through exactly one time
7035 // and can be left early with a "break"
7037 if (!m_rStream
.good() || !nRead
)
7039 pStd
.reset(); // report error with NULL
7042 rSkip
= cbStd
- m_cbSTDBaseInFile
;
7045 { // Fixed part too short
7047 m_rStream
.SeekRel( cbStd
); // skip leftovers
7053 std::unique_ptr
<WW8_STD
> WW8Style::Read1Style(sal_uInt16
& rSkip
, OUString
* pString
)
7055 // Attention: MacWord-Documents have their Stylenames
7056 // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
7058 std::unique_ptr
<WW8_STD
> pStd
= Read1STDFixed(rSkip
); // read STD
7065 sal_Int32 nLenStringBytes
= 0;
7066 switch( m_rFib
.m_nVersion
)
7070 // read pascal string
7071 *pString
= read_uInt8_BeltAndBracesString(m_rStream
, RTL_TEXTENCODING_MS_1252
);
7072 // leading len and trailing zero --> 2
7073 nLenStringBytes
= pString
->getLength() + 2;
7076 // handle Unicode-String with leading length short and
7078 if (TestBeltAndBraces(m_rStream
))
7080 *pString
= read_uInt16_BeltAndBracesString(m_rStream
);
7081 nLenStringBytes
= (pString
->getLength() + 2) * 2;
7087 This is supposed to be impossible, it's just supposed
7088 to be 16 bit count followed by the string and ending
7089 in a 0 short. But "Lotus SmartSuite Product: Word Pro"
7090 is creating invalid style names in ww7- format. So we
7091 use the belt and braces of the ms strings to see if
7092 they are not corrupt. If they are then we try them as
7095 *pString
= read_uInt8_BeltAndBracesString(m_rStream
,RTL_TEXTENCODING_MS_1252
);
7096 // leading len and trailing zero --> 2
7097 nLenStringBytes
= pString
->getLength() + 2;
7101 OSL_ENSURE(false, "It was forgotten to code nVersion!");
7104 if (nLenStringBytes
> rSkip
)
7106 SAL_WARN("sw.ww8", "WW8Style structure corrupt");
7107 nLenStringBytes
= rSkip
;
7109 rSkip
-= nLenStringBytes
;
7112 pString
->clear(); // can not return a name
7118 const sal_uInt16 maxStrSize
= 65;
7124 char szFfn
[maxStrSize
]; // 0x6 or 0x40 from Ver8 on zero terminated string that
7125 // records name of font.
7126 // Maximal size of szFfn is 65 characters.
7127 // Attention: This array can also be smaller!!!
7128 // Possibly followed by a second sz which records the
7129 // name of an alternate font to use if the first named
7130 // font does not exist on this system.
7135 // #i43762# check font name for illegal characters
7136 static void lcl_checkFontname( OUString
& sString
)
7138 // for efficiency, we'd like to use String methods as far as possible.
7140 // 1) convert all invalid chars to \u0001
7141 // 2) then erase all \u0001 chars (if anywhere found), and
7142 // 3) erase leading/trailing ';', in case a font name was
7143 // completely removed
7145 // convert all invalid chars to \u0001
7146 OUStringBuffer
aBuf(sString
);
7147 const sal_Int32 nLen
= aBuf
.getLength();
7148 bool bFound
= false;
7149 for ( sal_Int32 n
= 0; n
< nLen
; ++n
)
7151 if ( aBuf
[n
] < 0x20 )
7157 sString
= aBuf
.makeStringAndClear();
7159 // if anything was found, remove \u0001 + leading/trailing ';'
7162 sString
= comphelper::string::strip(sString
.replaceAll("\001", ""), ';');
7168 sal_uInt16
calcMaxFonts(sal_uInt8
*p
, sal_Int32 nFFn
)
7170 // Figure out the max number of fonts defined here
7171 sal_uInt16 nMax
= 0;
7172 sal_Int32 nRemaining
= nFFn
;
7175 //p[0] is cbFfnM1, the alleged total length of FFN - 1.
7176 //i.e. length after cbFfnM1
7177 const sal_uInt16 cbFfnM1
= *p
++;
7180 if (cbFfnM1
> nRemaining
)
7184 nRemaining
-= cbFfnM1
;
7190 template<typename T
> bool readU8(
7191 sal_uInt8
const * p
, std::size_t offset
, sal_uInt8
const * pEnd
,
7195 assert(value
!= nullptr);
7196 if (offset
>= o3tl::make_unsigned(pEnd
- p
)) {
7204 sal_uInt8
const * p
, std::size_t offset
, sal_uInt8
const * pEnd
,
7208 assert(value
!= nullptr);
7209 if (offset
> o3tl::make_unsigned(pEnd
- p
)
7210 || static_cast<std::size_t>(pEnd
- p
) - offset
< 2)
7214 *value
= unsigned(p
[offset
]) + (unsigned(p
[offset
+ 1]) << 8);
7218 sal_Int32
getStringLengthWithMax(
7219 sal_uInt8
const * p
, std::size_t offset
, sal_uInt8
const * pEnd
, std::size_t maxchars
)
7222 assert(pEnd
- p
<= SAL_MAX_INT32
);
7223 if (offset
>= o3tl::make_unsigned(pEnd
- p
)) {
7226 std::size_t nbytes
= static_cast<std::size_t>(pEnd
- p
) - offset
;
7227 std::size_t nsearch
= std::min(nbytes
, maxchars
+ 1);
7228 void const * p2
= std::memchr(p
+ offset
, 0, nsearch
);
7229 if (p2
== nullptr) {
7232 return static_cast<sal_uInt8
const *>(p2
) - (p
+ offset
);
7236 WW8Fonts::WW8Fonts( SvStream
& rSt
, WW8Fib
const & rFib
)
7238 // Attention: MacWord-Documents have their Fontnames
7239 // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
7240 if( rFib
.m_lcbSttbfffn
<= 2 )
7242 OSL_ENSURE( false, "font table is broken! (rFib.lcbSttbfffn < 2)" );
7246 if (!checkSeek(rSt
, rFib
.m_fcSttbfffn
))
7249 sal_Int32 nFFn
= rFib
.m_lcbSttbfffn
- 2;
7251 const sal_uInt64 nMaxPossible
= rSt
.remainingSize();
7252 if (o3tl::make_unsigned(nFFn
) > nMaxPossible
)
7254 SAL_WARN("sw.ww8", "FFN structure longer than available data");
7255 nFFn
= nMaxPossible
;
7258 // allocate Font Array
7259 std::vector
<sal_uInt8
> aA(nFFn
);
7260 memset(aA
.data(), 0, nFFn
);
7262 ww::WordVersion eVersion
= rFib
.GetFIBVersion();
7265 if( eVersion
>= ww::eWW8
)
7267 // bVer8: read the count of strings in nMax
7268 rSt
.ReadUInt16(nMax
);
7271 // Ver8: skip undefined uint16
7272 // Ver67: skip the herein stored total byte of structure
7273 // - we already got that information in rFib.lcbSttbfffn
7276 // read all font information
7277 nFFn
= rSt
.ReadBytes(aA
.data(), nFFn
);
7278 sal_uInt8
* const pEnd
= aA
.data() + nFFn
;
7279 const sal_uInt16 nCalcMax
= calcMaxFonts(aA
.data(), nFFn
);
7281 if (eVersion
< ww::eWW8
)
7285 //newer versions include supportive count of fonts, so take min of that
7287 nMax
= std::min(nMax
, nCalcMax
);
7292 // allocate Index Array
7293 m_aFontA
.resize(nMax
);
7294 WW8_FFN
* p
= m_aFontA
.data();
7296 if( eVersion
<= ww::eWW2
)
7298 sal_uInt8
const * pVer2
= aA
.data();
7300 for(; i
<nMax
; ++i
, ++p
)
7303 pVer2
, offsetof(WW8_FFN_BASE
, cbFfnM1
), pEnd
,
7304 &p
->aFFNBase
.cbFfnM1
))
7309 p
->aFFNBase
.prg
= 0;
7310 p
->aFFNBase
.fTrueType
= 0;
7313 if (!(readU8(pVer2
, 1, pEnd
, &p
->aFFNBase
.wWeight
)
7314 && readU8(pVer2
, 2, pEnd
, &p
->aFFNBase
.chs
)))
7319 #i8726# 7- seems to encode the name in the same encoding as
7320 the font, e.g load the doc in 97 and save to see the unicode
7321 ver of the asian fontnames in that example to confirm.
7323 rtl_TextEncoding eEnc
= WW8Fib::GetFIBCharset(p
->aFFNBase
.chs
, rFib
.m_lid
);
7324 if ((eEnc
== RTL_TEXTENCODING_SYMBOL
) || (eEnc
== RTL_TEXTENCODING_DONTKNOW
))
7325 eEnc
= RTL_TEXTENCODING_MS_1252
;
7327 const size_t nStringOffset
= 1 + 2;
7328 sal_Int32 n
= getStringLengthWithMax(pVer2
, nStringOffset
, pEnd
, maxStrSize
);
7332 p
->sFontname
= OUString(
7333 reinterpret_cast<char const *>(pVer2
+ nStringOffset
), n
, eEnc
);
7334 pVer2
= pVer2
+ p
->aFFNBase
.cbFfnM1
+ 1;
7338 else if( eVersion
< ww::eWW8
)
7340 sal_uInt8
const * pVer6
= aA
.data();
7342 for(; i
<nMax
; ++i
, ++p
)
7345 pVer6
, offsetof(WW8_FFN_BASE
, cbFfnM1
), pEnd
,
7346 &p
->aFFNBase
.cbFfnM1
))
7351 if (!readU8(pVer6
, 1, pEnd
, &c2
)) {
7355 p
->aFFNBase
.prg
= c2
& 0x02;
7356 p
->aFFNBase
.fTrueType
= (c2
& 0x04) >> 2;
7357 // skip a reserve bit
7358 p
->aFFNBase
.ff
= (c2
& 0x70) >> 4;
7361 pVer6
, offsetof(WW8_FFN_BASE
, wWeight
), pEnd
,
7362 &p
->aFFNBase
.wWeight
)
7364 pVer6
, offsetof(WW8_FFN_BASE
, chs
), pEnd
, &p
->aFFNBase
.chs
)
7366 pVer6
, offsetof(WW8_FFN_BASE
, ibszAlt
), pEnd
,
7367 &p
->aFFNBase
.ibszAlt
)))
7372 #i8726# 7- seems to encode the name in the same encoding as
7373 the font, e.g load the doc in 97 and save to see the unicode
7374 ver of the asian fontnames in that example to confirm.
7376 rtl_TextEncoding eEnc
= WW8Fib::GetFIBCharset(p
->aFFNBase
.chs
, rFib
.m_lid
);
7377 if ((eEnc
== RTL_TEXTENCODING_SYMBOL
) || (eEnc
== RTL_TEXTENCODING_DONTKNOW
))
7378 eEnc
= RTL_TEXTENCODING_MS_1252
;
7379 const size_t nStringOffset
= offsetof(WW8_FFN_Ver6
, szFfn
);
7380 sal_Int32 n
= getStringLengthWithMax(pVer6
, nStringOffset
, pEnd
, maxStrSize
);
7384 p
->sFontname
= OUString(reinterpret_cast<char const*>(pVer6
+ nStringOffset
), n
, eEnc
);
7385 if (p
->aFFNBase
.ibszAlt
&& p
->aFFNBase
.ibszAlt
< maxStrSize
) //don't start after end of string
7387 const size_t nAltStringOffset
= offsetof(WW8_FFN_Ver6
, szFfn
) + p
->aFFNBase
.ibszAlt
;
7388 n
= getStringLengthWithMax(pVer6
, nAltStringOffset
, pEnd
, maxStrSize
);
7392 p
->sFontname
+= ";" + OUString(reinterpret_cast<char const*>(pVer6
+ nAltStringOffset
),
7397 //#i18369# if it's a symbol font set Symbol as fallback
7399 RTL_TEXTENCODING_SYMBOL
== WW8Fib::GetFIBCharset(p
->aFFNBase
.chs
, rFib
.m_lid
)
7400 && p
->sFontname
!="Symbol"
7403 p
->sFontname
+= ";Symbol";
7406 pVer6
= pVer6
+ p
->aFFNBase
.cbFfnM1
+ 1;
7412 //count of bytes in minimum FontFamilyInformation payload
7413 const sal_uInt8 cbMinFFNPayload
= 41;
7414 sal_uInt16 nValidFonts
= 0;
7415 sal_Int32 nRemainingFFn
= nFFn
;
7416 sal_uInt8
* pRaw
= aA
.data();
7417 for (sal_uInt16 i
=0; i
< nMax
&& nRemainingFFn
; ++i
, ++p
)
7419 //pRaw[0] is cbFfnM1, the alleged total length of FFN - 1
7420 //i.e. length after cbFfnM1
7421 sal_uInt8 cbFfnM1
= *pRaw
++;
7424 if (cbFfnM1
> nRemainingFFn
)
7427 if (cbFfnM1
< cbMinFFNPayload
)
7430 p
->aFFNBase
.cbFfnM1
= cbFfnM1
;
7432 sal_uInt8
*pVer8
= pRaw
;
7434 sal_uInt8 c2
= *pVer8
++;
7437 p
->aFFNBase
.prg
= c2
& 0x02;
7438 p
->aFFNBase
.fTrueType
= (c2
& 0x04) >> 2;
7439 // skip a reserve bit
7440 p
->aFFNBase
.ff
= (c2
& 0x70) >> 4;
7442 p
->aFFNBase
.wWeight
= SVBT16ToUInt16(*reinterpret_cast<SVBT16
*>(pVer8
));
7446 p
->aFFNBase
.chs
= *pVer8
++;
7449 p
->aFFNBase
.ibszAlt
= *pVer8
++;
7452 pVer8
+= 10; //PANOSE
7454 pVer8
+= 24; //FONTSIGNATURE
7457 assert(cbFfnM1
>= 2);
7459 sal_uInt8 nMaxNullTerminatedPossible
= cbFfnM1
/2 - 1;
7460 sal_Unicode
*pPrimary
= reinterpret_cast<sal_Unicode
*>(pVer8
);
7461 pPrimary
[nMaxNullTerminatedPossible
] = 0;
7462 #ifdef OSL_BIGENDIAN
7463 swapEndian(pPrimary
);
7465 p
->sFontname
= pPrimary
;
7466 if (p
->aFFNBase
.ibszAlt
&& p
->aFFNBase
.ibszAlt
< nMaxNullTerminatedPossible
)
7468 sal_Unicode
*pSecondary
= pPrimary
+ p
->aFFNBase
.ibszAlt
;
7469 #ifdef OSL_BIGENDIAN
7470 swapEndian(pSecondary
);
7472 p
->sFontname
+= OUString::Concat(";") + pSecondary
;
7475 // #i43762# check font name for illegal characters
7476 lcl_checkFontname( p
->sFontname
);
7478 // set pointer one font back to original array
7479 pRaw
+= p
->aFFNBase
.cbFfnM1
;
7480 nRemainingFFn
-= p
->aFFNBase
.cbFfnM1
;
7483 OSL_ENSURE(nMax
== nValidFonts
, "Font count differs with availability");
7484 nMax
= std::min(nMax
, nValidFonts
);
7487 m_aFontA
.resize(nMax
);
7488 m_aFontA
.shrink_to_fit();
7491 const WW8_FFN
* WW8Fonts::GetFont( sal_uInt16 nNum
) const
7493 if (nNum
>= m_aFontA
.size())
7496 return &m_aFontA
[nNum
];
7499 // Search after a header/footer for an index in the ww list from header/footer
7501 // specials for WinWord6 and -7:
7503 // 1) At the start of reading we must build WWPLCF_HdFt with Fib and Dop
7504 // 2) The main text must be read sequentially over all sections
7505 // 3) For every header/footer in the main text, we must call UpdateIndex()
7506 // exactly once with the parameter from the attribute.
7507 // (per section can be maximally one). This call must take place *after*
7508 // the last call from GetTextPos().
7509 // 4) GetTextPos() can be called with exactly one flag
7510 // out of WW8_{FOOTER,HEADER}_{ODD,EVEN,FIRST} (Do not change!)
7511 // -> maybe we can get a right result then
7513 WW8PLCF_HdFt::WW8PLCF_HdFt( SvStream
* pSt
, WW8Fib
const & rFib
, WW8Dop
const & rDop
)
7514 : m_aPLCF(*pSt
, rFib
.m_fcPlcfhdd
, rFib
.m_lcbPlcfhdd
, 0)
7519 This dop.grpfIhdt has a bit set for each special
7520 footnote *and endnote!!* separator,continuation separator, and
7521 continuation notice entry, the documentation does not mention the
7522 endnote separators, the documentation also gets the index numbers
7523 backwards when specifying which bits to test. The bottom six bits
7524 of this value must be tested and skipped over. Each section's
7525 grpfIhdt is then tested for the existence of the appropriate headers
7526 and footers, at the end of each section the nIdxOffset must be updated
7527 to point to the beginning of the next section's group of headers and
7528 footers in this PLCF, UpdateIndex does that task.
7530 for( sal_uInt8 nI
= 0x1; nI
<= 0x20; nI
<<= 1 )
7531 if( nI
& rDop
.grpfIhdt
) // bit set?
7535 bool WW8PLCF_HdFt::GetTextPos(sal_uInt8 grpfIhdt
, sal_uInt8 nWhich
, WW8_CP
& rStart
,
7538 sal_uInt8 nI
= 0x01;
7539 short nIdx
= m_nIdxOffset
;
7545 nIdx
++; // uninteresting Header / Footer
7546 nI
<<= 1; // text next bit
7548 return false; // not found
7550 // nIdx is HdFt-Index
7554 m_aPLCF
.SetIdx( nIdx
); // Lookup suitable CP
7555 m_aPLCF
.Get( rStart
, nEnd
, pData
);
7558 SAL_WARN("sw.ww8", "End " << nEnd
<< " before Start " << rStart
);
7562 bool bFail
= o3tl::checked_sub(nEnd
, rStart
, rLen
);
7565 SAL_WARN("sw.ww8", "broken offset, ignoring");
7574 void WW8PLCF_HdFt::GetTextPosExact(short nIdx
, WW8_CP
& rStart
, WW8_CP
& rLen
)
7579 m_aPLCF
.SetIdx( nIdx
); // Lookup suitable CP
7580 m_aPLCF
.Get( rStart
, nEnd
, pData
);
7583 SAL_WARN("sw.ww8", "End " << nEnd
<< " before Start " << rStart
);
7587 if (o3tl::checked_sub(nEnd
, rStart
, rLen
))
7589 SAL_WARN("sw.ww8", "GetTextPosExact overflow");
7594 void WW8PLCF_HdFt::UpdateIndex( sal_uInt8 grpfIhdt
)
7596 // Caution: Description is not correct
7597 for( sal_uInt8 nI
= 0x01; nI
<= 0x20; nI
<<= 1 )
7602 WW8Dop::WW8Dop(SvStream
& rSt
, sal_Int16 nFib
, sal_Int32 nPos
, sal_uInt32 nSize
):
7603 fFacingPages(false), fWidowControl(false), fPMHMainDoc(false), grfSuppression(0), fpc(0),
7604 grpfIhdt(0), rncFootnote(0), nFootnote(0), fOutlineDirtySave(false), fOnlyMacPics(false),
7605 fOnlyWinPics(false), fLabelDoc(false), fHyphCapitals(false), fAutoHyphen(false),
7606 fFormNoFields(false), fLinkStyles(false), fRevMarking(false), fBackup(false),
7607 fExactCWords(false), fPagHidden(false), fPagResults(false), fLockAtn(false),
7608 fMirrorMargins(false), fReadOnlyRecommended(false), fDfltTrueType(false),
7609 fPagSuppressTopSpacing(false), fProtEnabled(false), fDispFormFieldSel(false), fRMView(false),
7610 fRMPrint(false), fWriteReservation(false), fLockRev(false), fEmbedFonts(false),
7611 copts_fNoTabForInd(false), copts_fNoSpaceRaiseLower(false), copts_fSuppressSpbfAfterPgBrk(false),
7612 copts_fWrapTrailSpaces(false), copts_fMapPrintTextColor(false), copts_fNoColumnBalance(false),
7613 copts_fConvMailMergeEsc(false), copts_fSuppressTopSpacing(false),
7614 copts_fOrigWordTableRules(false), copts_fTransparentMetafiles(false),
7615 copts_fShowBreaksInFrames(false), copts_fSwapBordersFacingPgs(false), copts_fExpShRtn(false),
7616 rncEdn(0), nEdn(0), epc(0), fPrintFormData(false), fSaveFormData(false), fShadeFormData(false),
7617 fWCFootnoteEdn(false), wvkSaved(0), wScaleSaved(0), zkSaved(0), fRotateFontW6(false),
7618 iGutterPos(false), fNoTabForInd(false), fNoSpaceRaiseLower(false),
7619 fSuppressSpbfAfterPageBreak(false), fWrapTrailSpaces(false), fMapPrintTextColor(false),
7620 fNoColumnBalance(false), fConvMailMergeEsc(false), fSuppressTopSpacing(false),
7621 fOrigWordTableRules(false), fTransparentMetafiles(false), fShowBreaksInFrames(false),
7622 fSwapBordersFacingPgs(false), fCompatibilityOptions_Unknown1_13(false), fExpShRtn(false),
7623 fCompatibilityOptions_Unknown1_15(false), fCompatibilityOptions_Unknown1_16(false),
7624 fSuppressTopSpacingMac5(false), fTruncDxaExpand(false), fPrintBodyBeforeHdr(false),
7625 fNoLeading(false), fCompatibilityOptions_Unknown1_21(false), fMWSmallCaps(false),
7626 fCompatibilityOptions_Unknown1_23(false), fCompatibilityOptions_Unknown1_24(false),
7627 fCompatibilityOptions_Unknown1_25(false), fCompatibilityOptions_Unknown1_26(false),
7628 fCompatibilityOptions_Unknown1_27(false), fCompatibilityOptions_Unknown1_28(false),
7629 fCompatibilityOptions_Unknown1_29(false), fCompatibilityOptions_Unknown1_30(false),
7630 fCompatibilityOptions_Unknown1_31(false), fUsePrinterMetrics(false), lvl(0), fHtmlDoc(false),
7631 fSnapBorder(false), fIncludeHeader(false), fIncludeFooter(false), fForcePageSizePag(false),
7632 fMinFontSizePag(false), fHaveVersions(false), fAutoVersion(false),
7633 fCompatibilityOptions_Unknown2_1(false), fCompatibilityOptions_Unknown2_2(false),
7634 fDontUseHTMLAutoSpacing(false), fCompatibilityOptions_Unknown2_4(false),
7635 fCompatibilityOptions_Unknown2_5(false), fCompatibilityOptions_Unknown2_6(false),
7636 fCompatibilityOptions_Unknown2_7(false), fCompatibilityOptions_Unknown2_8(false),
7637 fCompatibilityOptions_Unknown2_9(false), fCompatibilityOptions_Unknown2_10(false),
7638 fDontBreakWrappedTables(false), fCompatibilityOptions_Unknown2_12(false),
7639 fCompatibilityOptions_Unknown2_13(false), fCompatibilityOptions_Unknown2_14(false),
7640 fCompatibilityOptions_Unknown2_15(false), fCompatibilityOptions_Unknown2_16(false),
7641 fCompatibilityOptions_Unknown2_17(false), fCompatibilityOptions_Unknown2_18(false),
7642 fCompatibilityOptions_Unknown2_19(false), fCompatibilityOptions_Unknown2_20(false),
7643 fCompatibilityOptions_Unknown2_21(false), fCompatibilityOptions_Unknown2_22(false),
7644 fCompatibilityOptions_Unknown2_23(false), fCompatibilityOptions_Unknown2_24(false),
7645 fCompatibilityOptions_Unknown2_25(false), fCompatibilityOptions_Unknown2_26(false),
7646 fCompatibilityOptions_Unknown2_27(false), fCompatibilityOptions_Unknown2_28(false),
7647 fCompatibilityOptions_Unknown2_29(false), fCompatibilityOptions_Unknown2_30(false),
7648 fCompatibilityOptions_Unknown2_31(false), fCompatibilityOptions_Unknown2_32(false),
7649 fUnknown3(0), fUseBackGroundInAllmodes(false), fDoNotEmbedSystemFont(false), fWordCompat(false),
7650 fLiveRecover(false), fEmbedFactoids(false), fFactoidXML(false), fFactoidAllDone(false),
7651 fFolioPrint(false), fReverseFolio(false), iTextLineEnding(0), fHideFcc(false),
7652 fAcetateShowMarkup(false), fAcetateShowAtn(false), fAcetateShowInsDel(false),
7653 fAcetateShowProps(false)
7654 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
7655 // above bit-field member initializations can be moved to the class definition
7657 fDontUseHTMLAutoSpacing
= true; //default
7658 fAcetateShowAtn
= true; //default
7659 const sal_uInt32 nMaxDopSize
= 0x268;
7660 std::unique_ptr
<sal_uInt8
[]> pDataPtr( new sal_uInt8
[ nMaxDopSize
] );
7661 sal_uInt8
* pData
= pDataPtr
.get();
7663 sal_uInt32 nRead
= std::min(nMaxDopSize
, nSize
);
7664 if (nSize
< 2 || !checkSeek(rSt
, nPos
) || nRead
!= rSt
.ReadBytes(pData
, nRead
))
7665 nDopError
= ERR_SWG_READ_ERROR
; // report error
7668 if (nMaxDopSize
> nRead
)
7669 memset( pData
+ nRead
, 0, nMaxDopSize
- nRead
);
7671 // interpret the data
7676 a16Bit
= Get_UShort( pData
); // 0 0x00
7677 fFacingPages
= 0 != ( a16Bit
& 0x0001 ) ;
7678 fWidowControl
= 0 != ( a16Bit
& 0x0002 ) ;
7679 fPMHMainDoc
= 0 != ( a16Bit
& 0x0004 ) ;
7680 grfSuppression
= ( a16Bit
& 0x0018 ) >> 3;
7681 fpc
= ( a16Bit
& 0x0060 ) >> 5;
7682 grpfIhdt
= ( a16Bit
& 0xff00 ) >> 8;
7684 a16Bit
= Get_UShort( pData
); // 2 0x02
7685 rncFootnote
= a16Bit
& 0x0003 ;
7686 nFootnote
= ( a16Bit
& ~0x0003 ) >> 2 ;
7688 a8Bit
= Get_Byte( pData
); // 4 0x04
7689 fOutlineDirtySave
= 0 != ( a8Bit
& 0x01 );
7691 a8Bit
= Get_Byte( pData
); // 5 0x05
7692 fOnlyMacPics
= 0 != ( a8Bit
& 0x01 );
7693 fOnlyWinPics
= 0 != ( a8Bit
& 0x02 );
7694 fLabelDoc
= 0 != ( a8Bit
& 0x04 );
7695 fHyphCapitals
= 0 != ( a8Bit
& 0x08 );
7696 fAutoHyphen
= 0 != ( a8Bit
& 0x10 );
7697 fFormNoFields
= 0 != ( a8Bit
& 0x20 );
7698 fLinkStyles
= 0 != ( a8Bit
& 0x40 );
7699 fRevMarking
= 0 != ( a8Bit
& 0x80 );
7701 a8Bit
= Get_Byte( pData
); // 6 0x06
7702 fBackup
= 0 != ( a8Bit
& 0x01 );
7703 fExactCWords
= 0 != ( a8Bit
& 0x02 );
7704 fPagHidden
= 0 != ( a8Bit
& 0x04 );
7705 fPagResults
= 0 != ( a8Bit
& 0x08 );
7706 fLockAtn
= 0 != ( a8Bit
& 0x10 );
7707 fMirrorMargins
= 0 != ( a8Bit
& 0x20 );
7708 fReadOnlyRecommended
= 0 != ( a8Bit
& 0x40 );
7709 fDfltTrueType
= 0 != ( a8Bit
& 0x80 );
7711 a8Bit
= Get_Byte( pData
); // 7 0x07
7712 fPagSuppressTopSpacing
= 0 != ( a8Bit
& 0x01 );
7713 fProtEnabled
= 0 != ( a8Bit
& 0x02 );
7714 fDispFormFieldSel
= 0 != ( a8Bit
& 0x04 );
7715 fRMView
= 0 != ( a8Bit
& 0x08 );
7716 fRMPrint
= 0 != ( a8Bit
& 0x10 );
7717 fWriteReservation
= 0 != ( a8Bit
& 0x20 );
7718 fLockRev
= 0 != ( a8Bit
& 0x40 );
7719 fEmbedFonts
= 0 != ( a8Bit
& 0x80 );
7721 a8Bit
= Get_Byte( pData
); // 8 0x08
7722 copts_fNoTabForInd
= 0 != ( a8Bit
& 0x01 );
7723 copts_fNoSpaceRaiseLower
= 0 != ( a8Bit
& 0x02 );
7724 copts_fSuppressSpbfAfterPgBrk
= 0 != ( a8Bit
& 0x04 );
7725 copts_fWrapTrailSpaces
= 0 != ( a8Bit
& 0x08 );
7726 copts_fMapPrintTextColor
= 0 != ( a8Bit
& 0x10 );
7727 copts_fNoColumnBalance
= 0 != ( a8Bit
& 0x20 );
7728 copts_fConvMailMergeEsc
= 0 != ( a8Bit
& 0x40 );
7729 copts_fSuppressTopSpacing
= 0 != ( a8Bit
& 0x80 );
7731 a8Bit
= Get_Byte( pData
); // 9 0x09
7732 copts_fOrigWordTableRules
= 0 != ( a8Bit
& 0x01 );
7733 copts_fTransparentMetafiles
= 0 != ( a8Bit
& 0x02 );
7734 copts_fShowBreaksInFrames
= 0 != ( a8Bit
& 0x04 );
7735 copts_fSwapBordersFacingPgs
= 0 != ( a8Bit
& 0x08 );
7736 copts_fExpShRtn
= 0 != ( a8Bit
& 0x20 ); // #i56856#
7738 dxaTab
= Get_Short( pData
); // 10 0x0a
7739 wSpare
= Get_UShort( pData
); // 12 0x0c
7740 dxaHotZ
= Get_UShort( pData
); // 14 0x0e
7741 cConsecHypLim
= Get_UShort( pData
); // 16 0x10
7742 wSpare2
= Get_UShort( pData
); // 18 0x12
7743 dttmCreated
= Get_Long( pData
); // 20 0x14
7744 dttmRevised
= Get_Long( pData
); // 24 0x18
7745 dttmLastPrint
= Get_Long( pData
); // 28 0x1c
7746 nRevision
= Get_Short( pData
); // 32 0x20
7747 tmEdited
= Get_Long( pData
); // 34 0x22
7748 cWords
= Get_Long( pData
); // 38 0x26
7749 cCh
= Get_Long( pData
); // 42 0x2a
7750 cPg
= Get_Short( pData
); // 46 0x2e
7751 cParas
= Get_Long( pData
); // 48 0x30
7753 a16Bit
= Get_UShort( pData
); // 52 0x34
7754 rncEdn
= a16Bit
& 0x0003 ;
7755 nEdn
= ( a16Bit
& ~0x0003 ) >> 2;
7757 a16Bit
= Get_UShort( pData
); // 54 0x36
7758 epc
= a16Bit
& 0x0003 ;
7759 nfcFootnoteRef
= ( a16Bit
& 0x003c ) >> 2;
7760 nfcEdnRef
= ( a16Bit
& 0x03c0 ) >> 6;
7761 fPrintFormData
= 0 != ( a16Bit
& 0x0400 );
7762 fSaveFormData
= 0 != ( a16Bit
& 0x0800 );
7763 fShadeFormData
= 0 != ( a16Bit
& 0x1000 );
7764 fWCFootnoteEdn
= 0 != ( a16Bit
& 0x8000 );
7766 cLines
= Get_Long( pData
); // 56 0x38
7767 cWordsFootnoteEnd
= Get_Long( pData
); // 60 0x3c
7768 cChFootnoteEdn
= Get_Long( pData
); // 64 0x40
7769 cPgFootnoteEdn
= Get_Short( pData
); // 68 0x44
7770 cParasFootnoteEdn
= Get_Long( pData
); // 70 0x46
7771 cLinesFootnoteEdn
= Get_Long( pData
); // 74 0x4a
7772 lKeyProtDoc
= Get_Long( pData
); // 78 0x4e
7774 a16Bit
= Get_UShort( pData
); // 82 0x52
7775 wvkSaved
= a16Bit
& 0x0007 ;
7776 wScaleSaved
= ( a16Bit
& 0x0ff8 ) >> 3 ;
7777 zkSaved
= ( a16Bit
& 0x3000 ) >> 12;
7778 fRotateFontW6
= ( a16Bit
& 0x4000 ) >> 14;
7779 iGutterPos
= ( a16Bit
& 0x8000 ) >> 15;
7781 if (nFib
>= 103) // Word 6/32bit, 95, 97, 2000, 2002, 2003, 2007
7783 a32Bit
= Get_ULong( pData
); // 84 0x54
7784 SetCompatibilityOptions(a32Bit
);
7787 //#i22436#, for all WW7- documents
7788 if (nFib
<= 104) // Word 95
7789 fUsePrinterMetrics
= true;
7791 if (nFib
> 105) // Word 97, 2000, 2002, 2003, 2007
7793 adt
= Get_Short( pData
); // 88 0x58
7795 doptypography
.ReadFromMem(pData
); // 90 0x5a
7797 memcpy( &dogrid
, pData
, sizeof( WW8_DOGRID
)); // 400 0x190
7798 pData
+= sizeof( WW8_DOGRID
);
7800 a16Bit
= Get_UShort( pData
); // 410 0x19a
7801 // the following 9 bit are uninteresting
7802 fHtmlDoc
= ( a16Bit
& 0x0200 ) >> 9 ;
7803 fSnapBorder
= ( a16Bit
& 0x0800 ) >> 11 ;
7804 fIncludeHeader
= ( a16Bit
& 0x1000 ) >> 12 ;
7805 fIncludeFooter
= ( a16Bit
& 0x2000 ) >> 13 ;
7806 fForcePageSizePag
= ( a16Bit
& 0x4000 ) >> 14 ;
7807 fMinFontSizePag
= ( a16Bit
& 0x8000 ) >> 15 ;
7809 a16Bit
= Get_UShort( pData
); // 412 0x19c
7810 fHaveVersions
= 0 != ( a16Bit
& 0x0001 );
7811 fAutoVersion
= 0 != ( a16Bit
& 0x0002 );
7813 pData
+= 12; // 414 0x19e
7815 cChWS
= Get_Long( pData
); // 426 0x1aa
7816 cChWSFootnoteEdn
= Get_Long( pData
); // 430 0x1ae
7817 grfDocEvents
= Get_Long( pData
); // 434 0x1b2
7819 pData
+= 4+30+8; // 438 0x1b6; 442 0x1ba; 472 0x1d8; 476 0x1dc
7821 cDBC
= Get_Long( pData
); // 480 0x1e0
7822 cDBCFootnoteEdn
= Get_Long( pData
); // 484 0x1e4
7824 pData
+= 1 * sizeof( sal_Int32
); // 488 0x1e8
7826 nfcFootnoteRef
= Get_Short( pData
); // 492 0x1ec
7827 nfcEdnRef
= Get_Short( pData
); // 494 0x1ee
7828 hpsZoomFontPag
= Get_Short( pData
); // 496 0x1f0
7829 dywDispPag
= Get_Short( pData
); // 498 0x1f2
7833 //500 -> 508, Appear to be repeated here in 2000+
7834 pData
+= 8; // 500 0x1f4
7835 a32Bit
= Get_Long( pData
); // 508 0x1fc
7836 SetCompatibilityOptions(a32Bit
);
7837 a32Bit
= Get_Long( pData
); // 512 0x200
7840 SetCompatibilityOptions2(a32Bit
);
7845 a16Bit
= Get_UShort( pData
);
7846 fDoNotEmbedSystemFont
= ( a16Bit
& 0x0001 );
7847 fWordCompat
= ( a16Bit
& 0x0002 ) >> 1;
7848 fLiveRecover
= ( a16Bit
& 0x0004 ) >> 2;
7849 fEmbedFactoids
= ( a16Bit
& 0x0008 ) >> 3;
7850 fFactoidXML
= ( a16Bit
& 0x00010 ) >> 4;
7851 fFactoidAllDone
= ( a16Bit
& 0x0020 ) >> 5;
7852 fFolioPrint
= ( a16Bit
& 0x0040 ) >> 6;
7853 fReverseFolio
= ( a16Bit
& 0x0080 ) >> 7;
7854 iTextLineEnding
= ( a16Bit
& 0x0700 ) >> 8;
7855 fHideFcc
= ( a16Bit
& 0x0800 ) >> 11;
7856 fAcetateShowMarkup
= ( a16Bit
& 0x1000 ) >> 12;
7857 fAcetateShowAtn
= ( a16Bit
& 0x2000 ) >> 13;
7858 fAcetateShowInsDel
= ( a16Bit
& 0x4000 ) >> 14;
7859 fAcetateShowProps
= ( a16Bit
& 0x8000 ) >> 15;
7864 a16Bit
= Get_Short(pData
);
7865 fUseBackGroundInAllmodes
= (a16Bit
& 0x0080) >> 7;
7872 fFacingPages(false), fWidowControl(true), fPMHMainDoc(false), grfSuppression(0), fpc(1),
7873 grpfIhdt(0), rncFootnote(0), nFootnote(1), fOutlineDirtySave(true), fOnlyMacPics(false),
7874 fOnlyWinPics(false), fLabelDoc(false), fHyphCapitals(true), fAutoHyphen(false),
7875 fFormNoFields(false), fLinkStyles(false), fRevMarking(false), fBackup(true),
7876 fExactCWords(false), fPagHidden(true), fPagResults(true), fLockAtn(false),
7877 fMirrorMargins(false), fReadOnlyRecommended(false), fDfltTrueType(true),
7878 fPagSuppressTopSpacing(false), fProtEnabled(false), fDispFormFieldSel(false), fRMView(true),
7879 fRMPrint(true), fWriteReservation(false), fLockRev(false), fEmbedFonts(false),
7880 copts_fNoTabForInd(false), copts_fNoSpaceRaiseLower(false), copts_fSuppressSpbfAfterPgBrk(false),
7881 copts_fWrapTrailSpaces(false), copts_fMapPrintTextColor(false), copts_fNoColumnBalance(false),
7882 copts_fConvMailMergeEsc(false), copts_fSuppressTopSpacing(false),
7883 copts_fOrigWordTableRules(false), copts_fTransparentMetafiles(false),
7884 copts_fShowBreaksInFrames(false), copts_fSwapBordersFacingPgs(false), copts_fExpShRtn(false),
7885 dxaTab(0x2d0), dxaHotZ(0x168), nRevision(1),
7886 rncEdn(0), nEdn(1), epc(3), fPrintFormData(false), fSaveFormData(false), fShadeFormData(true),
7887 fWCFootnoteEdn(false), wvkSaved(2), wScaleSaved(100), zkSaved(0), fRotateFontW6(false),
7888 iGutterPos(false), fNoTabForInd(false), fNoSpaceRaiseLower(false),
7889 fSuppressSpbfAfterPageBreak(false), fWrapTrailSpaces(false), fMapPrintTextColor(false),
7890 fNoColumnBalance(false), fConvMailMergeEsc(false), fSuppressTopSpacing(false),
7891 fOrigWordTableRules(false), fTransparentMetafiles(false), fShowBreaksInFrames(false),
7892 fSwapBordersFacingPgs(false), fCompatibilityOptions_Unknown1_13(false), fExpShRtn(false),
7893 fCompatibilityOptions_Unknown1_15(false), fCompatibilityOptions_Unknown1_16(false),
7894 fSuppressTopSpacingMac5(false), fTruncDxaExpand(false), fPrintBodyBeforeHdr(false),
7895 fNoLeading(true), fCompatibilityOptions_Unknown1_21(false), fMWSmallCaps(false),
7896 fCompatibilityOptions_Unknown1_23(false), fCompatibilityOptions_Unknown1_24(false),
7897 fCompatibilityOptions_Unknown1_25(false), fCompatibilityOptions_Unknown1_26(false),
7898 fCompatibilityOptions_Unknown1_27(false), fCompatibilityOptions_Unknown1_28(false),
7899 fCompatibilityOptions_Unknown1_29(false), fCompatibilityOptions_Unknown1_30(false),
7900 fCompatibilityOptions_Unknown1_31(false), fUsePrinterMetrics(true), lvl(9), fHtmlDoc(false),
7901 fSnapBorder(false), fIncludeHeader(true), fIncludeFooter(true), fForcePageSizePag(false),
7902 fMinFontSizePag(false), fHaveVersions(false), fAutoVersion(false),
7903 cChWS(0), cChWSFootnoteEdn(0), cDBC(0), cDBCFootnoteEdn(0), nfcEdnRef(2),
7904 fCompatibilityOptions_Unknown2_1(false), fCompatibilityOptions_Unknown2_2(false),
7905 fDontUseHTMLAutoSpacing(false), fCompatibilityOptions_Unknown2_4(false),
7906 fCompatibilityOptions_Unknown2_5(false), fCompatibilityOptions_Unknown2_6(false),
7907 fCompatibilityOptions_Unknown2_7(false), fCompatibilityOptions_Unknown2_8(false),
7908 fCompatibilityOptions_Unknown2_9(false), fCompatibilityOptions_Unknown2_10(false),
7909 fDontBreakWrappedTables(false), fCompatibilityOptions_Unknown2_12(false),
7910 fCompatibilityOptions_Unknown2_13(false), fCompatibilityOptions_Unknown2_14(false),
7911 fCompatibilityOptions_Unknown2_15(false), fCompatibilityOptions_Unknown2_16(false),
7912 fCompatibilityOptions_Unknown2_17(false), fCompatibilityOptions_Unknown2_18(false),
7913 fCompatibilityOptions_Unknown2_19(false), fCompatibilityOptions_Unknown2_20(false),
7914 fCompatibilityOptions_Unknown2_21(false), fCompatibilityOptions_Unknown2_22(false),
7915 fCompatibilityOptions_Unknown2_23(false), fCompatibilityOptions_Unknown2_24(false),
7916 fCompatibilityOptions_Unknown2_25(false), fCompatibilityOptions_Unknown2_26(false),
7917 fCompatibilityOptions_Unknown2_27(false), fCompatibilityOptions_Unknown2_28(false),
7918 fCompatibilityOptions_Unknown2_29(false), fCompatibilityOptions_Unknown2_30(false),
7919 fCompatibilityOptions_Unknown2_31(false), fCompatibilityOptions_Unknown2_32(false),
7920 fUnknown3(0), fUseBackGroundInAllmodes(false), fDoNotEmbedSystemFont(false), fWordCompat(false),
7921 fLiveRecover(false), fEmbedFactoids(false), fFactoidXML(false), fFactoidAllDone(false),
7922 fFolioPrint(false), fReverseFolio(false), iTextLineEnding(0), fHideFcc(false),
7923 fAcetateShowMarkup(false), fAcetateShowAtn(true), fAcetateShowInsDel(false),
7924 fAcetateShowProps(false)
7925 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
7926 // above bit-field member initializations can be moved to the class definition
7929 Writer acts like this all the time at the moment, ideally we need an
7930 option for these two as well to import word docs that are not like
7933 // put in initialization list
7934 // fNoLeading = true;
7935 //fUsePrinterMetrics = true;
7938 void WW8Dop::SetCompatibilityOptions(sal_uInt32 a32Bit
)
7940 fNoTabForInd
= ( a32Bit
& 0x00000001 ) ;
7941 fNoSpaceRaiseLower
= ( a32Bit
& 0x00000002 ) >> 1 ;
7942 fSuppressSpbfAfterPageBreak
= ( a32Bit
& 0x00000004 ) >> 2 ;
7943 fWrapTrailSpaces
= ( a32Bit
& 0x00000008 ) >> 3 ;
7944 fMapPrintTextColor
= ( a32Bit
& 0x00000010 ) >> 4 ;
7945 fNoColumnBalance
= ( a32Bit
& 0x00000020 ) >> 5 ;
7946 fConvMailMergeEsc
= ( a32Bit
& 0x00000040 ) >> 6 ;
7947 fSuppressTopSpacing
= ( a32Bit
& 0x00000080 ) >> 7 ;
7948 fOrigWordTableRules
= ( a32Bit
& 0x00000100 ) >> 8 ;
7949 fTransparentMetafiles
= ( a32Bit
& 0x00000200 ) >> 9 ;
7950 fShowBreaksInFrames
= ( a32Bit
& 0x00000400 ) >> 10 ;
7951 fSwapBordersFacingPgs
= ( a32Bit
& 0x00000800 ) >> 11 ;
7952 fCompatibilityOptions_Unknown1_13
= ( a32Bit
& 0x00001000 ) >> 12 ;
7953 fExpShRtn
= ( a32Bit
& 0x00002000 ) >> 13 ; // #i56856#
7954 fCompatibilityOptions_Unknown1_15
= ( a32Bit
& 0x00004000 ) >> 14 ;
7955 fCompatibilityOptions_Unknown1_16
= ( a32Bit
& 0x00008000 ) >> 15 ;
7956 fSuppressTopSpacingMac5
= ( a32Bit
& 0x00010000 ) >> 16 ;
7957 fTruncDxaExpand
= ( a32Bit
& 0x00020000 ) >> 17 ;
7958 fPrintBodyBeforeHdr
= ( a32Bit
& 0x00040000 ) >> 18 ;
7959 fNoLeading
= ( a32Bit
& 0x00080000 ) >> 19 ;
7960 fCompatibilityOptions_Unknown1_21
= ( a32Bit
& 0x00100000 ) >> 20 ;
7961 fMWSmallCaps
= ( a32Bit
& 0x00200000 ) >> 21 ;
7962 fCompatibilityOptions_Unknown1_23
= ( a32Bit
& 0x00400000 ) >> 22 ;
7963 fCompatibilityOptions_Unknown1_24
= ( a32Bit
& 0x00800800 ) >> 23 ;
7964 fCompatibilityOptions_Unknown1_25
= ( a32Bit
& 0x01000000 ) >> 24 ;
7965 fCompatibilityOptions_Unknown1_26
= ( a32Bit
& 0x02000000 ) >> 25 ;
7966 fCompatibilityOptions_Unknown1_27
= ( a32Bit
& 0x04000000 ) >> 26 ;
7967 fCompatibilityOptions_Unknown1_28
= ( a32Bit
& 0x08000000 ) >> 27 ;
7968 fCompatibilityOptions_Unknown1_29
= ( a32Bit
& 0x10000000 ) >> 28 ;
7969 fCompatibilityOptions_Unknown1_30
= ( a32Bit
& 0x20000000 ) >> 29 ;
7970 fCompatibilityOptions_Unknown1_31
= ( a32Bit
& 0x40000000 ) >> 30 ;
7972 fUsePrinterMetrics
= ( a32Bit
& 0x80000000 ) >> 31 ;
7975 sal_uInt32
WW8Dop::GetCompatibilityOptions() const
7977 sal_uInt32 a32Bit
= 0;
7978 if (fNoTabForInd
) a32Bit
|= 0x00000001;
7979 if (fNoSpaceRaiseLower
) a32Bit
|= 0x00000002;
7980 if (fSuppressSpbfAfterPageBreak
) a32Bit
|= 0x00000004;
7981 if (fWrapTrailSpaces
) a32Bit
|= 0x00000008;
7982 if (fMapPrintTextColor
) a32Bit
|= 0x00000010;
7983 if (fNoColumnBalance
) a32Bit
|= 0x00000020;
7984 if (fConvMailMergeEsc
) a32Bit
|= 0x00000040;
7985 if (fSuppressTopSpacing
) a32Bit
|= 0x00000080;
7986 if (fOrigWordTableRules
) a32Bit
|= 0x00000100;
7987 if (fTransparentMetafiles
) a32Bit
|= 0x00000200;
7988 if (fShowBreaksInFrames
) a32Bit
|= 0x00000400;
7989 if (fSwapBordersFacingPgs
) a32Bit
|= 0x00000800;
7990 if (fCompatibilityOptions_Unknown1_13
) a32Bit
|= 0x00001000;
7991 if (fExpShRtn
) a32Bit
|= 0x00002000; // #i56856#
7992 if (fCompatibilityOptions_Unknown1_15
) a32Bit
|= 0x00004000;
7993 if (fCompatibilityOptions_Unknown1_16
) a32Bit
|= 0x00008000;
7994 if (fSuppressTopSpacingMac5
) a32Bit
|= 0x00010000;
7995 if (fTruncDxaExpand
) a32Bit
|= 0x00020000;
7996 if (fPrintBodyBeforeHdr
) a32Bit
|= 0x00040000;
7997 if (fNoLeading
) a32Bit
|= 0x00080000;
7998 if (fCompatibilityOptions_Unknown1_21
) a32Bit
|= 0x00100000;
7999 if (fMWSmallCaps
) a32Bit
|= 0x00200000;
8000 if (fCompatibilityOptions_Unknown1_23
) a32Bit
|= 0x00400000;
8001 if (fCompatibilityOptions_Unknown1_24
) a32Bit
|= 0x00800000;
8002 if (fCompatibilityOptions_Unknown1_25
) a32Bit
|= 0x01000000;
8003 if (fCompatibilityOptions_Unknown1_26
) a32Bit
|= 0x02000000;
8004 if (fCompatibilityOptions_Unknown1_27
) a32Bit
|= 0x04000000;
8005 if (fCompatibilityOptions_Unknown1_28
) a32Bit
|= 0x08000000;
8006 if (fCompatibilityOptions_Unknown1_29
) a32Bit
|= 0x10000000;
8007 if (fCompatibilityOptions_Unknown1_30
) a32Bit
|= 0x20000000;
8008 if (fCompatibilityOptions_Unknown1_31
) a32Bit
|= 0x40000000;
8009 if (fUsePrinterMetrics
) a32Bit
|= 0x80000000;
8014 void WW8Dop::SetCompatibilityOptions2(sal_uInt32 a32Bit
)
8016 fCompatibilityOptions_Unknown2_1
= ( a32Bit
& 0x00000001 );
8017 fCompatibilityOptions_Unknown2_2
= ( a32Bit
& 0x00000002 ) >> 1 ;
8018 fDontUseHTMLAutoSpacing
= ( a32Bit
& 0x00000004 ) >> 2 ;
8019 fCompatibilityOptions_Unknown2_4
= ( a32Bit
& 0x00000008 ) >> 3 ;
8020 fCompatibilityOptions_Unknown2_5
= ( a32Bit
& 0x00000010 ) >> 4 ;
8021 fCompatibilityOptions_Unknown2_6
= ( a32Bit
& 0x00000020 ) >> 5 ;
8022 fCompatibilityOptions_Unknown2_7
= ( a32Bit
& 0x00000040 ) >> 6 ;
8023 fCompatibilityOptions_Unknown2_8
= ( a32Bit
& 0x00000080 ) >> 7 ;
8024 fCompatibilityOptions_Unknown2_9
= ( a32Bit
& 0x00000100 ) >> 8 ;
8025 fCompatibilityOptions_Unknown2_10
= ( a32Bit
& 0x00000200 ) >> 9 ;
8026 fDontBreakWrappedTables
= ( a32Bit
& 0x00000400 ) >> 10 ;
8027 fCompatibilityOptions_Unknown2_12
= ( a32Bit
& 0x00000800 ) >> 11 ;
8028 fCompatibilityOptions_Unknown2_13
= ( a32Bit
& 0x00001000 ) >> 12 ;
8029 fCompatibilityOptions_Unknown2_14
= ( a32Bit
& 0x00002000 ) >> 13 ;
8030 fCompatibilityOptions_Unknown2_15
= ( a32Bit
& 0x00004000 ) >> 14 ;
8031 fCompatibilityOptions_Unknown2_16
= ( a32Bit
& 0x00008000 ) >> 15 ;
8032 fCompatibilityOptions_Unknown2_17
= ( a32Bit
& 0x00010000 ) >> 16 ;
8033 fCompatibilityOptions_Unknown2_18
= ( a32Bit
& 0x00020000 ) >> 17 ;
8034 fCompatibilityOptions_Unknown2_19
= ( a32Bit
& 0x00040000 ) >> 18 ;
8035 fCompatibilityOptions_Unknown2_20
= ( a32Bit
& 0x00080000 ) >> 19 ;
8036 fCompatibilityOptions_Unknown2_21
= ( a32Bit
& 0x00100000 ) >> 20 ;
8037 fCompatibilityOptions_Unknown2_22
= ( a32Bit
& 0x00200000 ) >> 21 ;
8038 fCompatibilityOptions_Unknown2_23
= ( a32Bit
& 0x00400000 ) >> 22 ;
8039 fCompatibilityOptions_Unknown2_24
= ( a32Bit
& 0x00800800 ) >> 23 ;
8040 fCompatibilityOptions_Unknown2_25
= ( a32Bit
& 0x01000800 ) >> 24 ;
8041 fCompatibilityOptions_Unknown2_26
= ( a32Bit
& 0x02000800 ) >> 25 ;
8042 fCompatibilityOptions_Unknown2_27
= ( a32Bit
& 0x04000800 ) >> 26 ;
8043 fCompatibilityOptions_Unknown2_28
= ( a32Bit
& 0x08000800 ) >> 27 ;
8044 fCompatibilityOptions_Unknown2_29
= ( a32Bit
& 0x10000800 ) >> 28 ;
8045 fCompatibilityOptions_Unknown2_30
= ( a32Bit
& 0x20000800 ) >> 29 ;
8046 fCompatibilityOptions_Unknown2_31
= ( a32Bit
& 0x40000800 ) >> 30 ;
8047 fCompatibilityOptions_Unknown2_32
= ( a32Bit
& 0x80000000 ) >> 31 ;
8050 sal_uInt32
WW8Dop::GetCompatibilityOptions2() const
8052 sal_uInt32 a32Bit
= 0;
8053 if (fCompatibilityOptions_Unknown2_1
) a32Bit
|= 0x00000001;
8054 if (fCompatibilityOptions_Unknown2_2
) a32Bit
|= 0x00000002;
8055 if (fDontUseHTMLAutoSpacing
) a32Bit
|= 0x00000004;
8056 if (fCompatibilityOptions_Unknown2_4
) a32Bit
|= 0x00000008;
8057 if (fCompatibilityOptions_Unknown2_5
) a32Bit
|= 0x00000010;
8058 if (fCompatibilityOptions_Unknown2_6
) a32Bit
|= 0x00000020;
8059 if (fCompatibilityOptions_Unknown2_7
) a32Bit
|= 0x00000040;
8060 if (fCompatibilityOptions_Unknown2_8
) a32Bit
|= 0x00000080;
8061 if (fCompatibilityOptions_Unknown2_9
) a32Bit
|= 0x00000100;
8062 if (fCompatibilityOptions_Unknown2_10
) a32Bit
|= 0x00000200;
8063 if (fDontBreakWrappedTables
) a32Bit
|= 0x00000400;
8064 if (fCompatibilityOptions_Unknown2_12
) a32Bit
|= 0x00000800;
8065 if (fCompatibilityOptions_Unknown2_13
) a32Bit
|= 0x00001000;
8066 //#i42909# set thai "line breaking rules" compatibility option
8067 // pflin, wonder whether bUseThaiLineBreakingRules is correct
8068 // when importing word document.
8069 if (bUseThaiLineBreakingRules
) a32Bit
|= 0x00002000;
8070 else if (fCompatibilityOptions_Unknown2_14
) a32Bit
|= 0x00002000;
8071 if (fCompatibilityOptions_Unknown2_15
) a32Bit
|= 0x00004000;
8072 if (fCompatibilityOptions_Unknown2_16
) a32Bit
|= 0x00008000;
8073 if (fCompatibilityOptions_Unknown2_17
) a32Bit
|= 0x00010000;
8074 if (fCompatibilityOptions_Unknown2_18
) a32Bit
|= 0x00020000;
8075 if (fCompatibilityOptions_Unknown2_19
) a32Bit
|= 0x00040000;
8076 if (fCompatibilityOptions_Unknown2_20
) a32Bit
|= 0x00080000;
8077 if (fCompatibilityOptions_Unknown2_21
) a32Bit
|= 0x00100000;
8078 if (fCompatibilityOptions_Unknown2_22
) a32Bit
|= 0x00200000;
8079 if (fCompatibilityOptions_Unknown2_23
) a32Bit
|= 0x00400000;
8080 if (fCompatibilityOptions_Unknown2_24
) a32Bit
|= 0x00800000;
8081 if (fCompatibilityOptions_Unknown2_25
) a32Bit
|= 0x01000000;
8082 if (fCompatibilityOptions_Unknown2_26
) a32Bit
|= 0x02000000;
8083 if (fCompatibilityOptions_Unknown2_27
) a32Bit
|= 0x04000000;
8084 if (fCompatibilityOptions_Unknown2_28
) a32Bit
|= 0x08000000;
8085 if (fCompatibilityOptions_Unknown2_29
) a32Bit
|= 0x10000000;
8086 if (fCompatibilityOptions_Unknown2_30
) a32Bit
|= 0x20000000;
8087 if (fCompatibilityOptions_Unknown2_31
) a32Bit
|= 0x40000000;
8088 if (fCompatibilityOptions_Unknown2_32
) a32Bit
|= 0x80000000;
8092 void WW8Dop::Write(SvStream
& rStrm
, WW8Fib
& rFib
) const
8094 const int nMaxDopLen
= 610;
8095 sal_uInt32 nLen
= 8 == rFib
.m_nVersion
? nMaxDopLen
: 84;
8096 rFib
.m_fcDop
= rStrm
.Tell();
8097 rFib
.m_lcbDop
= nLen
;
8099 sal_uInt8 aData
[ nMaxDopLen
] = {};
8100 sal_uInt8
* pData
= aData
;
8106 a16Bit
= 0; // 0 0x00
8113 a16Bit
|= ( 0x0018 & (grfSuppression
<< 3));
8114 a16Bit
|= ( 0x0060 & (fpc
<< 5));
8115 a16Bit
|= ( 0xff00 & (grpfIhdt
<< 8));
8116 Set_UInt16( pData
, a16Bit
);
8118 a16Bit
= 0; // 2 0x02
8119 a16Bit
|= ( 0x0003 & rncFootnote
);
8120 a16Bit
|= ( ~0x0003 & (nFootnote
<< 2));
8121 Set_UInt16( pData
, a16Bit
);
8123 a8Bit
= 0; // 4 0x04
8124 if( fOutlineDirtySave
) a8Bit
|= 0x01;
8125 Set_UInt8( pData
, a8Bit
);
8127 a8Bit
= 0; // 5 0x05
8128 if( fOnlyMacPics
) a8Bit
|= 0x01;
8129 if( fOnlyWinPics
) a8Bit
|= 0x02;
8130 if( fLabelDoc
) a8Bit
|= 0x04;
8131 if( fHyphCapitals
) a8Bit
|= 0x08;
8132 if( fAutoHyphen
) a8Bit
|= 0x10;
8133 if( fFormNoFields
) a8Bit
|= 0x20;
8134 if( fLinkStyles
) a8Bit
|= 0x40;
8135 if( fRevMarking
) a8Bit
|= 0x80;
8136 Set_UInt8( pData
, a8Bit
);
8138 a8Bit
= 0; // 6 0x06
8139 if( fBackup
) a8Bit
|= 0x01;
8140 if( fExactCWords
) a8Bit
|= 0x02;
8141 if( fPagHidden
) a8Bit
|= 0x04;
8142 if( fPagResults
) a8Bit
|= 0x08;
8143 if( fLockAtn
) a8Bit
|= 0x10;
8144 if( fMirrorMargins
) a8Bit
|= 0x20;
8145 if( fReadOnlyRecommended
) a8Bit
|= 0x40;
8146 if( fDfltTrueType
) a8Bit
|= 0x80;
8147 Set_UInt8( pData
, a8Bit
);
8149 a8Bit
= 0; // 7 0x07
8150 if( fPagSuppressTopSpacing
) a8Bit
|= 0x01;
8151 if( fProtEnabled
) a8Bit
|= 0x02;
8152 if( fDispFormFieldSel
) a8Bit
|= 0x04;
8153 if( fRMView
) a8Bit
|= 0x08;
8154 if( fRMPrint
) a8Bit
|= 0x10;
8155 if( fWriteReservation
) a8Bit
|= 0x20;
8156 if( fLockRev
) a8Bit
|= 0x40;
8157 if( fEmbedFonts
) a8Bit
|= 0x80;
8158 Set_UInt8( pData
, a8Bit
);
8160 a8Bit
= 0; // 8 0x08
8161 if( copts_fNoTabForInd
) a8Bit
|= 0x01;
8162 if( copts_fNoSpaceRaiseLower
) a8Bit
|= 0x02;
8163 if( copts_fSuppressSpbfAfterPgBrk
) a8Bit
|= 0x04;
8164 if( copts_fWrapTrailSpaces
) a8Bit
|= 0x08;
8165 if( copts_fMapPrintTextColor
) a8Bit
|= 0x10;
8166 if( copts_fNoColumnBalance
) a8Bit
|= 0x20;
8167 if( copts_fConvMailMergeEsc
) a8Bit
|= 0x40;
8168 if( copts_fSuppressTopSpacing
) a8Bit
|= 0x80;
8169 Set_UInt8( pData
, a8Bit
);
8171 a8Bit
= 0; // 9 0x09
8172 if( copts_fOrigWordTableRules
) a8Bit
|= 0x01;
8173 if( copts_fTransparentMetafiles
) a8Bit
|= 0x02;
8174 if( copts_fShowBreaksInFrames
) a8Bit
|= 0x04;
8175 if( copts_fSwapBordersFacingPgs
) a8Bit
|= 0x08;
8176 if( copts_fExpShRtn
) a8Bit
|= 0x20; // #i56856#
8177 Set_UInt8( pData
, a8Bit
);
8179 Set_UInt16( pData
, dxaTab
); // 10 0x0a
8180 Set_UInt16( pData
, wSpare
); // 12 0x0c
8181 Set_UInt16( pData
, dxaHotZ
); // 14 0x0e
8182 Set_UInt16( pData
, cConsecHypLim
); // 16 0x10
8183 Set_UInt16( pData
, wSpare2
); // 18 0x12
8184 Set_UInt32( pData
, dttmCreated
); // 20 0x14
8185 Set_UInt32( pData
, dttmRevised
); // 24 0x18
8186 Set_UInt32( pData
, dttmLastPrint
); // 28 0x1c
8187 Set_UInt16( pData
, nRevision
); // 32 0x20
8188 Set_UInt32( pData
, tmEdited
); // 34 0x22
8189 Set_UInt32( pData
, cWords
); // 38 0x26
8190 Set_UInt32( pData
, cCh
); // 42 0x2a
8191 Set_UInt16( pData
, cPg
); // 46 0x2e
8192 Set_UInt32( pData
, cParas
); // 48 0x30
8194 a16Bit
= 0; // 52 0x34
8195 a16Bit
|= ( 0x0003 & rncEdn
);
8196 a16Bit
|= (~0x0003 & ( nEdn
<< 2));
8197 Set_UInt16( pData
, a16Bit
);
8199 a16Bit
= 0; // 54 0x36
8200 a16Bit
|= (0x0003 & epc
);
8201 a16Bit
|= (0x003c & (nfcFootnoteRef
<< 2));
8202 a16Bit
|= (0x03c0 & (nfcEdnRef
<< 6));
8203 if( fPrintFormData
) a16Bit
|= 0x0400;
8204 if( fSaveFormData
) a16Bit
|= 0x0800;
8205 if( fShadeFormData
) a16Bit
|= 0x1000;
8206 if( fWCFootnoteEdn
) a16Bit
|= 0x8000;
8207 Set_UInt16( pData
, a16Bit
);
8209 Set_UInt32( pData
, cLines
); // 56 0x38
8210 Set_UInt32( pData
, cWordsFootnoteEnd
); // 60 0x3c
8211 Set_UInt32( pData
, cChFootnoteEdn
); // 64 0x40
8212 Set_UInt16( pData
, cPgFootnoteEdn
); // 68 0x44
8213 Set_UInt32( pData
, cParasFootnoteEdn
); // 70 0x46
8214 Set_UInt32( pData
, cLinesFootnoteEdn
); // 74 0x4a
8215 Set_UInt32( pData
, lKeyProtDoc
); // 78 0x4e
8217 a16Bit
= 0; // 82 0x52
8220 a16Bit
|= (0x0ff8 & (wScaleSaved
<< 3));
8221 a16Bit
|= (0x3000 & (zkSaved
<< 12));
8224 // Last bit: gutter at top.
8227 Set_UInt16( pData
, a16Bit
);
8229 if( 8 == rFib
.m_nVersion
)
8231 Set_UInt32(pData
, GetCompatibilityOptions()); // 84 0x54
8233 Set_UInt16( pData
, adt
); // 88 0x58
8235 doptypography
.WriteToMem(pData
); // 400 0x190
8237 memcpy( pData
, &dogrid
, sizeof( WW8_DOGRID
));
8238 pData
+= sizeof( WW8_DOGRID
);
8240 a16Bit
= 0x12; // set lvl to 9 // 410 0x19a
8241 if( fHtmlDoc
) a16Bit
|= 0x0200;
8242 if( fSnapBorder
) a16Bit
|= 0x0800;
8243 if( fIncludeHeader
) a16Bit
|= 0x1000;
8244 if( fIncludeFooter
) a16Bit
|= 0x2000;
8245 if( fForcePageSizePag
) a16Bit
|= 0x4000;
8246 if( fMinFontSizePag
) a16Bit
|= 0x8000;
8247 Set_UInt16( pData
, a16Bit
);
8249 a16Bit
= 0; // 412 0x19c
8250 if( fHaveVersions
) a16Bit
|= 0x0001;
8251 if( fAutoVersion
) a16Bit
|= 0x0002;
8252 Set_UInt16( pData
, a16Bit
);
8254 pData
+= 12; // 414 0x19e
8256 Set_UInt32( pData
, cChWS
); // 426 0x1aa
8257 Set_UInt32( pData
, cChWSFootnoteEdn
); // 430 0x1ae
8258 Set_UInt32( pData
, grfDocEvents
); // 434 0x1b2
8260 pData
+= 4+30+8; // 438 0x1b6; 442 0x1ba; 472 0x1d8; 476 0x1dc
8262 Set_UInt32( pData
, cDBC
); // 480 0x1e0
8263 Set_UInt32( pData
, cDBCFootnoteEdn
); // 484 0x1e4
8265 pData
+= 1 * sizeof( sal_Int32
); // 488 0x1e8
8267 Set_UInt16( pData
, nfcFootnoteRef
); // 492 0x1ec
8268 Set_UInt16( pData
, nfcEdnRef
); // 494 0x1ee
8269 Set_UInt16( pData
, hpsZoomFontPag
); // 496 0x1f0
8270 Set_UInt16( pData
, dywDispPag
); // 498 0x1f2
8272 //500 -> 508, Appear to be repeated here in 2000+
8274 Set_UInt32(pData
, GetCompatibilityOptions());
8275 Set_UInt32(pData
, GetCompatibilityOptions2());
8281 if (fAcetateShowMarkup
)
8283 //Word XP at least requires fAcetateShowMarkup to honour fAcetateShowAtn
8284 if (fAcetateShowAtn
)
8289 Set_UInt16(pData
, a16Bit
);
8293 Set_UInt16(pData
, a16Bit
);
8295 rStrm
.WriteBytes(aData
, nLen
);
8298 void WW8DopTypography::ReadFromMem(sal_uInt8
*&pData
)
8300 sal_uInt16 a16Bit
= Get_UShort(pData
);
8301 m_fKerningPunct
= (a16Bit
& 0x0001);
8302 m_iJustification
= (a16Bit
& 0x0006) >> 1;
8303 m_iLevelOfKinsoku
= (a16Bit
& 0x0018) >> 3;
8304 m_f2on1
= (a16Bit
& 0x0020) >> 5;
8305 m_reserved1
= (a16Bit
& 0x03C0) >> 6;
8306 m_reserved2
= (a16Bit
& 0xFC00) >> 10;
8308 m_cchFollowingPunct
= Get_Short(pData
);
8309 m_cchLeadingPunct
= Get_Short(pData
);
8312 for (i
=0; i
< nMaxFollowing
; ++i
)
8313 m_rgxchFPunct
[i
] = Get_Short(pData
);
8314 for (i
=0; i
< nMaxLeading
; ++i
)
8315 m_rgxchLPunct
[i
] = Get_Short(pData
);
8317 if (m_cchFollowingPunct
>= 0 && m_cchFollowingPunct
< nMaxFollowing
)
8318 m_rgxchFPunct
[m_cchFollowingPunct
]=0;
8320 m_rgxchFPunct
[nMaxFollowing
- 1]=0;
8322 if (m_cchLeadingPunct
>= 0 && m_cchLeadingPunct
< nMaxLeading
)
8323 m_rgxchLPunct
[m_cchLeadingPunct
]=0;
8325 m_rgxchLPunct
[nMaxLeading
- 1]=0;
8329 void WW8DopTypography::WriteToMem(sal_uInt8
*&pData
) const
8331 sal_uInt16 a16Bit
= sal_uInt16(m_fKerningPunct
);
8332 a16Bit
|= (m_iJustification
<< 1) & 0x0006;
8333 a16Bit
|= (m_iLevelOfKinsoku
<< 3) & 0x0018;
8334 a16Bit
|= (int(m_f2on1
) << 5) & 0x0020;
8335 a16Bit
|= (m_reserved1
<< 6) & 0x03C0;
8336 a16Bit
|= (m_reserved2
<< 10) & 0xFC00;
8337 Set_UInt16(pData
,a16Bit
);
8339 Set_UInt16(pData
,m_cchFollowingPunct
);
8340 Set_UInt16(pData
,m_cchLeadingPunct
);
8343 for (i
=0; i
< nMaxFollowing
; ++i
)
8344 Set_UInt16(pData
,m_rgxchFPunct
[i
]);
8345 for (i
=0; i
< nMaxLeading
; ++i
)
8346 Set_UInt16(pData
,m_rgxchLPunct
[i
]);
8349 LanguageType
WW8DopTypography::GetConvertedLang() const
8352 //I have assumed people's republic/taiwan == simplified/traditional
8354 //This isn't a documented issue, so we might have it all wrong,
8355 //i.e. i.e. what's with the powers of two ?
8358 One example of 3 for reserved1 which was really Japanese, perhaps last bit
8359 is for some other use ?, or redundant. If more examples trigger the assert
8360 we might be able to figure it out.
8362 switch(m_reserved1
& 0xE)
8365 nLang
= LANGUAGE_JAPANESE
;
8367 case 4: //Chinese (People's Republic)
8368 nLang
= LANGUAGE_CHINESE_SIMPLIFIED
;
8371 nLang
= LANGUAGE_KOREAN
;
8373 case 8: //Chinese (Taiwan)
8374 nLang
= LANGUAGE_CHINESE_TRADITIONAL
;
8377 OSL_ENSURE(false, "Unknown MS Asian Typography language, report");
8378 nLang
= LANGUAGE_CHINESE_SIMPLIFIED_LEGACY
;
8381 //And here we have the possibility that it says 2, but it's really
8382 //a bug and only japanese level 2 has been selected after a custom
8383 //version was chosen on last save!
8384 nLang
= LANGUAGE_JAPANESE
;
8392 sal_uInt16
wwSprmParser::GetSprmTailLen(sal_uInt16 nId
, const sal_uInt8
* pSprm
, sal_Int32 nRemLen
)
8395 SprmInfo aSprm
= GetSprmInfo(nId
);
8396 sal_uInt16 nL
= 0; // number of Bytes to read
8403 if( pSprm
[1 + mnDelta
] != 255 )
8404 nL
= static_cast< sal_uInt16
>(pSprm
[1 + mnDelta
] + aSprm
.nLen
);
8407 sal_uInt8 nDelIdx
= 2 + mnDelta
;
8408 sal_uInt8 nDel
= nDelIdx
< nRemLen
? pSprm
[nDelIdx
] : 0;
8409 sal_uInt8 nInsIdx
= 3 + mnDelta
+ 4 * nDel
;
8410 sal_uInt8 nIns
= nInsIdx
< nRemLen
? pSprm
[nInsIdx
] : 0;
8412 nL
= 2 + 4 * nDel
+ 3 * nIns
;
8416 switch (aSprm
.nVari
)
8419 nL
= aSprm
.nLen
; // Excl. Token
8422 // Variable 1-Byte Length
8423 // parameter length (i.e. excluding token and length byte)
8424 nL
= static_cast< sal_uInt16
>(pSprm
[1 + mnDelta
] + aSprm
.nLen
);
8428 // Variable 2-Byte Length
8429 // For sprmTDefTable and sprmTDefTable10, the length of the
8430 // parameter plus 1 is recorded in the two bytes beginning
8431 // at offset (WW7-) 1 or (WW8+) 2
8432 sal_uInt8 nIndex
= 1 + mnDelta
;
8434 if (nIndex
+ 1 >= nRemLen
)
8436 SAL_WARN("sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong");
8441 nCount
= SVBT16ToUInt16(&pSprm
[nIndex
]);
8442 SAL_WARN_IF(nCount
< 1, "sw.ww8", "length should have been at least 1");
8446 nL
= static_cast<sal_uInt16
>(nCount
+ aSprm
.nLen
);
8450 OSL_ENSURE(false, "Unknown sprm variant");
8458 // one or two bytes at the beginning at the sprm id
8459 sal_uInt16
wwSprmParser::GetSprmId(const sal_uInt8
* pSp
) const
8461 OSL_ENSURE(pSp
, "Why GetSprmId with pSp of 0");
8467 if (ww::IsSevenMinus(meVersion
))
8469 nId
= *pSp
; // [0..0xff]
8473 nId
= SVBT16ToUInt16(pSp
);
8481 // with tokens and length byte
8482 sal_Int32
wwSprmParser::GetSprmSize(sal_uInt16 nId
, const sal_uInt8
* pSprm
, sal_Int32 nRemLen
) const
8484 return GetSprmTailLen(nId
, pSprm
, nRemLen
) + 1 + mnDelta
+ SprmDataOfs(nId
);
8487 sal_uInt8
wwSprmParser::SprmDataOfs(sal_uInt16 nId
) const
8489 return GetSprmInfo(nId
).nVari
;
8492 sal_Int32
wwSprmParser::DistanceToData(sal_uInt16 nId
) const
8494 return 1 + mnDelta
+ SprmDataOfs(nId
);
8497 SprmResult
wwSprmParser::findSprmData(sal_uInt16 nId
, sal_uInt8
* pSprms
,
8498 sal_Int32 nLen
) const
8500 while (nLen
>= MinSprmLen())
8502 const sal_uInt16 nCurrentId
= GetSprmId(pSprms
);
8503 // set pointer to data
8504 sal_Int32 nSize
= GetSprmSize(nCurrentId
, pSprms
, nLen
);
8506 bool bValid
= nSize
<= nLen
;
8508 SAL_WARN_IF(!bValid
, "sw.ww8",
8509 "sprm 0x" << std::hex
<< nCurrentId
<< std::dec
<< " longer than remaining bytes, " <<
8510 nSize
<< " vs " << nLen
<< "doc or parser is wrong");
8512 if (nCurrentId
== nId
&& bValid
) // Sprm found
8514 sal_Int32 nFixedLen
= DistanceToData(nId
);
8515 return SprmResult(pSprms
+ nFixedLen
, nSize
- nFixedLen
);
8518 //Clip to available size if wrong
8519 nSize
= std::min(nSize
, nLen
);
8524 return SprmResult();
8528 bkc(2), fTitlePage(0), fAutoPgn(0), nfcPgn(0), fUnlocked(0), cnsPgn(0),
8529 fPgnRestart(0), fEndNote(1), lnc(0), grpfIhdt(0), nLnnMod(0), dxaLnn(0),
8530 dxaPgn(720), dyaPgn(720), fLBetween(0), vjc(0), dmBinFirst(0),
8531 dmBinOther(0), dmPaperReq(0), fPropRMark(0), ibstPropRMark(0),
8532 dttmPropRMark(0), dxtCharSpace(0), dyaLinePitch(0), clm(0), reserved1(0),
8533 dmOrientPage(0), iHeadingPgn(0), pgnStart(1), lnnMin(0), wTextFlow(0),
8534 reserved2(0), pgbApplyTo(0), pgbPageDepth(0), pgbOffsetFrom(0),
8535 xaPage(lLetterWidth
), yaPage(lLetterHeight
), xaPageNUp(lLetterWidth
), yaPageNUp(lLetterHeight
),
8536 dxaLeft(1800), dxaRight(1800), dyaTop(1440), dyaBottom(1440), dzaGutter(0),
8537 dyaHdrTop(720), dyaHdrBottom(720), ccolM1(0), fEvenlySpaced(1),
8538 reserved3(0), fBiDi(0), fFacingCol(0), fRTLGutter(0), fRTLAlignment(0),
8539 dxaColumns(720), dxaColumnWidth(0), dmOrientFirst(0), fLayout(0),
8544 bool checkRead(SvStream
&rSt
, void *pDest
, sal_uInt32 nLength
)
8546 return (rSt
.ReadBytes(pDest
, nLength
) == static_cast<std::size_t>(nLength
));
8549 #ifdef OSL_BIGENDIAN
8550 void swapEndian(sal_Unicode
*pString
)
8552 for (sal_Unicode
*pWork
= pString
; *pWork
; ++pWork
)
8553 *pWork
= OSL_SWAPWORD(*pWork
);
8557 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */