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 using namespace ::com::sun::star::lang
;
52 winword strings are typically Belt and Braces strings preceded with a
53 pascal style count, and ending with a c style 0 terminator. 16bit chars
54 and count for ww8+ and 8bit chars and count for ww7-. The count and 0
55 can be checked for integrity to catch errors (e.g. lotus created
56 documents) where in error 8bit strings are used instead of 16bits
57 strings for style names.
59 bool TestBeltAndBraces(SvStream
& rStrm
)
62 sal_uInt64 nOldPos
= rStrm
.Tell();
64 rStrm
.ReadUInt16( nBelt
);
65 nBelt
*= sizeof(sal_Unicode
);
66 if (rStrm
.good() && (rStrm
.remainingSize() >= (nBelt
+ sizeof(sal_Unicode
))))
71 sal_Unicode
cBraces(0);
72 rStrm
.ReadUtf16( cBraces
);
73 if (rStrm
.good() && cBraces
== 0)
82 const wwSprmSearcher
*wwSprmParser::GetWW2SprmSearcher()
86 static const SprmInfoRow aSprms
[] =
88 { 0, { 0, L_FIX
} }, // "Default-sprm", will be skipped
89 { 2, { 1, L_FIX
} }, // "sprmPIstd", pap.istd (style code)
90 { 3, { 0, L_VAR
} }, // "sprmPIstdPermute pap.istd permutation
91 { 4, { 1, L_FIX
} }, // "sprmPIncLv1" pap.istddifference
92 { 5, { 1, L_FIX
} }, // "sprmPJc" pap.jc (justification)
93 { 6, { 1, L_FIX
} }, // "sprmPFSideBySide" pap.fSideBySide
94 { 7, { 1, L_FIX
} }, // "sprmPFKeep" pap.fKeep
95 { 8, { 1, L_FIX
} }, // "sprmPFKeepFollow " pap.fKeepFollow
96 { 9, { 1, L_FIX
} }, // "sprmPPageBreakBefore" pap.fPageBreakBefore
97 { 10, { 1, L_FIX
} }, // "sprmPBrcl" pap.brcl
98 { 11, { 1, L_FIX
} }, // "sprmPBrcp" pap.brcp
99 { 12, { 1, L_FIX
} }, // "sprmPNfcSeqNumb" pap.nfcSeqNumb
100 { 13, { 1, L_FIX
} }, // "sprmPNoSeqNumb" pap.nnSeqNumb
101 { 14, { 1, L_FIX
} }, // "sprmPFNoLineNumb" pap.fNoLnn
102 { 15, { 0, L_VAR
} }, // "?sprmPChgTabsPapx" pap.itbdMac, ...
103 { 16, { 2, L_FIX
} }, // "sprmPDxaRight" pap.dxaRight
104 { 17, { 2, L_FIX
} }, // "sprmPDxaLeft" pap.dxaLeft
105 { 18, { 2, L_FIX
} }, // "sprmPNest" pap.dxaLeft
106 { 19, { 2, L_FIX
} }, // "sprmPDxaLeft1" pap.dxaLeft1
107 { 20, { 2, L_FIX
} }, // "sprmPDyaLine" pap.lspd an LSPD
108 { 21, { 2, L_FIX
} }, // "sprmPDyaBefore" pap.dyaBefore
109 { 22, { 2, L_FIX
} }, // "sprmPDyaAfter" pap.dyaAfter
110 { 23, { 0, L_VAR
} }, // "?sprmPChgTabs" pap.itbdMac, pap.rgdxaTab, ...
111 { 24, { 1, L_FIX
} }, // "sprmPFInTable" pap.fInTable
112 { 25, { 1, L_FIX
} }, // "sprmPTtp" pap.fTtp
113 { 26, { 2, L_FIX
} }, // "sprmPDxaAbs" pap.dxaAbs
114 { 27, { 2, L_FIX
} }, // "sprmPDyaAbs" pap.dyaAbs
115 { 28, { 2, L_FIX
} }, // "sprmPDxaWidth" pap.dxaWidth
116 { 29, { 1, L_FIX
} }, // "sprmPPc" pap.pcHorz, pap.pcVert
117 { 30, { 2, L_FIX
} }, // "sprmPBrcTop10" pap.brcTop BRC10
118 { 31, { 2, L_FIX
} }, // "sprmPBrcLeft10" pap.brcLeft BRC10
119 { 32, { 2, L_FIX
} }, // "sprmPBrcBottom10" pap.brcBottom BRC10
120 { 33, { 2, L_FIX
} }, // "sprmPBrcRight10" pap.brcRight BRC10
121 { 34, { 2, L_FIX
} }, // "sprmPBrcBetween10" pap.brcBetween BRC10
122 { 35, { 2, L_FIX
} }, // "sprmPBrcBar10" pap.brcBar BRC10
123 { 36, { 2, L_FIX
} }, // "sprmPFromText10" pap.dxaFromText dxa
124 { 37, { 1, L_FIX
} }, // "sprmPWr" pap.wr wr
125 { 38, { 2, L_FIX
} }, // "sprmPBrcTop" pap.brcTop BRC
126 { 39, { 2, L_FIX
} }, // "sprmPBrcLeft" pap.brcLeft BRC
127 { 40, { 2, L_FIX
} }, // "sprmPBrcBottom" pap.brcBottom BRC
128 { 41, { 2, L_FIX
} }, // "sprmPBrcRight" pap.brcRight BRC
129 { 42, { 2, L_FIX
} }, // "sprmPBrcBetween" pap.brcBetween BRC
130 { 43, { 2, L_FIX
} }, // "sprmPBrcBar" pap.brcBar BRC word
131 { 44, { 1, L_FIX
} }, // "sprmPFNoAutoHyph" pap.fNoAutoHyph
132 { 45, { 2, L_FIX
} }, // "sprmPWHeightAbs" pap.wHeightAbs w
133 { 46, { 2, L_FIX
} }, // "sprmPDcs" pap.dcs DCS
134 { 47, { 2, L_FIX
} }, // "sprmPShd" pap.shd SHD
135 { 48, { 2, L_FIX
} }, // "sprmPDyaFromText" pap.dyaFromText dya
136 { 49, { 2, L_FIX
} }, // "sprmPDxaFromText" pap.dxaFromText dxa
137 { 50, { 1, L_FIX
} }, // "sprmPFBiDi" pap.fBiDi 0 or 1 byte
138 { 51, { 1, L_FIX
} }, // "sprmPFWidowControl" pap.fWidowControl 0 or 1 byte
139 { 52, { 0, L_FIX
} }, // "?sprmPRuler 52"
140 { 53, { 1, L_FIX
} }, // "sprmCFStrikeRM" chp.fRMarkDel 1 or 0 bit
141 { 54, { 1, L_FIX
} }, // "sprmCFRMark" chp.fRMark 1 or 0 bit
142 { 55, { 1, L_FIX
} }, // "sprmCFFieldVanish" chp.fFieldVanish 1 or 0 bit
143 { 57, { 0, L_VAR
} }, // "sprmCDefault" whole CHP
144 { 58, { 0, L_FIX
} }, // "sprmCPlain" whole CHP
145 { 60, { 1, L_FIX
} }, // "sprmCFBold" chp.fBold 0,1, 128, or 129
146 { 61, { 1, L_FIX
} }, // "sprmCFItalic" chp.fItalic 0,1, 128, or 129
147 { 62, { 1, L_FIX
} }, // "sprmCFStrike" chp.fStrike 0,1, 128, or 129
148 { 63, { 1, L_FIX
} }, // "sprmCFOutline" chp.fOutline 0,1, 128, or 129
149 { 64, { 1, L_FIX
} }, // "sprmCFShadow" chp.fShadow 0,1, 128, or 129
150 { 65, { 1, L_FIX
} }, // "sprmCFSmallCaps" chp.fSmallCaps 0,1, 128, or 129
151 { 66, { 1, L_FIX
} }, // "sprmCFCaps" chp.fCaps 0,1, 128, or 129
152 { 67, { 1, L_FIX
} }, // "sprmCFVanish" chp.fVanish 0,1, 128, or 129
153 { 68, { 2, L_FIX
} }, // "sprmCFtc" chp.ftc ftc word
154 { 69, { 1, L_FIX
} }, // "sprmCKul" chp.kul kul byte
155 { 70, { 3, L_FIX
} }, // "sprmCSizePos" chp.hps, chp.hpsPos
156 { 71, { 2, L_FIX
} }, // "sprmCDxaSpace" chp.dxaSpace dxa
157 { 72, { 2, L_FIX
} }, // "sprmCLid" chp.lid LID
158 { 73, { 1, L_FIX
} }, // "sprmCIco" chp.ico ico byte
159 { 74, { 1, L_FIX
} }, // "sprmCHps" chp.hps hps !word!
160 { 75, { 1, L_FIX
} }, // "sprmCHpsInc" chp.hps
161 { 76, { 1, L_FIX
} }, // "sprmCHpsPos" chp.hpsPos hps !word!
162 { 77, { 1, L_FIX
} }, // "sprmCHpsPosAdj" chp.hpsPos hps
163 { 78, { 0, L_VAR
} }, // "?sprmCMajority" chp.fBold, chp.fItalic, ...
164 { 80, { 1, L_FIX
} }, // "sprmCFBoldBi" chp.fBoldBi
165 { 81, { 1, L_FIX
} }, // "sprmCFItalicBi" chp.fItalicBi
166 { 82, { 2, L_FIX
} }, // "sprmCFtcBi" chp.ftcBi
167 { 83, { 2, L_FIX
} }, // "sprmClidBi" chp.lidBi
168 { 84, { 1, L_FIX
} }, // "sprmCIcoBi" chp.icoBi
169 { 85, { 1, L_FIX
} }, // "sprmCHpsBi" chp.hpsBi
170 { 86, { 1, L_FIX
} }, // "sprmCFBiDi" chp.fBiDi
171 { 87, { 1, L_FIX
} }, // "sprmCFDiacColor" chp.fDiacUSico
172 { 94, { 1, L_FIX
} }, // "sprmPicBrcl" pic.brcl brcl (see PIC definition)
173 { 95, {12, L_VAR
} }, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
174 { 96, { 2, L_FIX
} }, // "sprmPicBrcTop" pic.brcTop BRC word
175 { 97, { 2, L_FIX
} }, // "sprmPicBrcLeft" pic.brcLeft BRC word
176 { 98, { 2, L_FIX
} }, // "sprmPicBrcBottom" pic.brcBottom BRC word
177 { 99, { 2, L_FIX
} }, // "sprmPicBrcRight" pic.brcRight BRC word
178 {112, { 1, L_FIX
} }, // "sprmSFRTLGutter", set to one if gutter is on
179 {114, { 1, L_FIX
} }, // "sprmSFBiDi" ;;;
180 {115, { 2, L_FIX
} }, // "sprmSDmBinFirst" sep.dmBinFirst word
181 {116, { 2, L_FIX
} }, // "sprmSDmBinOther" sep.dmBinOther word
182 {117, { 1, L_FIX
} }, // "sprmSBkc" sep.bkc bkc byte
183 {118, { 1, L_FIX
} }, // "sprmSFTitlePage" sep.fTitlePage 0 or 1 byte
184 {119, { 2, L_FIX
} }, // "sprmSCcolumns" sep.ccolM1 # of cols - 1 word
185 {120, { 2, L_FIX
} }, // "sprmSDxaColumns" sep.dxaColumns dxa word
186 {121, { 1, L_FIX
} }, // "sprmSFAutoPgn" sep.fAutoPgn obsolete byte
187 {122, { 1, L_FIX
} }, // "sprmSNfcPgn" sep.nfcPgn nfc byte
188 {123, { 2, L_FIX
} }, // "sprmSDyaPgn" sep.dyaPgn dya short
189 {124, { 2, L_FIX
} }, // "sprmSDxaPgn" sep.dxaPgn dya short
190 {125, { 1, L_FIX
} }, // "sprmSFPgnRestart" sep.fPgnRestart 0 or 1 byte
191 {126, { 1, L_FIX
} }, // "sprmSFEndnote" sep.fEndnote 0 or 1 byte
192 {127, { 1, L_FIX
} }, // "sprmSLnc" sep.lnc lnc byte
193 {128, { 1, L_FIX
} }, // "sprmSGprfIhdt" sep.grpfIhdt grpfihdt
194 {129, { 2, L_FIX
} }, // "sprmSNLnnMod" sep.nLnnMod non-neg int. word
195 {130, { 2, L_FIX
} }, // "sprmSDxaLnn" sep.dxaLnn dxa word
196 {131, { 2, L_FIX
} }, // "sprmSDyaHdrTop" sep.dyaHdrTop dya word
197 {132, { 2, L_FIX
} }, // "sprmSDyaHdrBottom" sep.dyaHdrBottom dya word
198 {133, { 1, L_FIX
} }, // "sprmSLBetween" sep.fLBetween 0 or 1 byte
199 {134, { 1, L_FIX
} }, // "sprmSVjc" sep.vjc vjc byte
200 {135, { 2, L_FIX
} }, // "sprmSLnnMin" sep.lnnMin lnn word
201 {136, { 2, L_FIX
} }, // "sprmSPgnStart" sep.pgnStart pgn word
202 {137, { 1, L_FIX
} }, // "sprmSBOrientation" sep.dmOrientPage dm byte
203 {138, { 1, L_FIX
} }, // "sprmSFFacingCol" ;;;
204 {139, { 2, L_FIX
} }, // "sprmSXaPage" sep.xaPage xa word
205 {140, { 2, L_FIX
} }, // "sprmSYaPage" sep.yaPage ya word
206 {141, { 2, L_FIX
} }, // "sprmSDxaLeft" sep.dxaLeft dxa word
207 {142, { 2, L_FIX
} }, // "sprmSDxaRight" sep.dxaRight dxa word
208 {143, { 2, L_FIX
} }, // "sprmSDyaTop" sep.dyaTop dya word
209 {144, { 2, L_FIX
} }, // "sprmSDyaBottom" sep.dyaBottom dya word
210 {145, { 2, L_FIX
} }, // "sprmSDzaGutter" sep.dzaGutter dza word
211 {146, { 2, L_FIX
} }, // "sprmTJc" tap.jc jc (low order byte is significant)
212 {147, { 2, L_FIX
} }, // "sprmTDxaLeft" tap.rgdxaCenter dxa word
213 {148, { 2, L_FIX
} }, // "sprmTDxaGapHalf" tap.dxaGapHalf, tap.rgdxaCenter
214 {149, { 1, L_FIX
} }, // "sprmTFBiDi" ;;;
215 {152, { 0, L_VAR2
} },// "sprmTDefTable10" tap.rgdxaCenter, tap.rgtc complex
216 {153, { 2, L_FIX
} }, // "sprmTDyaRowHeight" tap.dyaRowHeight dya word
217 {154, { 0, L_VAR2
} },// "sprmTDefTable" tap.rgtc complex
218 {155, { 1, L_VAR
} }, // "sprmTDefTableShd" tap.rgshd complex
219 {157, { 5, L_FIX
} }, // "sprmTSetBrc" tap.rgtc[].rgbrc complex 5 bytes
220 {158, { 4, L_FIX
} }, // "sprmTInsert" tap.rgdxaCenter,tap.rgtc complex
221 {159, { 2, L_FIX
} }, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc complex
222 {160, { 4, L_FIX
} }, // "sprmTDxaCol" tap.rgdxaCenter complex
223 {161, { 2, L_FIX
} }, // "sprmTMerge" tap.fFirstMerged, tap.fMerged complex
224 {162, { 2, L_FIX
} }, // "sprmTSplit" tap.fFirstMerged, tap.fMerged complex
225 {163, { 5, L_FIX
} }, // "sprmTSetBrc10" tap.rgtc[].rgbrc complex 5 bytes
226 {164, { 4, L_FIX
} }, // "sprmTSetShd", tap.rgshd complex 4 bytes
229 static wwSprmSearcher
aSprmSrch(aSprms
, SAL_N_ELEMENTS(aSprms
));
233 const wwSprmSearcher
*wwSprmParser::GetWW6SprmSearcher(const WW8Fib
& rFib
)
237 static const SprmInfoRow aSprms
[] =
239 { 0, { 0, L_FIX
} }, // "Default-sprm", is skipped
240 {NS_sprm::v6::sprmPIstd
, { 2, L_FIX
} }, // pap.istd (style code)
241 {NS_sprm::v6::sprmPIstdPermute
, { 3, L_VAR
} }, // pap.istd permutation
242 {NS_sprm::v6::sprmPIncLv1
, { 1, L_FIX
} }, // pap.istddifference
243 {NS_sprm::v6::sprmPJc
, { 1, L_FIX
} }, // pap.jc (justification)
244 {NS_sprm::v6::sprmPFSideBySide
, { 1, L_FIX
} }, // pap.fSideBySide
245 {NS_sprm::v6::sprmPFKeep
, { 1, L_FIX
} }, // pap.fKeep
246 {NS_sprm::v6::sprmPFKeepFollow
, { 1, L_FIX
} }, // pap.fKeepFollow
247 {NS_sprm::v6::sprmPPageBreakBefore
, { 1, L_FIX
} }, // pap.fPageBreakBefore
248 {NS_sprm::v6::sprmPBrcl
, { 1, L_FIX
} }, // pap.brcl
249 {NS_sprm::v6::sprmPBrcp
, { 1, L_FIX
} }, // pap.brcp
250 {NS_sprm::v6::sprmPAnld
, { 0, L_VAR
} }, // pap.anld (ANLD structure)
251 {NS_sprm::v6::sprmPNLvlAnm
, { 1, L_FIX
} }, // pap.nLvlAnm nn
252 {NS_sprm::v6::sprmPFNoLineNumb
, { 1, L_FIX
} }, // pap.fNoLnn
253 {NS_sprm::v6::sprmPChgTabsPapx
, { 0, L_VAR
} }, // pap.itbdMac, ...
254 {NS_sprm::v6::sprmPDxaRight
, { 2, L_FIX
} }, // pap.dxaRight
255 {NS_sprm::v6::sprmPDxaLeft
, { 2, L_FIX
} }, // pap.dxaLeft
256 {NS_sprm::v6::sprmPNest
, { 2, L_FIX
} }, // pap.dxaLeft
257 {NS_sprm::v6::sprmPDxaLeft1
, { 2, L_FIX
} }, // pap.dxaLeft1
258 {NS_sprm::v6::sprmPDyaLine
, { 4, L_FIX
} }, // pap.lspd an LSPD
259 {NS_sprm::v6::sprmPDyaBefore
, { 2, L_FIX
} }, // pap.dyaBefore
260 {NS_sprm::v6::sprmPDyaAfter
, { 2, L_FIX
} }, // pap.dyaAfter
261 {NS_sprm::v6::sprmPChgTabs
, { 0, L_VAR
} }, // pap.itbdMac, pap.rgdxaTab, ...
262 {NS_sprm::v6::sprmPFInTable
, { 1, L_FIX
} }, // pap.fInTable
263 {NS_sprm::v6::sprmPTtp
, { 1, L_FIX
} }, // pap.fTtp
264 {NS_sprm::v6::sprmPDxaAbs
, { 2, L_FIX
} }, // pap.dxaAbs
265 {NS_sprm::v6::sprmPDyaAbs
, { 2, L_FIX
} }, // pap.dyaAbs
266 {NS_sprm::v6::sprmPDxaWidth
, { 2, L_FIX
} }, // pap.dxaWidth
267 {NS_sprm::v6::sprmPPc
, { 1, L_FIX
} }, // pap.pcHorz, pap.pcVert
268 {NS_sprm::v6::sprmPBrcTop10
, { 2, L_FIX
} }, // pap.brcTop BRC10
269 {NS_sprm::v6::sprmPBrcLeft10
, { 2, L_FIX
} }, // pap.brcLeft BRC10
270 {NS_sprm::v6::sprmPBrcBottom10
, { 2, L_FIX
} }, // pap.brcBottom BRC10
271 {NS_sprm::v6::sprmPBrcRight10
, { 2, L_FIX
} }, // pap.brcRight BRC10
272 {NS_sprm::v6::sprmPBrcBetween10
, { 2, L_FIX
} }, // pap.brcBetween BRC10
273 {NS_sprm::v6::sprmPBrcBar10
, { 2, L_FIX
} }, // pap.brcBar BRC10
274 {NS_sprm::v6::sprmPFromText10
, { 2, L_FIX
} }, // pap.dxaFromText dxa
275 {NS_sprm::v6::sprmPWr
, { 1, L_FIX
} }, // pap.wr wr
276 {NS_sprm::v6::sprmPBrcTop
, { 2, L_FIX
} }, // pap.brcTop BRC
277 {NS_sprm::v6::sprmPBrcLeft
, { 2, L_FIX
} }, // pap.brcLeft BRC
278 {NS_sprm::v6::sprmPBrcBottom
, { 2, L_FIX
} }, // pap.brcBottom BRC
279 {NS_sprm::v6::sprmPBrcRight
, { 2, L_FIX
} }, // pap.brcRight BRC
280 {NS_sprm::v6::sprmPBrcBetween
, { 2, L_FIX
} }, // pap.brcBetween BRC
281 {NS_sprm::v6::sprmPBrcBar
, { 2, L_FIX
} }, // pap.brcBar BRC word
282 {NS_sprm::v6::sprmPFNoAutoHyph
, { 1, L_FIX
} }, // pap.fNoAutoHyph
283 {NS_sprm::v6::sprmPWHeightAbs
, { 2, L_FIX
} }, // pap.wHeightAbs w
284 {NS_sprm::v6::sprmPDcs
, { 2, L_FIX
} }, // pap.dcs DCS
285 {NS_sprm::v6::sprmPShd
, { 2, L_FIX
} }, // pap.shd SHD
286 {NS_sprm::v6::sprmPDyaFromText
, { 2, L_FIX
} }, // pap.dyaFromText dya
287 {NS_sprm::v6::sprmPDxaFromText
, { 2, L_FIX
} }, // pap.dxaFromText dxa
288 {NS_sprm::v6::sprmPFLocked
, { 1, L_FIX
} }, // pap.fLocked 0 or 1 byte
289 {NS_sprm::v6::sprmPFWidowControl
, { 1, L_FIX
} }, // pap.fWidowControl 0 or 1 byte
290 {NS_sprm::v6::sprmPRuler
, { 0, L_FIX
} },
291 { 64, { 0, L_VAR
} }, // rtl property ?
292 {NS_sprm::v6::sprmCFStrikeRM
, { 1, L_FIX
} }, // chp.fRMarkDel 1 or 0 bit
293 {NS_sprm::v6::sprmCFRMark
, { 1, L_FIX
} }, // chp.fRMark 1 or 0 bit
294 {NS_sprm::v6::sprmCFFldVanish
, { 1, L_FIX
} }, // chp.fFieldVanish 1 or 0 bit
295 {NS_sprm::v6::sprmCPicLocation
, { 0, L_VAR
} }, // chp.fcPic and chp.fSpec
296 {NS_sprm::v6::sprmCIbstRMark
, { 2, L_FIX
} }, // chp.ibstRMark index into sttbRMark
297 {NS_sprm::v6::sprmCDttmRMark
, { 4, L_FIX
} }, // chp.dttm DTTM long
298 {NS_sprm::v6::sprmCFData
, { 1, L_FIX
} }, // chp.fData 1 or 0 bit
299 {NS_sprm::v6::sprmCRMReason
, { 2, L_FIX
} }, // chp.idslRMReason an index to a table
300 {NS_sprm::v6::sprmCChse
, { 3, L_FIX
} }, // chp.fChsDiff and chp.chse
301 {NS_sprm::v6::sprmCSymbol
, { 0, L_VAR
} }, // chp.fSpec, chp.chSym and chp.ftcSym
302 {NS_sprm::v6::sprmCFOle2
, { 1, L_FIX
} }, // chp.fOle2 1 or 0 bit
303 { 77, { 0, L_VAR
} }, // unknown
304 { 79, { 0, L_VAR
} }, // unknown
305 {NS_sprm::v6::sprmCIstd
, { 2, L_FIX
} }, // chp.istd istd, see stylesheet definition
306 {NS_sprm::v6::sprmCIstdPermute
, { 0, L_VAR
} }, // chp.istd permutation vector
307 {NS_sprm::v6::sprmCDefault
, { 0, L_VAR
} }, // whole CHP
308 {NS_sprm::v6::sprmCPlain
, { 0, L_FIX
} }, // whole CHP
309 {NS_sprm::v6::sprmCFBold
, { 1, L_FIX
} }, // chp.fBold 0,1, 128, or 129
310 {NS_sprm::v6::sprmCFItalic
, { 1, L_FIX
} }, // chp.fItalic 0,1, 128, or 129
311 {NS_sprm::v6::sprmCFStrike
, { 1, L_FIX
} }, // chp.fStrike 0,1, 128, or 129
312 {NS_sprm::v6::sprmCFOutline
, { 1, L_FIX
} }, // chp.fOutline 0,1, 128, or 129
313 {NS_sprm::v6::sprmCFShadow
, { 1, L_FIX
} }, // chp.fShadow 0,1, 128, or 129
314 {NS_sprm::v6::sprmCFSmallCaps
, { 1, L_FIX
} }, // chp.fSmallCaps 0,1, 128, or 129
315 {NS_sprm::v6::sprmCFCaps
, { 1, L_FIX
} }, // chp.fCaps 0,1, 128, or 129
316 {NS_sprm::v6::sprmCFVanish
, { 1, L_FIX
} }, // chp.fVanish 0,1, 128, or 129
317 {NS_sprm::v6::sprmCFtc
, { 2, L_FIX
} }, // chp.ftc ftc word
318 {NS_sprm::v6::sprmCKul
, { 1, L_FIX
} }, // chp.kul kul byte
319 {NS_sprm::v6::sprmCSizePos
, { 3, L_FIX
} }, // chp.hps, chp.hpsPos
320 {NS_sprm::v6::sprmCDxaSpace
, { 2, L_FIX
} }, // chp.dxaSpace dxa
321 {NS_sprm::v6::sprmCLid
, { 2, L_FIX
} }, // chp.lid LID
322 {NS_sprm::v6::sprmCIco
, { 1, L_FIX
} }, // chp.ico ico byte
323 {NS_sprm::v6::sprmCHps
, { 2, L_FIX
} }, // chp.hps hps !word!
324 {NS_sprm::v6::sprmCHpsInc
, { 1, L_FIX
} }, // chp.hps
325 {NS_sprm::v6::sprmCHpsPos
, { 2, L_FIX
} }, // chp.hpsPos hps !word!
326 {NS_sprm::v6::sprmCHpsPosAdj
, { 1, L_FIX
} }, // chp.hpsPos hps
327 {NS_sprm::v6::sprmCMajority
, { 0, L_VAR
} }, // chp.fBold, chp.fItalic, ...
328 {NS_sprm::v6::sprmCIss
, { 1, L_FIX
} }, // chp.iss iss
329 {NS_sprm::v6::sprmCHpsNew50
, { 0, L_VAR
} }, // chp.hps hps variable width
330 {NS_sprm::v6::sprmCHpsInc1
, { 0, L_VAR
} }, // chp.hps complex
331 {NS_sprm::v6::sprmCHpsKern
, { 2, L_FIX
} }, // chp.hpsKern hps
332 {NS_sprm::v6::sprmCMajority50
, { 0, L_VAR
} }, // chp.fBold, chp.fItalic, ...
333 {NS_sprm::v6::sprmCHpsMul
, { 2, L_FIX
} }, // chp.hps percentage to grow hps
334 {NS_sprm::v6::sprmCCondHyhen
, { 2, L_FIX
} }, // chp.ysri ysri
335 {111, { 0, L_VAR
} }, // sprmCFBoldBi or font code
336 {112, { 0, L_VAR
} }, // sprmCFItalicBi or font code
337 {113, { 0, L_VAR
} }, // ww7 rtl font
338 {114, { 0, L_VAR
} }, // ww7 lid
339 {115, { 0, L_VAR
} }, // ww7 CJK font
340 {116, { 0, L_VAR
} }, // ww7 fontsize
341 {NS_sprm::v6::sprmCFSpec
, { 1, L_FIX
} }, // chp.fSpec 1 or 0 bit
342 {NS_sprm::v6::sprmCFObj
, { 1, L_FIX
} }, // chp.fObj 1 or 0 bit
343 {NS_sprm::v6::sprmPicBrcl
, { 1, L_FIX
} }, // pic.brcl brcl (see PIC definition)
344 {NS_sprm::v6::sprmPicScale
, {12, L_VAR
} }, // pic.mx, pic.my, pic.dxaCropleft,
345 {NS_sprm::v6::sprmPicBrcTop
, { 2, L_FIX
} }, // pic.brcTop BRC word
346 {NS_sprm::v6::sprmPicBrcLeft
, { 2, L_FIX
} }, // pic.brcLeft BRC word
347 {NS_sprm::v6::sprmPicBrcBottom
, { 2, L_FIX
} }, // pic.brcBottom BRC word
348 {NS_sprm::v6::sprmPicBrcRight
, { 2, L_FIX
} }, // pic.brcRight BRC word
349 {NS_sprm::v6::sprmSScnsPgn
, { 1, L_FIX
} }, // sep.cnsPgn cns byte
350 {NS_sprm::v6::sprmSiHeadingPgn
, { 1, L_FIX
} }, // sep.iHeadingPgn
351 {NS_sprm::v6::sprmSOlstAnm
, { 0, L_VAR
} }, // sep.olstAnm OLST variable length
352 {NS_sprm::v6::sprmSDxaColWidth
, { 3, L_FIX
} }, // sep.rgdxaColWidthSpacing complex
353 {NS_sprm::v6::sprmSDxaColSpacing
, { 3, L_FIX
} }, // sep.rgdxaColWidthSpacing
354 {NS_sprm::v6::sprmSFEvenlySpaced
, { 1, L_FIX
} }, // sep.fEvenlySpaced 1 or 0
355 {NS_sprm::v6::sprmSFProtected
, { 1, L_FIX
} }, // sep.fUnlocked 1 or 0 byte
356 {NS_sprm::v6::sprmSDmBinFirst
, { 2, L_FIX
} }, // sep.dmBinFirst word
357 {NS_sprm::v6::sprmSDmBinOther
, { 2, L_FIX
} }, // sep.dmBinOther word
358 {NS_sprm::v6::sprmSBkc
, { 1, L_FIX
} }, // sep.bkc bkc byte
359 {NS_sprm::v6::sprmSFTitlePage
, { 1, L_FIX
} }, // sep.fTitlePage 0 or 1 byte
360 {NS_sprm::v6::sprmSCcolumns
, { 2, L_FIX
} }, // sep.ccolM1 # of cols - 1 word
361 {NS_sprm::v6::sprmSDxaColumns
, { 2, L_FIX
} }, // sep.dxaColumns dxa word
362 {NS_sprm::v6::sprmSFAutoPgn
, { 1, L_FIX
} }, // sep.fAutoPgn obsolete byte
363 {NS_sprm::v6::sprmSNfcPgn
, { 1, L_FIX
} }, // sep.nfcPgn nfc byte
364 {NS_sprm::v6::sprmSDyaPgn
, { 2, L_FIX
} }, // sep.dyaPgn dya short
365 {NS_sprm::v6::sprmSDxaPgn
, { 2, L_FIX
} }, // sep.dxaPgn dya short
366 {NS_sprm::v6::sprmSFPgnRestart
, { 1, L_FIX
} }, // sep.fPgnRestart 0 or 1 byte
367 {NS_sprm::v6::sprmSFEndnote
, { 1, L_FIX
} }, // sep.fEndnote 0 or 1 byte
368 {NS_sprm::v6::sprmSLnc
, { 1, L_FIX
} }, // sep.lnc lnc byte
369 {NS_sprm::v6::sprmSGprfIhdt
, { 1, L_FIX
} }, // sep.grpfIhdt grpfihdt
370 {NS_sprm::v6::sprmSNLnnMod
, { 2, L_FIX
} }, // sep.nLnnMod non-neg int. word
371 {NS_sprm::v6::sprmSDxaLnn
, { 2, L_FIX
} }, // sep.dxaLnn dxa word
372 {NS_sprm::v6::sprmSDyaHdrTop
, { 2, L_FIX
} }, // sep.dyaHdrTop dya word
373 {NS_sprm::v6::sprmSDyaHdrBottom
, { 2, L_FIX
} }, // sep.dyaHdrBottom dya word
374 {NS_sprm::v6::sprmSLBetween
, { 1, L_FIX
} }, // sep.fLBetween 0 or 1 byte
375 {NS_sprm::v6::sprmSVjc
, { 1, L_FIX
} }, // sep.vjc vjc byte
376 {NS_sprm::v6::sprmSLnnMin
, { 2, L_FIX
} }, // sep.lnnMin lnn word
377 {NS_sprm::v6::sprmSPgnStart
, { 2, L_FIX
} }, // sep.pgnStart pgn word
378 {NS_sprm::v6::sprmSBOrientation
, { 1, L_FIX
} }, // sep.dmOrientPage dm byte
379 {NS_sprm::v6::sprmSBCustomize
, { 0, L_FIX
} },
380 {NS_sprm::v6::sprmSXaPage
, { 2, L_FIX
} }, // sep.xaPage xa word
381 {NS_sprm::v6::sprmSYaPage
, { 2, L_FIX
} }, // sep.yaPage ya word
382 {NS_sprm::v6::sprmSDxaLeft
, { 2, L_FIX
} }, // sep.dxaLeft dxa word
383 {NS_sprm::v6::sprmSDxaRight
, { 2, L_FIX
} }, // sep.dxaRight dxa word
384 {NS_sprm::v6::sprmSDyaTop
, { 2, L_FIX
} }, // sep.dyaTop dya word
385 {NS_sprm::v6::sprmSDyaBottom
, { 2, L_FIX
} }, // sep.dyaBottom dya word
386 {NS_sprm::v6::sprmSDzaGutter
, { 2, L_FIX
} }, // sep.dzaGutter dza word
387 {NS_sprm::v6::sprmSDMPaperReq
, { 2, L_FIX
} }, // sep.dmPaperReq dm word
388 {179, { 0, L_VAR
} }, // rtl property ?
389 {181, { 0, L_VAR
} }, // rtl property ?
390 {NS_sprm::v6::sprmTJc
, { 2, L_FIX
} }, // tap.jc jc (low order byte is significant)
391 {NS_sprm::v6::sprmTDxaLeft
, { 2, L_FIX
} }, // tap.rgdxaCenter dxa word
392 {NS_sprm::v6::sprmTDxaGapHalf
, { 2, L_FIX
} }, // tap.dxaGapHalf, tap.rgdxaCenter
393 {NS_sprm::v6::sprmTFCantSplit
, { 1, L_FIX
} }, // tap.fCantSplit 1 or 0 byte
394 {NS_sprm::v6::sprmTTableHeader
, { 1, L_FIX
} }, // tap.fTableHeader 1 or 0 byte
395 {NS_sprm::v6::sprmTTableBorders
, {12, L_FIX
} }, // tap.rgbrcTable complex 12 bytes
396 {NS_sprm::v6::sprmTDefTable10
, { 0, L_VAR2
} }, // tap.rgdxaCenter, tap.rgtc complex
397 {NS_sprm::v6::sprmTDyaRowHeight
, { 2, L_FIX
} }, // tap.dyaRowHeight dya word
398 {NS_sprm::v6::sprmTDefTable
, { 0, L_VAR2
} }, // tap.rgtc complex
399 {NS_sprm::v6::sprmTDefTableShd
, { 1, L_VAR
} }, // tap.rgshd complex
400 {NS_sprm::v6::sprmTTlp
, { 4, L_FIX
} }, // tap.tlp TLP 4 bytes
401 {NS_sprm::v6::sprmTSetBrc
, { 5, L_FIX
} }, // tap.rgtc[].rgbrc complex 5 bytes
402 {NS_sprm::v6::sprmTInsert
, { 4, L_FIX
} }, // tap.rgdxaCenter,tap.rgtc complex
403 {NS_sprm::v6::sprmTDelete
, { 2, L_FIX
} }, // tap.rgdxaCenter, tap.rgtc complex
404 {NS_sprm::v6::sprmTDxaCol
, { 4, L_FIX
} }, // tap.rgdxaCenter complex
405 {NS_sprm::v6::sprmTMerge
, { 2, L_FIX
} }, // tap.fFirstMerged, tap.fMerged complex
406 {NS_sprm::v6::sprmTSplit
, { 2, L_FIX
} }, // tap.fFirstMerged, tap.fMerged complex
407 {NS_sprm::v6::sprmTSetBrc10
, { 5, L_FIX
} }, // tap.rgtc[].rgbrc complex 5 bytes
408 {NS_sprm::v6::sprmTSetShd
, { 4, L_FIX
} }, // tap.rgshd complex 4 bytes
409 {207, { 0, L_VAR
} } // rtl property ?
412 if (rFib
.m_wIdent
>= 0xa697 && rFib
.m_wIdent
<= 0xa699)
414 //see Read_AmbiguousSPRM for this oddity
415 static wwSprmSearcher
aSprmSrch(aSprms
, SAL_N_ELEMENTS(aSprms
), true);
419 static wwSprmSearcher
aSprmSrch(aSprms
, SAL_N_ELEMENTS(aSprms
));
423 void wwSprmSearcher::patchCJKVariant()
425 for (sal_uInt16 nId
= 111; nId
<= 113; ++nId
)
427 SprmInfo
& amb1
= map_
[nId
];
429 amb1
.nVari
= wwSprmParser::L_FIX
;
433 template <class Sprm
> static constexpr SprmInfoRow
InfoRow()
435 return { Sprm::val
, { Sprm::len
, Sprm::varlen
? wwSprmParser::L_VAR
: wwSprmParser::L_FIX
} };
438 const wwSprmSearcher
*wwSprmParser::GetWW8SprmSearcher()
442 static const SprmInfoRow aSprms
[] =
444 { 0, { 0, L_FIX
} }, // "Default-sprm"/ is skipped
445 InfoRow
<NS_sprm::PIstd
>(), // pap.istd;istd (style code);short;
446 InfoRow
<NS_sprm::PIstdPermute
>(), // pap.istd;permutation vector
447 InfoRow
<NS_sprm::PIncLvl
>(), // pap.istd, pap.lvl;difference
448 // between istd of base PAP and istd of PAP to be
450 InfoRow
<NS_sprm::PJc80
>(), // pap.jc;jc (justification);byte;
451 {NS_sprm::LN_PFSideBySide
, { 1, L_FIX
} }, // "sprmPFSideBySide" pap.fSideBySide;0 or 1;byte;
452 InfoRow
<NS_sprm::PFKeep
>(), // pap.fKeep;0 or 1;byte;
453 InfoRow
<NS_sprm::PFKeepFollow
>(), // pap.fKeepFollow;0 or 1;byte;
454 InfoRow
<NS_sprm::PFPageBreakBefore
>(), // pap.fPageBreakBefore;
456 {NS_sprm::LN_PBrcl
, { 1, L_FIX
} }, // "sprmPBrcl" pap.brcl;brcl;byte;
457 {NS_sprm::LN_PBrcp
, { 1, L_FIX
} }, // "sprmPBrcp" pap.brcp;brcp;byte;
458 InfoRow
<NS_sprm::PIlvl
>(), // pap.ilvl;ilvl;byte;
459 InfoRow
<NS_sprm::PIlfo
>(), // pap.ilfo;ilfo (list index) ;short;
460 InfoRow
<NS_sprm::PFNoLineNumb
>(), // pap.fNoLnn;0 or 1;byte;
461 InfoRow
<NS_sprm::PChgTabsPapx
>(), // pap.itbdMac, pap.rgdxaTab,
463 InfoRow
<NS_sprm::PDxaRight80
>(), // pap.dxaRight;dxa;word;
464 InfoRow
<NS_sprm::PDxaLeft80
>(), // pap.dxaLeft;dxa;word;
465 InfoRow
<NS_sprm::PNest80
>(), // pap.dxaLeft;dxa
466 InfoRow
<NS_sprm::PDxaLeft180
>(), // pap.dxaLeft1;dxa;word;
467 InfoRow
<NS_sprm::PDyaLine
>(), // pap.lspd;an LSPD, a long word
468 // structure consisting of a short of dyaLine
469 // followed by a short of fMultLinespace
470 InfoRow
<NS_sprm::PDyaBefore
>(), // pap.dyaBefore;dya;word;
471 InfoRow
<NS_sprm::PDyaAfter
>(), // pap.dyaAfter;dya;word;
472 InfoRow
<NS_sprm::PChgTabs
>(), // pap.itbdMac, pap.rgdxaTab,
474 InfoRow
<NS_sprm::PFInTable
>(), // pap.fInTable;0 or 1;byte;
475 InfoRow
<NS_sprm::PFTtp
>(), // pap.fTtp;0 or 1;byte;
476 InfoRow
<NS_sprm::PDxaAbs
>(), // pap.dxaAbs;dxa;word;
477 InfoRow
<NS_sprm::PDyaAbs
>(), // pap.dyaAbs;dya;word;
478 InfoRow
<NS_sprm::PDxaWidth
>(), // pap.dxaWidth;dxa;word;
479 InfoRow
<NS_sprm::PPc
>(), // pap.pcHorz, pap.pcVert;complex
480 {NS_sprm::LN_PBrcTop10
, { 2, L_FIX
} }, // "sprmPBrcTop10" pap.brcTop;BRC10;word;
481 {NS_sprm::LN_PBrcLeft10
, { 2, L_FIX
} }, // "sprmPBrcLeft10" pap.brcLeft;BRC10;word;
482 {NS_sprm::LN_PBrcBottom10
, { 2, L_FIX
} }, // "sprmPBrcBottom10" pap.brcBottom;BRC10;word;
483 {NS_sprm::LN_PBrcRight10
, { 2, L_FIX
} }, // "sprmPBrcRight10" pap.brcRight;BRC10;word;
484 {NS_sprm::LN_PBrcBetween10
, { 2, L_FIX
} }, // "sprmPBrcBetween10" pap.brcBetween;BRC10;word;
485 {NS_sprm::LN_PBrcBar10
, { 2, L_FIX
} }, // "sprmPBrcBar10" pap.brcBar;BRC10;word;
486 {NS_sprm::LN_PDxaFromText10
, { 2, L_FIX
} }, // "sprmPDxaFromText10" pap.dxaFromText;dxa;word;
487 InfoRow
<NS_sprm::PWr
>(), // pap.wr;wr
488 InfoRow
<NS_sprm::PBrcTop80
>(), // pap.brcTop;BRC;long;
489 InfoRow
<NS_sprm::PBrcLeft80
>(), // pap.brcLeft;BRC;long;
490 InfoRow
<NS_sprm::PBrcBottom80
>(), // pap.brcBottom;BRC;long;
491 InfoRow
<NS_sprm::PBrcRight80
>(), // pap.brcRight;BRC;long;
492 InfoRow
<NS_sprm::PBrcBetween80
>(), // pap.brcBetween;BRC;long;
493 InfoRow
<NS_sprm::PBrcBar80
>(), // pap.brcBar;BRC;long;
494 InfoRow
<NS_sprm::PFNoAutoHyph
>(), // pap.fNoAutoHyph;0 or 1;byte;
495 InfoRow
<NS_sprm::PWHeightAbs
>(), // pap.wHeightAbs;w;word;
496 InfoRow
<NS_sprm::PDcs
>(), // pap.dcs;DCS;short;
497 InfoRow
<NS_sprm::PShd80
>(), // pap.shd;SHD;word;
498 InfoRow
<NS_sprm::PDyaFromText
>(), // pap.dyaFromText;dya;word;
499 InfoRow
<NS_sprm::PDxaFromText
>(), // pap.dxaFromText;dxa;word;
500 InfoRow
<NS_sprm::PFLocked
>(), // pap.fLocked;0 or 1;byte;
501 InfoRow
<NS_sprm::PFWidowControl
>(), // pap.fWidowControl;0 or 1
502 {NS_sprm::LN_PRuler
, { 0, L_VAR
} }, // "sprmPRuler" ;;variable length;
503 InfoRow
<NS_sprm::PFKinsoku
>(), // pap.fKinsoku;0 or 1;byte;
504 InfoRow
<NS_sprm::PFWordWrap
>(), // pap.fWordWrap;0 or 1;byte;
505 InfoRow
<NS_sprm::PFOverflowPunct
>(), // pap.fOverflowPunct;0 or 1
506 InfoRow
<NS_sprm::PFTopLinePunct
>(), // pap.fTopLinePunct;0 or 1
507 InfoRow
<NS_sprm::PFAutoSpaceDE
>(), // pap.fAutoSpaceDE;0 or 1
508 InfoRow
<NS_sprm::PFAutoSpaceDN
>(), // pap.fAutoSpaceDN;0 or 1
509 InfoRow
<NS_sprm::PWAlignFont
>(), // pap.wAlignFont;iFa
510 InfoRow
<NS_sprm::PFrameTextFlow
>(), // pap.fVertical pap.fBackward
511 // pap.fRotateFont;complex
512 {NS_sprm::LN_PISnapBaseLine
, { 1, L_FIX
} }, // "sprmPISnapBaseLine" obsolete: not applicable in
513 // Word97 and later versions;
514 {NS_sprm::LN_PAnld
, { 0, L_VAR
} }, // "sprmPAnld" pap.anld;;variable length;
515 {NS_sprm::LN_PPropRMark
, { 0, L_VAR
} }, // "sprmPPropRMark" pap.fPropRMark;complex
516 InfoRow
<NS_sprm::POutLvl
>(), // pap.lvl;has no effect if pap.istd
518 InfoRow
<NS_sprm::PFBiDi
>(), // ;;byte;
519 InfoRow
<NS_sprm::PFNumRMIns
>(), // pap.fNumRMIns;1 or 0;bit;
520 {NS_sprm::LN_PCrLf
, { 1, L_FIX
} }, // "sprmPCrLf" ;;byte;
521 InfoRow
<NS_sprm::PNumRM
>(), // pap.numrm;;variable length;
522 {NS_sprm::LN_PHugePapx
, { 4, L_FIX
} }, // "sprmPHugePapx" fc in the data stream to locate
524 InfoRow
<NS_sprm::PHugePapx
>(), // fc in the data stream to locate
526 InfoRow
<NS_sprm::PFUsePgsuSettings
>(), // pap.fUsePgsuSettings;
528 InfoRow
<NS_sprm::PFAdjustRight
>(), // pap.fAdjustRight;1 or 0;byte;
529 InfoRow
<NS_sprm::CFRMarkDel
>(), // chp.fRMarkDel;1 or 0;bit;
530 InfoRow
<NS_sprm::CFRMarkIns
>(), // chp.fRMark;1 or 0;bit;
531 InfoRow
<NS_sprm::CFFldVanish
>(), // chp.fFieldVanish;1 or 0;bit;
532 InfoRow
<NS_sprm::CPicLocation
>(), // chp.fcPic and chp.fSpec;
533 InfoRow
<NS_sprm::CIbstRMark
>(), // chp.ibstRMark;index into
535 InfoRow
<NS_sprm::CDttmRMark
>(), // chp.dttmRMark;DTTM;long;
536 InfoRow
<NS_sprm::CFData
>(), // chp.fData;1 or 0;bit;
537 InfoRow
<NS_sprm::CIdslRMark
>(), // chp.idslRMReason;an index to a
538 // table of strings defined in Word 6.0
539 // executables;short;
540 {NS_sprm::LN_CChs
, { 1, L_FIX
} }, // "sprmCChs" chp.fChsDiff and chp.chse;
541 InfoRow
<NS_sprm::CSymbol
>(), // chp.fSpec, chp.xchSym and
543 InfoRow
<NS_sprm::CFOle2
>(), // chp.fOle2;1 or 0;bit;
544 {NS_sprm::LN_CIdCharType
, { 0, L_FIX
} }, // "sprmCIdCharType" obsolete: not applicable in
545 // Word97 and later versions;
546 InfoRow
<NS_sprm::CHighlight
>(), // chp.fHighlight,
547 // chp.icoHighlight;ico (fHighlight is set to 1 iff
549 {NS_sprm::LN_CObjLocation
, { 4, L_FIX
} }, // "sprmCObjLocation" chp.fcObj;FC;long;
550 {NS_sprm::LN_CFFtcAsciSymb
, { 0, L_FIX
} }, // "sprmCFFtcAsciSymb" ;;;
551 InfoRow
<NS_sprm::CIstd
>(), // chp.istd;istd, see stylesheet def
552 InfoRow
<NS_sprm::CIstdPermute
>(), // chp.istd;permutation vector
553 {NS_sprm::LN_CDefault
, { 0, L_VAR
} }, // "sprmCDefault" whole CHP;none;variable length;
554 InfoRow
<NS_sprm::CPlain
>(), // whole CHP;none;0;
555 InfoRow
<NS_sprm::CKcd
>(), // ;;;
556 InfoRow
<NS_sprm::CFBold
>(), // chp.fBold;0,1, 128, or 129
557 InfoRow
<NS_sprm::CFItalic
>(), // chp.fItalic;0,1, 128, or 129
558 InfoRow
<NS_sprm::CFStrike
>(), // chp.fStrike;0,1, 128, or 129
559 InfoRow
<NS_sprm::CFOutline
>(), // chp.fOutline;0,1, 128, or 129
560 InfoRow
<NS_sprm::CFShadow
>(), // chp.fShadow;0,1, 128, or 129
561 InfoRow
<NS_sprm::CFSmallCaps
>(), // chp.fSmallCaps;0,1, 128, or 129
562 InfoRow
<NS_sprm::CFCaps
>(), // chp.fCaps;0,1, 128, or 129
563 InfoRow
<NS_sprm::CFVanish
>(), // chp.fVanish;0,1, 128, or 129
564 {NS_sprm::LN_CFtcDefault
, { 2, L_FIX
} }, // "sprmCFtcDefault" ;ftc, only used internally
565 InfoRow
<NS_sprm::CKul
>(), // chp.kul;kul;byte;
566 {NS_sprm::LN_CSizePos
, { 3, L_FIX
} }, // "sprmCSizePos" chp.hps, chp.hpsPos;3 bytes;
567 InfoRow
<NS_sprm::CDxaSpace
>(), // chp.dxaSpace;dxa;word;
568 {NS_sprm::LN_CLid
, { 2, L_FIX
} }, // "sprmCLid" ;only used internally never stored
569 InfoRow
<NS_sprm::CIco
>(), // chp.ico;ico;byte;
570 InfoRow
<NS_sprm::CHps
>(), // chp.hps;hps
571 {NS_sprm::LN_CHpsInc
, { 1, L_FIX
} }, // "sprmCHpsInc" chp.hps;
572 InfoRow
<NS_sprm::CHpsPos
>(), // chp.hpsPos;hps;short; (doc wrong)
573 {NS_sprm::LN_CHpsPosAdj
, { 1, L_FIX
} }, // "sprmCHpsPosAdj" chp.hpsPos;hps
574 InfoRow
<NS_sprm::CMajority
>(), // chp.fBold, chp.fItalic,
575 // chp.fSmallCaps, chp.fVanish, chp.fStrike,
576 // chp.fCaps, chp.rgftc, chp.hps, chp.hpsPos,
577 // chp.kul, chp.dxaSpace, chp.ico,
578 // chp.rglid;complex;variable length, length byte
579 // plus size of following grpprl;
580 InfoRow
<NS_sprm::CIss
>(), // chp.iss;iss;byte;
581 {NS_sprm::LN_CHpsNew50
, { 0, L_VAR
} }, // "sprmCHpsNew50" chp.hps;hps;variable width
582 {NS_sprm::LN_CHpsInc1
, { 0, L_VAR
} }, // "sprmCHpsInc1" chp.hps;complex
583 InfoRow
<NS_sprm::CHpsKern
>(), // chp.hpsKern;hps;short;
584 {NS_sprm::LN_CMajority50
, { 2, L_FIX
} }, // "sprmCMajority50" chp.fBold, chp.fItalic,
585 // chp.fSmallCaps, chp.fVanish, chp.fStrike,
586 // chp.fCaps, chp.ftc, chp.hps, chp.hpsPos, chp.kul,
587 // chp.dxaSpace, chp.ico,;complex
588 {NS_sprm::LN_CHpsMul
, { 2, L_FIX
} }, // "sprmCHpsMul" chp.hps;percentage to grow hps
589 InfoRow
<NS_sprm::CHresi
>(), // chp.ysri;ysri;short;
590 InfoRow
<NS_sprm::CRgFtc0
>(), // chp.rgftc[0];ftc for ASCII text
591 InfoRow
<NS_sprm::CRgFtc1
>(), // chp.rgftc[1];ftc for Far East text
592 InfoRow
<NS_sprm::CRgFtc2
>(), // chp.rgftc[2];ftc for non-FE text
593 InfoRow
<NS_sprm::CCharScale
>(),
594 InfoRow
<NS_sprm::CFDStrike
>(), // chp.fDStrike;;byte;
595 InfoRow
<NS_sprm::CFImprint
>(), // chp.fImprint;1 or 0;bit;
596 InfoRow
<NS_sprm::CFSpec
>(), // chp.fSpec ;1 or 0;bit;
597 InfoRow
<NS_sprm::CFObj
>(), // chp.fObj;1 or 0;bit;
598 InfoRow
<NS_sprm::CPropRMark90
>(), // chp.fPropRMark,
599 // chp.ibstPropRMark, chp.dttmPropRMark;Complex
600 InfoRow
<NS_sprm::CFEmboss
>(), // chp.fEmboss;1 or 0;bit;
601 InfoRow
<NS_sprm::CSfxText
>(), // chp.sfxtText;text animation;byte;
602 InfoRow
<NS_sprm::CFBiDi
>(), // ;;;
603 {NS_sprm::LN_CFDiacColor
, { 1, L_FIX
} }, // "sprmCFDiacColor" ;;;
604 InfoRow
<NS_sprm::CFBoldBi
>(), // ;;;
605 InfoRow
<NS_sprm::CFItalicBi
>(), // ;;;
606 InfoRow
<NS_sprm::CFtcBi
>(),
607 InfoRow
<NS_sprm::CLidBi
>(), // ;;;
608 InfoRow
<NS_sprm::CIcoBi
>(), // ;;;
609 InfoRow
<NS_sprm::CHpsBi
>(), // ;;;
610 InfoRow
<NS_sprm::CDispFldRMark
>(), // chp.fDispFieldRMark,
611 // chp.ibstDispFieldRMark, chp.dttmDispFieldRMark ;
612 InfoRow
<NS_sprm::CIbstRMarkDel
>(), // chp.ibstRMarkDel;index into
614 InfoRow
<NS_sprm::CDttmRMarkDel
>(), // chp.dttmRMarkDel;DTTM;long;
615 InfoRow
<NS_sprm::CBrc80
>(), // chp.brc;BRC;long;
616 InfoRow
<NS_sprm::CShd80
>(), // chp.shd;SHD;short;
617 InfoRow
<NS_sprm::CIdslRMarkDel
>(), // chp.idslRMReasonDel;an index
618 // to a table of strings defined in Word 6.0
619 // executables;short;
620 InfoRow
<NS_sprm::CFUsePgsuSettings
>(),
621 // chp.fUsePgsuSettings;1 or 0
622 {NS_sprm::LN_CCpg
, { 2, L_FIX
} }, // "sprmCCpg" ;;word;
623 InfoRow
<NS_sprm::CRgLid0_80
>(), // chp.rglid[0];LID: for non-FE text
624 InfoRow
<NS_sprm::CRgLid1_80
>(), // chp.rglid[1];LID: for Far East text
625 InfoRow
<NS_sprm::CIdctHint
>(), // chp.idctHint;IDCT:
626 {NS_sprm::LN_PicBrcl
, { 1, L_FIX
} }, // "sprmPicBrcl" pic.brcl;brcl (see PIC definition)
627 {NS_sprm::LN_PicScale
, { 0, L_VAR
} }, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
628 // pic.dyaCropTop pic.dxaCropRight,
629 // pic.dyaCropBottom;Complex
630 InfoRow
<NS_sprm::PicBrcTop80
>(), // pic.brcTop;BRC;long;
631 InfoRow
<NS_sprm::PicBrcLeft80
>(), // pic.brcLeft;BRC;long;
632 InfoRow
<NS_sprm::PicBrcBottom80
>(), // pic.brcBottom;BRC;long;
633 InfoRow
<NS_sprm::PicBrcRight80
>(), // pic.brcRight;BRC;long;
634 InfoRow
<NS_sprm::ScnsPgn
>(), // sep.cnsPgn;cns;byte;
635 InfoRow
<NS_sprm::SiHeadingPgn
>(), // sep.iHeadingPgn;heading number
637 {NS_sprm::LN_SOlstAnm
, { 0, L_VAR
} }, // "sprmSOlstAnm" sep.olstAnm;OLST;variable length;
638 InfoRow
<NS_sprm::SDxaColWidth
>(), // sep.rgdxaColWidthSpacing;
639 InfoRow
<NS_sprm::SDxaColSpacing
>(), // sep.rgdxaColWidthSpacing;
641 InfoRow
<NS_sprm::SFEvenlySpaced
>(), // sep.fEvenlySpaced;1 or 0
642 InfoRow
<NS_sprm::SFProtected
>(), // sep.fUnlocked;1 or 0;byte;
643 InfoRow
<NS_sprm::SDmBinFirst
>(), // sep.dmBinFirst;;word;
644 InfoRow
<NS_sprm::SDmBinOther
>(), // sep.dmBinOther;;word;
645 InfoRow
<NS_sprm::SBkc
>(), // sep.bkc;bkc;byte;
646 InfoRow
<NS_sprm::SFTitlePage
>(), // sep.fTitlePage;0 or 1;byte;
647 InfoRow
<NS_sprm::SCcolumns
>(), // sep.ccolM1;# of cols - 1;word;
648 InfoRow
<NS_sprm::SDxaColumns
>(), // sep.dxaColumns;dxa;word;
649 {NS_sprm::LN_SFAutoPgn
, { 1, L_FIX
} }, // "sprmSFAutoPgn" sep.fAutoPgn;obsolete;byte;
650 InfoRow
<NS_sprm::SNfcPgn
>(), // sep.nfcPgn;nfc;byte;
651 {NS_sprm::LN_SDyaPgn
, { 2, L_FIX
} }, // "sprmSDyaPgn" sep.dyaPgn;dya;short;
652 {NS_sprm::LN_SDxaPgn
, { 2, L_FIX
} }, // "sprmSDxaPgn" sep.dxaPgn;dya;short;
653 InfoRow
<NS_sprm::SFPgnRestart
>(), // sep.fPgnRestart;0 or 1;byte;
654 InfoRow
<NS_sprm::SFEndnote
>(), // sep.fEndnote;0 or 1;byte;
655 InfoRow
<NS_sprm::SLnc
>(), // sep.lnc;lnc;byte;
656 {NS_sprm::LN_SGprfIhdt
, { 1, L_FIX
} }, // "sprmSGprfIhdt" sep.grpfIhdt;grpfihdt
657 InfoRow
<NS_sprm::SNLnnMod
>(), // sep.nLnnMod;non-neg int.;word;
658 InfoRow
<NS_sprm::SDxaLnn
>(), // sep.dxaLnn;dxa;word;
659 InfoRow
<NS_sprm::SDyaHdrTop
>(), // sep.dyaHdrTop;dya;word;
660 InfoRow
<NS_sprm::SDyaHdrBottom
>(), // sep.dyaHdrBottom;dya;word;
661 InfoRow
<NS_sprm::SLBetween
>(), // sep.fLBetween;0 or 1;byte;
662 InfoRow
<NS_sprm::SVjc
>(), // sep.vjc;vjc;byte;
663 InfoRow
<NS_sprm::SLnnMin
>(), // sep.lnnMin;lnn;word;
664 InfoRow
<NS_sprm::SPgnStart97
>(), // sep.pgnStart;pgn;word;
665 InfoRow
<NS_sprm::SBOrientation
>(), // sep.dmOrientPage;dm;byte;
666 {NS_sprm::LN_SBCustomize
, { 1, L_FIX
} }, // "sprmSBCustomize" ;;;
667 InfoRow
<NS_sprm::SXaPage
>(), // sep.xaPage;xa;word;
668 InfoRow
<NS_sprm::SYaPage
>(), // sep.yaPage;ya;word;
669 InfoRow
<NS_sprm::SDxaLeft
>(), // sep.dxaLeft;dxa;word;
670 InfoRow
<NS_sprm::SDxaRight
>(), // sep.dxaRight;dxa;word;
671 InfoRow
<NS_sprm::SDyaTop
>(), // sep.dyaTop;dya;word;
672 InfoRow
<NS_sprm::SDyaBottom
>(), // sep.dyaBottom;dya;word;
673 InfoRow
<NS_sprm::SDzaGutter
>(), // sep.dzaGutter;dza;word;
674 InfoRow
<NS_sprm::SDmPaperReq
>(), // sep.dmPaperReq;dm;word;
675 {NS_sprm::LN_SPropRMark
, { 0, L_VAR
} }, // "sprmSPropRMark" sep.fPropRMark,
676 // sep.ibstPropRMark, sep.dttmPropRMark ;complex
677 InfoRow
<NS_sprm::SFBiDi
>(), // ;;;
678 {NS_sprm::LN_SFFacingCol
, { 1, L_FIX
} }, // "sprmSFFacingCol" ;;;
679 InfoRow
<NS_sprm::SFRTLGutter
>(), //, set to one if gutter is on
681 InfoRow
<NS_sprm::SBrcTop80
>(), // sep.brcTop;BRC;long;
682 InfoRow
<NS_sprm::SBrcLeft80
>(), // sep.brcLeft;BRC;long;
683 InfoRow
<NS_sprm::SBrcBottom80
>(), // sep.brcBottom;BRC;long;
684 InfoRow
<NS_sprm::SBrcRight80
>(), // sep.brcRight;BRC;long;
685 InfoRow
<NS_sprm::SPgbProp
>(), // sep.pgbProp;;word;
686 InfoRow
<NS_sprm::SDxtCharSpace
>(), // sep.dxtCharSpace;dxt;long;
687 InfoRow
<NS_sprm::SDyaLinePitch
>(),
688 // sep.dyaLinePitch;dya; WRONG:long; RIGHT:short; !
689 InfoRow
<NS_sprm::SClm
>(), // ;;;
690 InfoRow
<NS_sprm::STextFlow
>(), // sep.wTextFlow;complex
691 InfoRow
<NS_sprm::TJc90
>(), // tap.jc;jc;word (low order byte is
693 InfoRow
<NS_sprm::TDxaLeft
>(), // tap.rgdxaCenter
694 InfoRow
<NS_sprm::TDxaGapHalf
>(), // tap.dxaGapHalf,
696 InfoRow
<NS_sprm::TFCantSplit90
>(), // tap.fCantSplit90;1 or 0;byte;
697 InfoRow
<NS_sprm::TTableHeader
>(), // tap.fTableHeader;1 or 0;byte;
698 InfoRow
<NS_sprm::TFCantSplit
>(), // tap.fCantSplit;1 or 0;byte;
699 InfoRow
<NS_sprm::TTableBorders80
>(), // tap.rgbrcTable;complex
700 {NS_sprm::LN_TDefTable10
, { 0, L_VAR2
} }, // "sprmTDefTable10" tap.rgdxaCenter,
702 InfoRow
<NS_sprm::TDyaRowHeight
>(), // tap.dyaRowHeight;dya;word;
703 {NS_sprm::LN_TDefTable
, { 0, L_VAR2
} }, // "sprmTDefTable" tap.rgtc;complex
704 InfoRow
<NS_sprm::TDefTableShd80
>(), // tap.rgshd;complex
705 InfoRow
<NS_sprm::TTlp
>(), // tap.tlp;TLP;4 bytes;
706 InfoRow
<NS_sprm::TFBiDi
>(), // ;;;
707 {NS_sprm::LN_THTMLProps
, { 1, L_FIX
} }, // "sprmTHTMLProps" ;;;
708 InfoRow
<NS_sprm::TSetBrc80
>(), // tap.rgtc[].rgbrc;complex
709 InfoRow
<NS_sprm::TInsert
>(), // tap.rgdxaCenter, tap.rgtc;complex
710 InfoRow
<NS_sprm::TDelete
>(), // tap.rgdxaCenter, tap.rgtc;complex
711 InfoRow
<NS_sprm::TDxaCol
>(), // tap.rgdxaCenter;complex
712 InfoRow
<NS_sprm::TMerge
>(), // tap.fFirstMerged, tap.fMerged;
713 InfoRow
<NS_sprm::TSplit
>(), // tap.fFirstMerged, tap.fMerged;
714 {NS_sprm::LN_TSetBrc10
, { 0, L_VAR
} }, // "sprmTSetBrc10" tap.rgtc[].rgbrc;complex
715 {NS_sprm::LN_TSetShd80
, { 0, L_VAR
} }, // "sprmTSetShd80" tap.rgshd;complex
716 {NS_sprm::LN_TSetShdOdd80
, { 0, L_VAR
} }, // "sprmTSetShdOdd80" tap.rgshd;complex
717 InfoRow
<NS_sprm::TTextFlow
>(), // tap.rgtc[].fVerticaltap,
718 // rgtc[].fBackwardtap, rgtc[].fRotateFont;0 or 10
720 {NS_sprm::LN_TDiagLine
, { 1, L_FIX
} }, // "sprmTDiagLine" ;;;
721 InfoRow
<NS_sprm::TVertMerge
>(), // tap.rgtc[].vertMerge
722 InfoRow
<NS_sprm::TVertAlign
>(), // tap.rgtc[].vertAlign
723 InfoRow
<NS_sprm::CFELayout
>(),
724 InfoRow
<NS_sprm::PItap
>(), // undocumented
725 InfoRow
<NS_sprm::TTableWidth
>(), // undocumented
726 InfoRow
<NS_sprm::TDefTableShd
>(),
727 InfoRow
<NS_sprm::TTableBorders
>(),
728 InfoRow
<NS_sprm::TBrcTopCv
>(), // undocumented
729 InfoRow
<NS_sprm::TBrcLeftCv
>(), // undocumented
730 InfoRow
<NS_sprm::TBrcBottomCv
>(), // undocumented
731 InfoRow
<NS_sprm::TBrcRightCv
>(), // undocumented
732 InfoRow
<NS_sprm::TCellPadding
>(), // undocumented
733 InfoRow
<NS_sprm::TCellPaddingDefault
>(), // undocumented
734 {0xD238, { 0, L_VAR
} }, // undocumented sep
735 InfoRow
<NS_sprm::PBrcTop
>(),
736 InfoRow
<NS_sprm::PBrcLeft
>(),
737 InfoRow
<NS_sprm::PBrcBottom
>(),
738 InfoRow
<NS_sprm::PBrcRight
>(),
739 InfoRow
<NS_sprm::PBrcBetween
>(),
740 InfoRow
<NS_sprm::TWidthIndent
>(), // undocumented
741 InfoRow
<NS_sprm::CRgLid0
>(), // chp.rglid[0];LID: for non-FE text
742 InfoRow
<NS_sprm::CRgLid1
>(), // chp.rglid[1];LID: for Far East text
743 {0x6463, { 4, L_FIX
} }, // undocumented
744 InfoRow
<NS_sprm::PJc
>(), // undoc, must be asian version of "sprmPJc"
745 InfoRow
<NS_sprm::PDxaRight
>(), // undoc, must be asian version of "sprmPDxaRight"
746 InfoRow
<NS_sprm::PDxaLeft
>(), // undoc, must be asian version of "sprmPDxaLeft"
747 InfoRow
<NS_sprm::PDxaLeft1
>(), // undoc, must be asian version of "sprmPDxaLeft1"
748 InfoRow
<NS_sprm::TFAutofit
>(), // undocumented
749 InfoRow
<NS_sprm::TPc
>(), // undocumented
750 InfoRow
<NS_sprm::SRsid
>(), // undocumented, sep, perhaps related to textgrids ?
751 InfoRow
<NS_sprm::SFpc
>(), // undocumented, sep
752 InfoRow
<NS_sprm::PFInnerTableCell
>(), // undocumented, subtable "sprmPFInTable" equiv ?
753 InfoRow
<NS_sprm::PFInnerTtp
>(), // undocumented, subtable "sprmPFTtp" equiv ?
754 InfoRow
<NS_sprm::TDxaAbs
>(), // undocumented
755 InfoRow
<NS_sprm::TDyaAbs
>(), // undocumented
756 InfoRow
<NS_sprm::TDxaFromText
>(), // undocumented
757 InfoRow
<NS_sprm::CRsidProp
>(), // undocumented
758 InfoRow
<NS_sprm::CRsidText
>(), // undocumented
759 InfoRow
<NS_sprm::CCv
>(), // text colour
760 InfoRow
<NS_sprm::PShd
>(), // undocumented, para back colour
761 InfoRow
<NS_sprm::PRsid
>(), // undocumented
762 InfoRow
<NS_sprm::PTableProps
>(), // undocumented
763 InfoRow
<NS_sprm::TWidthBefore
>(), // undocumented
764 InfoRow
<NS_sprm::TSetShdTable
>(), // undocumented, something to do with colour.
765 InfoRow
<NS_sprm::TDefTableShdRaw
>(), // undocumented, something to do with colour.
766 InfoRow
<NS_sprm::CShd
>(), // text backcolour
767 InfoRow
<NS_sprm::SRncFtn
>(), // undocumented, sep
768 InfoRow
<NS_sprm::PFDyaBeforeAuto
>(), // undocumented, para autobefore
769 InfoRow
<NS_sprm::PFDyaAfterAuto
>(), // undocumented, para autoafter
770 // "sprmPFContextualSpacing", don't add space between para of the same style
771 InfoRow
<NS_sprm::PFContextualSpacing
>(),
774 static wwSprmSearcher
aSprmSrch(aSprms
, SAL_N_ELEMENTS(aSprms
));
778 wwSprmParser::wwSprmParser(const WW8Fib
& rFib
) : meVersion(rFib
.GetFIBVersion())
780 OSL_ENSURE((meVersion
>= ww::eWW1
&& meVersion
<= ww::eWW8
),
781 "Impossible value for version");
783 mnDelta
= (ww::IsSevenMinus(meVersion
)) ? 0 : 1;
785 if (meVersion
<= ww::eWW2
)
786 mpKnownSprms
= GetWW2SprmSearcher();
787 else if (meVersion
< ww::eWW8
)
788 mpKnownSprms
= GetWW6SprmSearcher(rFib
);
790 mpKnownSprms
= GetWW8SprmSearcher();
793 SprmInfo
wwSprmParser::GetSprmInfo(sal_uInt16 nId
) const
795 const SprmInfo
* pFound
= mpKnownSprms
->search(nId
);
796 if (pFound
!= nullptr)
801 OSL_ENSURE(ww::IsEightPlus(meVersion
),
802 "Unknown ww7- sprm, dangerous, report to development");
804 //All the unknown ww7 sprms appear to be variable (which makes sense)
805 SprmInfo aSrch
= { 0, L_VAR
};
806 if (ww::IsEightPlus(meVersion
)) //We can recover perfectly in this case
840 static sal_uInt8
Get_Byte( sal_uInt8
*& p
)
847 static sal_uInt16
Get_UShort( sal_uInt8
*& p
)
849 const sal_uInt16 n
= SVBT16ToUInt16( *reinterpret_cast<SVBT16
*>(p
) );
854 static sal_Int16
Get_Short( sal_uInt8
*& p
)
856 return Get_UShort(p
);
859 static sal_uInt32
Get_ULong( sal_uInt8
*& p
)
861 sal_uInt32 n
= SVBT32ToUInt32( *reinterpret_cast<SVBT32
*>(p
) );
866 static sal_Int32
Get_Long( sal_uInt8
*& p
)
871 WW8SprmIter::WW8SprmIter(const sal_uInt8
* pSprms_
, sal_Int32 nLen_
,
872 const wwSprmParser
&rParser
)
873 : mrSprmParser(rParser
), m_pSprms( pSprms_
), m_nRemLen( nLen_
)
878 void WW8SprmIter::SetSprms(const sal_uInt8
* pSprms_
, sal_Int32 nLen_
)
885 void WW8SprmIter::advance()
889 sal_uInt16 nSize
= m_nCurrentSize
;
890 if (nSize
> m_nRemLen
)
898 void WW8SprmIter::UpdateMyMembers()
900 bool bValid
= (m_pSprms
&& m_nRemLen
>= mrSprmParser
.MinSprmLen());
904 m_nCurrentId
= mrSprmParser
.GetSprmId(m_pSprms
);
905 m_nCurrentSize
= mrSprmParser
.GetSprmSize(m_nCurrentId
, m_pSprms
, m_nRemLen
);
906 m_pCurrentParams
= m_pSprms
+ mrSprmParser
.DistanceToData(m_nCurrentId
);
907 bValid
= m_nCurrentSize
<= m_nRemLen
;
908 SAL_WARN_IF(!bValid
, "sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong");
914 m_pCurrentParams
= nullptr;
920 SprmResult
WW8SprmIter::FindSprm(sal_uInt16 nId
, bool bFindFirst
, const sal_uInt8
* pNextByteMatch
)
926 if (GetCurrentId() == nId
)
928 sal_Int32 nFixedLen
= mrSprmParser
.DistanceToData(nId
);
929 sal_Int32 nL
= mrSprmParser
.GetSprmSize(nId
, GetSprms(), GetRemLen());
930 SprmResult
aSprmResult(GetCurrentParams(), nL
- nFixedLen
);
931 // typically pNextByteMatch is nullptr and we just return the first match
932 // very occasionally we want one with a specific following byte
933 if ( !pNextByteMatch
|| (aSprmResult
.nRemainingData
>= 1 && *aSprmResult
.pSprm
== *pNextByteMatch
) )
947 // WW8PLCFx_PCDAttrs cling to WW8PLCF_Pcd and therefore do not have their own iterators.
948 // All methods relating to iterators are therefore dummies.
949 WW8PLCFx_PCDAttrs::WW8PLCFx_PCDAttrs(const WW8Fib
& rFib
,
950 WW8PLCFx_PCD
* pPLCFx_PCD
, const WW8ScannerBase
* pBase
)
951 : WW8PLCFx(rFib
, true), m_pPcdI(pPLCFx_PCD
->GetPLCFIter()),
952 m_pPcd(pPLCFx_PCD
), mrGrpprls(pBase
->m_aPieceGrpprls
)
956 sal_uInt32
WW8PLCFx_PCDAttrs::GetIdx() const
961 void WW8PLCFx_PCDAttrs::SetIdx(sal_uInt32
)
965 bool WW8PLCFx_PCDAttrs::SeekPos(WW8_CP
)
970 void WW8PLCFx_PCDAttrs::advance()
974 WW8_CP
WW8PLCFx_PCDAttrs::Where()
976 return m_pPcd
? m_pPcd
->Where() : WW8_CP_MAX
;
979 void WW8PLCFx_PCDAttrs::GetSprms(WW8PLCFxDesc
* p
)
983 p
->bRealLineEnd
= false;
984 if ( !m_pPcdI
|| !m_pPcdI
->Get(p
->nStartPos
, p
->nEndPos
, pData
) )
986 // PLCF fully processed
987 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
988 p
->pMemPos
= nullptr;
993 const sal_uInt16 nPrm
= SVBT16ToUInt16( static_cast<WW8_PCD
*>(pData
)->prm
);
997 const sal_uInt16 nSprmIdx
= nPrm
>> 1;
999 if( nSprmIdx
>= mrGrpprls
.size() )
1002 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
1003 p
->pMemPos
= nullptr;
1007 const sal_uInt8
* pSprms
= mrGrpprls
[ nSprmIdx
].get();
1009 p
->nSprmsLen
= SVBT16ToUInt16( pSprms
); // Length
1011 p
->pMemPos
= pSprms
; // Position
1015 // SPRM is stored directly into members var
1017 These are the attr that are in the piece-table instead of in the text!
1020 if (IsSevenMinus(GetFIBVersion()))
1022 m_aShortSprm
[0] = static_cast<sal_uInt8
>( ( nPrm
& 0xfe) >> 1 );
1023 m_aShortSprm
[1] = static_cast<sal_uInt8
>( nPrm
>> 8 );
1024 p
->nSprmsLen
= nPrm
? 2 : 0; // length
1026 // store Position of internal mini storage in Data Pointer
1027 p
->pMemPos
= m_aShortSprm
;
1031 p
->pMemPos
= nullptr;
1033 sal_uInt8 nSprmListIdx
= static_cast<sal_uInt8
>((nPrm
& 0xfe) >> 1);
1036 // process Sprm Id Matching as explained in MS Documentation
1038 // ''Property Modifier(variant 1) (PRM)''
1039 // see file: s62f39.htm
1041 // Since Sprm is 7 bits, rgsprmPrm can hold 0x80 entries.
1042 static const sal_uInt16 aSprmId
[0x80] =
1044 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1045 0x0000,0x0000,0x0000,0x0000,
1046 // sprmPIncLvl, sprmPJc, sprmPFSideBySide, sprmPFKeep
1047 0x2402,0x2403,NS_sprm::LN_PFSideBySide
,0x2405,
1048 // sprmPFKeepFollow, sprmPFPageBreakBefore, sprmPBrcl,
1050 0x2406,0x2407,NS_sprm::LN_PBrcl
,NS_sprm::LN_PBrcp
,
1051 // sprmPIlvl, sprmNoop, sprmPFNoLineNumb, sprmNoop
1052 0x260A,0x0000,0x240C,0x0000,
1053 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1054 0x0000,0x0000,0x0000,0x0000,
1055 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1056 0x0000,0x0000,0x0000,0x0000,
1057 // sprmPFInTable, sprmPFTtp, sprmNoop, sprmNoop
1058 0x2416,0x2417,0x0000,0x0000,
1059 // sprmNoop, sprmPPc, sprmNoop, sprmNoop
1060 0x0000,0x261B,0x0000,0x0000,
1061 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1062 0x0000,0x0000,0x0000,0x0000,
1063 // sprmNoop, sprmPWr, sprmNoop, sprmNoop
1064 0x0000,0x2423,0x0000,0x0000,
1065 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1066 0x0000,0x0000,0x0000,0x0000,
1067 // sprmPFNoAutoHyph, sprmNoop, sprmNoop, sprmNoop
1068 0x242A,0x0000,0x0000,0x0000,
1069 // sprmNoop, sprmNoop, sprmPFLocked, sprmPFWidowControl
1070 0x0000,0x0000,0x2430,0x2431,
1071 // sprmNoop, sprmPFKinsoku, sprmPFWordWrap,
1072 // sprmPFOverflowPunct
1073 0x0000,0x2433,0x2434,0x2435,
1074 // sprmPFTopLinePunct, sprmPFAutoSpaceDE,
1075 // sprmPFAutoSpaceDN, sprmNoop
1076 0x2436,0x2437,0x2438,0x0000,
1077 // sprmNoop, sprmPISnapBaseLine, sprmNoop, sprmNoop
1078 0x0000,NS_sprm::LN_PISnapBaseLine
,0x000,0x0000,
1079 // sprmNoop, sprmCFStrikeRM, sprmCFRMark, sprmCFFieldVanish
1080 0x0000,0x0800,0x0801,0x0802,
1081 // sprmNoop, sprmNoop, sprmNoop, sprmCFData
1082 0x0000,0x0000,0x0000,0x0806,
1083 // sprmNoop, sprmNoop, sprmNoop, sprmCFOle2
1084 0x0000,0x0000,0x0000,0x080A,
1085 // sprmNoop, sprmCHighlight, sprmCFEmboss, sprmCSfxText
1086 0x0000,0x2A0C,0x0858,0x2859,
1087 // sprmNoop, sprmNoop, sprmNoop, sprmCPlain
1088 0x0000,0x0000,0x0000,0x2A33,
1089 // sprmNoop, sprmCFBold, sprmCFItalic, sprmCFStrike
1090 0x0000,0x0835,0x0836,0x0837,
1091 // sprmCFOutline, sprmCFShadow, sprmCFSmallCaps, sprmCFCaps,
1092 0x0838,0x0839,0x083a,0x083b,
1093 // sprmCFVanish, sprmNoop, sprmCKul, sprmNoop,
1094 0x083C,0x0000,0x2A3E,0x0000,
1095 // sprmNoop, sprmNoop, sprmCIco, sprmNoop,
1096 0x0000,0x0000,0x2A42,0x0000,
1097 // sprmCHpsInc, sprmNoop, sprmCHpsPosAdj, sprmNoop,
1098 NS_sprm::LN_CHpsInc
,0x0000,NS_sprm::LN_CHpsPosAdj
,0x0000,
1099 // sprmCIss, sprmNoop, sprmNoop, sprmNoop,
1100 0x2A48,0x0000,0x0000,0x0000,
1101 // sprmNoop, sprmNoop, sprmNoop, sprmNoop,
1102 0x0000,0x0000,0x0000,0x0000,
1103 // sprmNoop, sprmNoop, sprmNoop, sprmCFDStrike,
1104 0x0000,0x0000,0x0000,0x2A53,
1105 // sprmCFImprint, sprmCFSpec, sprmCFObj, sprmPicBrcl,
1106 0x0854,0x0855,0x0856,NS_sprm::LN_PicBrcl
,
1107 // sprmPOutLvl, sprmPFBiDi, sprmNoop, sprmNoop,
1108 0x2640,0x2441,0x0000,0x0000,
1109 // sprmNoop, sprmNoop, sprmPPnbrRMarkNot
1110 0x0000,0x0000,0x0000,0x0000
1113 // find real Sprm Id:
1114 const sal_uInt16 nSprmId
= aSprmId
[ nSprmListIdx
];
1118 // move Sprm Id and Sprm Param to internal mini storage:
1119 m_aShortSprm
[0] = static_cast<sal_uInt8
>( nSprmId
& 0x00ff) ;
1120 m_aShortSprm
[1] = static_cast<sal_uInt8
>( ( nSprmId
& 0xff00) >> 8 );
1121 m_aShortSprm
[2] = static_cast<sal_uInt8
>( nPrm
>> 8 );
1123 // store Sprm Length in member:
1124 p
->nSprmsLen
= nPrm
? 3 : 0;
1126 // store Position of internal mini storage in Data Pointer
1127 p
->pMemPos
= m_aShortSprm
;
1134 WW8PLCFx_PCD::WW8PLCFx_PCD(const WW8Fib
& rFib
, WW8PLCFpcd
* pPLCFpcd
,
1135 WW8_CP nStartCp
, bool bVer67P
)
1136 : WW8PLCFx(rFib
, false), m_nClipStart(-1)
1138 // construct own iterator
1139 m_pPcdI
.reset( new WW8PLCFpcd_Iter(*pPLCFpcd
, nStartCp
) );
1143 WW8PLCFx_PCD::~WW8PLCFx_PCD()
1147 sal_uInt32
WW8PLCFx_PCD::GetIMax() const
1149 return m_pPcdI
? m_pPcdI
->GetIMax() : 0;
1152 sal_uInt32
WW8PLCFx_PCD::GetIdx() const
1154 return m_pPcdI
? m_pPcdI
->GetIdx() : 0;
1157 void WW8PLCFx_PCD::SetIdx(sal_uInt32 nIdx
)
1160 m_pPcdI
->SetIdx( nIdx
);
1163 bool WW8PLCFx_PCD::SeekPos(WW8_CP nCpPos
)
1165 return m_pPcdI
&& m_pPcdI
->SeekPos( nCpPos
);
1168 WW8_CP
WW8PLCFx_PCD::Where()
1170 return m_pPcdI
? m_pPcdI
->Where() : WW8_CP_MAX
;
1173 tools::Long
WW8PLCFx_PCD::GetNoSprms( WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
1178 if ( !m_pPcdI
|| !m_pPcdI
->Get(rStart
, rEnd
, pData
) )
1180 rStart
= rEnd
= WW8_CP_MAX
;
1183 return m_pPcdI
->GetIdx();
1186 void WW8PLCFx_PCD::advance()
1188 OSL_ENSURE(m_pPcdI
, "missing pPcdI");
1193 WW8_FC
WW8PLCFx_PCD::CurrentPieceStartCp2Fc( WW8_CP nCp
)
1195 WW8_CP nCpStart
, nCpEnd
;
1198 if ( !m_pPcdI
->Get(nCpStart
, nCpEnd
, pData
) )
1200 OSL_ENSURE( false, "CurrentPieceStartCp2Fc() with false Cp found (1)" );
1204 OSL_ENSURE( nCp
>= nCpStart
&& nCp
< nCpEnd
,
1205 "AktPieceCp2Fc() with false Cp found (2)" );
1207 if( nCp
< nCpStart
)
1212 bool bIsUnicode
= false;
1213 WW8_FC nFC
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
1215 nFC
= WW8PLCFx_PCD::TransformPieceAddress( nFC
, bIsUnicode
);
1218 bool bFail
= o3tl::checked_sub(nCp
, nCpStart
, nDistance
);
1221 SAL_WARN("sw.ww8", "broken offset, ignoring");
1227 bFail
= o3tl::checked_multiply
<WW8_CP
>(nDistance
, 2, nDistance
);
1230 SAL_WARN("sw.ww8", "broken offset, ignoring");
1236 bFail
= o3tl::checked_add(nFC
, nDistance
, nRet
);
1239 SAL_WARN("sw.ww8", "broken offset, ignoring");
1246 void WW8PLCFx_PCD::CurrentPieceFc2Cp( WW8_CP
& rStartPos
, WW8_CP
& rEndPos
,
1247 const WW8ScannerBase
*pSBase
)
1249 //No point going anywhere with this
1250 if ((rStartPos
== WW8_CP_MAX
) && (rEndPos
== WW8_CP_MAX
))
1253 rStartPos
= pSBase
->WW8Fc2Cp( rStartPos
);
1254 rEndPos
= pSBase
->WW8Fc2Cp( rEndPos
);
1257 WW8_CP
WW8PLCFx_PCD::CurrentPieceStartFc2Cp( WW8_FC nStartPos
)
1259 WW8_CP nCpStart
, nCpEnd
;
1261 if ( !m_pPcdI
->Get( nCpStart
, nCpEnd
, pData
) )
1263 OSL_ENSURE( false, "CurrentPieceStartFc2Cp() - error" );
1266 bool bIsUnicode
= false;
1267 sal_Int32 nFcStart
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
1269 nFcStart
= WW8PLCFx_PCD::TransformPieceAddress( nFcStart
, bIsUnicode
);
1271 sal_Int32 nUnicodeFactor
= bIsUnicode
? 2 : 1;
1273 if( nStartPos
< nFcStart
)
1274 nStartPos
= nFcStart
;
1277 bool bFail
= o3tl::checked_sub(nCpEnd
, nCpStart
, nCpLen
);
1280 SAL_WARN("sw.ww8", "broken offset, ignoring");
1285 bFail
= o3tl::checked_multiply(nCpLen
, nUnicodeFactor
, nCpLenBytes
);
1288 SAL_WARN("sw.ww8", "broken offset, ignoring");
1293 bFail
= o3tl::checked_add(nFcStart
, nCpLenBytes
, nFcLen
);
1296 SAL_WARN("sw.ww8", "broken offset, ignoring");
1301 bFail
= o3tl::checked_add(nFcStart
, nFcLen
, nFcEnd
);
1304 SAL_WARN("sw.ww8", "broken offset, ignoring");
1309 if (nStartPos
>= nFcEnd
)
1310 nStartPos
= nFcEnd
- (1 * nUnicodeFactor
);
1312 WW8_FC nFcDiff
= (nStartPos
- nFcStart
) / nUnicodeFactor
;
1315 bFail
= o3tl::checked_add(nCpStart
, nFcDiff
, nCpRet
);
1318 SAL_WARN("sw.ww8", "broken offset, ignoring");
1325 // Helper routines for all
1327 // Convert BRC from WW6 to WW8 format
1328 WW8_BRC::WW8_BRC(const WW8_BRCVer6
& brcVer6
)
1330 sal_uInt8 _dptLineWidth
= brcVer6
.dxpLineWidth(),
1331 _brcType
= brcVer6
.brcType();
1333 if (_dptLineWidth
> 5) // this signifies dashed(6) or dotted(7) line
1335 _brcType
= _dptLineWidth
;
1338 _dptLineWidth
*= 6; // convert units from 0.75pt to 1/8pt
1340 *this = WW8_BRC(_dptLineWidth
, _brcType
, brcVer6
.ico(), brcVer6
.dxpSpace(),
1341 brcVer6
.fShadow(), false);
1344 // Convert BRC from WW8 to WW9 format
1345 WW8_BRCVer9::WW8_BRCVer9(const WW8_BRC
& brcVer8
)
1347 if (brcVer8
.isNil()) {
1348 UInt32ToSVBT32(0, aBits1
);
1349 UInt32ToSVBT32(0xffffffff, aBits2
);
1353 sal_uInt32 _cv
= brcVer8
.ico() == 0 ? 0xff000000 // "auto" colour
1354 : wwUtility::RGBToBGR(SwWW8ImplReader::GetCol(brcVer8
.ico()));
1355 *this = WW8_BRCVer9(_cv
, brcVer8
.dptLineWidth(), brcVer8
.brcType(),
1356 brcVer8
.dptSpace(), brcVer8
.fShadow(), brcVer8
.fFrame());
1360 short WW8_BRC::DetermineBorderProperties(short *pSpace
) const
1362 WW8_BRCVer9
brcVer9(*this);
1363 return brcVer9
.DetermineBorderProperties(pSpace
);
1366 short WW8_BRCVer9::DetermineBorderProperties(short *pSpace
) const
1369 Word does not factor the width of the border into the width/height
1370 stored in the information for graphic/table/object widths, so we need
1371 to figure out this extra width here and utilize the returned size in
1374 short nMSTotalWidth
;
1376 //Specification in 8ths of a point, 1 Point = 20 Twips, so by 2.5
1377 nMSTotalWidth
= static_cast<short>(dptLineWidth()) * 20 / 8;
1379 //Figure out the real size of the border according to word
1382 //Note that codes over 25 are undocumented, and I can't create
1383 //these 4 here in the wild.
1388 OSL_FAIL("Can't create these from the menus, please report");
1391 case 23: //Only 3pt in the menus, but honours the size setting.
1395 triple line is five times the width of an ordinary line,
1396 except that the smallest 1/4 point size appears to have
1397 exactly the same total border width as a 3/4 point size
1398 ordinary line, i.e. three times the nominal line width. The
1399 second smallest 1/2 point size appears to have exactly the
1400 total border width as a 2 1/4 border, i.e 4.5 times the size.
1402 if (nMSTotalWidth
== 5)
1404 else if (nMSTotalWidth
== 10)
1405 nMSTotalWidth
= nMSTotalWidth
*9/2;
1411 wave, the dimensions appear to be created by the drawing of
1412 the wave, so we have only two possibilities in the menus, 3/4
1413 point is equal to solid 3 point. This calculation seems to
1414 match well to results.
1420 double wave, the dimensions appear to be created by the
1421 drawing of the wave, so we have only one possibilities in the
1422 menus, that of 3/4 point is equal to solid 3 point. This
1423 calculation seems to match well to results.
1425 nMSTotalWidth
+= 45*2;
1430 *pSpace
= static_cast<short>(dptSpace()) * 20; // convert from points to twips
1431 return nMSTotalWidth
;
1435 * WW8Cp2Fc is a good method, a CP always maps to a FC
1436 * WW8Fc2Cp on the other hand is more dubious, a random FC
1437 * may not map to a valid CP. Try and avoid WW8Fc2Cp where
1440 WW8_CP
WW8ScannerBase::WW8Fc2Cp( WW8_FC nFcPos
) const
1442 WW8_CP nFallBackCpEnd
= WW8_CP_MAX
;
1443 if( nFcPos
== WW8_FC_MAX
)
1444 return nFallBackCpEnd
;
1447 if (m_pWw8Fib
->m_nVersion
>= 8)
1450 bIsUnicode
= m_pWw8Fib
->m_fExtChar
;
1452 if( m_pPieceIter
) // Complex File ?
1454 sal_uInt32 nOldPos
= m_pPieceIter
->GetIdx();
1456 for (m_pPieceIter
->SetIdx(0);
1457 m_pPieceIter
->GetIdx() < m_pPieceIter
->GetIMax(); m_pPieceIter
->advance())
1459 WW8_CP nCpStart
, nCpEnd
;
1461 if( !m_pPieceIter
->Get( nCpStart
, nCpEnd
, pData
) )
1462 { // outside PLCFfpcd ?
1463 OSL_ENSURE( false, "PLCFpcd-WW8Fc2Cp() went wrong" );
1466 sal_Int32 nFcStart
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
1467 if (m_pWw8Fib
->m_nVersion
>= 8)
1469 nFcStart
= WW8PLCFx_PCD::TransformPieceAddress( nFcStart
,
1474 bIsUnicode
= m_pWw8Fib
->m_fExtChar
;
1478 if (o3tl::checked_sub(nCpEnd
, nCpStart
, nLen
))
1480 SAL_WARN("sw.ww8", "broken offset, ignoring");
1485 if (o3tl::checked_multiply
<WW8_CP
>(nLen
, 2, nLen
))
1487 SAL_WARN("sw.ww8", "broken offset, ignoring");
1493 If this cp is inside this piece, or it's the last piece and we are
1494 on the very last cp of that piece
1496 if (nFcPos
>= nFcStart
)
1500 if (o3tl::checked_sub(nFcPos
, nFcStart
, nFcDiff
))
1502 SAL_WARN("sw.ww8", "broken offset, ignoring");
1508 if (o3tl::checked_add(nCpStart
, nFcDiff
, nTempCp
))
1510 SAL_WARN("sw.ww8", "broken offset, ignoring");
1514 if (o3tl::checked_add(nFcStart
, nLen
, nFcEnd
))
1516 SAL_WARN("sw.ww8", "broken offset, ignoring");
1519 if (nFcPos
< nFcEnd
)
1521 m_pPieceIter
->SetIdx( nOldPos
);
1524 else if (nFcPos
== nFcEnd
)
1526 //Keep this cp as its on a piece boundary because we might
1527 //need it if tests fail
1528 nFallBackCpEnd
= nTempCp
;
1533 m_pPieceIter
->SetIdx( nOldPos
); // not found
1535 If it was not found, then this is because it has fallen between two
1536 stools, i.e. either it is the last cp/fc of the last piece, or it is
1537 the last cp/fc of a disjoint piece.
1539 return nFallBackCpEnd
;
1543 if (o3tl::checked_sub(nFcPos
, m_pWw8Fib
->m_fcMin
, nFcDiff
))
1545 SAL_WARN("sw.ww8", "broken offset, ignoring");
1551 nFallBackCpEnd
= nFcDiff
;
1553 nFallBackCpEnd
= (nFcDiff
+ 1) / 2;
1555 return nFallBackCpEnd
;
1558 // the fib of WinWord2 has a last entry of cpnBtePap of 2 byte sized type PN at
1560 const int nSmallestPossibleFib
= 326;
1562 WW8_FC
WW8ScannerBase::WW8Cp2Fc(WW8_CP nCpPos
, bool* pIsUnicode
,
1563 WW8_CP
* pNextPieceCp
, bool* pTestFlag
) const
1567 if( WW8_CP_MAX
== nCpPos
)
1572 pIsUnicode
= &bIsUnicode
;
1574 if (m_pWw8Fib
->m_nVersion
>= 8)
1575 *pIsUnicode
= false;
1577 *pIsUnicode
= m_pWw8Fib
->m_fExtChar
;
1585 *pNextPieceCp
= WW8_CP_MAX
;
1587 if( !m_pPieceIter
->SeekPos( nCpPos
) )
1592 OSL_ENSURE( false, "Handed over wrong CP to WW8Cp2Fc()" );
1596 WW8_CP nCpStart
, nCpEnd
;
1598 if( !m_pPieceIter
->Get( nCpStart
, nCpEnd
, pData
) )
1603 OSL_ENSURE( false, "PLCFfpcd-Get went wrong" );
1608 *pNextPieceCp
= nCpEnd
;
1610 nRet
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
1611 if (m_pWw8Fib
->m_nVersion
>= 8)
1612 nRet
= WW8PLCFx_PCD::TransformPieceAddress( nRet
, *pIsUnicode
);
1614 *pIsUnicode
= m_pWw8Fib
->m_fExtChar
;
1617 bool bFail
= o3tl::checked_sub(nCpPos
, nCpStart
, nCpLen
);
1620 SAL_WARN("sw.ww8", "broken offset, ignoring");
1626 bFail
= o3tl::checked_multiply
<WW8_CP
>(nCpLen
, 2, nCpLen
);
1629 SAL_WARN("sw.ww8", "broken offset, ignoring");
1634 bFail
= o3tl::checked_add(nRet
, nCpLen
, nRet
);
1637 SAL_WARN("sw.ww8", "broken offset, ignoring");
1646 const bool bFail
= o3tl::checked_multiply
<WW8_CP
>(nCpPos
, 2, nCpPos
);
1649 SAL_WARN("sw.ww8", "broken offset, ignoring");
1655 const bool bFail
= o3tl::checked_add(m_pWw8Fib
->m_fcMin
, nCpPos
, nRet
);
1658 SAL_WARN("sw.ww8", "broken offset, ignoring");
1662 // the text and the fib share the same stream, if the text is inside the fib
1663 // then it's definitely a bad offset. The smallest FIB supported is that of
1664 // WW2 which is 326 bytes in size
1665 if (nRet
< nSmallestPossibleFib
)
1667 SAL_WARN("sw.ww8", "broken offset, ignoring");
1674 std::unique_ptr
<WW8PLCFpcd
> WW8ScannerBase::OpenPieceTable( SvStream
* pStr
, const WW8Fib
* pWwF
)
1676 if ( ((8 > m_pWw8Fib
->m_nVersion
) && !pWwF
->m_fComplex
) || !pWwF
->m_lcbClx
)
1679 if (pWwF
->m_lcbClx
< 0)
1682 WW8_FC nClxPos
= pWwF
->m_fcClx
;
1684 if (!checkSeek(*pStr
, nClxPos
))
1687 sal_Int32 nClxLen
= pWwF
->m_lcbClx
;
1688 sal_Int32 nLeft
= nClxLen
;
1693 pStr
->ReadUChar( clxt
);
1695 if( 2 == clxt
) // PLCFfpcd ?
1696 break; // PLCFfpcd found
1698 pStr
->ReadUInt16( nLen
);
1701 return nullptr; // gone wrong
1702 if( 1 == clxt
) // clxtGrpprl ?
1704 if (m_aPieceGrpprls
.size() == SHRT_MAX
)
1706 if (nLen
> pStr
->remainingSize())
1708 std::unique_ptr
<sal_uInt8
[]> p(new sal_uInt8
[nLen
+2]); // allocate
1709 ShortToSVBT16(nLen
, p
.get()); // add length
1710 if (!checkRead(*pStr
, p
.get()+2, nLen
)) // read grpprl
1714 m_aPieceGrpprls
.push_back(std::move(p
)); // add to array
1718 nLen
= std::min
<sal_uInt64
>(nLen
, pStr
->remainingSize());
1719 pStr
->Seek(pStr
->Tell() + nLen
); // non-Grpprl left
1723 // read Piece Table PLCF
1724 sal_Int32
nPLCFfLen(0);
1725 if (pWwF
->GetFIBVersion() <= ww::eWW2
)
1727 sal_Int16
nWordTwoLen(0);
1728 pStr
->ReadInt16( nWordTwoLen
);
1729 nPLCFfLen
= nWordTwoLen
;
1732 pStr
->ReadInt32( nPLCFfLen
);
1733 OSL_ENSURE( 65536 > nPLCFfLen
, "PLCFfpcd above 64 k" );
1734 return std::make_unique
<WW8PLCFpcd
>( pStr
, pStr
->Tell(), nPLCFfLen
, 8 );
1737 WW8ScannerBase::WW8ScannerBase( SvStream
* pSt
, SvStream
* pTableSt
,
1738 SvStream
* pDataSt
, WW8Fib
* pWwFib
)
1741 m_pPiecePLCF
= OpenPieceTable( pTableSt
, m_pWw8Fib
); // Complex
1744 m_pPieceIter
.reset(new WW8PLCFpcd_Iter( *m_pPiecePLCF
));
1745 m_pPLCFx_PCD
.reset( new WW8PLCFx_PCD(*pWwFib
, m_pPiecePLCF
.get(), 0,
1746 IsSevenMinus(m_pWw8Fib
->GetFIBVersion())));
1747 m_pPLCFx_PCDAttrs
.reset(new WW8PLCFx_PCDAttrs(*pWwFib
,
1748 m_pPLCFx_PCD
.get(), this));
1752 m_pPieceIter
= nullptr;
1753 m_pPLCFx_PCD
= nullptr;
1754 m_pPLCFx_PCDAttrs
= nullptr;
1757 // pChpPLCF and pPapPLCF may NOT be created before pPLCFx_PCD !!
1758 m_pChpPLCF
.reset(new WW8PLCFx_Cp_FKP( pSt
, pTableSt
, pDataSt
, *this, CHP
)); // CHPX
1759 m_pPapPLCF
.reset(new WW8PLCFx_Cp_FKP( pSt
, pTableSt
, pDataSt
, *this, PAP
)); // PAPX
1761 m_pSepPLCF
.reset(new WW8PLCFx_SEPX( pSt
, pTableSt
, *pWwFib
, 0 )); // SEPX
1764 m_pFootnotePLCF
.reset(new WW8PLCFx_SubDoc( pTableSt
, *pWwFib
, 0,
1765 pWwFib
->m_fcPlcffndRef
, pWwFib
->m_lcbPlcffndRef
, pWwFib
->m_fcPlcffndText
,
1766 pWwFib
->m_lcbPlcffndText
, 2 ));
1768 m_pEdnPLCF
.reset(new WW8PLCFx_SubDoc( pTableSt
, *pWwFib
, 0,
1769 pWwFib
->m_fcPlcfendRef
, pWwFib
->m_lcbPlcfendRef
, pWwFib
->m_fcPlcfendText
,
1770 pWwFib
->m_lcbPlcfendText
, 2 ));
1772 m_pAndPLCF
.reset(new WW8PLCFx_SubDoc( pTableSt
, *pWwFib
, 0,
1773 pWwFib
->m_fcPlcfandRef
, pWwFib
->m_lcbPlcfandRef
, pWwFib
->m_fcPlcfandText
,
1774 pWwFib
->m_lcbPlcfandText
, IsSevenMinus(pWwFib
->GetFIBVersion()) ? 20 : 30));
1777 m_pFieldPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_MAINTEXT
));
1778 // Fields Header / Footer
1779 m_pFieldHdFtPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_HDFT
));
1781 m_pFieldFootnotePLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_FTN
));
1783 m_pFieldEdnPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_EDN
));
1785 m_pFieldAndPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_AND
));
1786 // Fields in Textboxes in Main Text
1787 m_pFieldTxbxPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_TXBX
));
1788 // Fields in Textboxes in Header / Footer
1789 m_pFieldTxbxHdFtPLCF
.reset(new WW8PLCFx_FLD(pTableSt
,*pWwFib
,MAN_TXBX_HDFT
));
1791 // Note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
1792 switch( m_pWw8Fib
->m_nVersion
)
1796 if( pWwFib
->m_fcPlcfdoaMom
&& pWwFib
->m_lcbPlcfdoaMom
)
1798 m_pMainFdoa
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfdoaMom
,
1799 pWwFib
->m_lcbPlcfdoaMom
, 6 ));
1801 if( pWwFib
->m_fcPlcfdoaHdr
&& pWwFib
->m_lcbPlcfdoaHdr
)
1803 m_pHdFtFdoa
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfdoaHdr
,
1804 pWwFib
->m_lcbPlcfdoaHdr
, 6 ));
1808 if( pWwFib
->m_fcPlcfspaMom
&& pWwFib
->m_lcbPlcfspaMom
)
1810 m_pMainFdoa
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfspaMom
,
1811 pWwFib
->m_lcbPlcfspaMom
, 26 ));
1813 if( pWwFib
->m_fcPlcfspaHdr
&& pWwFib
->m_lcbPlcfspaHdr
)
1815 m_pHdFtFdoa
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfspaHdr
,
1816 pWwFib
->m_lcbPlcfspaHdr
, 26 ));
1818 // PLCF for TextBox break-descriptors in the main text
1819 if( pWwFib
->m_fcPlcftxbxBkd
&& pWwFib
->m_lcbPlcftxbxBkd
)
1821 m_pMainTxbxBkd
.reset(new WW8PLCFspecial( pTableSt
,
1822 pWwFib
->m_fcPlcftxbxBkd
, pWwFib
->m_lcbPlcftxbxBkd
, 0));
1824 // PLCF for TextBox break-descriptors in Header/Footer range
1825 if( pWwFib
->m_fcPlcfHdrtxbxBkd
&& pWwFib
->m_lcbPlcfHdrtxbxBkd
)
1827 m_pHdFtTxbxBkd
.reset(new WW8PLCFspecial( pTableSt
,
1828 pWwFib
->m_fcPlcfHdrtxbxBkd
, pWwFib
->m_lcbPlcfHdrtxbxBkd
, 0));
1830 // Sub table cp positions
1831 if (pWwFib
->m_fcPlcfTch
&& pWwFib
->m_lcbPlcfTch
)
1833 m_pMagicTables
.reset(new WW8PLCFspecial( pTableSt
,
1834 pWwFib
->m_fcPlcfTch
, pWwFib
->m_lcbPlcfTch
, 4));
1836 // Sub document cp positions
1837 if (pWwFib
->m_fcPlcfwkb
&& pWwFib
->m_lcbPlcfwkb
)
1839 m_pSubdocs
.reset(new WW8PLCFspecial( pTableSt
,
1840 pWwFib
->m_fcPlcfwkb
, pWwFib
->m_lcbPlcfwkb
, 12));
1843 if (pWwFib
->m_fcAtrdExtra
&& pWwFib
->m_lcbAtrdExtra
)
1845 sal_uInt64
const nOldPos
= pTableSt
->Tell();
1846 if (checkSeek(*pTableSt
, pWwFib
->m_fcAtrdExtra
) && (pTableSt
->remainingSize() >= pWwFib
->m_lcbAtrdExtra
))
1848 m_pExtendedAtrds
.reset( new sal_uInt8
[pWwFib
->m_lcbAtrdExtra
] );
1849 pWwFib
->m_lcbAtrdExtra
= pTableSt
->ReadBytes(m_pExtendedAtrds
.get(), pWwFib
->m_lcbAtrdExtra
);
1852 pWwFib
->m_lcbAtrdExtra
= 0;
1853 pTableSt
->Seek(nOldPos
);
1858 OSL_ENSURE( false, "nVersion not implemented!" );
1862 // PLCF for TextBox stories in main text
1863 sal_uInt32 nLenTxBxS
= (8 > m_pWw8Fib
->m_nVersion
) ? 0 : 22;
1864 if( pWwFib
->m_fcPlcftxbxText
&& pWwFib
->m_lcbPlcftxbxText
)
1866 m_pMainTxbx
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcftxbxText
,
1867 pWwFib
->m_lcbPlcftxbxText
, nLenTxBxS
));
1870 // PLCF for TextBox stories in Header/Footer range
1871 if( pWwFib
->m_fcPlcfHdrtxbxText
&& pWwFib
->m_lcbPlcfHdrtxbxText
)
1873 m_pHdFtTxbx
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfHdrtxbxText
,
1874 pWwFib
->m_lcbPlcfHdrtxbxText
, nLenTxBxS
));
1877 m_pBook
.reset(new WW8PLCFx_Book(pTableSt
, *pWwFib
));
1878 m_pAtnBook
.reset(new WW8PLCFx_AtnBook(pTableSt
, *pWwFib
));
1879 m_pFactoidBook
.reset(new WW8PLCFx_FactoidBook(pTableSt
, *pWwFib
));
1882 WW8ScannerBase::~WW8ScannerBase()
1884 m_aPieceGrpprls
.clear();
1885 m_pPLCFx_PCDAttrs
.reset();
1886 m_pPLCFx_PCD
.reset();
1887 m_pPieceIter
.reset();
1888 m_pPiecePLCF
.reset();
1889 m_pFactoidBook
.reset();
1892 m_pFieldEdnPLCF
.reset();
1893 m_pFieldFootnotePLCF
.reset();
1894 m_pFieldAndPLCF
.reset();
1895 m_pFieldHdFtPLCF
.reset();
1896 m_pFieldPLCF
.reset();
1897 m_pFieldTxbxPLCF
.reset();
1898 m_pFieldTxbxHdFtPLCF
.reset();
1900 m_pFootnotePLCF
.reset();
1905 m_pMainFdoa
.reset();
1906 m_pHdFtFdoa
.reset();
1907 m_pMainTxbx
.reset();
1908 m_pMainTxbxBkd
.reset();
1909 m_pHdFtTxbx
.reset();
1910 m_pHdFtTxbxBkd
.reset();
1911 m_pMagicTables
.reset();
1917 static bool WW8SkipField(WW8PLCFspecial
& rPLCF
)
1922 if (!rPLCF
.Get(nP
, pData
)) // End of PLCFspecial?
1927 if((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) != 0x13 ) // No beginning?
1928 return true; // Do not terminate on error
1930 if( !rPLCF
.Get( nP
, pData
) )
1933 while((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x13 )
1935 // still new (nested) beginnings ?
1936 WW8SkipField( rPLCF
); // nested Field in description
1937 if( !rPLCF
.Get( nP
, pData
) )
1941 if((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x14 )
1944 // Field Separator ?
1947 if( !rPLCF
.Get( nP
, pData
) )
1950 while ((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x13)
1952 // still new (nested) beginnings?
1953 WW8SkipField( rPLCF
); // nested Field in Results
1954 if( !rPLCF
.Get( nP
, pData
) )
1963 static bool WW8GetFieldPara(WW8PLCFspecial
& rPLCF
, WW8FieldDesc
& rF
)
1966 sal_uInt32 nOldIdx
= rPLCF
.GetIdx();
1968 rF
.nLen
= rF
.nId
= rF
.nOpt
= 0;
1969 rF
.bCodeNest
= rF
.bResNest
= false;
1971 if (!rPLCF
.Get(rF
.nSCode
, pData
) || rF
.nSCode
< 0) // end of PLCFspecial?
1976 if (!pData
|| (static_cast<sal_uInt8
*>(pData
)[0] & 0x1f) != 0x13) // No beginning?
1979 rF
.nId
= static_cast<sal_uInt8
*>(pData
)[1];
1981 if( !rPLCF
.Get( rF
.nLCode
, pData
) )
1984 if (rF
.nLCode
< rF
.nSCode
)
1987 rF
.nSRes
= rF
.nLCode
; // Default
1988 rF
.nSCode
++; // without markers
1989 rF
.nLCode
-= rF
.nSCode
; // Pos -> length
1991 while((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x13 )
1993 // still new (nested) beginnings ?
1994 WW8SkipField( rPLCF
); // nested Field in description
1995 rF
.bCodeNest
= true;
1996 if (!rPLCF
.Get(rF
.nSRes
, pData
) || rF
.nSRes
< 0)
2000 if ((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x14 ) // Field Separator?
2004 if (!rPLCF
.Get(rF
.nLRes
, pData
) || rF
.nLRes
< 0)
2007 while((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x13 )
2009 // still new (nested) beginnings ?
2010 WW8SkipField( rPLCF
); // nested Field in results
2012 if (!rPLCF
.Get(rF
.nLRes
, pData
) || rF
.nLRes
< 0)
2016 if (o3tl::checked_sub
<WW8_CP
>(rF
.nLRes
, rF
.nSCode
, nTmp
))
2021 if (o3tl::checked_add
<WW8_CP
>(nTmp
, 2, rF
.nLen
)) // nLRes is still the final position
2026 rF
.nLRes
-= rF
.nSRes
; // now: nLRes = length
2027 if (o3tl::checked_add
<WW8_CP
>(rF
.nSRes
, 1, rF
.nSRes
)) // Endpos including Markers
2034 rF
.nLRes
= 0; // no result found
2036 if (o3tl::checked_sub
<WW8_CP
>(rF
.nSRes
, rF
.nSCode
, nTmp
))
2041 if (o3tl::checked_add
<WW8_CP
>(nTmp
, 2, rF
.nLen
)) // total length
2055 if((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x15 )
2058 // INDEX-Field has set Bit7?
2059 rF
.nOpt
= static_cast<sal_uInt8
*>(pData
)[1]; // yes -> copy flags
2061 rF
.nId
= 0; // no -> Field invalid
2064 rPLCF
.SetIdx( nOldIdx
);
2067 rPLCF
.SetIdx( nOldIdx
);
2071 OUString
read_uInt8_BeltAndBracesString(SvStream
& rStrm
, rtl_TextEncoding eEnc
)
2073 const OUString aRet
= read_uInt8_lenPrefixed_uInt8s_ToOUString(rStrm
, eEnc
);
2074 rStrm
.SeekRel(sizeof(sal_uInt8
)); // skip null-byte at end
2078 OUString
read_uInt16_BeltAndBracesString(SvStream
& rStrm
)
2080 const OUString aRet
= read_uInt16_PascalString(rStrm
);
2081 rStrm
.SeekRel(sizeof(sal_Unicode
)); // skip null-byte at end
2085 sal_Int32
WW8ScannerBase::WW8ReadString( SvStream
& rStrm
, OUString
& rStr
,
2086 WW8_CP nCurrentStartCp
, tools::Long nTotalLen
, rtl_TextEncoding eEnc
) const
2088 // Read in plain text, which can extend over several pieces
2091 if (nCurrentStartCp
< 0 || nTotalLen
< 0)
2094 WW8_CP nBehindTextCp
= nCurrentStartCp
+ nTotalLen
;
2095 WW8_CP nNextPieceCp
= nBehindTextCp
; // Initialization, important for Ver6
2096 tools::Long nTotalRead
= 0;
2099 bool bIsUnicode(false), bPosOk(false);
2100 WW8_FC fcAct
= WW8Cp2Fc(nCurrentStartCp
,&bIsUnicode
,&nNextPieceCp
,&bPosOk
);
2102 // Probably aimed beyond file end, doesn't matter!
2106 bool bValid
= checkSeek(rStrm
, fcAct
);
2110 WW8_CP nEnd
= (nNextPieceCp
< nBehindTextCp
) ? nNextPieceCp
2113 const bool bFail
= o3tl::checked_sub(nEnd
, nCurrentStartCp
, nLen
);
2121 ? read_uInt16s_ToOUString(rStrm
, nLen
)
2122 : read_uInt8s_ToOUString(rStrm
, nLen
, eEnc
);
2125 nCurrentStartCp
+= nLen
;
2126 if ( nTotalRead
!= rStr
.getLength() )
2129 while( nTotalRead
< nTotalLen
);
2131 return rStr
.getLength();
2134 WW8PLCFspecial::WW8PLCFspecial(SvStream
* pSt
, sal_uInt32 nFilePos
,
2135 sal_uInt32 nPLCF
, sal_uInt32 nStruct
)
2136 : m_nIdx(0), m_nStru(nStruct
)
2138 const sal_uInt32 nValidMin
=4;
2140 sal_uInt64
const nOldPos
= pSt
->Tell();
2142 bool bValid
= checkSeek(*pSt
, nFilePos
);
2143 std::size_t nRemainingSize
= pSt
->remainingSize();
2144 if( nRemainingSize
< nValidMin
|| nPLCF
< nValidMin
)
2146 nPLCF
= bValid
? std::min(nRemainingSize
, static_cast<std::size_t>(nPLCF
)) : nValidMin
;
2148 // Pointer to Pos- and Struct-array
2149 m_pPLCF_PosArray
.reset( new sal_Int32
[ ( nPLCF
+ 3 ) / 4 ] );
2150 m_pPLCF_PosArray
[0] = 0;
2152 nPLCF
= bValid
? pSt
->ReadBytes(m_pPLCF_PosArray
.get(), nPLCF
) : nValidMin
;
2154 nPLCF
= std::max(nPLCF
, nValidMin
);
2156 m_nIMax
= ( nPLCF
- 4 ) / ( 4 + nStruct
);
2157 #ifdef OSL_BIGENDIAN
2158 for( m_nIdx
= 0; m_nIdx
<= m_nIMax
; m_nIdx
++ )
2159 m_pPLCF_PosArray
[m_nIdx
] = OSL_SWAPDWORD( m_pPLCF_PosArray
[m_nIdx
] );
2161 #endif // OSL_BIGENDIAN
2162 if( nStruct
) // Pointer to content array
2163 m_pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&m_pPLCF_PosArray
[m_nIMax
+ 1]);
2165 m_pPLCF_Contents
= nullptr; // no content
2170 // WW8PLCFspecial::SeekPos() sets WW8PLCFspecial to position nPos, while also the entry is used
2171 // that begins before nPos and ends after nPos.
2172 // Suitable for normal attributes. However, the beginning of the attribute is not corrected onto
2173 // the position nPos.
2174 bool WW8PLCFspecial::SeekPos(tools::Long nP
)
2176 if( nP
< m_pPLCF_PosArray
[0] )
2179 return false; // Not found: nP less than smallest entry
2182 // Search from beginning?
2183 if ((m_nIdx
< 1) || (nP
< m_pPLCF_PosArray
[m_nIdx
- 1]))
2186 tools::Long nI
= m_nIdx
;
2187 tools::Long nEnd
= m_nIMax
;
2189 for(int n
= (1==m_nIdx
? 1 : 2); n
; --n
)
2191 for( ; nI
<=nEnd
; ++nI
)
2192 { // search with an index that is incremented by 1
2193 if( nP
< m_pPLCF_PosArray
[nI
] )
2195 m_nIdx
= nI
- 1; // nI - 1 is the correct index
2196 return true; // done
2202 m_nIdx
= m_nIMax
; // not found, greater than all entries
2206 // WW8PLCFspecial::SeekPosExact() like SeekPos(), but it is ensured that no attribute is cut,
2207 // i.e. the next given attribute begins at or after nPos.
2208 // Is used for fields and bookmarks.
2209 bool WW8PLCFspecial::SeekPosExact(tools::Long nP
)
2211 if( nP
< m_pPLCF_PosArray
[0] )
2214 return false; // Not found: nP less than smallest entry
2216 // Search from beginning?
2217 if( nP
<=m_pPLCF_PosArray
[m_nIdx
] )
2220 tools::Long nI
= m_nIdx
? m_nIdx
-1 : 0;
2221 tools::Long nEnd
= m_nIMax
;
2223 for(int n
= (0==m_nIdx
? 1 : 2); n
; --n
)
2225 for( ; nI
< nEnd
; ++nI
)
2227 if( nP
<=m_pPLCF_PosArray
[nI
] )
2229 m_nIdx
= nI
; // nI is the correct index
2230 return true; // done
2236 m_nIdx
= m_nIMax
; // Not found, greater than all entries
2240 bool WW8PLCFspecial::Get(WW8_CP
& rPos
, void*& rpValue
) const
2242 return GetData( m_nIdx
, rPos
, rpValue
);
2245 bool WW8PLCFspecial::GetData(tools::Long nInIdx
, WW8_CP
& rPos
, void*& rpValue
) const
2247 if ( nInIdx
>= m_nIMax
)
2252 rPos
= m_pPLCF_PosArray
[nInIdx
];
2253 rpValue
= m_pPLCF_Contents
? static_cast<void*>(&m_pPLCF_Contents
[nInIdx
* m_nStru
]) : nullptr;
2257 // WW8PLCF e.g. for SEPX
2258 // Ctor for *others* than Fkps
2259 // With nStartPos < 0, the first element of PLCFs will be taken
2260 WW8PLCF::WW8PLCF(SvStream
& rSt
, WW8_FC nFilePos
, sal_Int32 nPLCF
, int nStruct
,
2261 WW8_CP nStartPos
) : m_nIdx(0), m_nStru(nStruct
)
2265 SAL_WARN("sw.ww8", "broken WW8PLCF, ignoring");
2269 m_nIMax
= (nPLCF
- 4) / (4 + nStruct
);
2271 ReadPLCF(rSt
, nFilePos
, nPLCF
);
2273 if( nStartPos
>= 0 )
2274 SeekPos( nStartPos
);
2277 // Ctor *only* for Fkps
2278 // The last 2 parameters are needed for PLCF.Chpx and PLCF.Papx.
2279 // If ncpN != 0, then an incomplete PLCF will be completed. This is always required for WW6 with
2280 // lack of resources and for WordPad (W95).
2281 // With nStartPos < 0, the first element of the PLCFs is taken.
2282 WW8PLCF::WW8PLCF(SvStream
& rSt
, WW8_FC nFilePos
, sal_Int32 nPLCF
, int nStruct
,
2283 WW8_CP nStartPos
, sal_Int32 nPN
, sal_Int32 ncpN
): m_nIdx(0),
2288 SAL_WARN("sw.ww8", "broken WW8PLCF, ignoring");
2289 m_nIMax
= SAL_MAX_INT32
;
2292 m_nIMax
= (nPLCF
- 4) / (4 + nStruct
);
2294 if( m_nIMax
>= ncpN
)
2295 ReadPLCF(rSt
, nFilePos
, nPLCF
);
2297 GeneratePLCF(rSt
, nPN
, ncpN
);
2299 if( nStartPos
>= 0 )
2300 SeekPos( nStartPos
);
2303 void WW8PLCF::ReadPLCF(SvStream
& rSt
, WW8_FC nFilePos
, sal_uInt32 nPLCF
)
2305 sal_uInt64
const nOldPos
= rSt
.Tell();
2306 bool bValid
= nPLCF
!= 0 && checkSeek(rSt
, nFilePos
)
2307 && (rSt
.remainingSize() >= nPLCF
);
2311 // Pointer to Pos-array
2312 const size_t nEntries
= (nPLCF
+ 3) / 4;
2313 m_pPLCF_PosArray
.reset(new WW8_CP
[nEntries
]);
2314 bValid
= checkRead(rSt
, m_pPLCF_PosArray
.get(), nPLCF
);
2315 size_t nBytesAllocated
= nEntries
* sizeof(WW8_CP
);
2316 if (bValid
&& nPLCF
!= nBytesAllocated
)
2318 sal_uInt8
* pStartBlock
= reinterpret_cast<sal_uInt8
*>(m_pPLCF_PosArray
.get());
2319 memset(pStartBlock
+ nPLCF
, 0, nBytesAllocated
- nPLCF
);
2325 #ifdef OSL_BIGENDIAN
2326 for( m_nIdx
= 0; m_nIdx
<= m_nIMax
; m_nIdx
++ )
2327 m_pPLCF_PosArray
[m_nIdx
] = OSL_SWAPDWORD( m_pPLCF_PosArray
[m_nIdx
] );
2329 #endif // OSL_BIGENDIAN
2330 // Pointer to content array
2331 m_pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&m_pPLCF_PosArray
[m_nIMax
+ 1]);
2333 TruncToSortedRange();
2336 OSL_ENSURE(bValid
, "Document has corrupt PLCF, ignoring it");
2344 void WW8PLCF::MakeFailedPLCF()
2347 m_pPLCF_PosArray
.reset( new WW8_CP
[2] );
2348 m_pPLCF_PosArray
[0] = m_pPLCF_PosArray
[1] = WW8_CP_MAX
;
2349 m_pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&m_pPLCF_PosArray
[m_nIMax
+ 1]);
2354 sal_Int32
TruncToSortedRange(const sal_Int32
* pPLCF_PosArray
, sal_Int32 nIMax
)
2356 //Docs state that: ... all Plcs ... are sorted in ascending order.
2357 //So ensure that here for broken documents.
2358 for (auto nI
= 0; nI
< nIMax
; ++nI
)
2360 if (pPLCF_PosArray
[nI
] > pPLCF_PosArray
[nI
+1])
2362 SAL_WARN("sw.ww8", "Document has unsorted PLCF, truncated to sorted portion");
2371 void WW8PLCFpcd::TruncToSortedRange()
2373 m_nIMax
= ::TruncToSortedRange(m_pPLCF_PosArray
.get(), m_nIMax
);
2376 void WW8PLCF::TruncToSortedRange()
2378 m_nIMax
= ::TruncToSortedRange(m_pPLCF_PosArray
.get(), m_nIMax
);
2381 void WW8PLCF::GeneratePLCF(SvStream
& rSt
, sal_Int32 nPN
, sal_Int32 ncpN
)
2383 OSL_ENSURE( m_nIMax
< ncpN
, "Pcl.Fkp: Why is PLCF too big?" );
2385 bool failure
= false;
2388 if ((m_nIMax
< 1) || (m_nIMax
> (WW8_CP_MAX
- 4) / (4 + m_nStru
)) || nPN
< 0)
2393 // Check arguments to ShortToSVBT16 in loop below will all be valid:
2395 failure
= o3tl::checked_add(nPN
, ncpN
, nResult
) || nResult
> SAL_MAX_UINT16
;
2400 size_t nSiz
= (4 + m_nStru
) * m_nIMax
+ 4;
2401 size_t nElems
= ( nSiz
+ 3 ) / 4;
2402 m_pPLCF_PosArray
.reset( new WW8_CP
[ nElems
] ); // Pointer to Pos-array
2404 for (sal_Int32 i
= 0; i
< ncpN
&& !failure
; ++i
)
2407 // construct FC entries
2408 // first FC entry of each Fkp
2409 if (!checkSeek(rSt
, (nPN
+ i
) << 9))
2413 rSt
.ReadInt32( nFc
);
2414 m_pPLCF_PosArray
[i
] = nFc
;
2416 failure
= bool(rSt
.GetError());
2426 std::size_t nLastFkpPos
= nPN
+ m_nIMax
- 1;
2427 nLastFkpPos
= nLastFkpPos
<< 9;
2428 // number of FC entries of last Fkp
2429 if (!checkSeek(rSt
, nLastFkpPos
+ 511))
2433 rSt
.ReadUChar( nb
);
2434 // last FC entry of last Fkp
2435 if (!checkSeek(rSt
, nLastFkpPos
+ nb
* 4))
2439 rSt
.ReadInt32( nFc
);
2440 m_pPLCF_PosArray
[m_nIMax
] = nFc
; // end of the last Fkp
2442 failure
= bool(rSt
.GetError());
2448 // Pointer to content array
2449 m_pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&m_pPLCF_PosArray
[m_nIMax
+ 1]);
2450 sal_uInt8
* p
= m_pPLCF_Contents
;
2452 for (sal_Int32 i
= 0; i
< ncpN
; ++i
) // construct PNs
2454 ShortToSVBT16(o3tl::narrowing
<sal_uInt16
>(nPN
+ i
), p
);
2459 SAL_WARN_IF(failure
, "sw.ww8", "Document has corrupt PLCF, ignoring it");
2465 bool WW8PLCF::SeekPos(WW8_CP nPos
)
2469 if( nP
< m_pPLCF_PosArray
[0] )
2472 // not found: nPos less than smallest entry
2476 // Search from beginning?
2477 if ((m_nIdx
< 1) || (nP
< m_pPLCF_PosArray
[m_nIdx
- 1]))
2480 sal_Int32 nI
= m_nIdx
;
2481 sal_Int32 nEnd
= m_nIMax
;
2483 for(int n
= (1==m_nIdx
? 1 : 2); n
; --n
)
2485 for( ; nI
<=nEnd
; ++nI
) // search with an index that is incremented by 1
2487 if( nP
< m_pPLCF_PosArray
[nI
] ) // found position
2489 m_nIdx
= nI
- 1; // nI - 1 is the correct index
2490 return true; // done
2497 m_nIdx
= m_nIMax
; // not found, greater than all entries
2501 bool WW8PLCF::Get(WW8_CP
& rStart
, WW8_CP
& rEnd
, void*& rpValue
) const
2503 if ( m_nIdx
>= m_nIMax
)
2505 rStart
= rEnd
= WW8_CP_MAX
;
2508 rStart
= m_pPLCF_PosArray
[ m_nIdx
];
2509 rEnd
= m_pPLCF_PosArray
[ m_nIdx
+ 1 ];
2510 rpValue
= static_cast<void*>(&m_pPLCF_Contents
[m_nIdx
* m_nStru
]);
2514 WW8_CP
WW8PLCF::Where() const
2516 if ( m_nIdx
>= m_nIMax
)
2519 return m_pPLCF_PosArray
[m_nIdx
];
2522 WW8PLCFpcd::WW8PLCFpcd(SvStream
* pSt
, sal_uInt32 nFilePos
,
2523 sal_uInt32 nPLCF
, sal_uInt32 nStruct
)
2524 : m_nStru( nStruct
)
2526 const sal_uInt32 nValidMin
=4;
2528 sal_uInt64
const nOldPos
= pSt
->Tell();
2530 bool bValid
= checkSeek(*pSt
, nFilePos
);
2531 std::size_t nRemainingSize
= pSt
->remainingSize();
2532 if( nRemainingSize
< nValidMin
|| nPLCF
< nValidMin
)
2534 nPLCF
= bValid
? std::min(nRemainingSize
, static_cast<std::size_t>(nPLCF
)) : nValidMin
;
2536 m_pPLCF_PosArray
.reset( new WW8_CP
[ ( nPLCF
+ 3 ) / 4 ] ); // Pointer to Pos-array
2537 m_pPLCF_PosArray
[0] = 0;
2539 nPLCF
= bValid
? pSt
->ReadBytes(m_pPLCF_PosArray
.get(), nPLCF
) : nValidMin
;
2540 nPLCF
= std::max(nPLCF
, nValidMin
);
2542 m_nIMax
= ( nPLCF
- 4 ) / ( 4 + nStruct
);
2543 #ifdef OSL_BIGENDIAN
2544 for( tools::Long nI
= 0; nI
<= m_nIMax
; nI
++ )
2545 m_pPLCF_PosArray
[nI
] = OSL_SWAPDWORD( m_pPLCF_PosArray
[nI
] );
2546 #endif // OSL_BIGENDIAN
2548 // Pointer to content array
2549 m_pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&m_pPLCF_PosArray
[m_nIMax
+ 1]);
2550 TruncToSortedRange();
2552 pSt
->Seek( nOldPos
);
2555 // If nStartPos < 0, the first element of PLCFs will be taken
2556 WW8PLCFpcd_Iter::WW8PLCFpcd_Iter( WW8PLCFpcd
& rPLCFpcd
, tools::Long nStartPos
)
2557 :m_rPLCF( rPLCFpcd
), m_nIdx( 0 )
2559 if( nStartPos
>= 0 )
2560 SeekPos( nStartPos
);
2563 bool WW8PLCFpcd_Iter::SeekPos(tools::Long nPos
)
2565 tools::Long nP
= nPos
;
2567 if( nP
< m_rPLCF
.m_pPLCF_PosArray
[0] )
2570 return false; // not found: nPos less than smallest entry
2572 // Search from beginning?
2573 if ((m_nIdx
< 1) || (nP
< m_rPLCF
.m_pPLCF_PosArray
[m_nIdx
- 1]))
2576 tools::Long nI
= m_nIdx
;
2577 tools::Long nEnd
= m_rPLCF
.m_nIMax
;
2579 for(int n
= (1==m_nIdx
? 1 : 2); n
; --n
)
2581 for( ; nI
<=nEnd
; ++nI
)
2582 { // search with an index that is incremented by 1
2583 if( nP
< m_rPLCF
.m_pPLCF_PosArray
[nI
] )
2585 m_nIdx
= nI
- 1; // nI - 1 is the correct index
2586 return true; // done
2592 m_nIdx
= m_rPLCF
.m_nIMax
; // not found, greater than all entries
2596 bool WW8PLCFpcd_Iter::Get(WW8_CP
& rStart
, WW8_CP
& rEnd
, void*& rpValue
) const
2598 if( m_nIdx
>= m_rPLCF
.m_nIMax
)
2600 rStart
= rEnd
= WW8_CP_MAX
;
2603 rStart
= m_rPLCF
.m_pPLCF_PosArray
[m_nIdx
];
2604 rEnd
= m_rPLCF
.m_pPLCF_PosArray
[m_nIdx
+ 1];
2605 rpValue
= static_cast<void*>(&m_rPLCF
.m_pPLCF_Contents
[m_nIdx
* m_rPLCF
.m_nStru
]);
2609 sal_Int32
WW8PLCFpcd_Iter::Where() const
2611 if ( m_nIdx
>= m_rPLCF
.m_nIMax
)
2612 return SAL_MAX_INT32
;
2614 return m_rPLCF
.m_pPLCF_PosArray
[m_nIdx
];
2617 bool WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator<
2618 (const WW8PLCFx_Fc_FKP::WW8Fkp::Entry
& rSecond
) const
2620 return (mnFC
< rSecond
.mnFC
);
2623 static bool IsReplaceAllSprm(sal_uInt16 nSpId
)
2625 return (NS_sprm::LN_PHugePapx
== nSpId
|| 0x6646 == nSpId
);
2628 static bool IsExpandableSprm(sal_uInt16 nSpId
)
2630 return 0x646B == nSpId
;
2633 void WW8PLCFx_Fc_FKP::WW8Fkp::FillEntry(WW8PLCFx_Fc_FKP::WW8Fkp::Entry
&rEntry
,
2634 std::size_t nDataOffset
, sal_uInt16 nLen
)
2636 bool bValidPos
= (nDataOffset
< sizeof(maRawData
));
2638 OSL_ENSURE(bValidPos
, "sprm sequence offset is out of range, ignoring");
2646 const sal_uInt16 nAvailableData
= sizeof(maRawData
)-nDataOffset
;
2647 OSL_ENSURE(nLen
<= nAvailableData
, "sprm sequence len is out of range, clipping");
2648 rEntry
.mnLen
= std::min(nLen
, nAvailableData
);
2649 rEntry
.mpData
= maRawData
+ nDataOffset
;
2652 WW8PLCFx_Fc_FKP::WW8Fkp::WW8Fkp(const WW8Fib
& rFib
, SvStream
* pSt
,
2653 SvStream
* pDataSt
, tools::Long _nFilePos
, tools::Long nItemSiz
, ePLCFT ePl
,
2655 : m_nItemSize(nItemSiz
), m_nFilePos(_nFilePos
), mnIdx(0), m_ePLCF(ePl
)
2656 , mnMustRemainCached(0), maSprmParser(rFib
)
2658 memset(maRawData
, 0, 512);
2660 const ww::WordVersion eVersion
= rFib
.GetFIBVersion();
2662 sal_uInt64
const nOldPos
= pSt
->Tell();
2664 bool bCouldSeek
= checkSeek(*pSt
, m_nFilePos
);
2665 bool bCouldRead
= bCouldSeek
&& checkRead(*pSt
, maRawData
, 512);
2667 mnIMax
= bCouldRead
? maRawData
[511] : 0;
2669 sal_uInt8
*pStart
= maRawData
;
2670 // Offset-Location in maRawData
2671 const size_t nRawDataStart
= (mnIMax
+ 1) * 4;
2673 for (mnIdx
= 0; mnIdx
< mnIMax
; ++mnIdx
)
2675 const size_t nRawDataOffset
= nRawDataStart
+ mnIdx
* m_nItemSize
;
2677 //clip to available data, corrupt fkp
2678 if (nRawDataOffset
>= 511)
2684 unsigned int nOfs
= maRawData
[nRawDataOffset
] * 2;
2685 // nOfs in [0..0xff*2=510]
2687 Entry
aEntry(Get_Long(pStart
));
2695 aEntry
.mnLen
= maRawData
[nOfs
];
2698 std::size_t nDataOffset
= nOfs
+ 1;
2700 FillEntry(aEntry
, nDataOffset
, aEntry
.mnLen
);
2702 if (aEntry
.mnLen
&& eVersion
<= ww::eWW2
)
2704 Word2CHPX aChpx
= ReadWord2Chpx(*pSt
, m_nFilePos
+ nOfs
+ 1, static_cast< sal_uInt8
>(aEntry
.mnLen
));
2705 std::vector
<sal_uInt8
> aSprms
= ChpxToSprms(aChpx
);
2706 aEntry
.mnLen
= static_cast< sal_uInt16
>(aSprms
.size());
2709 aEntry
.mpData
= new sal_uInt8
[aEntry
.mnLen
];
2710 memcpy(aEntry
.mpData
, aSprms
.data(), aEntry
.mnLen
);
2711 aEntry
.mbMustDelete
= true;
2718 sal_uInt8 nDelta
= 0;
2720 aEntry
.mnLen
= maRawData
[nOfs
];
2721 if (IsEightPlus(eVersion
) && !aEntry
.mnLen
)
2723 aEntry
.mnLen
= maRawData
[nOfs
+1];
2728 //stylecode, std/istd
2729 if (eVersion
<= ww::eWW2
)
2731 if (aEntry
.mnLen
>= 1)
2733 aEntry
.mnIStd
= *(maRawData
+nOfs
+1+nDelta
);
2734 aEntry
.mnLen
--; //style code
2735 if (aEntry
.mnLen
>= 6)
2737 aEntry
.mnLen
-=6; //PHE
2738 //skip stc, len byte + 6 byte PHE
2739 unsigned int nOffset
= nOfs
+ 8;
2740 if (nOffset
>= 511) //Bad offset
2742 if (aEntry
.mnLen
) //start is ok
2744 if (nOffset
+ aEntry
.mnLen
> 512) //Bad end, clip
2745 aEntry
.mnLen
= 512 - nOffset
;
2746 aEntry
.mpData
= maRawData
+ nOffset
;
2750 aEntry
.mnLen
=0; //Too short
2755 if (aEntry
.mnLen
>= 2)
2757 //len byte + optional extra len byte
2758 std::size_t nDataOffset
= nOfs
+ 1 + nDelta
;
2759 aEntry
.mnIStd
= nDataOffset
<= sizeof(maRawData
)-sizeof(aEntry
.mnIStd
) ?
2760 SVBT16ToUInt16(maRawData
+nDataOffset
) : 0;
2761 aEntry
.mnLen
-=2; //istd
2765 nDataOffset
+= sizeof(aEntry
.mnIStd
);
2767 FillEntry(aEntry
, nDataOffset
, aEntry
.mnLen
);
2771 aEntry
.mnLen
=0; //Too short, ignore
2774 const sal_uInt16 nSpId
= aEntry
.mnLen
2775 ? maSprmParser
.GetSprmId(aEntry
.mpData
) : 0;
2778 If we replace then we throw away the old data, if we
2779 are expanding, then we tack the old data onto the end
2782 const bool bExpand
= IsExpandableSprm(nSpId
);
2783 const sal_uInt8
* pStartData
2784 = aEntry
.mpData
== nullptr ? nullptr : aEntry
.mpData
+ 2;
2785 const sal_uInt8
* pLastValidDataPos
= maRawData
+ 512 - sizeof(sal_uInt32
);
2786 if (pStartData
!= nullptr && pStartData
> pLastValidDataPos
)
2787 pStartData
= nullptr;
2788 if ((IsReplaceAllSprm(nSpId
) || bExpand
) && pStartData
)
2790 sal_uInt64 nCurr
= pDataSt
->Tell();
2791 sal_uInt32 nPos
= SVBT32ToUInt32(pStartData
);
2794 bool bOk
= checkSeek(*pDataSt
, nPos
);
2797 pDataSt
->ReadUInt16( nLen
);
2798 bOk
= nLen
<= pDataSt
->remainingSize();
2803 const sal_uInt16 nOrigLen
= bExpand
? aEntry
.mnLen
: 0;
2804 sal_uInt8
*pOrigData
= bExpand
? aEntry
.mpData
: nullptr;
2806 aEntry
.mnLen
= nLen
;
2808 new sal_uInt8
[aEntry
.mnLen
+ nOrigLen
];
2809 aEntry
.mbMustDelete
= true;
2811 pDataSt
->ReadBytes(aEntry
.mpData
, aEntry
.mnLen
);
2813 pDataSt
->Seek( nCurr
);
2817 memcpy(aEntry
.mpData
+ aEntry
.mnLen
,
2818 pOrigData
, nOrigLen
);
2819 aEntry
.mnLen
= aEntry
.mnLen
+ nOrigLen
;
2826 OSL_FAIL("sweet god, what have you done!");
2831 maEntries
.push_back(aEntry
);
2834 //one more FC than grrpl entries
2835 maEntries
.emplace_back(Get_Long(pStart
));
2837 //we expect them sorted, but it appears possible for them to arrive unsorted
2838 std::stable_sort(maEntries
.begin(), maEntries
.end());
2848 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::Entry(const Entry
&rEntry
)
2849 : mnFC(rEntry
.mnFC
), mnLen(rEntry
.mnLen
), mnIStd(rEntry
.mnIStd
),
2850 mbMustDelete(rEntry
.mbMustDelete
)
2854 mpData
= new sal_uInt8
[mnLen
];
2855 memcpy(mpData
, rEntry
.mpData
, mnLen
);
2858 mpData
= rEntry
.mpData
;
2861 WW8PLCFx_Fc_FKP::WW8Fkp::Entry
&
2862 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator=(const Entry
&rEntry
)
2864 if (this == &rEntry
)
2871 mnLen
= rEntry
.mnLen
;
2872 mnIStd
= rEntry
.mnIStd
;
2873 mbMustDelete
= rEntry
.mbMustDelete
;
2875 if (rEntry
.mbMustDelete
)
2877 mpData
= new sal_uInt8
[mnLen
];
2878 memcpy(mpData
, rEntry
.mpData
, mnLen
);
2881 mpData
= rEntry
.mpData
;
2886 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::~Entry()
2892 void WW8PLCFx_Fc_FKP::WW8Fkp::Reset(WW8_FC nFc
)
2899 bool WW8PLCFx_Fc_FKP::WW8Fkp::SeekPos(WW8_FC nFc
)
2901 if (nFc
< maEntries
[0].mnFC
)
2904 return false; // not found: nPos less than smallest entry
2907 // Search from beginning?
2908 if ((mnIdx
< 1) || (nFc
< maEntries
[mnIdx
- 1].mnFC
))
2911 sal_uInt8 nI
= mnIdx
;
2912 sal_uInt8 nEnd
= mnIMax
;
2914 for(sal_uInt8 n
= (1==mnIdx
? 1 : 2); n
; --n
)
2916 for( ; nI
<=nEnd
; ++nI
)
2917 { // search with an index that is incremented by 1
2918 if (nFc
< maEntries
[nI
].mnFC
)
2920 mnIdx
= nI
- 1; // nI - 1 is the correct index
2921 return true; // done
2927 mnIdx
= mnIMax
; // not found, greater than all entries
2931 sal_uInt8
* WW8PLCFx_Fc_FKP::WW8Fkp::Get(WW8_FC
& rStart
, WW8_FC
& rEnd
, sal_Int32
& rLen
)
2936 if (mnIdx
>= mnIMax
)
2938 rStart
= WW8_FC_MAX
;
2942 rStart
= maEntries
[mnIdx
].mnFC
;
2943 rEnd
= maEntries
[mnIdx
+ 1].mnFC
;
2945 sal_uInt8
* pSprms
= GetLenAndIStdAndSprms( rLen
);
2949 void WW8PLCFx_Fc_FKP::WW8Fkp::SetIdx(sal_uInt8 nI
)
2957 sal_uInt8
* WW8PLCFx_Fc_FKP::WW8Fkp::GetLenAndIStdAndSprms(sal_Int32
& rLen
) const
2959 rLen
= maEntries
[mnIdx
].mnLen
;
2960 return maEntries
[mnIdx
].mpData
;
2963 SprmResult
WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm( sal_uInt16 nId
, bool bFindFirst
)
2965 if (mnIdx
>= mnIMax
)
2966 return SprmResult();
2969 sal_uInt8
* pSprms
= GetLenAndIStdAndSprms( nLen
);
2971 WW8SprmIter
aIter(pSprms
, nLen
, maSprmParser
);
2972 return aIter
.FindSprm(nId
, bFindFirst
);
2975 void WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm(sal_uInt16 nId
,
2976 std::vector
<SprmResult
> &rResult
)
2978 if (mnIdx
>= mnIMax
)
2982 sal_uInt8
* pSprms
= GetLenAndIStdAndSprms( nLen
);
2984 WW8SprmIter
aIter(pSprms
, nLen
, maSprmParser
);
2986 while(aIter
.GetSprms())
2988 if (aIter
.GetCurrentId() == nId
)
2990 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId
);
2991 sal_Int32 nL
= maSprmParser
.GetSprmSize(nId
, aIter
.GetSprms(), aIter
.GetRemLen());
2992 rResult
.emplace_back(aIter
.GetCurrentParams(), nL
- nFixedLen
);
2998 ww::WordVersion
WW8PLCFx::GetFIBVersion() const
3000 return mrFib
.GetFIBVersion();
3003 void WW8PLCFx::GetSprms( WW8PLCFxDesc
* p
)
3005 OSL_ENSURE( false, "Called wrong GetSprms" );
3006 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
3007 p
->pMemPos
= nullptr;
3009 p
->bRealLineEnd
= false;
3012 tools::Long
WW8PLCFx::GetNoSprms( WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
3014 OSL_ENSURE( false, "Called wrong GetNoSprms" );
3015 rStart
= rEnd
= WW8_CP_MAX
;
3020 // ...Idx2: Default: ignore
3021 sal_uInt32
WW8PLCFx::GetIdx2() const
3026 void WW8PLCFx::SetIdx2(sal_uInt32
)
3037 explicit SamePos(tools::Long nPo
) : mnPo(nPo
) {}
3038 bool operator()(const std::unique_ptr
<WW8PLCFx_Fc_FKP::WW8Fkp
>& pFkp
)
3039 {return mnPo
== pFkp
->GetFilePos();}
3044 bool WW8PLCFx_Fc_FKP::NewFkp()
3046 WW8_CP nPLCFStart
, nPLCFEnd
;
3049 static const int WW8FkpSizeTabVer2
[ PLCF_END
] =
3051 1, 1, 0 /*, 0, 0, 0*/
3053 static const int WW8FkpSizeTabVer6
[ PLCF_END
] =
3055 1, 7, 0 /*, 0, 0, 0*/
3057 static const int WW8FkpSizeTabVer8
[ PLCF_END
] =
3059 1, 13, 0 /*, 0, 0, 0*/
3061 const int* pFkpSizeTab
;
3063 switch (GetFIBVersion())
3067 pFkpSizeTab
= WW8FkpSizeTabVer2
;
3071 pFkpSizeTab
= WW8FkpSizeTabVer6
;
3074 pFkpSizeTab
= WW8FkpSizeTabVer8
;
3078 OSL_ENSURE( false, "nVersion not implemented!" );
3082 if (!m_pPLCF
->Get( nPLCFStart
, nPLCFEnd
, pPage
))
3085 return false; // PLCF completely processed
3088 tools::Long nPo
= SVBT16ToUInt16( static_cast<sal_uInt8
*>(pPage
) );
3089 nPo
<<= 9; // shift as LONG
3091 tools::Long nCurrentFkpFilePos
= m_pFkp
? m_pFkp
->GetFilePos() : -1;
3092 if (nCurrentFkpFilePos
== nPo
)
3093 m_pFkp
->Reset(GetStartFc());
3097 std::find_if(maFkpCache
.begin(), maFkpCache
.end(), SamePos(nPo
));
3098 if (aIter
!= maFkpCache
.end())
3100 m_pFkp
= aIter
->get();
3101 m_pFkp
->Reset(GetStartFc());
3105 m_pFkp
= new WW8Fkp(GetFIB(), m_pFKPStrm
, m_pDataStrm
, nPo
,
3106 pFkpSizeTab
[ m_ePLCF
], m_ePLCF
, GetStartFc());
3107 maFkpCache
.push_back(std::unique_ptr
<WW8Fkp
>(m_pFkp
));
3109 if (maFkpCache
.size() > eMaxCache
)
3111 WW8Fkp
* pCachedFkp
= maFkpCache
.front().get();
3112 if (!pCachedFkp
->IsMustRemainCache())
3114 maFkpCache
.pop_front();
3120 SetStartFc( -1 ); // only the first time
3124 WW8PLCFx_Fc_FKP::WW8PLCFx_Fc_FKP(SvStream
* pSt
, SvStream
* pTableSt
,
3125 SvStream
* pDataSt
, const WW8Fib
& rFib
, ePLCFT ePl
, WW8_FC nStartFcL
)
3126 : WW8PLCFx(rFib
, true), m_pFKPStrm(pSt
), m_pDataStrm(pDataSt
)
3127 , m_pFkp(nullptr), m_ePLCF(ePl
)
3129 SetStartFc(nStartFcL
);
3130 tools::Long nLenStruct
= (8 > rFib
.m_nVersion
) ? 2 : 4;
3133 m_pPLCF
.reset(new WW8PLCF(*pTableSt
, rFib
.m_fcPlcfbteChpx
, rFib
.m_lcbPlcfbteChpx
,
3134 nLenStruct
, GetStartFc(), rFib
.m_pnChpFirst
, rFib
.m_cpnBteChp
));
3138 m_pPLCF
.reset(new WW8PLCF(*pTableSt
, rFib
.m_fcPlcfbtePapx
, rFib
.m_lcbPlcfbtePapx
,
3139 nLenStruct
, GetStartFc(), rFib
.m_pnPapFirst
, rFib
.m_cpnBtePap
));
3143 WW8PLCFx_Fc_FKP::~WW8PLCFx_Fc_FKP()
3147 m_pPCDAttrs
.reset();
3150 sal_uInt32
WW8PLCFx_Fc_FKP::GetIdx() const
3152 sal_uInt32 u
= m_pPLCF
->GetIdx() << 8;
3154 u
|= m_pFkp
->GetIdx();
3158 void WW8PLCFx_Fc_FKP::SetIdx(sal_uInt32 nIdx
)
3160 if( !( nIdx
& 0xffffff00L
) )
3162 m_pPLCF
->SetIdx( nIdx
>> 8 );
3166 { // there was a Fkp
3167 // Set PLCF one position back to retrieve the address of the Fkp
3168 m_pPLCF
->SetIdx( ( nIdx
>> 8 ) - 1 );
3169 if (NewFkp()) // read Fkp again
3171 sal_uInt8 nFkpIdx
= static_cast<sal_uInt8
>(nIdx
& 0xff);
3172 m_pFkp
->SetIdx(nFkpIdx
); // set Fkp-Pos again
3177 bool WW8PLCFx_Fc_FKP::SeekPos(WW8_FC nFcPos
)
3179 // StartPos for next Where()
3180 SetStartFc( nFcPos
);
3182 // find StartPos for next pPLCF->Get()
3183 bool bRet
= m_pPLCF
->SeekPos(nFcPos
);
3185 // make FKP invalid?
3186 WW8_CP nPLCFStart
, nPLCFEnd
;
3188 if( m_pFkp
&& m_pPLCF
->Get( nPLCFStart
, nPLCFEnd
, pPage
) )
3190 tools::Long nPo
= SVBT16ToUInt16( static_cast<sal_uInt8
*>(pPage
) );
3191 nPo
<<= 9; // shift as LONG
3192 if (nPo
!= m_pFkp
->GetFilePos())
3195 m_pFkp
->SeekPos( nFcPos
);
3200 WW8_FC
WW8PLCFx_Fc_FKP::Where()
3202 if( !m_pFkp
&& !NewFkp() )
3204 WW8_FC nP
= m_pFkp
? m_pFkp
->Where() : WW8_FC_MAX
;
3205 if( nP
!= WW8_FC_MAX
)
3208 m_pFkp
= nullptr; // FKP finished -> get new
3209 return Where(); // easiest way: do it recursively
3212 sal_uInt8
* WW8PLCFx_Fc_FKP::GetSprmsAndPos(WW8_FC
& rStart
, WW8_FC
& rEnd
, sal_Int32
& rLen
)
3214 rLen
= 0; // Default
3215 rStart
= rEnd
= WW8_FC_MAX
;
3217 if( !m_pFkp
) // Fkp not there ?
3223 sal_uInt8
* pPos
= m_pFkp
? m_pFkp
->Get( rStart
, rEnd
, rLen
) : nullptr;
3224 if( rStart
== WW8_FC_MAX
) //Not found
3229 void WW8PLCFx_Fc_FKP::advance()
3231 if( !m_pFkp
&& !NewFkp() )
3238 if( m_pFkp
->Where() == WW8_FC_MAX
)
3242 sal_uInt16
WW8PLCFx_Fc_FKP::GetIstd() const
3244 return m_pFkp
? m_pFkp
->GetIstd() : 0xFFFF;
3247 void WW8PLCFx_Fc_FKP::GetPCDSprms( WW8PLCFxDesc
& rDesc
)
3249 rDesc
.pMemPos
= nullptr;
3250 rDesc
.nSprmsLen
= 0;
3255 OSL_FAIL("+Problem: GetPCDSprms: NewFkp necessary (not possible!)" );
3259 m_pPCDAttrs
->GetSprms(&rDesc
);
3263 SprmResult
WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId
, bool bFindFirst
)
3265 // const would be nicer, but for that, NewFkp() would need to be replaced or eliminated
3268 OSL_FAIL( "+Motz: HasSprm: NewFkp needed ( no const possible )" );
3269 // happens in BugDoc 31722
3271 return SprmResult();
3275 return SprmResult();
3277 SprmResult aRes
= m_pFkp
->HasSprm(nId
, bFindFirst
);
3282 GetPCDSprms( aDesc
);
3286 WW8SprmIter
aIter(aDesc
.pMemPos
, aDesc
.nSprmsLen
,
3287 m_pFkp
->GetSprmParser());
3288 aRes
= aIter
.FindSprm(nId
, bFindFirst
);
3295 void WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId
, std::vector
<SprmResult
> &rResult
)
3297 // const would be nicer, but for that, NewFkp() would need to be replaced or eliminated
3300 OSL_FAIL( "+Motz: HasSprm: NewFkp needed ( no const possible )" );
3301 // happens in BugDoc 31722
3309 m_pFkp
->HasSprm(nId
, rResult
);
3312 GetPCDSprms( aDesc
);
3317 const wwSprmParser
&rSprmParser
= m_pFkp
->GetSprmParser();
3318 WW8SprmIter
aIter(aDesc
.pMemPos
, aDesc
.nSprmsLen
, rSprmParser
);
3319 while(aIter
.GetSprms())
3321 if (aIter
.GetCurrentId() == nId
)
3323 sal_Int32 nFixedLen
= rSprmParser
.DistanceToData(nId
);
3324 sal_Int32 nL
= rSprmParser
.GetSprmSize(nId
, aIter
.GetSprms(), aIter
.GetRemLen());
3325 rResult
.emplace_back(aIter
.GetCurrentParams(), nL
- nFixedLen
);
3331 WW8PLCFx_Cp_FKP::WW8PLCFx_Cp_FKP( SvStream
* pSt
, SvStream
* pTableSt
,
3332 SvStream
* pDataSt
, const WW8ScannerBase
& rBase
, ePLCFT ePl
)
3333 : WW8PLCFx_Fc_FKP(pSt
, pTableSt
, pDataSt
, *rBase
.m_pWw8Fib
, ePl
,
3334 rBase
.WW8Cp2Fc(0)), m_rSBase(rBase
), m_nAttrStart(-1), m_nAttrEnd(-1),
3336 m_bComplex( (7 < rBase
.m_pWw8Fib
->m_nVersion
) || rBase
.m_pWw8Fib
->m_fComplex
)
3338 ResetAttrStartEnd();
3340 if (m_rSBase
.m_pPiecePLCF
)
3341 m_pPcd
.reset( new WW8PLCFx_PCD(GetFIB(), rBase
.m_pPiecePLCF
.get(), 0, IsSevenMinus(GetFIBVersion())) );
3344 Make a copy of the piece attributes for so that the calls to HasSprm on a
3345 Fc_FKP will be able to take into account the current piece attributes,
3346 despite the fact that such attributes can only be found through a cp based
3351 m_pPCDAttrs
.reset( m_rSBase
.m_pPLCFx_PCDAttrs
? new WW8PLCFx_PCDAttrs(
3352 *m_rSBase
.m_pWw8Fib
, m_pPcd
.get(), &m_rSBase
) : nullptr);
3355 m_pPieceIter
= m_rSBase
.m_pPieceIter
.get();
3358 WW8PLCFx_Cp_FKP::~WW8PLCFx_Cp_FKP()
3362 void WW8PLCFx_Cp_FKP::ResetAttrStartEnd()
3369 sal_uInt32
WW8PLCFx_Cp_FKP::GetPCDIdx() const
3371 return m_pPcd
? m_pPcd
->GetIdx() : 0;
3374 bool WW8PLCFx_Cp_FKP::SeekPos(WW8_CP nCpPos
)
3376 if( m_pPcd
) // Complex
3378 if( !m_pPcd
->SeekPos( nCpPos
) ) // set piece
3380 if (m_pPCDAttrs
&& !m_pPCDAttrs
->GetIter()->SeekPos(nCpPos
))
3382 return WW8PLCFx_Fc_FKP::SeekPos(m_pPcd
->CurrentPieceStartCp2Fc(nCpPos
));
3384 // NO piece table !!!
3385 return WW8PLCFx_Fc_FKP::SeekPos( m_rSBase
.WW8Cp2Fc(nCpPos
) );
3388 WW8_CP
WW8PLCFx_Cp_FKP::Where()
3390 WW8_FC nFc
= WW8PLCFx_Fc_FKP::Where();
3392 return m_pPcd
->CurrentPieceStartFc2Cp( nFc
); // identify piece
3393 return m_rSBase
.WW8Fc2Cp( nFc
); // NO piece table !!!
3396 void WW8PLCFx_Cp_FKP::GetSprms(WW8PLCFxDesc
* p
)
3398 WW8_CP nOrigCp
= p
->nStartPos
;
3400 if (!GetDirty()) //Normal case
3402 p
->pMemPos
= WW8PLCFx_Fc_FKP::GetSprmsAndPos(p
->nStartPos
, p
->nEndPos
,
3408 For the odd case where we have a location in a fastsaved file which
3409 does not have an entry in the FKP, perhaps its para end is in the next
3410 piece, or perhaps the cp just doesn't exist at all in this document.
3411 AdvSprm doesn't know so it sets the PLCF as dirty and we figure out
3412 in this method what the situation is
3414 It doesn't exist then the piece iterator will not be able to find it.
3415 Otherwise our cool fastsave algorithm can be brought to bear on the
3420 const sal_uInt32 nOldPos
= m_pPieceIter
->GetIdx();
3421 bool bOk
= m_pPieceIter
->SeekPos(nOrigCp
);
3422 m_pPieceIter
->SetIdx(nOldPos
);
3427 if( m_pPcd
) // piece table available
3429 // Init ( no ++ called, yet )
3430 if( (m_nAttrStart
> m_nAttrEnd
) || (m_nAttrStart
== -1) )
3432 p
->bRealLineEnd
= (m_ePLCF
== PAP
);
3434 if ( ((m_ePLCF
== PAP
) || (m_ePLCF
== CHP
)) && (nOrigCp
!= WW8_CP_MAX
) )
3436 bool bIsUnicode
=false;
3438 To find the end of a paragraph for a character in a
3439 complex format file.
3441 It is necessary to know the piece that contains the
3442 character and the FC assigned to the character.
3445 //We set the piece iterator to the piece that contains the
3446 //character, now we have the correct piece for this character
3447 sal_uInt32 nOldPos
= m_pPieceIter
->GetIdx();
3448 p
->nStartPos
= nOrigCp
;
3449 m_pPieceIter
->SeekPos( p
->nStartPos
);
3451 //This is the FC assigned to the character, but we already
3452 //have the result of the next stage, so we can skip this step
3453 //WW8_FC nStartFc = rSBase.WW8Cp2Fc(p->nStartPos, &bIsUnicode);
3456 Using the FC of the character, first search the FKP that
3457 describes the character to find the smallest FC in the rgfc
3458 that is larger than the character FC.
3460 //But the search has already been done, the next largest FC is
3462 WW8_FC nOldEndPos
= p
->nEndPos
;
3465 If the FC found in the FKP is less than or equal to the limit
3466 FC of the piece, the end of the paragraph that contains the
3467 character is at the FKP FC minus 1.
3469 WW8_CP nCpStart
, nCpEnd
;
3470 void* pData
=nullptr;
3471 bool bOk
= m_pPieceIter
->Get(nCpStart
, nCpEnd
, pData
);
3475 m_pPieceIter
->SetIdx(nOldPos
);
3479 WW8_FC nLimitFC
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
3480 WW8_FC nBeginLimitFC
= nLimitFC
;
3481 if (IsEightPlus(GetFIBVersion()))
3484 WW8PLCFx_PCD::TransformPieceAddress(nLimitFC
,
3489 bool bFail
= o3tl::checked_sub(nCpEnd
, nCpStart
, nCpLen
);
3492 SAL_WARN("sw.ww8", "broken offset, ignoring");
3493 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3494 m_pPieceIter
->SetIdx(nOldPos
);
3500 bFail
= o3tl::checked_multiply
<WW8_CP
>(nCpLen
, 2, nCpLen
);
3503 SAL_WARN("sw.ww8", "broken offset, ignoring");
3504 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3505 m_pPieceIter
->SetIdx(nOldPos
);
3510 bFail
= o3tl::checked_add(nBeginLimitFC
, nCpLen
, nLimitFC
);
3513 SAL_WARN("sw.ww8", "broken offset, ignoring");
3514 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3515 m_pPieceIter
->SetIdx(nOldPos
);
3519 if (nOldEndPos
<= nLimitFC
)
3521 bFail
= o3tl::checked_sub(nLimitFC
, nOldEndPos
, nCpLen
);
3524 SAL_WARN("sw.ww8", "broken offset, ignoring");
3525 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3526 m_pPieceIter
->SetIdx(nOldPos
);
3530 nCpLen
/= (bIsUnicode
? 2 : 1);
3532 bFail
= o3tl::checked_sub(nCpEnd
, nCpLen
, p
->nEndPos
);
3535 SAL_WARN("sw.ww8", "broken offset, ignoring");
3536 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3537 m_pPieceIter
->SetIdx(nOldPos
);
3543 p
->nEndPos
= nCpEnd
;
3547 If the FKP FC that was found was greater than the FC
3548 of the end of the piece, scan piece by piece toward
3549 the end of the document until a piece is found that
3550 contains a paragraph end mark.
3554 It's possible to check if a piece contains a paragraph
3555 mark by using the FC of the beginning of the piece to
3556 search in the FKPs for the smallest FC in the FKP rgfc
3557 that is greater than the FC of the beginning of the
3558 piece. If the FC found is less than or equal to the
3559 limit FC of the piece, then the character that ends
3560 the paragraph is the character immediately before the
3564 m_pPieceIter
->advance();
3566 for (;m_pPieceIter
->GetIdx() < m_pPieceIter
->GetIMax();
3567 m_pPieceIter
->advance())
3569 if( !m_pPieceIter
->Get( nCpStart
, nCpEnd
, pData
) )
3571 OSL_ENSURE( false, "piece iter broken!" );
3575 sal_Int32 nFcStart
=SVBT32ToUInt32(static_cast<WW8_PCD
*>(pData
)->fc
);
3577 if (IsEightPlus(GetFIBVersion()))
3580 WW8PLCFx_PCD::TransformPieceAddress(
3581 nFcStart
,bIsUnicode
);
3584 bFail
= o3tl::checked_sub(nCpEnd
, nCpStart
, nCpLen
);
3587 SAL_WARN("sw.ww8", "broken offset, ignoring");
3588 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3594 bFail
= o3tl::checked_multiply
<WW8_CP
>(nCpLen
, 2, nCpLen
);
3597 SAL_WARN("sw.ww8", "broken offset, ignoring");
3598 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3603 bFail
= o3tl::checked_add(nFcStart
, nCpLen
, nLimitFC
);
3606 SAL_WARN("sw.ww8", "broken offset, ignoring");
3607 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3611 //if it doesn't exist, skip it
3612 if (!SeekPos(nCpStart
))
3615 WW8_FC nOne
,nSmallest
;
3616 p
->pMemPos
= WW8PLCFx_Fc_FKP::GetSprmsAndPos(nOne
,
3617 nSmallest
, p
->nSprmsLen
);
3619 if (nSmallest
<= nLimitFC
)
3622 bFail
= o3tl::checked_sub(nLimitFC
, nSmallest
, nCpDiff
);
3625 SAL_WARN("sw.ww8", "broken offset, ignoring");
3626 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3633 bFail
= o3tl::checked_sub(nCpEnd
, nCpDiff
, nEndPos
);
3636 SAL_WARN("sw.ww8", "broken offset, ignoring");
3637 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3641 OSL_ENSURE(nEndPos
>= p
->nStartPos
, "EndPos before StartPos");
3643 if (nEndPos
>= p
->nStartPos
)
3644 p
->nEndPos
= nEndPos
;
3651 m_pPieceIter
->SetIdx( nOldPos
);
3654 WW8PLCFx_PCD::CurrentPieceFc2Cp( p
->nStartPos
, p
->nEndPos
,&m_rSBase
);
3658 p
->nStartPos
= m_nAttrStart
;
3659 p
->nEndPos
= m_nAttrEnd
;
3660 p
->bRealLineEnd
= m_bLineEnd
;
3663 else // NO piece table !!!
3665 p
->nStartPos
= m_rSBase
.WW8Fc2Cp( p
->nStartPos
);
3666 p
->nEndPos
= m_rSBase
.WW8Fc2Cp( p
->nEndPos
);
3667 p
->bRealLineEnd
= m_ePLCF
== PAP
;
3671 void WW8PLCFx_Cp_FKP::advance()
3673 WW8PLCFx_Fc_FKP::advance();
3674 // !pPcd: emergency break
3675 if ( !m_bComplex
|| !m_pPcd
)
3678 if( GetPCDIdx() >= m_pPcd
->GetIMax() ) // End of PLCF
3680 m_nAttrStart
= m_nAttrEnd
= WW8_CP_MAX
;
3684 sal_Int32 nFkpLen
; // Fkp entry
3686 WW8PLCFx_Fc_FKP::GetSprmsAndPos(m_nAttrStart
, m_nAttrEnd
, nFkpLen
);
3688 WW8PLCFx_PCD::CurrentPieceFc2Cp( m_nAttrStart
, m_nAttrEnd
, &m_rSBase
);
3689 m_bLineEnd
= (m_ePLCF
== PAP
);
3692 WW8PLCFx_SEPX::WW8PLCFx_SEPX(SvStream
* pSt
, SvStream
* pTableSt
,
3693 const WW8Fib
& rFib
, WW8_CP nStartCp
)
3694 : WW8PLCFx(rFib
, true), maSprmParser(rFib
),
3695 m_pStrm(pSt
), m_nArrMax(256), m_nSprmSiz(0)
3697 if (rFib
.m_lcbPlcfsed
)
3698 m_pPLCF
.reset( new WW8PLCF(*pTableSt
, rFib
.m_fcPlcfsed
, rFib
.m_lcbPlcfsed
,
3699 GetFIBVersion() <= ww::eWW2
? 6 : 12, nStartCp
) );
3701 m_pSprms
.reset( new sal_uInt8
[m_nArrMax
] ); // maximum length
3704 WW8PLCFx_SEPX::~WW8PLCFx_SEPX()
3708 sal_uInt32
WW8PLCFx_SEPX::GetIdx() const
3710 return m_pPLCF
? m_pPLCF
->GetIdx() : 0;
3713 void WW8PLCFx_SEPX::SetIdx(sal_uInt32 nIdx
)
3715 if( m_pPLCF
) m_pPLCF
->SetIdx( nIdx
);
3718 bool WW8PLCFx_SEPX::SeekPos(WW8_CP nCpPos
)
3720 return m_pPLCF
&& m_pPLCF
->SeekPos( nCpPos
);
3723 WW8_CP
WW8PLCFx_SEPX::Where()
3725 return m_pPLCF
? m_pPLCF
->Where() : 0;
3728 void WW8PLCFx_SEPX::GetSprms(WW8PLCFxDesc
* p
)
3730 if( !m_pPLCF
) return;
3734 p
->bRealLineEnd
= false;
3735 if (!m_pPLCF
->Get( p
->nStartPos
, p
->nEndPos
, pData
))
3737 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
; // PLCF completely processed
3738 p
->pMemPos
= nullptr;
3743 sal_uInt32 nPo
= SVBT32ToUInt32( static_cast<sal_uInt8
*>(pData
)+2 );
3744 if (nPo
== 0xFFFFFFFF || !checkSeek(*m_pStrm
, nPo
))
3746 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
; // Sepx empty
3747 p
->pMemPos
= nullptr;
3753 if (GetFIBVersion() <= ww::eWW2
) // eWW6 ?, docs say yes, but...
3756 m_pStrm
->ReadUChar( nSiz
);
3761 m_pStrm
->ReadUInt16( m_nSprmSiz
);
3764 std::size_t nRemaining
= m_pStrm
->remainingSize();
3765 if (m_nSprmSiz
> nRemaining
)
3766 m_nSprmSiz
= nRemaining
;
3768 if( m_nSprmSiz
> m_nArrMax
)
3770 m_nArrMax
= m_nSprmSiz
; // Get more memory
3771 m_pSprms
.reset( new sal_uInt8
[m_nArrMax
] );
3773 m_nSprmSiz
= m_pStrm
->ReadBytes(m_pSprms
.get(), m_nSprmSiz
); // read Sprms
3775 p
->nSprmsLen
= m_nSprmSiz
;
3776 p
->pMemPos
= m_pSprms
.get(); // return Position
3781 void WW8PLCFx_SEPX::advance()
3787 SprmResult
WW8PLCFx_SEPX::HasSprm(sal_uInt16 nId
) const
3789 return HasSprm(nId
, m_pSprms
.get(), m_nSprmSiz
);
3792 SprmResult
WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId
, const sal_uInt8
* pOtherSprms
,
3793 tools::Long nOtherSprmSiz
) const
3798 WW8SprmIter
aIter(pOtherSprms
, nOtherSprmSiz
, maSprmParser
);
3799 aRet
= aIter
.FindSprm(nId
, /*bFindFirst=*/true);
3804 bool WW8PLCFx_SEPX::Find4Sprms(sal_uInt16 nId1
,sal_uInt16 nId2
,sal_uInt16 nId3
,sal_uInt16 nId4
,
3805 SprmResult
& r1
, SprmResult
& r2
, SprmResult
& r3
, SprmResult
& r4
) const
3810 bool bFound
= false;
3812 sal_uInt8
* pSp
= m_pSprms
.get();
3814 while (i
+ maSprmParser
.MinSprmLen() <= m_nSprmSiz
)
3817 const sal_uInt16 nCurrentId
= maSprmParser
.GetSprmId(pSp
);
3818 sal_Int32 nRemLen
= m_nSprmSiz
- i
;
3819 const sal_Int32 x
= maSprmParser
.GetSprmSize(nCurrentId
, pSp
, nRemLen
);
3820 bool bValid
= x
<= nRemLen
;
3823 SAL_WARN("sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong");
3827 if( nCurrentId
== nId1
)
3829 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId1
);
3830 r1
= SprmResult(pSp
+ nFixedLen
, x
- nFixedLen
);
3832 else if( nCurrentId
== nId2
)
3834 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId2
);
3835 r2
= SprmResult(pSp
+ nFixedLen
, x
- nFixedLen
);
3837 else if( nCurrentId
== nId3
)
3839 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId3
);
3840 r3
= SprmResult(pSp
+ nFixedLen
, x
- nFixedLen
);
3842 else if( nCurrentId
== nId4
)
3844 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId4
);
3845 r4
= SprmResult(pSp
+ nFixedLen
, x
- nFixedLen
);
3850 // increment pointer so that it points to next SPRM
3857 SprmResult
WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId
, sal_uInt8 n2nd
) const
3862 WW8SprmIter
aIter(m_pSprms
.get(), m_nSprmSiz
, maSprmParser
);
3863 aRet
= aIter
.FindSprm(nId
, /*bFindFirst=*/true, &n2nd
);
3868 WW8PLCFx_SubDoc::WW8PLCFx_SubDoc(SvStream
* pSt
, const WW8Fib
& rFib
,
3869 WW8_CP nStartCp
, tools::Long nFcRef
, tools::Long nLenRef
, tools::Long nFcText
, tools::Long nLenText
,
3870 tools::Long nStruct
)
3871 : WW8PLCFx(rFib
, true)
3873 if( nLenRef
&& nLenText
)
3875 m_pRef
.reset(new WW8PLCF(*pSt
, nFcRef
, nLenRef
, nStruct
, nStartCp
));
3876 m_pText
.reset(new WW8PLCF(*pSt
, nFcText
, nLenText
, 0, nStartCp
));
3880 WW8PLCFx_SubDoc::~WW8PLCFx_SubDoc()
3886 sal_uInt32
WW8PLCFx_SubDoc::GetIdx() const
3888 // Probably pText ... no need for it
3890 return ( m_pRef
->GetIdx() << 16 | m_pText
->GetIdx() );
3894 void WW8PLCFx_SubDoc::SetIdx(sal_uInt32 nIdx
)
3898 m_pRef
->SetIdx( nIdx
>> 16 );
3899 // Probably pText ... no need for it
3900 m_pText
->SetIdx( nIdx
& 0xFFFF );
3904 bool WW8PLCFx_SubDoc::SeekPos( WW8_CP nCpPos
)
3906 return m_pRef
&& m_pRef
->SeekPos( nCpPos
);
3909 WW8_CP
WW8PLCFx_SubDoc::Where()
3911 return m_pRef
? m_pRef
->Where() : WW8_CP_MAX
;
3914 void WW8PLCFx_SubDoc::GetSprms(WW8PLCFxDesc
* p
)
3916 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
3917 p
->pMemPos
= nullptr;
3919 p
->bRealLineEnd
= false;
3924 sal_uInt32 nNr
= m_pRef
->GetIdx();
3928 if (!m_pRef
->Get(p
->nStartPos
, nFoo
, pData
))
3930 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
3934 if (o3tl::checked_add
<WW8_CP
>(p
->nStartPos
, 1, p
->nEndPos
))
3936 SAL_WARN("sw.ww8", "broken offset, ignoring");
3937 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
3944 m_pText
->SetIdx(nNr
);
3946 if (!m_pText
->Get(p
->nCp2OrIdx
, p
->nSprmsLen
, pData
))
3948 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
3953 if (p
->nCp2OrIdx
< 0 || p
->nCp2OrIdx
> p
->nSprmsLen
)
3955 SAL_WARN("sw.ww8", "Document has invalid Cp or Idx, ignoring it");
3956 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
3961 p
->nSprmsLen
-= p
->nCp2OrIdx
;
3964 void WW8PLCFx_SubDoc::advance()
3966 if (m_pRef
&& m_pText
)
3974 WW8PLCFx_FLD::WW8PLCFx_FLD( SvStream
* pSt
, const WW8Fib
& rMyFib
, short nType
)
3975 : WW8PLCFx(rMyFib
, true), m_rFib(rMyFib
)
3983 nFc
= m_rFib
.m_fcPlcffldHdr
;
3984 nLen
= m_rFib
.m_lcbPlcffldHdr
;
3987 nFc
= m_rFib
.m_fcPlcffldFootnote
;
3988 nLen
= m_rFib
.m_lcbPlcffldFootnote
;
3991 nFc
= m_rFib
.m_fcPlcffldEdn
;
3992 nLen
= m_rFib
.m_lcbPlcffldEdn
;
3995 nFc
= m_rFib
.m_fcPlcffldAtn
;
3996 nLen
= m_rFib
.m_lcbPlcffldAtn
;
3999 nFc
= m_rFib
.m_fcPlcffldTxbx
;
4000 nLen
= m_rFib
.m_lcbPlcffldTxbx
;
4003 nFc
= m_rFib
.m_fcPlcffldHdrTxbx
;
4004 nLen
= m_rFib
.m_lcbPlcffldHdrTxbx
;
4007 nFc
= m_rFib
.m_fcPlcffldMom
;
4008 nLen
= m_rFib
.m_lcbPlcffldMom
;
4013 m_pPLCF
.reset( new WW8PLCFspecial( pSt
, nFc
, nLen
, 2 ) );
4016 WW8PLCFx_FLD::~WW8PLCFx_FLD()
4020 sal_uInt32
WW8PLCFx_FLD::GetIdx() const
4022 return m_pPLCF
? m_pPLCF
->GetIdx() : 0;
4025 void WW8PLCFx_FLD::SetIdx(sal_uInt32 nIdx
)
4028 m_pPLCF
->SetIdx( nIdx
);
4031 bool WW8PLCFx_FLD::SeekPos(WW8_CP nCpPos
)
4033 return m_pPLCF
&& m_pPLCF
->SeekPosExact( nCpPos
);
4036 WW8_CP
WW8PLCFx_FLD::Where()
4038 return m_pPLCF
? m_pPLCF
->Where() : WW8_CP_MAX
;
4041 bool WW8PLCFx_FLD::StartPosIsFieldStart()
4045 return m_pPLCF
&& m_pPLCF
->Get(nTest
, pData
) && ((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f) == 0x13);
4048 bool WW8PLCFx_FLD::EndPosIsFieldEnd(WW8_CP
& nCP
)
4054 tools::Long n
= m_pPLCF
->GetIdx();
4060 if ( m_pPLCF
->Get(nTest
, pData
) && ((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f) == 0x15) )
4072 void WW8PLCFx_FLD::GetSprms(WW8PLCFxDesc
* p
)
4074 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
4075 p
->pMemPos
= nullptr;
4077 p
->bRealLineEnd
= false;
4081 p
->nStartPos
= WW8_CP_MAX
; // there are no fields
4085 tools::Long n
= m_pPLCF
->GetIdx();
4089 if (!m_pPLCF
->Get(nP
, pData
)) // end of PLCFspecial?
4091 p
->nStartPos
= WW8_CP_MAX
; // PLCF completely processed
4098 if (!m_pPLCF
->Get(nP
, pData
)) // end of PLCFspecial?
4100 p
->nStartPos
= WW8_CP_MAX
; // PLCF completely processed
4108 p
->nCp2OrIdx
= m_pPLCF
->GetIdx();
4111 void WW8PLCFx_FLD::advance()
4113 SAL_WARN_IF(!m_pPLCF
, "sw.ww8", "Call without PLCFspecial field");
4119 bool WW8PLCFx_FLD::GetPara(tools::Long nIdx
, WW8FieldDesc
& rF
)
4121 SAL_WARN_IF(!m_pPLCF
, "sw.ww8", "Call without PLCFspecial field");
4125 tools::Long n
= m_pPLCF
->GetIdx();
4126 m_pPLCF
->SetIdx(nIdx
);
4128 bool bOk
= WW8GetFieldPara(*m_pPLCF
, rF
);
4135 void WW8ReadSTTBF(bool bVer8
, SvStream
& rStrm
, sal_uInt32 nStart
, sal_Int32 nLen
,
4136 sal_uInt16 nExtraLen
, rtl_TextEncoding eCS
, std::vector
<OUString
> &rArray
,
4137 std::vector
<ww::bytes
>* pExtraArray
, std::vector
<OUString
>* pValueArray
)
4139 if (nLen
==0) // Handle Empty STTBF
4142 sal_uInt64
const nOldPos
= rStrm
.Tell();
4143 if (checkSeek(rStrm
, nStart
))
4145 sal_uInt16
nLen2(0);
4146 rStrm
.ReadUInt16( nLen2
); // bVer67: total length of structure
4147 // bVer8 : count of strings
4151 sal_uInt16
nStrings(0);
4152 bool bUnicode
= (0xFFFF == nLen2
);
4154 rStrm
.ReadUInt16( nStrings
);
4158 rStrm
.ReadUInt16( nExtraLen
);
4160 const size_t nMinStringLen
= bUnicode
? sizeof(sal_uInt16
) : sizeof(sal_uInt8
);
4161 const size_t nMinRecordSize
= nExtraLen
+ nMinStringLen
;
4162 assert(nMinRecordSize
!= 0 && "impossible to be zero");
4163 const size_t nMaxPossibleStrings
= rStrm
.remainingSize() / nMinRecordSize
;
4164 if (nStrings
> nMaxPossibleStrings
)
4166 SAL_WARN("sw.ww8", "STTBF claims " << nStrings
<< " entries, but only " << nMaxPossibleStrings
<< " are possible");
4167 nStrings
= nMaxPossibleStrings
;
4170 if (nExtraLen
&& nStrings
)
4172 const size_t nMaxExtraLen
= (rStrm
.remainingSize() - (nStrings
* nMinStringLen
)) / nStrings
;
4173 if (nExtraLen
> nMaxExtraLen
)
4175 SAL_WARN("sw.ww8", "STTBF claims " << nMaxExtraLen
<< " extra len, but only " << nMaxExtraLen
<< " are possible");
4176 nExtraLen
= nMaxExtraLen
;
4180 for (sal_uInt16 i
=0; i
< nStrings
; ++i
)
4183 rArray
.push_back(read_uInt16_PascalString(rStrm
));
4186 OString aTmp
= read_uInt8_lenPrefixed_uInt8s_ToOString(rStrm
);
4187 rArray
.push_back(OStringToOUString(aTmp
, eCS
));
4190 // Skip the extra data
4195 ww::bytes
extraData(nExtraLen
);
4196 rStrm
.ReadBytes(extraData
.data(), nExtraLen
);
4197 pExtraArray
->push_back(extraData
);
4200 rStrm
.SeekRel( nExtraLen
);
4203 // read the value of the document variables, if requested.
4206 for (sal_uInt16 i
=0; i
< nStrings
; ++i
)
4209 pValueArray
->push_back(read_uInt16_PascalString(rStrm
));
4212 OString aTmp
= read_uInt8_lenPrefixed_uInt8s_ToOString(rStrm
);
4213 pValueArray
->push_back(OStringToOUString(aTmp
, eCS
));
4222 OSL_ENSURE(nLen2
== nLen
,
4223 "Fib length and read length are different");
4224 if (nLen
> SAL_MAX_UINT16
)
4225 nLen
= SAL_MAX_UINT16
;
4228 nLen2
= o3tl::narrowing
<sal_uInt16
>(nLen
);
4230 sal_uLong nRead
= 2;
4231 while (nRead
< nLen2
)
4233 sal_uInt8
nBChar(0);
4234 rStrm
.ReadUChar( nBChar
);
4238 OString aTmp
= read_uInt8s_ToOString(rStrm
, nBChar
);
4239 nRead
+= aTmp
.getLength();
4240 rArray
.push_back(OStringToOUString(aTmp
, eCS
));
4243 rArray
.emplace_back();
4245 // Skip the extra data (for bVer67 versions this must come from
4246 // external knowledge)
4251 ww::bytes
extraData(nExtraLen
);
4252 rStrm
.ReadBytes(extraData
.data(), nExtraLen
);
4253 pExtraArray
->push_back(extraData
);
4256 rStrm
.SeekRel( nExtraLen
);
4262 rStrm
.Seek(nOldPos
);
4265 WW8PLCFx_Book::WW8PLCFx_Book(SvStream
* pTableSt
, const WW8Fib
& rFib
)
4266 : WW8PLCFx(rFib
, false), m_nIsEnd(0), m_nBookmarkId(1)
4268 if( !rFib
.m_fcPlcfbkf
|| !rFib
.m_lcbPlcfbkf
|| !rFib
.m_fcPlcfbkl
||
4269 !rFib
.m_lcbPlcfbkl
|| !rFib
.m_fcSttbfbkmk
|| !rFib
.m_lcbSttbfbkmk
)
4275 m_pBook
[0].reset( new WW8PLCFspecial(pTableSt
,rFib
.m_fcPlcfbkf
,rFib
.m_lcbPlcfbkf
,4) );
4277 m_pBook
[1].reset( new WW8PLCFspecial(pTableSt
,rFib
.m_fcPlcfbkl
,rFib
.m_lcbPlcfbkl
,0) );
4279 rtl_TextEncoding eStructChrSet
= WW8Fib::GetFIBCharset(rFib
.m_chseTables
, rFib
.m_lid
);
4281 WW8ReadSTTBF( (7 < rFib
.m_nVersion
), *pTableSt
, rFib
.m_fcSttbfbkmk
,
4282 rFib
.m_lcbSttbfbkmk
, 0, eStructChrSet
, m_aBookNames
);
4284 m_nIMax
= m_aBookNames
.size();
4286 if( m_pBook
[0]->GetIMax() < m_nIMax
) // Count of Bookmarks
4287 m_nIMax
= m_pBook
[0]->GetIMax();
4288 if( m_pBook
[1]->GetIMax() < m_nIMax
)
4289 m_nIMax
= m_pBook
[1]->GetIMax();
4290 m_aStatus
.resize(m_nIMax
);
4294 WW8PLCFx_Book::~WW8PLCFx_Book()
4298 sal_uInt32
WW8PLCFx_Book::GetIdx() const
4300 return m_nIMax
? m_pBook
[0]->GetIdx() : 0;
4303 void WW8PLCFx_Book::SetIdx(sal_uInt32 nI
)
4306 m_pBook
[0]->SetIdx( nI
);
4309 sal_uInt32
WW8PLCFx_Book::GetIdx2() const
4311 return m_nIMax
? ( m_pBook
[1]->GetIdx() | ( m_nIsEnd
? 0x80000000 : 0 ) ) : 0;
4314 void WW8PLCFx_Book::SetIdx2(sal_uInt32 nI
)
4318 m_pBook
[1]->SetIdx( nI
& 0x7fffffff );
4319 m_nIsEnd
= o3tl::narrowing
<sal_uInt16
>( ( nI
>> 31 ) & 1 ); // 0 or 1
4323 bool WW8PLCFx_Book::SeekPos(WW8_CP nCpPos
)
4328 bool bOk
= m_pBook
[0]->SeekPosExact( nCpPos
);
4329 bOk
&= m_pBook
[1]->SeekPosExact( nCpPos
);
4335 WW8_CP
WW8PLCFx_Book::Where()
4337 return m_pBook
[m_nIsEnd
]->Where();
4340 tools::Long
WW8PLCFx_Book::GetNoSprms( WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
4346 if (!m_pBook
[0] || !m_pBook
[1] || !m_nIMax
|| (m_pBook
[m_nIsEnd
]->GetIdx()) >= m_nIMax
)
4348 rStart
= rEnd
= WW8_CP_MAX
;
4352 (void)m_pBook
[m_nIsEnd
]->Get( rStart
, pData
); // query position
4353 return m_pBook
[m_nIsEnd
]->GetIdx();
4356 // The operator ++ has a pitfall: If 2 bookmarks adjoin each other,
4357 // we should first go to the end of the first one
4358 // and then to the beginning of the second one.
4359 // But if 2 bookmarks with the length of 0 lie on top of each other,
4360 // we *must* first find the start and end of each bookmark.
4364 // is not solved yet.
4365 // Because I must jump back and forth in the start- and end-indices then.
4366 // This would require one more index or bitfield to remember
4367 // the already processed bookmarks.
4369 void WW8PLCFx_Book::advance()
4371 if( !(m_pBook
[0] && m_pBook
[1] && m_nIMax
) )
4374 (*m_pBook
[m_nIsEnd
]).advance();
4376 sal_uLong l0
= m_pBook
[0]->Where();
4377 sal_uLong l1
= m_pBook
[1]->Where();
4384 const void * p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx());
4385 tools::Long nPairFor
= (p
== nullptr) ? 0 : SVBT16ToUInt16(*static_cast<SVBT16
const *>(p
));
4386 if (nPairFor
== m_pBook
[1]->GetIdx())
4389 m_nIsEnd
= m_nIsEnd
? 0 : 1;
4393 tools::Long
WW8PLCFx_Book::GetLen() const
4397 OSL_ENSURE( false, "Incorrect call (1) of PLCF_Book::GetLen()" );
4402 if( !m_pBook
[0]->Get( nStartPos
, p
) )
4404 OSL_ENSURE( false, "Incorrect call (2) of PLCF_Book::GetLen()" );
4407 const sal_uInt16 nEndIdx
= SVBT16ToUInt16( *static_cast<SVBT16
*>(p
) );
4408 tools::Long nNum
= m_pBook
[1]->GetPos( nEndIdx
);
4413 void WW8PLCFx_Book::SetStatus(sal_uInt16 nIndex
, eBookStatus eStat
)
4415 SAL_WARN_IF(nIndex
>= m_nIMax
, "sw.ww8",
4416 "bookmark index " << nIndex
<< " invalid");
4417 eBookStatus eStatus
= m_aStatus
.at(nIndex
);
4418 m_aStatus
[nIndex
] = static_cast<eBookStatus
>(eStatus
| eStat
);
4421 eBookStatus
WW8PLCFx_Book::GetStatus() const
4423 if (m_aStatus
.empty())
4425 tools::Long nEndIdx
= GetHandle();
4426 return ( nEndIdx
< m_nIMax
) ? m_aStatus
[nEndIdx
] : BOOK_NORMAL
;
4429 tools::Long
WW8PLCFx_Book::GetHandle() const
4431 if( !m_pBook
[0] || !m_pBook
[1] )
4435 return m_pBook
[1]->GetIdx();
4438 if (const void* p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx()))
4439 return SVBT16ToUInt16( *static_cast<SVBT16
const *>(p
) );
4445 OUString
WW8PLCFx_Book::GetBookmark(tools::Long nStart
,tools::Long nEnd
, sal_uInt16
&nIndex
)
4447 bool bFound
= false;
4449 if (m_pBook
[0] && m_pBook
[1])
4451 WW8_CP nStartCurrent
, nEndCurrent
;
4452 while (sal::static_int_cast
<decltype(m_aBookNames
)::size_type
>(i
) < m_aBookNames
.size())
4457 if( m_pBook
[0]->GetData( i
, nStartCurrent
, p
) && p
)
4458 nEndIdx
= SVBT16ToUInt16( *static_cast<SVBT16
*>(p
) );
4461 OSL_ENSURE( false, "Bookmark-EndIdx not readable" );
4465 nEndCurrent
= m_pBook
[1]->GetPos( nEndIdx
);
4467 if ((nStartCurrent
>= nStart
) && (nEndCurrent
<= nEnd
))
4476 return bFound
? m_aBookNames
[i
] : OUString();
4479 OUString
WW8PLCFx_Book::GetUniqueBookmarkName(const OUString
&rSuggestedName
)
4481 OUString
aRet(rSuggestedName
.isEmpty() ? u
"Unnamed"_ustr
: rSuggestedName
);
4483 while (i
< m_aBookNames
.size())
4485 if (aRet
== m_aBookNames
[i
])
4487 sal_Int32 len
= aRet
.getLength();
4488 sal_Int32 p
= len
- 1;
4489 while (p
> 0 && aRet
[p
] >= '0' && aRet
[p
] <= '9')
4491 aRet
= aRet
.subView(0, p
+1) + OUString::number(m_nBookmarkId
++);
4492 i
= 0; // start search from beginning
4500 void WW8PLCFx_Book::MapName(OUString
& rName
)
4502 if( !m_pBook
[0] || !m_pBook
[1] )
4506 while (i
< m_aBookNames
.size())
4508 if (rName
.equalsIgnoreAsciiCase(m_aBookNames
[i
]))
4510 rName
= m_aBookNames
[i
];
4517 const OUString
* WW8PLCFx_Book::GetName() const
4519 const OUString
*pRet
= nullptr;
4520 if (!m_nIsEnd
&& (m_pBook
[0]->GetIdx() < m_nIMax
))
4521 pRet
= &(m_aBookNames
[m_pBook
[0]->GetIdx()]);
4525 WW8PLCFx_AtnBook::WW8PLCFx_AtnBook(SvStream
* pTableSt
, const WW8Fib
& rFib
)
4526 : WW8PLCFx(rFib
, /*bSprm=*/false),
4529 if (!rFib
.m_fcPlcfAtnbkf
|| !rFib
.m_lcbPlcfAtnbkf
|| !rFib
.m_fcPlcfAtnbkl
|| !rFib
.m_lcbPlcfAtnbkl
)
4535 m_pBook
[0].reset( new WW8PLCFspecial(pTableSt
, rFib
.m_fcPlcfAtnbkf
, rFib
.m_lcbPlcfAtnbkf
, 4) );
4536 m_pBook
[1].reset( new WW8PLCFspecial(pTableSt
, rFib
.m_fcPlcfAtnbkl
, rFib
.m_lcbPlcfAtnbkl
, 0) );
4538 m_nIMax
= m_pBook
[0]->GetIMax();
4539 if (m_pBook
[1]->GetIMax() < m_nIMax
)
4540 m_nIMax
= m_pBook
[1]->GetIMax();
4544 WW8PLCFx_AtnBook::~WW8PLCFx_AtnBook()
4548 sal_uInt32
WW8PLCFx_AtnBook::GetIdx() const
4550 return m_nIMax
? m_pBook
[0]->GetIdx() : 0;
4553 void WW8PLCFx_AtnBook::SetIdx(sal_uInt32 nI
)
4556 m_pBook
[0]->SetIdx( nI
);
4559 sal_uInt32
WW8PLCFx_AtnBook::GetIdx2() const
4562 return m_pBook
[1]->GetIdx() | ( m_bIsEnd
? 0x80000000 : 0 );
4567 void WW8PLCFx_AtnBook::SetIdx2(sal_uInt32 nI
)
4571 m_pBook
[1]->SetIdx( nI
& 0x7fffffff );
4572 m_bIsEnd
= static_cast<bool>(( nI
>> 31 ) & 1);
4576 bool WW8PLCFx_AtnBook::SeekPos(WW8_CP nCpPos
)
4581 bool bOk
= m_pBook
[0]->SeekPosExact(nCpPos
);
4582 bOk
&= m_pBook
[1]->SeekPosExact(nCpPos
);
4588 WW8_CP
WW8PLCFx_AtnBook::Where()
4590 return m_pBook
[static_cast<int>(m_bIsEnd
)]->Where();
4593 tools::Long
WW8PLCFx_AtnBook::GetNoSprms( WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
4599 if (!m_pBook
[0] || !m_pBook
[1] || !m_nIMax
|| (m_pBook
[static_cast<int>(m_bIsEnd
)]->GetIdx()) >= m_nIMax
)
4601 rStart
= rEnd
= WW8_CP_MAX
;
4605 (void)m_pBook
[static_cast<int>(m_bIsEnd
)]->Get(rStart
, pData
);
4606 return m_pBook
[static_cast<int>(m_bIsEnd
)]->GetIdx();
4609 void WW8PLCFx_AtnBook::advance()
4611 if( !(m_pBook
[0] && m_pBook
[1] && m_nIMax
) )
4614 (*m_pBook
[static_cast<int>(m_bIsEnd
)]).advance();
4616 sal_uLong l0
= m_pBook
[0]->Where();
4617 sal_uLong l1
= m_pBook
[1]->Where();
4624 const void * p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx());
4625 tools::Long nPairFor
= (p
== nullptr) ? 0 : SVBT16ToUInt16(*static_cast<SVBT16
const *>(p
));
4626 if (nPairFor
== m_pBook
[1]->GetIdx())
4629 m_bIsEnd
= !m_bIsEnd
;
4633 tools::Long
WW8PLCFx_AtnBook::getHandle() const
4635 if (!m_pBook
[0] || !m_pBook
[1])
4639 return m_pBook
[1]->GetIdx();
4642 if (const void* p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx()))
4643 return SVBT16ToUInt16(*static_cast<const SVBT16
*>(p
));
4649 bool WW8PLCFx_AtnBook::getIsEnd() const
4654 WW8PLCFx_FactoidBook::WW8PLCFx_FactoidBook(SvStream
* pTableSt
, const WW8Fib
& rFib
)
4655 : WW8PLCFx(rFib
, /*bSprm=*/false),
4658 if (!rFib
.m_fcPlcfBkfFactoid
|| !rFib
.m_lcbPlcfBkfFactoid
|| !rFib
.m_fcPlcfBklFactoid
|| !rFib
.m_lcbPlcfBklFactoid
)
4664 m_pBook
[0].reset(new WW8PLCFspecial(pTableSt
, rFib
.m_fcPlcfBkfFactoid
, rFib
.m_lcbPlcfBkfFactoid
, 6));
4665 m_pBook
[1].reset(new WW8PLCFspecial(pTableSt
, rFib
.m_fcPlcfBklFactoid
, rFib
.m_lcbPlcfBklFactoid
, 4));
4667 m_nIMax
= m_pBook
[0]->GetIMax();
4668 if (m_pBook
[1]->GetIMax() < m_nIMax
)
4669 m_nIMax
= m_pBook
[1]->GetIMax();
4673 WW8PLCFx_FactoidBook::~WW8PLCFx_FactoidBook()
4677 sal_uInt32
WW8PLCFx_FactoidBook::GetIdx() const
4679 return m_nIMax
? m_pBook
[0]->GetIdx() : 0;
4682 void WW8PLCFx_FactoidBook::SetIdx(sal_uInt32 nI
)
4685 m_pBook
[0]->SetIdx(nI
);
4688 sal_uInt32
WW8PLCFx_FactoidBook::GetIdx2() const
4691 return m_pBook
[1]->GetIdx() | (m_bIsEnd
? 0x80000000 : 0);
4696 void WW8PLCFx_FactoidBook::SetIdx2(sal_uInt32 nI
)
4700 m_pBook
[1]->SetIdx(nI
& 0x7fffffff);
4701 m_bIsEnd
= static_cast<bool>((nI
>> 31) & 1);
4705 bool WW8PLCFx_FactoidBook::SeekPos(WW8_CP nCpPos
)
4710 bool bOk
= m_pBook
[0]->SeekPosExact(nCpPos
);
4711 bOk
&= m_pBook
[1]->SeekPosExact(nCpPos
);
4717 WW8_CP
WW8PLCFx_FactoidBook::Where()
4719 return m_pBook
[static_cast<int>(m_bIsEnd
)]->Where();
4722 tools::Long
WW8PLCFx_FactoidBook::GetNoSprms(WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
4728 if (!m_pBook
[0] || !m_pBook
[1] || !m_nIMax
|| (m_pBook
[static_cast<int>(m_bIsEnd
)]->GetIdx()) >= m_nIMax
)
4730 rStart
= rEnd
= WW8_CP_MAX
;
4734 (void)m_pBook
[static_cast<int>(m_bIsEnd
)]->Get(rStart
, pData
);
4735 return m_pBook
[static_cast<int>(m_bIsEnd
)]->GetIdx();
4738 void WW8PLCFx_FactoidBook::advance()
4740 if (!(m_pBook
[0] && m_pBook
[1] && m_nIMax
))
4743 (*m_pBook
[static_cast<int>(m_bIsEnd
)]).advance();
4745 sal_uLong l0
= m_pBook
[0]->Where();
4746 sal_uLong l1
= m_pBook
[1]->Where();
4753 const void * p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx());
4754 tools::Long nPairFor
= (p
== nullptr) ? 0 : SVBT16ToUInt16(*static_cast<SVBT16
const *>(p
));
4755 if (nPairFor
== m_pBook
[1]->GetIdx())
4758 m_bIsEnd
= !m_bIsEnd
;
4762 tools::Long
WW8PLCFx_FactoidBook::getHandle() const
4764 if (!m_pBook
[0] || !m_pBook
[1])
4768 return m_pBook
[1]->GetIdx();
4771 if (const void* p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx()))
4772 return SVBT16ToUInt16(*static_cast<const SVBT16
*>(p
));
4778 bool WW8PLCFx_FactoidBook::getIsEnd() const
4783 // In the end of a paragraph in WW6 the attribute extends after the <CR>.
4784 // This will be reset by one character to be used with SW,
4785 // if we don't expect trouble thereby.
4786 void WW8PLCFMan::AdjustEnds( WW8PLCFxDesc
& rDesc
)
4788 // might be necessary to do this for pChp and/or pSep as well,
4789 // but its definitely the case for paragraphs that EndPos > StartPos
4790 // for a well formed paragraph as those always have a paragraph
4792 if (&rDesc
== m_pPap
&& rDesc
.bRealLineEnd
)
4794 if (rDesc
.nStartPos
== rDesc
.nEndPos
&& rDesc
.nEndPos
!= WW8_CP_MAX
)
4796 SAL_WARN("sw.ww8", "WW8PLCFxDesc End same as Start, abandoning to avoid looping");
4797 rDesc
.nEndPos
= WW8_CP_MAX
;
4801 //Store old end position for supercool new property finder that uses
4802 //cp instead of fc's as nature intended
4803 rDesc
.nOrigEndPos
= rDesc
.nEndPos
;
4804 rDesc
.nOrigStartPos
= rDesc
.nStartPos
;
4807 Normally given ^XXX{para end}^ we don't actually insert a para end
4808 character into the document, so we clip the para end property one to the
4809 left to make the para properties end when the paragraph text does. In a
4810 drawing textbox we actually do insert a para end character, so we don't
4811 clip it. Making the para end properties end after the para end char.
4813 if (GetDoingDrawTextBox())
4816 if ( (&rDesc
== m_pPap
) && rDesc
.bRealLineEnd
)
4818 if ( m_pPap
->nEndPos
!= WW8_CP_MAX
) // Para adjust
4820 m_nLineEnd
= m_pPap
->nEndPos
;// nLineEnd points *after* the <CR>
4821 m_pPap
->nEndPos
--; // shorten paragraph end by one character
4823 // Is there already a sep end, which points to the current paragraph end?
4824 // Then we also must shorten by one character
4825 if( m_pSep
->nEndPos
== m_nLineEnd
)
4829 else if (&rDesc
== m_pSep
)
4831 // Sep Adjust if end Char-Attr == paragraph end ...
4832 if( (rDesc
.nEndPos
== m_nLineEnd
) && (rDesc
.nEndPos
> rDesc
.nStartPos
) )
4833 rDesc
.nEndPos
--; // ... then shorten by one character
4837 void WW8PLCFxDesc::ReduceByOffset()
4839 SAL_WARN_IF(WW8_CP_MAX
!= nStartPos
&& nStartPos
> nEndPos
, "sw.ww8",
4840 "End " << nEndPos
<< " before Start " << nStartPos
);
4842 if( nStartPos
!= WW8_CP_MAX
)
4846 Force the property change to happen at the beginning of this
4847 subdocument, same as in GetNewNoSprms, except that the target type is
4848 attributes attached to a piece that might span subdocument boundaries
4850 if (nCpOfs
> nStartPos
)
4853 nStartPos
-= nCpOfs
;
4855 if (nEndPos
!= WW8_CP_MAX
)
4857 if (nCpOfs
> nEndPos
)
4859 SAL_WARN("sw.ww8", "broken subdocument piece entry");
4860 nEndPos
= WW8_CP_MAX
;
4867 void WW8PLCFMan::GetNewSprms( WW8PLCFxDesc
& rDesc
)
4869 rDesc
.pPLCFx
->GetSprms(&rDesc
);
4870 rDesc
.ReduceByOffset();
4872 rDesc
.bFirstSprm
= true;
4873 AdjustEnds( rDesc
);
4874 rDesc
.nOrigSprmsLen
= rDesc
.nSprmsLen
;
4877 void WW8PLCFMan::GetNewNoSprms( WW8PLCFxDesc
& rDesc
)
4879 rDesc
.nCp2OrIdx
= rDesc
.pPLCFx
->GetNoSprms(rDesc
.nStartPos
, rDesc
.nEndPos
,
4882 SAL_WARN_IF(WW8_CP_MAX
!= rDesc
.nStartPos
&& rDesc
.nStartPos
> rDesc
.nEndPos
, "sw.ww8",
4883 "End " << rDesc
.nEndPos
<< " before Start " << rDesc
.nStartPos
);
4885 rDesc
.ReduceByOffset();
4887 rDesc
.bFirstSprm
= true;
4888 rDesc
.nOrigSprmsLen
= rDesc
.nSprmsLen
;
4891 sal_uInt16
WW8PLCFMan::GetId(const WW8PLCFxDesc
* p
) const
4893 sal_uInt16 nId
= 0; // Id = 0 for empty attributes
4897 else if (p
== m_pFootnote
)
4899 else if (p
== m_pEdn
)
4901 else if (p
== m_pAnd
)
4903 else if (p
->nSprmsLen
>= maSprmParser
.MinSprmLen())
4904 nId
= maSprmParser
.GetSprmId(p
->pMemPos
);
4909 WW8PLCFMan::WW8PLCFMan(const WW8ScannerBase
* pBase
, ManTypes nType
, tools::Long nStartCp
,
4910 bool bDoingDrawTextBox
)
4911 : maSprmParser(*pBase
->m_pWw8Fib
),
4912 m_nLineEnd(WW8_CP_MAX
),
4913 mbDoingDrawTextBox(bDoingDrawTextBox
)
4915 m_pWwFib
= pBase
->m_pWw8Fib
;
4919 if( MAN_MAINTEXT
== nType
)
4921 // search order of the attributes
4922 m_nPLCF
= MAN_PLCF_COUNT
;
4923 m_pField
= &m_aD
[0];
4926 m_pFootnote
= &m_aD
[3];
4929 m_pPcd
= pBase
->m_pPLCFx_PCD
? &m_aD
[5] : nullptr;
4930 //pPcdA index == pPcd index + 1
4931 m_pPcdA
= pBase
->m_pPLCFx_PCDAttrs
? &m_aD
[6] : nullptr;
4936 m_pAtnBkm
= &m_aD
[10];
4937 m_pFactoidBkm
= &m_aD
[11];
4939 m_pSep
->pPLCFx
= pBase
->m_pSepPLCF
.get();
4940 m_pFootnote
->pPLCFx
= pBase
->m_pFootnotePLCF
.get();
4941 m_pEdn
->pPLCFx
= pBase
->m_pEdnPLCF
.get();
4942 m_pBkm
->pPLCFx
= pBase
->m_pBook
.get();
4943 m_pAnd
->pPLCFx
= pBase
->m_pAndPLCF
.get();
4944 m_pAtnBkm
->pPLCFx
= pBase
->m_pAtnBook
.get();
4945 m_pFactoidBkm
->pPLCFx
= pBase
->m_pFactoidBook
.get();
4950 // search order of the attributes
4952 m_pField
= &m_aD
[0];
4953 m_pBkm
= pBase
->m_pBook
? &m_aD
[1] : nullptr;
4955 m_pPcd
= pBase
->m_pPLCFx_PCD
? &m_aD
[2] : nullptr;
4956 //pPcdA index == pPcd index + 1
4957 m_pPcdA
= pBase
->m_pPLCFx_PCDAttrs
? &m_aD
[3] : nullptr;
4961 m_pSep
= &m_aD
[6]; // Dummy
4963 m_pAnd
= m_pAtnBkm
= m_pFactoidBkm
= m_pFootnote
= m_pEdn
= nullptr; // not used at SpezText
4966 m_pChp
->pPLCFx
= pBase
->m_pChpPLCF
.get();
4967 m_pPap
->pPLCFx
= pBase
->m_pPapPLCF
.get();
4969 m_pPcd
->pPLCFx
= pBase
->m_pPLCFx_PCD
.get();
4971 m_pPcdA
->pPLCFx
= pBase
->m_pPLCFx_PCDAttrs
.get();
4973 m_pBkm
->pPLCFx
= pBase
->m_pBook
.get();
4975 m_pMagicTables
= pBase
->m_pMagicTables
.get();
4976 m_pSubdocs
= pBase
->m_pSubdocs
.get();
4977 m_pExtendedAtrds
= pBase
->m_pExtendedAtrds
.get();
4979 switch( nType
) // field initialization
4982 m_pField
->pPLCFx
= pBase
->m_pFieldHdFtPLCF
.get();
4983 m_pFdoa
= pBase
->m_pHdFtFdoa
.get();
4984 m_pTxbx
= pBase
->m_pHdFtTxbx
.get();
4985 m_pTxbxBkd
= pBase
->m_pHdFtTxbxBkd
.get();
4988 m_pField
->pPLCFx
= pBase
->m_pFieldFootnotePLCF
.get();
4989 m_pFdoa
= m_pTxbx
= m_pTxbxBkd
= nullptr;
4992 m_pField
->pPLCFx
= pBase
->m_pFieldEdnPLCF
.get();
4993 m_pFdoa
= m_pTxbx
= m_pTxbxBkd
= nullptr;
4996 m_pField
->pPLCFx
= pBase
->m_pFieldAndPLCF
.get();
4997 m_pFdoa
= m_pTxbx
= m_pTxbxBkd
= nullptr;
5000 m_pField
->pPLCFx
= pBase
->m_pFieldTxbxPLCF
.get();
5001 m_pTxbx
= pBase
->m_pMainTxbx
.get();
5002 m_pTxbxBkd
= pBase
->m_pMainTxbxBkd
.get();
5006 m_pField
->pPLCFx
= pBase
->m_pFieldTxbxHdFtPLCF
.get();
5007 m_pTxbx
= pBase
->m_pHdFtTxbx
.get();
5008 m_pTxbxBkd
= pBase
->m_pHdFtTxbxBkd
.get();
5012 m_pField
->pPLCFx
= pBase
->m_pFieldPLCF
.get();
5013 m_pFdoa
= pBase
->m_pMainFdoa
.get();
5014 m_pTxbx
= pBase
->m_pMainTxbx
.get();
5015 m_pTxbxBkd
= pBase
->m_pMainTxbxBkd
.get();
5020 m_pWwFib
->GetBaseCp(nType
, &cp
); //TODO: check return value
5023 if( nStartCp
|| m_nCpO
)
5024 SeekPos( nStartCp
); // adjust PLCFe at text StartPos
5026 // initialization to the member vars Low-Level
5027 GetChpPLCF()->ResetAttrStartEnd();
5028 GetPapPLCF()->ResetAttrStartEnd();
5029 for( sal_uInt16 i
=0; i
< m_nPLCF
; ++i
)
5031 WW8PLCFxDesc
* p
= &m_aD
[i
];
5035 For subdocuments we modify the cp of properties to be relative to
5036 the beginning of subdocuments, we should also do the same for
5037 piecetable changes, and piecetable properties, otherwise a piece
5038 change that happens in a subdocument is lost.
5040 p
->nCpOfs
= ( p
== m_pChp
|| p
== m_pPap
|| p
== m_pBkm
|| p
== m_pPcd
||
5041 p
== m_pPcdA
) ? m_nCpO
: 0;
5044 p
->bFirstSprm
= false;
5045 p
->xIdStack
.reset();
5047 if ((p
== m_pChp
) || (p
== m_pPap
))
5048 p
->nStartPos
= p
->nEndPos
= nStartCp
;
5050 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
5053 // initialization to the member vars High-Level
5054 for( sal_uInt16 i
=0; i
<m_nPLCF
; ++i
){
5055 WW8PLCFxDesc
* p
= &m_aD
[i
];
5059 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
5063 if( p
->pPLCFx
->IsSprm() )
5065 // Careful: nEndPos must be
5066 p
->xIdStack
.emplace();
5067 if ((p
== m_pChp
) || (p
== m_pPap
))
5069 WW8_CP nTemp
= p
->nEndPos
+p
->nCpOfs
;
5070 p
->pMemPos
= nullptr;
5072 p
->nStartPos
= nTemp
;
5073 if (!(*p
->pPLCFx
).SeekPos(p
->nStartPos
))
5074 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
5079 GetNewSprms( *p
); // initialized at all PLCFs
5081 else if( p
->pPLCFx
)
5082 GetNewNoSprms( *p
);
5086 WW8PLCFMan::~WW8PLCFMan()
5088 for( sal_uInt16 i
=0; i
<m_nPLCF
; i
++)
5089 m_aD
[i
].xIdStack
.reset();
5092 // 0. which attr class,
5093 // 1. if it's an attr start,
5094 // 2. CP, where is next attr change
5095 sal_uInt16
WW8PLCFMan::WhereIdx(bool *const pbStart
, WW8_CP
*const pPos
) const
5097 OSL_ENSURE(m_nPLCF
,"What the hell");
5098 WW8_CP nNext
= WW8_CP_MAX
; // search order:
5099 sal_uInt16 nNextIdx
= m_nPLCF
;// first ending found ( CHP, PAP, ( SEP ) ),
5100 bool bStart
= true; // now find beginnings ( ( SEP ), PAP, CHP )
5101 const WW8PLCFxDesc
* pD
;
5102 for (sal_uInt16 i
=0; i
< m_nPLCF
; ++i
)
5107 if( (pD
->nEndPos
< nNext
) && (pD
->nStartPos
== WW8_CP_MAX
) )
5109 // otherwise start = end
5110 nNext
= pD
->nEndPos
;
5116 for (sal_uInt16 i
=m_nPLCF
; i
> 0; --i
)
5119 if (pD
!= m_pPcdA
&& pD
->nStartPos
< nNext
)
5121 nNext
= pD
->nStartPos
;
5133 // gives the CP pos of the next attr change
5134 WW8_CP
WW8PLCFMan::Where() const
5137 WhereIdx(nullptr, &l
);
5141 void WW8PLCFMan::SeekPos( tools::Long nNewCp
)
5143 m_pChp
->pPLCFx
->SeekPos( nNewCp
+ m_nCpO
); // create new attr
5144 m_pPap
->pPLCFx
->SeekPos( nNewCp
+ m_nCpO
);
5145 m_pField
->pPLCFx
->SeekPos( nNewCp
);
5147 m_pPcd
->pPLCFx
->SeekPos( nNewCp
+ m_nCpO
);
5149 m_pBkm
->pPLCFx
->SeekPos( nNewCp
+ m_nCpO
);
5152 void WW8PLCFMan::SaveAllPLCFx( WW8PLCFxSaveAll
& rSave
) const
5156 m_pPcd
->Save( rSave
.aS
[n
++] );
5158 m_pPcdA
->Save( rSave
.aS
[n
++] );
5160 for(sal_uInt16 i
=0; i
<m_nPLCF
; ++i
)
5161 if( m_pPcd
!= &m_aD
[i
] && m_pPcdA
!= &m_aD
[i
] )
5162 m_aD
[i
].Save( rSave
.aS
[n
++] );
5165 void WW8PLCFMan::RestoreAllPLCFx( const WW8PLCFxSaveAll
& rSave
)
5169 m_pPcd
->Restore( rSave
.aS
[n
++] );
5171 m_pPcdA
->Restore( rSave
.aS
[n
++] );
5173 for(sal_uInt16 i
=0; i
<m_nPLCF
; ++i
)
5174 if( m_pPcd
!= &m_aD
[i
] && m_pPcdA
!= &m_aD
[i
] )
5175 m_aD
[i
].Restore( rSave
.aS
[n
++] );
5180 bool IsSizeLegal(tools::Long nSprmLen
, sal_Int32 nSprmsLen
)
5182 if (nSprmLen
> nSprmsLen
)
5184 SAL_WARN("sw.ww8", "Short sprm, len " << nSprmLen
<< " claimed, max possible is " << nSprmsLen
);
5191 bool WW8PLCFMan::IsSprmLegalForCategory(sal_uInt16 nSprmId
, short nIdx
) const
5193 const WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5194 if (p
!= m_pSep
) // just check sep for now
5198 ww::WordVersion eVersion
= maSprmParser
.GetFIBVersion();
5199 if (eVersion
<= ww::eWW2
)
5200 bRet
= nSprmId
>= 112 && nSprmId
<= 145;
5201 else if (eVersion
< ww::eWW8
)
5202 bRet
= nSprmId
>= NS_sprm::v6::sprmSScnsPgn
&& nSprmId
<= NS_sprm::v6::sprmSDMPaperReq
;
5206 Sprm bits: 10-12 sgc sprm group; type of sprm (PAP, CHP, etc)
5208 sgc value type of sprm
5215 auto nSGC
= ((nSprmId
& 0x1C00) >> 10);
5219 SAL_INFO("sw.ww8", "sprm, id " << nSprmId
<< " wrong category for section properties");
5223 void WW8PLCFMan::GetSprmStart( short nIdx
, WW8PLCFManResult
* pRes
) const
5225 memset( pRes
, 0, sizeof( WW8PLCFManResult
) );
5231 const WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5233 // first Sprm in a Group
5237 pRes
->nFlags
|= MAN_MASK_NEW_PAP
;
5238 else if( p
== m_pSep
)
5239 pRes
->nFlags
|= MAN_MASK_NEW_SEP
;
5241 pRes
->pMemPos
= p
->pMemPos
;
5242 pRes
->nSprmId
= GetId(p
);
5243 pRes
->nCp2OrIdx
= p
->nCp2OrIdx
;
5244 if ((p
== m_pFootnote
) || (p
== m_pEdn
) || (p
== m_pAnd
))
5245 pRes
->nMemLen
= p
->nSprmsLen
;
5246 else if (p
->nSprmsLen
>= maSprmParser
.MinSprmLen()) //normal
5248 // Length of actual sprm
5249 pRes
->nMemLen
= maSprmParser
.GetSprmSize(pRes
->nSprmId
, pRes
->pMemPos
, p
->nSprmsLen
);
5250 if (!IsSizeLegal(pRes
->nMemLen
, p
->nSprmsLen
) || !IsSprmLegalForCategory(pRes
->nSprmId
, nIdx
))
5257 void WW8PLCFMan::GetSprmEnd( short nIdx
, WW8PLCFManResult
* pRes
) const
5259 memset( pRes
, 0, sizeof( WW8PLCFManResult
) );
5261 const WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5263 if (!(p
->xIdStack
->empty()))
5264 pRes
->nSprmId
= p
->xIdStack
->top(); // get end position
5267 OSL_ENSURE( false, "No Id on the Stack" );
5272 void WW8PLCFMan::GetNoSprmStart( short nIdx
, WW8PLCFManResult
* pRes
) const
5274 const WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5276 pRes
->nCpPos
= p
->nStartPos
;
5277 pRes
->nMemLen
= p
->nSprmsLen
;
5278 pRes
->nCp2OrIdx
= p
->nCp2OrIdx
;
5281 pRes
->nSprmId
= eFLD
;
5282 else if( p
== m_pFootnote
)
5283 pRes
->nSprmId
= eFTN
;
5284 else if( p
== m_pEdn
)
5285 pRes
->nSprmId
= eEDN
;
5286 else if( p
== m_pBkm
)
5287 pRes
->nSprmId
= eBKN
;
5288 else if (p
== m_pAtnBkm
)
5289 pRes
->nSprmId
= eATNBKN
;
5290 else if (p
== m_pFactoidBkm
)
5291 pRes
->nSprmId
= eFACTOIDBKN
;
5292 else if( p
== m_pAnd
)
5293 pRes
->nSprmId
= eAND
;
5294 else if( p
== m_pPcd
)
5296 //We slave the piece table attributes to the piece table, the piece
5297 //table attribute iterator contains the sprms for this piece.
5298 GetSprmStart( nIdx
+1, pRes
);
5301 pRes
->nSprmId
= 0; // default: not found
5304 void WW8PLCFMan::GetNoSprmEnd( short nIdx
, WW8PLCFManResult
* pRes
) const
5306 pRes
->nMemLen
= -1; // end tag
5308 if( &m_aD
[nIdx
] == m_pBkm
)
5309 pRes
->nSprmId
= eBKN
;
5310 else if (&m_aD
[nIdx
] == m_pAtnBkm
)
5311 pRes
->nSprmId
= eATNBKN
;
5312 else if (&m_aD
[nIdx
] == m_pFactoidBkm
)
5313 pRes
->nSprmId
= eFACTOIDBKN
;
5314 else if( &m_aD
[nIdx
] == m_pPcd
)
5316 //We slave the piece table attributes to the piece table, the piece
5317 //table attribute iterator contains the sprms for this piece.
5318 GetSprmEnd( nIdx
+1, pRes
);
5324 void WW8PLCFMan::TransferOpenSprms(std::stack
<sal_uInt16
> &rStack
)
5326 for (sal_uInt16 i
= 0; i
< m_nPLCF
; ++i
)
5328 WW8PLCFxDesc
* p
= &m_aD
[i
];
5329 if (!p
|| !p
->xIdStack
)
5331 while (!p
->xIdStack
->empty())
5333 rStack
.push(p
->xIdStack
->top());
5339 void WW8PLCFMan::AdvSprm(short nIdx
, bool bStart
)
5341 WW8PLCFxDesc
* p
= &m_aD
[nIdx
]; // determine sprm class(!)
5343 p
->bFirstSprm
= false;
5346 const sal_uInt16 nLastId
= GetId(p
);
5348 const sal_uInt16 nLastAttribStarted
= IsSprmLegalForCategory(nLastId
, nIdx
) ? nLastId
: 0;
5350 p
->xIdStack
->push(nLastAttribStarted
); // remember Id for attribute end
5354 Check, if we have to process more sprm(s).
5358 // Length of last sprm
5359 const sal_Int32 nSprmL
= maSprmParser
.GetSprmSize(nLastId
, p
->pMemPos
, p
->nSprmsLen
);
5361 // Reduce length of all sprms by length of last sprm
5362 p
->nSprmsLen
-= nSprmL
;
5364 // pos of next possible sprm
5365 if (p
->nSprmsLen
< maSprmParser
.MinSprmLen())
5367 // preventively set to 0, because the end follows!
5368 p
->pMemPos
= nullptr;
5372 p
->pMemPos
+= nSprmL
;
5377 if (p
->nSprmsLen
< maSprmParser
.MinSprmLen())
5378 p
->nStartPos
= WW8_CP_MAX
; // the ending follows
5382 if (!(p
->xIdStack
->empty()))
5384 if (p
->xIdStack
->empty())
5386 if ( (p
== m_pChp
) || (p
== m_pPap
) )
5388 p
->pMemPos
= nullptr;
5390 p
->nStartPos
= p
->nOrigEndPos
+p
->nCpOfs
;
5393 On failed seek we have run out of sprms, probably. But if it's
5394 a fastsaved file (has pPcd) then we may be just in a sprm free
5395 gap between pieces that have them, so set dirty flag in sprm
5396 finder to consider than.
5398 if (!(*p
->pPLCFx
).SeekPos(p
->nStartPos
))
5400 p
->nEndPos
= WW8_CP_MAX
;
5401 p
->pPLCFx
->SetDirty(true);
5403 if (!p
->pPLCFx
->GetDirty() || m_pPcd
)
5405 p
->pPLCFx
->SetDirty(false);
5409 To get the character and paragraph properties you first get
5410 the pap and chp and then apply the fastsaved pPcd properties
5411 to the range. If a pap or chp starts inside the pPcd range
5412 then we must bring the current pPcd range to a halt so as to
5413 end those sprms, then the pap/chp will be processed, and then
5414 we must force a restart of the pPcd on that pap/chp starting
5415 boundary. Doing that effectively means that the pPcd sprms will
5416 be applied to the new range. Not doing it means that the pPcd
5417 sprms will only be applied to the first pap/chp set of
5418 properties contained in the pap/chp range.
5420 So we bring the pPcd to a halt on this location here, by
5421 settings its end to the current start, then store the starting
5422 position of the current range to clipstart. The pPcd sprms
5423 will end as normal (albeit earlier than originally expected),
5424 and the existence of a clipstart will force the pPcd iterator
5425 to reread the current set of sprms instead of advancing to its
5426 next set. Then the clipstart will be set as the starting
5427 position which will force them to be applied directly after
5430 if (m_pPcd
&& ((p
->nStartPos
> m_pPcd
->nStartPos
) ||
5431 (m_pPcd
->nStartPos
== WW8_CP_MAX
)) &&
5432 (m_pPcd
->nEndPos
!= p
->nStartPos
))
5434 m_pPcd
->nEndPos
= p
->nStartPos
;
5435 static_cast<WW8PLCFx_PCD
*>(m_pPcd
->pPLCFx
)->SetClipStart(
5442 p
->pPLCFx
->advance(); // next Group of Sprms
5443 p
->pMemPos
= nullptr; // !!!
5447 SAL_WARN_IF(p
->nStartPos
> p
->nEndPos
, "sw.ww8",
5448 "End " << p
->nEndPos
<< " before Start " << p
->nStartPos
);
5453 void WW8PLCFMan::AdvNoSprm(short nIdx
, bool bStart
)
5456 For the case of a piece table we slave the piece table attribute iterator
5457 to the piece table and access it through that only. They are two separate
5458 structures, but act together as one logical one. The attributes only go
5459 to the next entry when the piece changes
5461 WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5465 AdvSprm(nIdx
+1,bStart
);
5467 p
->nStartPos
= m_aD
[nIdx
+1].nStartPos
;
5470 if (m_aD
[nIdx
+1].xIdStack
->empty())
5472 WW8PLCFx_PCD
*pTemp
= static_cast<WW8PLCFx_PCD
*>(m_pPcd
->pPLCFx
);
5475 As per normal, go on to the next set of properties, i.e. we
5476 have traversed over to the next piece. With a clipstart set
5477 we are being told to reread the current piece sprms so as to
5478 reapply them to a new chp or pap range.
5480 if (pTemp
->GetClipStart() == -1)
5481 p
->pPLCFx
->advance();
5482 p
->pMemPos
= nullptr;
5484 GetNewSprms( m_aD
[nIdx
+1] );
5485 GetNewNoSprms( *p
);
5486 if (pTemp
->GetClipStart() != -1)
5489 #i2325#, now we will force our starting position to the
5490 clipping start so as to force the application of these
5491 sprms after the current pap/chp sprms so as to apply the
5492 fastsave sprms to the current range.
5494 p
->nStartPos
= pTemp
->GetClipStart();
5495 pTemp
->SetClipStart(-1);
5501 { // NoSprm without end
5502 p
->pPLCFx
->advance();
5503 p
->pMemPos
= nullptr; // MemPos invalid
5505 GetNewNoSprms( *p
);
5509 void WW8PLCFMan::advance()
5512 const sal_uInt16 nIdx
= WhereIdx(&bStart
);
5515 WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5517 p
->bFirstSprm
= true; // Default
5519 if( p
->pPLCFx
->IsSprm() )
5520 AdvSprm( nIdx
, bStart
);
5522 AdvNoSprm( nIdx
, bStart
);
5526 // return true for the beginning of an attribute or error,
5527 // false for the end of an attribute
5528 // remaining return values are delivered to the caller from WW8PclxManResults.
5529 bool WW8PLCFMan::Get(WW8PLCFManResult
* pRes
) const
5531 memset( pRes
, 0, sizeof( WW8PLCFManResult
) );
5533 const sal_uInt16 nIdx
= WhereIdx(&bStart
);
5535 if( nIdx
>= m_nPLCF
)
5537 OSL_ENSURE( false, "Position not found" );
5541 if( m_aD
[nIdx
].pPLCFx
->IsSprm() )
5545 GetSprmStart( nIdx
, pRes
);
5550 GetSprmEnd( nIdx
, pRes
);
5558 GetNoSprmStart( nIdx
, pRes
);
5563 GetNoSprmEnd( nIdx
, pRes
);
5569 sal_uInt16
WW8PLCFMan::GetColl() const
5571 if( m_pPap
->pPLCFx
)
5572 return m_pPap
->pPLCFx
->GetIstd();
5575 OSL_ENSURE( false, "GetColl without PLCF_Pap" );
5580 WW8PLCFx_FLD
* WW8PLCFMan::GetField() const
5582 return static_cast<WW8PLCFx_FLD
*>(m_pField
->pPLCFx
);
5585 SprmResult
WW8PLCFMan::HasParaSprm( sal_uInt16 nId
) const
5587 return static_cast<WW8PLCFx_Cp_FKP
*>(m_pPap
->pPLCFx
)->HasSprm( nId
);
5590 SprmResult
WW8PLCFMan::HasCharSprm( sal_uInt16 nId
) const
5592 return static_cast<WW8PLCFx_Cp_FKP
*>(m_pChp
->pPLCFx
)->HasSprm( nId
);
5595 void WW8PLCFMan::HasCharSprm(sal_uInt16 nId
,
5596 std::vector
<SprmResult
> &rResult
) const
5598 static_cast<WW8PLCFx_Cp_FKP
*>(m_pChp
->pPLCFx
)->HasSprm(nId
, rResult
);
5601 void WW8PLCFx::Save( WW8PLCFxSave1
& rSave
) const
5603 rSave
.nPLCFxPos
= GetIdx();
5604 rSave
.nPLCFxPos2
= GetIdx2();
5605 rSave
.nPLCFxMemOfs
= 0;
5606 rSave
.nStartFC
= GetStartFc();
5609 void WW8PLCFx::Restore( const WW8PLCFxSave1
& rSave
)
5611 SetIdx( rSave
.nPLCFxPos
);
5612 SetIdx2( rSave
.nPLCFxPos2
);
5613 SetStartFc( rSave
.nStartFC
);
5616 sal_uInt32
WW8PLCFx_Cp_FKP::GetIdx2() const
5621 void WW8PLCFx_Cp_FKP::SetIdx2(sal_uInt32 nIdx
)
5624 m_pPcd
->SetIdx( nIdx
);
5627 void WW8PLCFx_Cp_FKP::Save( WW8PLCFxSave1
& rSave
) const
5630 m_pFkp
->IncMustRemainCache();
5631 WW8PLCFx::Save( rSave
);
5633 rSave
.nAttrStart
= m_nAttrStart
;
5634 rSave
.nAttrEnd
= m_nAttrEnd
;
5635 rSave
.bLineEnd
= m_bLineEnd
;
5638 void WW8PLCFx_Cp_FKP::Restore( const WW8PLCFxSave1
& rSave
)
5640 WW8PLCFx::Restore( rSave
);
5642 m_nAttrStart
= rSave
.nAttrStart
;
5643 m_nAttrEnd
= rSave
.nAttrEnd
;
5644 m_bLineEnd
= rSave
.bLineEnd
;
5647 m_pFkp
->DecMustRemainCache();
5650 void WW8PLCFxDesc::Save( WW8PLCFxSave1
& rSave
) const
5655 pPLCFx
->Save( rSave
);
5656 if( !pPLCFx
->IsSprm() )
5660 aD
.nStartPos
= nOrigStartPos
+nCpOfs
;
5661 aD
.nCpOfs
= rSave
.nCpOfs
= nCpOfs
;
5662 if (!(pPLCFx
->SeekPos(aD
.nStartPos
)))
5664 aD
.nEndPos
= WW8_CP_MAX
;
5665 pPLCFx
->SetDirty(true);
5667 pPLCFx
->GetSprms(&aD
);
5668 pPLCFx
->SetDirty(false);
5669 aD
.ReduceByOffset();
5670 rSave
.nStartCp
= aD
.nStartPos
;
5671 rSave
.nPLCFxMemOfs
= nOrigSprmsLen
- nSprmsLen
;
5674 void WW8PLCFxDesc::Restore( const WW8PLCFxSave1
& rSave
)
5679 pPLCFx
->Restore( rSave
);
5680 if( !pPLCFx
->IsSprm() )
5684 aD
.nStartPos
= rSave
.nStartCp
+rSave
.nCpOfs
;
5685 nCpOfs
= aD
.nCpOfs
= rSave
.nCpOfs
;
5686 if (!(pPLCFx
->SeekPos(aD
.nStartPos
)))
5688 aD
.nEndPos
= WW8_CP_MAX
;
5689 pPLCFx
->SetDirty(true);
5691 pPLCFx
->GetSprms(&aD
);
5692 pPLCFx
->SetDirty(false);
5693 aD
.ReduceByOffset();
5695 if (nOrigSprmsLen
> aD
.nSprmsLen
)
5697 //two entries exist for the same offset, cut and run
5698 SAL_WARN("sw.ww8", "restored properties don't match saved properties, bailing out");
5704 nSprmsLen
= nOrigSprmsLen
- rSave
.nPLCFxMemOfs
;
5705 pMemPos
= aD
.pMemPos
== nullptr ? nullptr : aD
.pMemPos
+ rSave
.nPLCFxMemOfs
;
5711 sal_uInt32
Readcb(SvStream
& rSt
, ww::WordVersion eVer
)
5713 if (eVer
<= ww::eWW2
)
5715 sal_uInt16
nShort(0);
5716 rSt
.ReadUInt16(nShort
);
5721 sal_uInt32
nLong(0);
5722 rSt
.ReadUInt32(nLong
);
5728 bool WW8Fib::GetBaseCp(ManTypes nType
, WW8_CP
* cp
) const
5730 assert(cp
!= nullptr);
5736 if (m_ccpTxbx
< 0) {
5739 nOffset
= m_ccpTxbx
;
5742 if (m_ccpEdn
< 0 || m_ccpEdn
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5745 nOffset
+= m_ccpEdn
;
5748 if (m_ccpAtn
< 0 || m_ccpAtn
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5751 nOffset
+= m_ccpAtn
;
5754 if (m_ccpMcr
< 0 || m_ccpMcr
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5757 nOffset
+= m_ccpMcr
;
5761 A subdocument of this kind (MAN_MACRO) probably exists in some defunct
5762 version of MSWord, but now ccpMcr is always 0. If some example that
5763 uses this comes to light, this is the likely calculation required
5767 if (m_ccpHdr
< 0 || m_ccpHdr
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5770 nOffset
+= m_ccpHdr
;
5773 if (m_ccpFootnote
< 0 || m_ccpFootnote
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5776 nOffset
+= m_ccpFootnote
;
5779 if (m_ccpText
< 0 || m_ccpText
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5782 nOffset
+= m_ccpText
;
5791 ww::WordVersion
WW8Fib::GetFIBVersion() const
5793 ww::WordVersion eVer
= ww::eWW8
;
5795 * Word for Windows 2 I think (1.X might work too if anyone has an example.
5797 * 0xA59B for Word 1 for Windows
5798 * 0xA59C for Word 1 for OS/2 "PM Word"
5800 * Various pages claim that the fileformats of Word 1 and 2 for Windows are
5801 * equivalent to Word for Macintosh 4 and 5. On the other hand
5803 * wIdents for Word for Mac versions...
5806 * 0xFE37 for Word 4 et 5.
5809 * http://cmsdoc.cern.ch/documents/docformat/CMS_CERN_LetterHead.word is
5810 * claimed to be "Word 5 for Mac" by Office etc and has that wIdent, but
5811 * its format isn't the same as that of Word 2 for windows. Nor is it
5812 * the same as that of Word for DOS/PCWord 5
5814 if (m_wIdent
== 0xa59b || m_wIdent
== 0xa59c)
5816 else if (m_wIdent
== 0xa5db)
5836 WW8Fib::WW8Fib(SvStream
& rSt
, sal_uInt8 nWantedVersion
, sal_uInt32 nOffset
):
5837 m_fDot(false), m_fGlsy(false), m_fComplex(false), m_fHasPic(false), m_cQuickSaves(0),
5838 m_fEncrypted(false), m_fWhichTableStm(false), m_fReadOnlyRecommended(false),
5839 m_fWriteReservation(false), m_fExtChar(false), m_fFarEast(false), m_fObfuscated(false),
5840 m_fMac(false), m_fEmptySpecial(false), m_fLoadOverridePage(false), m_fFuturesavedUndo(false),
5841 m_fWord97Saved(false), m_fWord2000Saved(false)
5842 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
5843 // above bit-field member initializations can be moved to the class definition
5845 // See [MS-DOC] 2.5.15 "How to read the FIB".
5846 rSt
.Seek( nOffset
);
5848 note desired number, identify file version number
5849 and check against desired number!
5851 m_nVersion
= nWantedVersion
;
5852 rSt
.ReadUInt16( m_wIdent
);
5853 rSt
.ReadUInt16( m_nFib
);
5854 rSt
.ReadUInt16( m_nProduct
);
5855 if( ERRCODE_NONE
!= rSt
.GetError() )
5859 // note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
5860 switch( m_nVersion
)
5863 nFibMin
= 0x0065; // from 101 WinWord 6.0
5865 // and 103 WinWord 6.0 for Macintosh
5867 nFibMax
= 0x0069; // to 105 WinWord 95
5870 nFibMin
= 0x0069; // from 105 WinWord 95
5871 nFibMax
= 0x0069; // to 105 WinWord 95
5874 nFibMin
= 0x006A; // from 106 WinWord 97
5875 nFibMax
= 0x00c1; // to 193 WinWord 97 (?)
5878 nFibMin
= 0; // program error!
5881 OSL_ENSURE( false, "nVersion not implemented!" );
5884 if ( (m_nFib
< nFibMin
) || (m_nFib
> nFibMax
) )
5886 m_nFibError
= ERR_SWG_READ_ERROR
; // report error
5891 ww::WordVersion eVer
= GetFIBVersion();
5893 // helper vars for Ver67:
5894 sal_Int16 pnChpFirst_Ver67
=0;
5895 sal_Int16 pnPapFirst_Ver67
=0;
5896 sal_Int16 cpnBteChp_Ver67
=0;
5897 sal_Int16 cpnBtePap_Ver67
=0;
5900 sal_uInt16 nTmpLid
= 0;
5901 rSt
.ReadUInt16(nTmpLid
);
5902 m_lid
= LanguageType(nTmpLid
);
5903 rSt
.ReadInt16( m_pnNext
);
5904 sal_uInt8
aBits1(0);
5905 rSt
.ReadUChar( aBits1
);
5906 sal_uInt8
aBits2(0);
5907 rSt
.ReadUChar( aBits2
);
5908 rSt
.ReadUInt16( m_nFibBack
);
5909 rSt
.ReadUInt16( m_nHash
);
5910 rSt
.ReadUInt16( m_nKey
);
5911 rSt
.ReadUChar( m_envr
);
5912 sal_uInt8
aVer8Bits1(0); // only used starting with WinWord 8
5913 rSt
.ReadUChar( aVer8Bits1
); // only have an empty reserve field under Ver67
5914 // content from aVer8Bits1
5916 // sal_uInt8 fMac :1;
5917 // sal_uInt8 fEmptySpecial :1;
5918 // sal_uInt8 fLoadOverridePage :1;
5919 // sal_uInt8 fFuturesavedUndo :1;
5920 // sal_uInt8 fWord97Saved :1;
5922 rSt
.ReadUInt16( m_chse
);
5923 rSt
.ReadUInt16( m_chseTables
);
5924 rSt
.ReadInt32( m_fcMin
);
5925 rSt
.ReadInt32( m_fcMac
);
5927 // insertion for WW8
5928 if (IsEightPlus(eVer
))
5930 rSt
.ReadUInt16( m_csw
);
5932 // Marke: "rgsw" Beginning of the array of shorts
5933 rSt
.ReadUInt16( m_wMagicCreated
);
5934 rSt
.ReadUInt16( m_wMagicRevised
);
5935 rSt
.ReadUInt16( m_wMagicCreatedPrivate
);
5936 rSt
.ReadUInt16( m_wMagicRevisedPrivate
);
5937 rSt
.SeekRel( 9 * sizeof( sal_Int16
) );
5940 // these are the 9 unused fields:
5941 && (bVer67 || WW8ReadINT16( rSt, pnFbpChpFirst_W6 )) // 1
5942 && (bVer67 || WW8ReadINT16( rSt, pnChpFirst_W6 )) // 2
5943 && (bVer67 || WW8ReadINT16( rSt, cpnBteChp_W6 )) // 3
5944 && (bVer67 || WW8ReadINT16( rSt, pnFbpPapFirst_W6 )) // 4
5945 && (bVer67 || WW8ReadINT16( rSt, pnPapFirst_W6 )) // 5
5946 && (bVer67 || WW8ReadINT16( rSt, cpnBtePap_W6 )) // 6
5947 && (bVer67 || WW8ReadINT16( rSt, pnFbpLvcFirst_W6 )) // 7
5948 && (bVer67 || WW8ReadINT16( rSt, pnLvcFirst_W6 )) // 8
5949 && (bVer67 || WW8ReadINT16( rSt, cpnBteLvc_W6 )) // 9
5951 sal_uInt16 nTmpFE
= 0;
5952 rSt
.ReadUInt16(nTmpFE
);
5953 m_lidFE
= LanguageType(nTmpFE
);
5954 rSt
.ReadUInt16( m_clw
);
5957 // end of the insertion for WW8
5959 // Marke: "rglw" Beginning of the array of longs
5960 rSt
.ReadInt32( m_cbMac
);
5962 // ignore 2 longs, because they are unimportant
5963 rSt
.SeekRel( 2 * sizeof( sal_Int32
) );
5965 // skipping 2 more longs only at Ver67
5966 if (IsSevenMinus(eVer
))
5967 rSt
.SeekRel( 2 * sizeof( sal_Int32
) );
5969 rSt
.ReadInt32( m_ccpText
);
5970 rSt
.ReadInt32( m_ccpFootnote
);
5971 rSt
.ReadInt32( m_ccpHdr
);
5972 rSt
.ReadInt32( m_ccpMcr
);
5973 rSt
.ReadInt32( m_ccpAtn
);
5974 rSt
.ReadInt32( m_ccpEdn
);
5975 rSt
.ReadInt32( m_ccpTxbx
);
5976 rSt
.ReadInt32( m_ccpHdrTxbx
);
5978 // only skip one more long at Ver67
5979 if (IsSevenMinus(eVer
))
5980 rSt
.SeekRel( 1 * sizeof( sal_Int32
) );
5983 // insertion for WW8
5984 rSt
.ReadInt32( m_pnFbpChpFirst
);
5985 rSt
.ReadInt32( m_pnChpFirst
);
5986 rSt
.ReadInt32( m_cpnBteChp
);
5987 rSt
.ReadInt32( m_pnFbpPapFirst
);
5988 rSt
.ReadInt32( m_pnPapFirst
);
5989 rSt
.ReadInt32( m_cpnBtePap
);
5990 rSt
.ReadInt32( m_pnFbpLvcFirst
);
5991 rSt
.ReadInt32( m_pnLvcFirst
);
5992 rSt
.ReadInt32( m_cpnBteLvc
);
5993 rSt
.ReadInt32( m_fcIslandFirst
);
5994 rSt
.ReadInt32( m_fcIslandLim
);
5995 rSt
.ReadUInt16( m_cfclcb
);
5997 // Read cswNew to find out if nFib should be ignored.
5998 sal_uInt64 nPos
= rSt
.Tell();
5999 rSt
.SeekRel(m_cfclcb
* 8);
6000 if (rSt
.good() && rSt
.remainingSize() >= 2)
6002 rSt
.ReadUInt16(m_cswNew
);
6007 // end of the insertion for WW8
6009 // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
6010 rSt
.ReadInt32( m_fcStshfOrig
);
6011 m_lcbStshfOrig
= Readcb(rSt
, eVer
);
6012 rSt
.ReadInt32( m_fcStshf
);
6013 m_lcbStshf
= Readcb(rSt
, eVer
);
6014 rSt
.ReadInt32( m_fcPlcffndRef
);
6015 m_lcbPlcffndRef
= Readcb(rSt
, eVer
);
6016 rSt
.ReadInt32( m_fcPlcffndText
);
6017 m_lcbPlcffndText
= Readcb(rSt
, eVer
);
6018 rSt
.ReadInt32( m_fcPlcfandRef
);
6019 m_lcbPlcfandRef
= Readcb(rSt
, eVer
);
6020 rSt
.ReadInt32( m_fcPlcfandText
);
6021 m_lcbPlcfandText
= Readcb(rSt
, eVer
);
6022 rSt
.ReadInt32( m_fcPlcfsed
);
6023 m_lcbPlcfsed
= Readcb(rSt
, eVer
);
6024 rSt
.ReadInt32( m_fcPlcfpad
);
6025 m_lcbPlcfpad
= Readcb(rSt
, eVer
);
6026 rSt
.ReadInt32( m_fcPlcfphe
);
6027 m_lcbPlcfphe
= Readcb(rSt
, eVer
);
6028 rSt
.ReadInt32( m_fcSttbfglsy
);
6029 m_lcbSttbfglsy
= Readcb(rSt
, eVer
);
6030 rSt
.ReadInt32( m_fcPlcfglsy
);
6031 m_lcbPlcfglsy
= Readcb(rSt
, eVer
);
6032 rSt
.ReadInt32( m_fcPlcfhdd
);
6033 m_lcbPlcfhdd
= Readcb(rSt
, eVer
);
6034 rSt
.ReadInt32( m_fcPlcfbteChpx
);
6035 m_lcbPlcfbteChpx
= Readcb(rSt
, eVer
);
6036 rSt
.ReadInt32( m_fcPlcfbtePapx
);
6037 m_lcbPlcfbtePapx
= Readcb(rSt
, eVer
);
6038 rSt
.ReadInt32( m_fcPlcfsea
);
6039 m_lcbPlcfsea
= Readcb(rSt
, eVer
);
6040 rSt
.ReadInt32( m_fcSttbfffn
);
6041 m_lcbSttbfffn
= Readcb(rSt
, eVer
);
6042 rSt
.ReadInt32( m_fcPlcffldMom
);
6043 m_lcbPlcffldMom
= Readcb(rSt
, eVer
);
6044 rSt
.ReadInt32( m_fcPlcffldHdr
);
6045 m_lcbPlcffldHdr
= Readcb(rSt
, eVer
);
6046 rSt
.ReadInt32( m_fcPlcffldFootnote
);
6047 m_lcbPlcffldFootnote
= Readcb(rSt
, eVer
);
6048 rSt
.ReadInt32( m_fcPlcffldAtn
);
6049 m_lcbPlcffldAtn
= Readcb(rSt
, eVer
);
6050 rSt
.ReadInt32( m_fcPlcffldMcr
);
6051 m_lcbPlcffldMcr
= Readcb(rSt
, eVer
);
6052 rSt
.ReadInt32( m_fcSttbfbkmk
);
6053 m_lcbSttbfbkmk
= Readcb(rSt
, eVer
);
6054 rSt
.ReadInt32( m_fcPlcfbkf
);
6055 m_lcbPlcfbkf
= Readcb(rSt
, eVer
);
6056 rSt
.ReadInt32( m_fcPlcfbkl
);
6057 m_lcbPlcfbkl
= Readcb(rSt
, eVer
);
6058 rSt
.ReadInt32( m_fcCmds
);
6059 m_lcbCmds
= Readcb(rSt
, eVer
);
6060 rSt
.ReadInt32( m_fcPlcfmcr
);
6061 m_lcbPlcfmcr
= Readcb(rSt
, eVer
);
6062 rSt
.ReadInt32( m_fcSttbfmcr
);
6063 m_lcbSttbfmcr
= Readcb(rSt
, eVer
);
6064 if (eVer
>= ww::eWW2
)
6066 rSt
.ReadInt32( m_fcPrDrvr
);
6067 m_lcbPrDrvr
= Readcb(rSt
, eVer
);
6068 rSt
.ReadInt32( m_fcPrEnvPort
);
6069 m_lcbPrEnvPort
= Readcb(rSt
, eVer
);
6070 rSt
.ReadInt32( m_fcPrEnvLand
);
6071 m_lcbPrEnvLand
= Readcb(rSt
, eVer
);
6075 rSt
.ReadInt32( m_fcPrEnvPort
);
6076 m_lcbPrEnvPort
= Readcb(rSt
, eVer
);
6078 rSt
.ReadInt32( m_fcWss
);
6079 m_lcbWss
= Readcb(rSt
, eVer
);
6080 rSt
.ReadInt32( m_fcDop
);
6081 m_lcbDop
= Readcb(rSt
, eVer
);
6082 rSt
.ReadInt32( m_fcSttbfAssoc
);
6083 m_lcbSttbfAssoc
= Readcb(rSt
, eVer
);
6084 rSt
.ReadInt32( m_fcClx
);
6085 m_lcbClx
= Readcb(rSt
, eVer
);
6086 rSt
.ReadInt32( m_fcPlcfpgdFootnote
);
6087 m_lcbPlcfpgdFootnote
= Readcb(rSt
, eVer
);
6088 rSt
.ReadInt32( m_fcAutosaveSource
);
6089 m_lcbAutosaveSource
= Readcb(rSt
, eVer
);
6090 rSt
.ReadInt32( m_fcGrpStAtnOwners
);
6091 m_lcbGrpStAtnOwners
= Readcb(rSt
, eVer
);
6092 rSt
.ReadInt32( m_fcSttbfAtnbkmk
);
6093 m_lcbSttbfAtnbkmk
= Readcb(rSt
, eVer
);
6095 // only skip more shot at Ver67
6096 if (IsSevenMinus(eVer
))
6098 if (eVer
== ww::eWW1
)
6099 rSt
.SeekRel(1*sizeof(sal_Int32
));
6100 rSt
.SeekRel(1*sizeof(sal_Int16
));
6102 if (eVer
>= ww::eWW2
)
6104 rSt
.ReadInt16(pnChpFirst_Ver67
);
6105 rSt
.ReadInt16(pnPapFirst_Ver67
);
6107 rSt
.ReadInt16(cpnBteChp_Ver67
);
6108 rSt
.ReadInt16(cpnBtePap_Ver67
);
6111 if (eVer
> ww::eWW2
)
6113 rSt
.ReadInt32( m_fcPlcfdoaMom
);
6114 rSt
.ReadInt32( m_lcbPlcfdoaMom
);
6115 rSt
.ReadInt32( m_fcPlcfdoaHdr
);
6116 rSt
.ReadInt32( m_lcbPlcfdoaHdr
);
6117 rSt
.ReadInt32( m_fcPlcfspaMom
);
6118 rSt
.ReadInt32( m_lcbPlcfspaMom
);
6119 rSt
.ReadInt32( m_fcPlcfspaHdr
);
6120 rSt
.ReadInt32( m_lcbPlcfspaHdr
);
6122 rSt
.ReadInt32( m_fcPlcfAtnbkf
);
6123 rSt
.ReadInt32( m_lcbPlcfAtnbkf
);
6124 rSt
.ReadInt32( m_fcPlcfAtnbkl
);
6125 rSt
.ReadInt32( m_lcbPlcfAtnbkl
);
6126 rSt
.ReadInt32( m_fcPms
);
6127 rSt
.ReadInt32( m_lcbPMS
);
6128 rSt
.ReadInt32( m_fcFormFieldSttbf
);
6129 rSt
.ReadInt32( m_lcbFormFieldSttbf
);
6130 rSt
.ReadInt32( m_fcPlcfendRef
);
6131 rSt
.ReadInt32( m_lcbPlcfendRef
);
6132 rSt
.ReadInt32( m_fcPlcfendText
);
6133 rSt
.ReadInt32( m_lcbPlcfendText
);
6134 rSt
.ReadInt32( m_fcPlcffldEdn
);
6135 rSt
.ReadInt32( m_lcbPlcffldEdn
);
6136 rSt
.ReadInt32( m_fcPlcfpgdEdn
);
6137 rSt
.ReadInt32( m_lcbPlcfpgdEdn
);
6138 rSt
.ReadInt32( m_fcDggInfo
);
6139 rSt
.ReadInt32( m_lcbDggInfo
);
6140 rSt
.ReadInt32( m_fcSttbfRMark
);
6141 rSt
.ReadInt32( m_lcbSttbfRMark
);
6142 rSt
.ReadInt32( m_fcSttbfCaption
);
6143 rSt
.ReadInt32( m_lcbSttbfCaption
);
6144 rSt
.ReadInt32( m_fcSttbAutoCaption
);
6145 rSt
.ReadInt32( m_lcbSttbAutoCaption
);
6146 rSt
.ReadInt32( m_fcPlcfwkb
);
6147 rSt
.ReadInt32( m_lcbPlcfwkb
);
6148 rSt
.ReadInt32( m_fcPlcfspl
);
6149 rSt
.ReadInt32( m_lcbPlcfspl
);
6150 rSt
.ReadInt32( m_fcPlcftxbxText
);
6151 rSt
.ReadInt32( m_lcbPlcftxbxText
);
6152 rSt
.ReadInt32( m_fcPlcffldTxbx
);
6153 rSt
.ReadInt32( m_lcbPlcffldTxbx
);
6154 rSt
.ReadInt32( m_fcPlcfHdrtxbxText
);
6155 rSt
.ReadInt32( m_lcbPlcfHdrtxbxText
);
6156 rSt
.ReadInt32( m_fcPlcffldHdrTxbx
);
6157 rSt
.ReadInt32( m_lcbPlcffldHdrTxbx
);
6158 rSt
.ReadInt32( m_fcStwUser
);
6159 rSt
.ReadUInt32( m_lcbStwUser
);
6160 rSt
.ReadInt32( m_fcSttbttmbd
);
6161 rSt
.ReadUInt32( m_lcbSttbttmbd
);
6164 if( ERRCODE_NONE
== rSt
.GetError() )
6167 m_fDot
= aBits1
& 0x01 ;
6168 m_fGlsy
= ( aBits1
& 0x02 ) >> 1;
6169 m_fComplex
= ( aBits1
& 0x04 ) >> 2;
6170 m_fHasPic
= ( aBits1
& 0x08 ) >> 3;
6171 m_cQuickSaves
= ( aBits1
& 0xf0 ) >> 4;
6172 m_fEncrypted
= aBits2
& 0x01 ;
6173 m_fWhichTableStm
= ( aBits2
& 0x02 ) >> 1;
6174 m_fReadOnlyRecommended
= (aBits2
& 0x4) >> 2;
6175 m_fWriteReservation
= (aBits2
& 0x8) >> 3;
6176 m_fExtChar
= ( aBits2
& 0x10 ) >> 4;
6177 // dummy = ( aBits2 & 0x20 ) >> 5;
6178 m_fFarEast
= ( aBits2
& 0x40 ) >> 6; // #i90932#
6179 // dummy = ( aBits2 & 0x80 ) >> 7;
6182 p.r.n. fill targeted variable with xxx_Ver67
6185 if (IsSevenMinus(eVer
))
6187 m_pnChpFirst
= pnChpFirst_Ver67
;
6188 m_pnPapFirst
= pnPapFirst_Ver67
;
6189 m_cpnBteChp
= cpnBteChp_Ver67
;
6190 m_cpnBtePap
= cpnBtePap_Ver67
;
6192 else if (IsEightPlus(eVer
))
6194 m_fMac
= aVer8Bits1
& 0x01 ;
6195 m_fEmptySpecial
= ( aVer8Bits1
& 0x02 ) >> 1;
6196 m_fLoadOverridePage
= ( aVer8Bits1
& 0x04 ) >> 2;
6197 m_fFuturesavedUndo
= ( aVer8Bits1
& 0x08 ) >> 3;
6198 m_fWord97Saved
= ( aVer8Bits1
& 0x10 ) >> 4;
6199 m_fWord2000Saved
= ( aVer8Bits1
& 0x20 ) >> 5;
6203 identify the values for PLCF and PLF LFO
6204 and PLCF for the textbox break descriptors
6206 sal_uInt64 nOldPos
= rSt
.Tell();
6209 rSt
.ReadInt32( m_fcSttbFnm
);
6210 rSt
.ReadInt32( m_lcbSttbFnm
);
6211 rSt
.ReadInt32( m_fcPlcfLst
);
6212 rSt
.ReadInt32( m_lcbPlcfLst
);
6213 rSt
.ReadInt32( m_fcPlfLfo
);
6214 rSt
.ReadInt32( m_lcbPlfLfo
);
6215 rSt
.ReadInt32( m_fcPlcftxbxBkd
);
6216 rSt
.ReadInt32( m_lcbPlcftxbxBkd
);
6217 rSt
.ReadInt32( m_fcPlcfHdrtxbxBkd
);
6218 rSt
.ReadInt32( m_lcbPlcfHdrtxbxBkd
);
6219 if( ERRCODE_NONE
!= rSt
.GetError() )
6221 m_nFibError
= ERR_SWG_READ_ERROR
;
6224 rSt
.Seek( 0x372 ); // fcSttbListNames
6225 rSt
.ReadInt32( m_fcSttbListNames
);
6226 rSt
.ReadInt32( m_lcbSttbListNames
);
6230 rSt
.Seek( 0x382 ); // MagicTables
6231 rSt
.ReadInt32( m_fcPlcfTch
);
6232 rSt
.ReadInt32( m_lcbPlcfTch
);
6237 rSt
.Seek( 0x41A ); // new ATRD
6238 rSt
.ReadInt32( m_fcAtrdExtra
);
6239 rSt
.ReadUInt32( m_lcbAtrdExtra
);
6242 // Factoid bookmarks
6246 rSt
.ReadInt32(m_fcPlcfBkfFactoid
);
6247 rSt
.ReadUInt32(m_lcbPlcfBkfFactoid
);
6250 rSt
.ReadInt32(m_fcPlcfBklFactoid
);
6251 rSt
.ReadUInt32(m_lcbPlcfBklFactoid
);
6254 rSt
.ReadInt32(m_fcFactoidData
);
6255 rSt
.ReadUInt32(m_lcbFactoidData
);
6258 if( ERRCODE_NONE
!= rSt
.GetError() )
6259 m_nFibError
= ERR_SWG_READ_ERROR
;
6261 rSt
.Seek( 0x5bc ); // Actual nFib introduced in Word 2003
6262 rSt
.ReadUInt16( m_nFib_actual
);
6264 rSt
.Seek( nOldPos
);
6269 m_nFibError
= ERR_SWG_READ_ERROR
; // report error
6273 WW8Fib::WW8Fib(sal_uInt8 nVer
, bool bDot
):
6274 m_nVersion(nVer
), m_fDot(false), m_fGlsy(false), m_fComplex(false), m_fHasPic(false), m_cQuickSaves(0),
6275 m_fEncrypted(false), m_fWhichTableStm(false), m_fReadOnlyRecommended(false),
6276 m_fWriteReservation(false), m_fExtChar(false), m_fFarEast(false), m_fObfuscated(false),
6277 m_fMac(false), m_fEmptySpecial(false), m_fLoadOverridePage(false), m_fFuturesavedUndo(false),
6278 m_fWord97Saved(false), m_fWord2000Saved(false)
6279 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
6280 // above bit-field member initializations can be moved to the class definition
6288 m_nProduct
= 0x204D;
6291 m_csw
= 0x0e; // Is this really necessary???
6292 m_cfclcb
= 0x88; // -""-
6293 m_clw
= 0x16; // -""-
6294 m_pnFbpChpFirst
= m_pnFbpPapFirst
= m_pnFbpLvcFirst
= 0x000fffff;
6296 m_fWord97Saved
= m_fWord2000Saved
= true;
6298 // Just a fancy way to write 'Caolan80'.
6299 m_wMagicCreated
= 0x6143;
6300 m_wMagicRevised
= 0x6C6F;
6301 m_wMagicCreatedPrivate
= 0x6E61;
6302 m_wMagicRevisedPrivate
= 0x3038;
6308 m_nFib
= m_nFibBack
= 0x65;
6309 m_nProduct
= 0xc02d;
6312 //If nFib is 0x00D9 or greater, then cQuickSaves MUST be 0xF
6313 m_cQuickSaves
= m_nFib
>= 0x00D9 ? 0xF : 0;
6316 m_lid
= LanguageType(0x409); // LANGUAGE_ENGLISH_US
6318 LanguageType nLang
= Application::GetSettings().GetLanguageTag().getLanguageType();
6319 m_fFarEast
= MsLangId::isCJK(nLang
);
6325 LanguageTag
aLanguageTag( m_lid
);
6326 LocaleDataWrapper
aLocaleWrapper( std::move(aLanguageTag
) );
6327 m_nNumDecimalSep
= aLocaleWrapper
.getNumDecimalSep()[0];
6331 void WW8Fib::WriteHeader(SvStream
& rStrm
)
6333 bool bVer8
= 8 == m_nVersion
;
6335 size_t nUnencryptedHdr
= bVer8
? 0x44 : 0x24;
6336 std::unique_ptr
<sal_uInt8
[]> pDataPtr( new sal_uInt8
[ nUnencryptedHdr
] );
6337 sal_uInt8
*pData
= pDataPtr
.get();
6338 memset( pData
, 0, nUnencryptedHdr
);
6340 m_cbMac
= rStrm
.TellEnd();
6342 Set_UInt16( pData
, m_wIdent
);
6343 Set_UInt16( pData
, m_nFib
);
6344 Set_UInt16( pData
, m_nProduct
);
6345 Set_UInt16( pData
, static_cast<sal_uInt16
>(m_lid
) );
6346 Set_UInt16( pData
, m_pnNext
);
6348 sal_uInt16 nBits16
= 0;
6349 if( m_fDot
) nBits16
|= 0x0001;
6350 if( m_fGlsy
) nBits16
|= 0x0002;
6351 if( m_fComplex
) nBits16
|= 0x0004;
6352 if( m_fHasPic
) nBits16
|= 0x0008;
6353 nBits16
|= (0xf0 & ( m_cQuickSaves
<< 4 ));
6354 if( m_fEncrypted
) nBits16
|= 0x0100;
6355 if( m_fWhichTableStm
) nBits16
|= 0x0200;
6357 if (m_fReadOnlyRecommended
)
6359 if (m_fWriteReservation
)
6362 if( m_fExtChar
) nBits16
|= 0x1000;
6363 if( m_fFarEast
) nBits16
|= 0x4000; // #i90932#
6364 if( m_fObfuscated
) nBits16
|= 0x8000;
6365 Set_UInt16( pData
, nBits16
);
6367 Set_UInt16( pData
, m_nFibBack
);
6368 Set_UInt16( pData
, m_nHash
);
6369 Set_UInt16( pData
, m_nKey
);
6370 Set_UInt8( pData
, m_envr
);
6372 sal_uInt8 nBits8
= 0;
6375 if( m_fMac
) nBits8
|= 0x0001;
6376 if( m_fEmptySpecial
) nBits8
|= 0x0002;
6377 if( m_fLoadOverridePage
) nBits8
|= 0x0004;
6378 if( m_fFuturesavedUndo
) nBits8
|= 0x0008;
6379 if( m_fWord97Saved
) nBits8
|= 0x0010;
6380 if( m_fWord2000Saved
) nBits8
|= 0x0020;
6382 // under Ver67 these are only reserved
6383 Set_UInt8( pData
, nBits8
);
6385 Set_UInt16( pData
, m_chse
);
6386 Set_UInt16( pData
, m_chseTables
);
6387 Set_UInt32( pData
, m_fcMin
);
6388 Set_UInt32( pData
, m_fcMac
);
6390 // insertion for WW8
6392 // Marke: "rgsw" Beginning of the array of shorts
6395 Set_UInt16( pData
, m_csw
);
6396 Set_UInt16( pData
, m_wMagicCreated
);
6397 Set_UInt16( pData
, m_wMagicRevised
);
6398 Set_UInt16( pData
, m_wMagicCreatedPrivate
);
6399 Set_UInt16( pData
, m_wMagicRevisedPrivate
);
6400 pData
+= 9 * sizeof( sal_Int16
);
6401 Set_UInt16( pData
, static_cast<sal_uInt16
>(m_lidFE
) );
6402 Set_UInt16( pData
, m_clw
);
6405 // end of the insertion for WW8
6407 // Marke: "rglw" Beginning of the array of longs
6408 Set_UInt32( pData
, m_cbMac
);
6410 rStrm
.WriteBytes(pDataPtr
.get(), nUnencryptedHdr
);
6413 void WW8Fib::Write(SvStream
& rStrm
)
6415 bool bVer8
= 8 == m_nVersion
;
6417 WriteHeader( rStrm
);
6419 size_t nUnencryptedHdr
= bVer8
? 0x44 : 0x24;
6421 std::unique_ptr
<sal_uInt8
[]> pDataPtr( new sal_uInt8
[ m_fcMin
- nUnencryptedHdr
] );
6422 sal_uInt8
*pData
= pDataPtr
.get();
6423 memset( pData
, 0, m_fcMin
- nUnencryptedHdr
);
6425 m_cbMac
= rStrm
.TellEnd();
6427 // ignore 2 longs, because they are unimportant
6428 pData
+= 2 * sizeof( sal_Int32
);
6430 // skipping 2 more longs only at Ver67
6432 pData
+= 2 * sizeof( sal_Int32
);
6434 Set_UInt32( pData
, m_ccpText
);
6435 Set_UInt32( pData
, m_ccpFootnote
);
6436 Set_UInt32( pData
, m_ccpHdr
);
6437 Set_UInt32( pData
, m_ccpMcr
);
6438 Set_UInt32( pData
, m_ccpAtn
);
6439 Set_UInt32( pData
, m_ccpEdn
);
6440 Set_UInt32( pData
, m_ccpTxbx
);
6441 Set_UInt32( pData
, m_ccpHdrTxbx
);
6443 // only skip one more long at Ver67
6445 pData
+= 1 * sizeof( sal_Int32
);
6447 // insertion for WW8
6450 Set_UInt32( pData
, m_pnFbpChpFirst
);
6451 Set_UInt32( pData
, m_pnChpFirst
);
6452 Set_UInt32( pData
, m_cpnBteChp
);
6453 Set_UInt32( pData
, m_pnFbpPapFirst
);
6454 Set_UInt32( pData
, m_pnPapFirst
);
6455 Set_UInt32( pData
, m_cpnBtePap
);
6456 Set_UInt32( pData
, m_pnFbpLvcFirst
);
6457 Set_UInt32( pData
, m_pnLvcFirst
);
6458 Set_UInt32( pData
, m_cpnBteLvc
);
6459 Set_UInt32( pData
, m_fcIslandFirst
);
6460 Set_UInt32( pData
, m_fcIslandLim
);
6461 Set_UInt16( pData
, m_cfclcb
);
6463 // end of the insertion for WW8
6465 // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
6466 Set_UInt32( pData
, m_fcStshfOrig
);
6467 Set_UInt32( pData
, m_lcbStshfOrig
);
6468 Set_UInt32( pData
, m_fcStshf
);
6469 Set_UInt32( pData
, m_lcbStshf
);
6470 Set_UInt32( pData
, m_fcPlcffndRef
);
6471 Set_UInt32( pData
, m_lcbPlcffndRef
);
6472 Set_UInt32( pData
, m_fcPlcffndText
);
6473 Set_UInt32( pData
, m_lcbPlcffndText
);
6474 Set_UInt32( pData
, m_fcPlcfandRef
);
6475 Set_UInt32( pData
, m_lcbPlcfandRef
);
6476 Set_UInt32( pData
, m_fcPlcfandText
);
6477 Set_UInt32( pData
, m_lcbPlcfandText
);
6478 Set_UInt32( pData
, m_fcPlcfsed
);
6479 Set_UInt32( pData
, m_lcbPlcfsed
);
6480 Set_UInt32( pData
, m_fcPlcfpad
);
6481 Set_UInt32( pData
, m_lcbPlcfpad
);
6482 Set_UInt32( pData
, m_fcPlcfphe
);
6483 Set_UInt32( pData
, m_lcbPlcfphe
);
6484 Set_UInt32( pData
, m_fcSttbfglsy
);
6485 Set_UInt32( pData
, m_lcbSttbfglsy
);
6486 Set_UInt32( pData
, m_fcPlcfglsy
);
6487 Set_UInt32( pData
, m_lcbPlcfglsy
);
6488 Set_UInt32( pData
, m_fcPlcfhdd
);
6489 Set_UInt32( pData
, m_lcbPlcfhdd
);
6490 Set_UInt32( pData
, m_fcPlcfbteChpx
);
6491 Set_UInt32( pData
, m_lcbPlcfbteChpx
);
6492 Set_UInt32( pData
, m_fcPlcfbtePapx
);
6493 Set_UInt32( pData
, m_lcbPlcfbtePapx
);
6494 Set_UInt32( pData
, m_fcPlcfsea
);
6495 Set_UInt32( pData
, m_lcbPlcfsea
);
6496 Set_UInt32( pData
, m_fcSttbfffn
);
6497 Set_UInt32( pData
, m_lcbSttbfffn
);
6498 Set_UInt32( pData
, m_fcPlcffldMom
);
6499 Set_UInt32( pData
, m_lcbPlcffldMom
);
6500 Set_UInt32( pData
, m_fcPlcffldHdr
);
6501 Set_UInt32( pData
, m_lcbPlcffldHdr
);
6502 Set_UInt32( pData
, m_fcPlcffldFootnote
);
6503 Set_UInt32( pData
, m_lcbPlcffldFootnote
);
6504 Set_UInt32( pData
, m_fcPlcffldAtn
);
6505 Set_UInt32( pData
, m_lcbPlcffldAtn
);
6506 Set_UInt32( pData
, m_fcPlcffldMcr
);
6507 Set_UInt32( pData
, m_lcbPlcffldMcr
);
6508 Set_UInt32( pData
, m_fcSttbfbkmk
);
6509 Set_UInt32( pData
, m_lcbSttbfbkmk
);
6510 Set_UInt32( pData
, m_fcPlcfbkf
);
6511 Set_UInt32( pData
, m_lcbPlcfbkf
);
6512 Set_UInt32( pData
, m_fcPlcfbkl
);
6513 Set_UInt32( pData
, m_lcbPlcfbkl
);
6514 Set_UInt32( pData
, m_fcCmds
);
6515 Set_UInt32( pData
, m_lcbCmds
);
6516 Set_UInt32( pData
, m_fcPlcfmcr
);
6517 Set_UInt32( pData
, m_lcbPlcfmcr
);
6518 Set_UInt32( pData
, m_fcSttbfmcr
);
6519 Set_UInt32( pData
, m_lcbSttbfmcr
);
6520 Set_UInt32( pData
, m_fcPrDrvr
);
6521 Set_UInt32( pData
, m_lcbPrDrvr
);
6522 Set_UInt32( pData
, m_fcPrEnvPort
);
6523 Set_UInt32( pData
, m_lcbPrEnvPort
);
6524 Set_UInt32( pData
, m_fcPrEnvLand
);
6525 Set_UInt32( pData
, m_lcbPrEnvLand
);
6526 Set_UInt32( pData
, m_fcWss
);
6527 Set_UInt32( pData
, m_lcbWss
);
6528 Set_UInt32( pData
, m_fcDop
);
6529 Set_UInt32( pData
, m_lcbDop
);
6530 Set_UInt32( pData
, m_fcSttbfAssoc
);
6531 Set_UInt32( pData
, m_lcbSttbfAssoc
);
6532 Set_UInt32( pData
, m_fcClx
);
6533 Set_UInt32( pData
, m_lcbClx
);
6534 Set_UInt32( pData
, m_fcPlcfpgdFootnote
);
6535 Set_UInt32( pData
, m_lcbPlcfpgdFootnote
);
6536 Set_UInt32( pData
, m_fcAutosaveSource
);
6537 Set_UInt32( pData
, m_lcbAutosaveSource
);
6538 Set_UInt32( pData
, m_fcGrpStAtnOwners
);
6539 Set_UInt32( pData
, m_lcbGrpStAtnOwners
);
6540 Set_UInt32( pData
, m_fcSttbfAtnbkmk
);
6541 Set_UInt32( pData
, m_lcbSttbfAtnbkmk
);
6543 // only skip one more short at Ver67
6546 pData
+= 1*sizeof( sal_Int16
);
6547 Set_UInt16( pData
, o3tl::narrowing
<sal_uInt16
>(m_pnChpFirst
) );
6548 Set_UInt16( pData
, o3tl::narrowing
<sal_uInt16
>(m_pnPapFirst
) );
6549 Set_UInt16( pData
, o3tl::narrowing
<sal_uInt16
>(m_cpnBteChp
) );
6550 Set_UInt16( pData
, o3tl::narrowing
<sal_uInt16
>(m_cpnBtePap
) );
6553 Set_UInt32( pData
, m_fcPlcfdoaMom
); // only at Ver67, in Ver8 unused
6554 Set_UInt32( pData
, m_lcbPlcfdoaMom
); // only at Ver67, in Ver8 unused
6555 Set_UInt32( pData
, m_fcPlcfdoaHdr
); // only at Ver67, in Ver8 unused
6556 Set_UInt32( pData
, m_lcbPlcfdoaHdr
); // only at Ver67, in Ver8 unused
6558 Set_UInt32( pData
, m_fcPlcfspaMom
); // in Ver67 empty reserve
6559 Set_UInt32( pData
, m_lcbPlcfspaMom
); // in Ver67 empty reserve
6560 Set_UInt32( pData
, m_fcPlcfspaHdr
); // in Ver67 empty reserve
6561 Set_UInt32( pData
, m_lcbPlcfspaHdr
); // in Ver67 empty reserve
6563 Set_UInt32( pData
, m_fcPlcfAtnbkf
);
6564 Set_UInt32( pData
, m_lcbPlcfAtnbkf
);
6565 Set_UInt32( pData
, m_fcPlcfAtnbkl
);
6566 Set_UInt32( pData
, m_lcbPlcfAtnbkl
);
6567 Set_UInt32( pData
, m_fcPms
);
6568 Set_UInt32( pData
, m_lcbPMS
);
6569 Set_UInt32( pData
, m_fcFormFieldSttbf
);
6570 Set_UInt32( pData
, m_lcbFormFieldSttbf
);
6571 Set_UInt32( pData
, m_fcPlcfendRef
);
6572 Set_UInt32( pData
, m_lcbPlcfendRef
);
6573 Set_UInt32( pData
, m_fcPlcfendText
);
6574 Set_UInt32( pData
, m_lcbPlcfendText
);
6575 Set_UInt32( pData
, m_fcPlcffldEdn
);
6576 Set_UInt32( pData
, m_lcbPlcffldEdn
);
6577 Set_UInt32( pData
, m_fcPlcfpgdEdn
);
6578 Set_UInt32( pData
, m_lcbPlcfpgdEdn
);
6579 Set_UInt32( pData
, m_fcDggInfo
); // in Ver67 empty reserve
6580 Set_UInt32( pData
, m_lcbDggInfo
); // in Ver67 empty reserve
6581 Set_UInt32( pData
, m_fcSttbfRMark
);
6582 Set_UInt32( pData
, m_lcbSttbfRMark
);
6583 Set_UInt32( pData
, m_fcSttbfCaption
);
6584 Set_UInt32( pData
, m_lcbSttbfCaption
);
6585 Set_UInt32( pData
, m_fcSttbAutoCaption
);
6586 Set_UInt32( pData
, m_lcbSttbAutoCaption
);
6587 Set_UInt32( pData
, m_fcPlcfwkb
);
6588 Set_UInt32( pData
, m_lcbPlcfwkb
);
6589 Set_UInt32( pData
, m_fcPlcfspl
); // in Ver67 empty reserve
6590 Set_UInt32( pData
, m_lcbPlcfspl
); // in Ver67 empty reserve
6591 Set_UInt32( pData
, m_fcPlcftxbxText
);
6592 Set_UInt32( pData
, m_lcbPlcftxbxText
);
6593 Set_UInt32( pData
, m_fcPlcffldTxbx
);
6594 Set_UInt32( pData
, m_lcbPlcffldTxbx
);
6595 Set_UInt32( pData
, m_fcPlcfHdrtxbxText
);
6596 Set_UInt32( pData
, m_lcbPlcfHdrtxbxText
);
6597 Set_UInt32( pData
, m_fcPlcffldHdrTxbx
);
6598 Set_UInt32( pData
, m_lcbPlcffldHdrTxbx
);
6602 pData
+= 0x2da - 0x27a; // Pos + Offset (fcPlcfLst - fcStwUser)
6603 Set_UInt32( pData
, m_fcSttbFnm
);
6604 Set_UInt32( pData
, m_lcbSttbFnm
);
6605 Set_UInt32( pData
, m_fcPlcfLst
);
6606 Set_UInt32( pData
, m_lcbPlcfLst
);
6607 Set_UInt32( pData
, m_fcPlfLfo
);
6608 Set_UInt32( pData
, m_lcbPlfLfo
);
6609 Set_UInt32( pData
, m_fcPlcftxbxBkd
);
6610 Set_UInt32( pData
, m_lcbPlcftxbxBkd
);
6611 Set_UInt32( pData
, m_fcPlcfHdrtxbxBkd
);
6612 Set_UInt32( pData
, m_lcbPlcfHdrtxbxBkd
);
6614 pData
+= 0x372 - 0x302; // Pos + Offset (fcSttbListNames - fcDocUndo)
6615 Set_UInt32( pData
, m_fcSttbListNames
);
6616 Set_UInt32( pData
, m_lcbSttbListNames
);
6618 pData
+= 0x382 - 0x37A;
6619 Set_UInt32( pData
, m_fcPlcfTch
);
6620 Set_UInt32( pData
, m_lcbPlcfTch
);
6622 pData
+= 0x3FA - 0x38A;
6623 Set_UInt16( pData
, sal_uInt16(0x0002));
6624 Set_UInt16( pData
, sal_uInt16(0x00D9));
6626 pData
+= 0x41A - 0x3FE;
6627 Set_UInt32( pData
, m_fcAtrdExtra
);
6628 Set_UInt32( pData
, m_lcbAtrdExtra
);
6630 pData
+= 0x42a - 0x422;
6631 Set_UInt32(pData
, m_fcSttbfBkmkFactoid
);
6632 Set_UInt32(pData
, m_lcbSttbfBkmkFactoid
);
6633 Set_UInt32(pData
, m_fcPlcfBkfFactoid
);
6634 Set_UInt32(pData
, m_lcbPlcfBkfFactoid
);
6636 pData
+= 0x442 - 0x43A;
6637 Set_UInt32(pData
, m_fcPlcfBklFactoid
);
6638 Set_UInt32(pData
, m_lcbPlcfBklFactoid
);
6639 Set_UInt32(pData
, m_fcFactoidData
);
6640 Set_UInt32(pData
, m_lcbFactoidData
);
6642 pData
+= 0x4BA - 0x452;
6643 Set_UInt32(pData
, m_fcPlcffactoid
);
6644 Set_UInt32(pData
, m_lcbPlcffactoid
);
6646 pData
+= 0x4DA - 0x4c2;
6647 Set_UInt32( pData
, m_fcHplxsdr
);
6648 Set_UInt32( pData
, 0);
6651 rStrm
.WriteBytes(pDataPtr
.get(), m_fcMin
- nUnencryptedHdr
);
6654 rtl_TextEncoding
WW8Fib::GetFIBCharset(sal_uInt16 chs
, LanguageType nLidLocale
)
6656 OSL_ENSURE(chs
<= 0x100, "overflowed winword charset set");
6658 return RTL_TEXTENCODING_APPLE_ROMAN
;
6659 if (chs
== 0 && static_cast<sal_uInt16
>(nLidLocale
) >= 999)
6663 language stamp -- localized version In pre-WinWord 2.0 files this
6664 value was the nLocale. If value is < 999, then it is the nLocale,
6665 otherwise it is the lid.
6667 css::lang::Locale
aLocale(LanguageTag::convertToLocale(nLidLocale
));
6668 return msfilter::util::getBestTextEncodingFromLocale(aLocale
);
6670 return rtl_getTextEncodingFromWindowsCharset(static_cast<sal_uInt8
>(chs
));
6673 MSOFactoidType::MSOFactoidType()
6678 namespace MSOPBString
6680 static OUString
Read(SvStream
& rStream
)
6685 rStream
.ReadUInt16(nBuf
);
6686 sal_uInt16 nCch
= nBuf
& 0x7fff; // Bits 1..15.
6687 bool bAnsiString
= (nBuf
& (1 << 15)) >> 15; // 16th bit.
6689 aRet
= OStringToOUString(read_uInt8s_ToOString(rStream
, nCch
), RTL_TEXTENCODING_ASCII_US
);
6691 aRet
= read_uInt16s_ToOUString(rStream
, nCch
);
6696 static void Write(std::u16string_view aString
, SvStream
& rStream
)
6698 sal_uInt16 nBuf
= 0;
6699 nBuf
|= sal_Int32(aString
.size()); // cch, 0..14th bits.
6700 nBuf
|= 0x8000; // fAnsiString, 15th bit.
6701 rStream
.WriteUInt16(nBuf
);
6702 SwWW8Writer::WriteString8(rStream
, aString
, false, RTL_TEXTENCODING_ASCII_US
);
6706 void MSOFactoidType::Read(SvStream
& rStream
)
6708 sal_uInt32
cbFactoid(0);
6709 rStream
.ReadUInt32(cbFactoid
);
6710 rStream
.ReadUInt32(m_nId
);
6711 m_aUri
= MSOPBString::Read(rStream
);
6712 m_aTag
= MSOPBString::Read(rStream
);
6713 MSOPBString::Read(rStream
); // rgbDownloadURL
6716 void MSOFactoidType::Write(WW8Export
& rExport
)
6718 SvStream
& rStream
= *rExport
.m_pTableStrm
;
6720 SvMemoryStream aStream
;
6721 aStream
.WriteUInt32(m_nId
); // id
6722 MSOPBString::Write(m_aUri
, aStream
);
6723 MSOPBString::Write(m_aTag
, aStream
);
6724 MSOPBString::Write(u
"", aStream
); // rgbDownloadURL
6725 rStream
.WriteUInt32(aStream
.Tell());
6727 rStream
.WriteStream(aStream
);
6730 void MSOPropertyBagStore::Read(SvStream
& rStream
)
6732 sal_uInt32
cFactoidType(0);
6733 rStream
.ReadUInt32(cFactoidType
);
6734 for (sal_uInt32 i
= 0; i
< cFactoidType
&& rStream
.good(); ++i
)
6736 MSOFactoidType aFactoidType
;
6737 aFactoidType
.Read(rStream
);
6738 m_aFactoidTypes
.push_back(aFactoidType
);
6740 sal_uInt16
cbHdr(0);
6741 rStream
.ReadUInt16(cbHdr
);
6742 SAL_WARN_IF(cbHdr
!= 0xc, "sw.ww8", "MSOPropertyBagStore::Read: unexpected cbHdr");
6744 rStream
.ReadUInt16(nVer
);
6745 SAL_WARN_IF(nVer
!= 0x0100, "sw.ww8", "MSOPropertyBagStore::Read: unexpected nVer");
6746 rStream
.SeekRel(4); // cfactoid
6747 sal_uInt32
nCste(0);
6748 rStream
.ReadUInt32(nCste
);
6750 //each string has a 2 byte len record at the start
6751 const size_t nMaxPossibleRecords
= rStream
.remainingSize() / sizeof(sal_uInt16
);
6752 if (nCste
> nMaxPossibleRecords
)
6754 SAL_WARN("sw.ww8", nCste
<< " records claimed, but max possible is " << nMaxPossibleRecords
);
6755 nCste
= nMaxPossibleRecords
;
6758 for (sal_uInt32 i
= 0; i
< nCste
; ++i
)
6760 OUString aString
= MSOPBString::Read(rStream
);
6761 m_aStringTable
.push_back(aString
);
6765 void MSOPropertyBagStore::Write(WW8Export
& rExport
)
6767 SvStream
& rStream
= *rExport
.m_pTableStrm
;
6768 rStream
.WriteUInt32(m_aFactoidTypes
.size()); // cFactoidType
6769 for (MSOFactoidType
& rType
: m_aFactoidTypes
)
6770 rType
.Write(rExport
);
6771 rStream
.WriteUInt16(0xc); // cbHdr
6772 rStream
.WriteUInt16(0x0100); // sVer
6773 rStream
.WriteUInt32(0); // cfactoid
6774 rStream
.WriteUInt32(m_aStringTable
.size()); // cste
6775 for (const OUString
& rString
: m_aStringTable
)
6776 MSOPBString::Write(rString
, rStream
);
6779 MSOProperty::MSOProperty()
6785 void MSOProperty::Read(SvStream
& rStream
)
6787 rStream
.ReadUInt32(m_nKey
);
6788 rStream
.ReadUInt32(m_nValue
);
6791 void MSOProperty::Write(SvStream
& rStream
)
6793 rStream
.WriteUInt32(m_nKey
);
6794 rStream
.WriteUInt32(m_nValue
);
6797 MSOPropertyBag::MSOPropertyBag()
6802 bool MSOPropertyBag::Read(SvStream
& rStream
)
6804 rStream
.ReadUInt16(m_nId
);
6805 sal_uInt16
cProp(0);
6806 rStream
.ReadUInt16(cProp
);
6807 if (!rStream
.good())
6809 rStream
.SeekRel(2); // cbUnknown
6810 //each MSOProperty is 8 bytes in size
6811 const size_t nMaxPossibleRecords
= rStream
.remainingSize() / 8;
6812 if (cProp
> nMaxPossibleRecords
)
6814 SAL_WARN("sw.ww8", cProp
<< " records claimed, but max possible is " << nMaxPossibleRecords
);
6815 cProp
= nMaxPossibleRecords
;
6817 for (sal_uInt16 i
= 0; i
< cProp
&& rStream
.good(); ++i
)
6819 MSOProperty aProperty
;
6820 aProperty
.Read(rStream
);
6821 m_aProperties
.push_back(aProperty
);
6823 return rStream
.good();
6826 void MSOPropertyBag::Write(WW8Export
& rExport
)
6828 SvStream
& rStream
= *rExport
.m_pTableStrm
;
6829 rStream
.WriteUInt16(m_nId
);
6830 rStream
.WriteUInt16(m_aProperties
.size());
6831 rStream
.WriteUInt16(0); // cbUnknown
6832 for (MSOProperty
& rProperty
: m_aProperties
)
6833 rProperty
.Write(rStream
);
6836 void WW8SmartTagData::Read(SvStream
& rStream
, WW8_FC fcFactoidData
, sal_uInt32 lcbFactoidData
)
6838 sal_uInt64 nOldPosition
= rStream
.Tell();
6839 if (!checkSeek(rStream
, fcFactoidData
))
6842 m_aPropBagStore
.Read(rStream
);
6843 while (rStream
.good() && rStream
.Tell() < fcFactoidData
+ lcbFactoidData
)
6845 MSOPropertyBag aPropertyBag
;
6846 if (!aPropertyBag
.Read(rStream
))
6848 m_aPropBags
.push_back(aPropertyBag
);
6851 rStream
.Seek(nOldPosition
);
6854 void WW8SmartTagData::Write(WW8Export
& rExport
)
6856 m_aPropBagStore
.Write(rExport
);
6857 for (MSOPropertyBag
& rPropertyBag
: m_aPropBags
)
6858 rPropertyBag
.Write(rExport
);
6861 WW8Style::WW8Style(SvStream
& rStream
, WW8Fib
& rFibPara
)
6862 : m_rFib(rFibPara
), m_rStream(rStream
), m_cstd(0), m_cbSTDBaseInFile(0), m_fStdStylenamesWritten(0)
6863 , m_stiMaxWhenSaved(0), m_istdMaxFixedWhenSaved(0), m_nVerBuiltInNamesWhenSaved(0)
6864 , m_ftcAsci(0), m_ftcFE(0), m_ftcOther(0), m_ftcBi(0)
6866 if (!checkSeek(m_rStream
, m_rFib
.m_fcStshf
))
6869 sal_uInt16 cbStshi
= 0; // 2 bytes size of the following STSHI structure
6870 sal_uInt32 nRemaining
= m_rFib
.m_lcbStshf
;
6871 const sal_uInt32 nMinValidStshi
= 4;
6873 if (m_rFib
.GetFIBVersion() <= ww::eWW2
)
6880 if (m_rFib
.m_nFib
< 67) // old Version ? (need to find this again to fix)
6881 cbStshi
= nMinValidStshi
;
6884 if (nRemaining
< sizeof(cbStshi
))
6886 // reads the length of the structure in the file
6887 m_rStream
.ReadUInt16( cbStshi
);
6892 cbStshi
= std::min(static_cast<sal_uInt32
>(cbStshi
), nRemaining
);
6893 if (cbStshi
< nMinValidStshi
)
6896 const sal_uInt16 nRead
= cbStshi
;
6899 m_rStream
.ReadUInt16( m_cstd
);
6901 m_rStream
.ReadUInt16( m_cbSTDBaseInFile
);
6903 if( 6 > nRead
) break;
6906 m_rStream
.ReadUInt16( a16Bit
);
6907 m_fStdStylenamesWritten
= a16Bit
& 0x0001;
6909 if( 8 > nRead
) break;
6910 m_rStream
.ReadUInt16( m_stiMaxWhenSaved
);
6912 if( 10 > nRead
) break;
6913 m_rStream
.ReadUInt16( m_istdMaxFixedWhenSaved
);
6915 if( 12 > nRead
) break;
6916 m_rStream
.ReadUInt16( m_nVerBuiltInNamesWhenSaved
);
6918 if( 14 > nRead
) break;
6919 m_rStream
.ReadUInt16( m_ftcAsci
);
6921 if( 16 > nRead
) break;
6922 m_rStream
.ReadUInt16( m_ftcFE
);
6924 if ( 18 > nRead
) break;
6925 m_rStream
.ReadUInt16( m_ftcOther
);
6927 m_ftcBi
= m_ftcOther
;
6929 if ( 20 > nRead
) break;
6930 m_rStream
.ReadUInt16( m_ftcBi
);
6932 // p.r.n. ignore the rest
6934 m_rStream
.SeekRel( nRead
-20 );
6936 while( false ); // trick: the block above will be passed through exactly one time
6937 // and that's why we can early exit with "break".
6939 nRemaining
-= cbStshi
;
6941 //There will be stshi.cstd (cbSTD, STD) pairs in the file following the
6942 //STSHI. Note that styles can be empty, i.e. cbSTD == 0
6943 const sal_uInt32 nMinRecordSize
= sizeof(sal_uInt16
);
6944 const sal_uInt16 nMaxPossibleRecords
= nRemaining
/nMinRecordSize
;
6946 OSL_ENSURE(m_cstd
<= nMaxPossibleRecords
,
6947 "allegedly more styles that available data");
6948 m_cstd
= o3tl::sanitizing_min(m_cstd
, nMaxPossibleRecords
);
6951 // Read1STDFixed() reads a style. If the style is completely existent,
6952 // so it has no empty slot, we should allocate memory and a pointer should
6953 // reference to STD (perhaps filled with 0). If the slot is empty,
6954 // it will return a null pointer.
6955 std::unique_ptr
<WW8_STD
> WW8Style::Read1STDFixed(sal_uInt16
& rSkip
)
6957 if (m_rStream
.remainingSize() < 2)
6963 std::unique_ptr
<WW8_STD
> pStd
;
6965 sal_uInt16
cbStd(0);
6966 m_rStream
.ReadUInt16(cbStd
); // read length
6968 if( cbStd
>= m_cbSTDBaseInFile
)
6970 // Fixed part completely available
6972 // read fixed part of STD
6973 pStd
.reset(new WW8_STD
);
6974 memset( pStd
.get(), 0, sizeof( *pStd
) );
6978 if( 2 > m_cbSTDBaseInFile
) break;
6980 sal_uInt16 a16Bit
= 0;
6981 m_rStream
.ReadUInt16( a16Bit
);
6982 pStd
->sti
= a16Bit
& 0x0fff ;
6983 pStd
->fScratch
= sal_uInt16(0 != ( a16Bit
& 0x1000 ));
6984 pStd
->fInvalHeight
= sal_uInt16(0 != ( a16Bit
& 0x2000 ));
6985 pStd
->fHasUpe
= sal_uInt16(0 != ( a16Bit
& 0x4000 ));
6986 pStd
->fMassCopy
= sal_uInt16(0 != ( a16Bit
& 0x8000 ));
6988 if( 4 > m_cbSTDBaseInFile
) break;
6990 m_rStream
.ReadUInt16( a16Bit
);
6991 pStd
->sgc
= a16Bit
& 0x000f ;
6992 pStd
->istdBase
= ( a16Bit
& 0xfff0 ) >> 4;
6994 if( 6 > m_cbSTDBaseInFile
) break;
6996 m_rStream
.ReadUInt16( a16Bit
);
6997 pStd
->cupx
= a16Bit
& 0x000f ;
6998 pStd
->istdNext
= ( a16Bit
& 0xfff0 ) >> 4;
7000 if( 8 > m_cbSTDBaseInFile
) break;
7001 m_rStream
.ReadUInt16( pStd
->bchUpe
);
7003 // from Ver8 this two fields should be added:
7004 if (10 > m_cbSTDBaseInFile
) break;
7006 m_rStream
.ReadUInt16( a16Bit
);
7007 pStd
->fAutoRedef
= a16Bit
& 0x0001 ;
7008 pStd
->fHidden
= ( a16Bit
& 0x0002 ) >> 1;
7009 // You never know: cautionary skipped
7010 if (m_cbSTDBaseInFile
> 10)
7012 auto nSkip
= std::min
<sal_uInt64
>(m_cbSTDBaseInFile
- 10, m_rStream
.remainingSize());
7013 m_rStream
.Seek(m_rStream
.Tell() + nSkip
);
7016 while( false ); // trick: the block above will passed through exactly one time
7017 // and can be left early with a "break"
7019 if (!m_rStream
.good() || !m_cbSTDBaseInFile
)
7021 pStd
.reset(); // report error with NULL
7024 rSkip
= cbStd
- m_cbSTDBaseInFile
;
7027 { // Fixed part too short
7029 m_rStream
.SeekRel( cbStd
); // skip leftovers
7035 std::unique_ptr
<WW8_STD
> WW8Style::Read1Style(sal_uInt16
& rSkip
, OUString
* pString
)
7037 // Attention: MacWord-Documents have their Stylenames
7038 // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
7040 std::unique_ptr
<WW8_STD
> pStd
= Read1STDFixed(rSkip
); // read STD
7047 sal_Int32 nLenStringBytes
= 0;
7048 switch( m_rFib
.m_nVersion
)
7052 // read pascal string
7053 *pString
= read_uInt8_BeltAndBracesString(m_rStream
, RTL_TEXTENCODING_MS_1252
);
7054 // leading len and trailing zero --> 2
7055 nLenStringBytes
= pString
->getLength() + 2;
7058 // handle Unicode-String with leading length short and
7060 if (TestBeltAndBraces(m_rStream
))
7062 *pString
= read_uInt16_BeltAndBracesString(m_rStream
);
7063 nLenStringBytes
= (pString
->getLength() + 2) * 2;
7069 This is supposed to be impossible, it's just supposed
7070 to be 16 bit count followed by the string and ending
7071 in a 0 short. But "Lotus SmartSuite Product: Word Pro"
7072 is creating invalid style names in ww7- format. So we
7073 use the belt and braces of the ms strings to see if
7074 they are not corrupt. If they are then we try them as
7077 *pString
= read_uInt8_BeltAndBracesString(m_rStream
,RTL_TEXTENCODING_MS_1252
);
7078 // leading len and trailing zero --> 2
7079 nLenStringBytes
= pString
->getLength() + 2;
7083 OSL_ENSURE(false, "It was forgotten to code nVersion!");
7086 if (nLenStringBytes
> rSkip
)
7088 SAL_WARN("sw.ww8", "WW8Style structure corrupt");
7089 nLenStringBytes
= rSkip
;
7091 rSkip
-= nLenStringBytes
;
7094 pString
->clear(); // can not return a name
7100 const sal_uInt16 maxStrSize
= 65;
7106 char szFfn
[maxStrSize
]; // 0x6 or 0x40 from Ver8 on zero terminated string that
7107 // records name of font.
7108 // Maximal size of szFfn is 65 characters.
7109 // Attention: This array can also be smaller!!!
7110 // Possibly followed by a second sz which records the
7111 // name of an alternate font to use if the first named
7112 // font does not exist on this system.
7117 // #i43762# check font name for illegal characters
7118 static void lcl_checkFontname( OUString
& sString
)
7120 // for efficiency, we'd like to use String methods as far as possible.
7122 // 1) convert all invalid chars to \u0001
7123 // 2) then erase all \u0001 chars (if anywhere found), and
7124 // 3) erase leading/trailing ';', in case a font name was
7125 // completely removed
7127 // convert all invalid chars to \u0001
7128 OUStringBuffer
aBuf(sString
);
7129 const sal_Int32 nLen
= aBuf
.getLength();
7130 bool bFound
= false;
7131 for ( sal_Int32 n
= 0; n
< nLen
; ++n
)
7133 if ( aBuf
[n
] < 0x20 )
7139 sString
= aBuf
.makeStringAndClear();
7141 // if anything was found, remove \u0001 + leading/trailing ';'
7144 sString
= comphelper::string::strip(sString
.replaceAll("\001", ""), ';');
7150 sal_uInt16
calcMaxFonts(sal_uInt8
*p
, sal_Int32 nFFn
)
7152 // Figure out the max number of fonts defined here
7153 sal_uInt16 nMax
= 0;
7154 sal_Int32 nRemaining
= nFFn
;
7157 //p[0] is cbFfnM1, the alleged total length of FFN - 1.
7158 //i.e. length after cbFfnM1
7159 const sal_uInt16 cbFfnM1
= *p
++;
7162 if (cbFfnM1
> nRemaining
)
7166 nRemaining
-= cbFfnM1
;
7172 template<typename T
> bool readU8(
7173 sal_uInt8
const * p
, std::size_t offset
, sal_uInt8
const * pEnd
,
7177 assert(value
!= nullptr);
7178 if (offset
>= o3tl::make_unsigned(pEnd
- p
)) {
7186 sal_uInt8
const * p
, std::size_t offset
, sal_uInt8
const * pEnd
,
7190 assert(value
!= nullptr);
7191 if (offset
> o3tl::make_unsigned(pEnd
- p
)
7192 || static_cast<std::size_t>(pEnd
- p
) - offset
< 2)
7196 *value
= unsigned(p
[offset
]) + (unsigned(p
[offset
+ 1]) << 8);
7200 sal_Int32
getStringLengthWithMax(
7201 sal_uInt8
const * p
, std::size_t offset
, sal_uInt8
const * pEnd
, std::size_t maxchars
)
7204 assert(pEnd
- p
<= SAL_MAX_INT32
);
7205 if (offset
>= o3tl::make_unsigned(pEnd
- p
)) {
7208 std::size_t nbytes
= static_cast<std::size_t>(pEnd
- p
) - offset
;
7209 std::size_t nsearch
= std::min(nbytes
, maxchars
+ 1);
7210 void const * p2
= std::memchr(p
+ offset
, 0, nsearch
);
7211 if (p2
== nullptr) {
7214 return static_cast<sal_uInt8
const *>(p2
) - (p
+ offset
);
7218 WW8Fonts::WW8Fonts( SvStream
& rSt
, WW8Fib
const & rFib
)
7220 // Attention: MacWord-Documents have their Fontnames
7221 // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
7222 if( rFib
.m_lcbSttbfffn
<= 2 )
7224 OSL_ENSURE( false, "font table is broken! (rFib.lcbSttbfffn < 2)" );
7228 if (!checkSeek(rSt
, rFib
.m_fcSttbfffn
))
7231 sal_Int32 nFFn
= rFib
.m_lcbSttbfffn
- 2;
7233 const sal_uInt64 nMaxPossible
= rSt
.remainingSize();
7234 if (o3tl::make_unsigned(nFFn
) > nMaxPossible
)
7236 SAL_WARN("sw.ww8", "FFN structure longer than available data");
7237 nFFn
= nMaxPossible
;
7240 // allocate Font Array
7241 std::vector
<sal_uInt8
> aA(nFFn
);
7242 memset(aA
.data(), 0, nFFn
);
7244 ww::WordVersion eVersion
= rFib
.GetFIBVersion();
7247 if( eVersion
>= ww::eWW8
)
7249 // bVer8: read the count of strings in nMax
7250 rSt
.ReadUInt16(nMax
);
7253 // Ver8: skip undefined uint16
7254 // Ver67: skip the herein stored total byte of structure
7255 // - we already got that information in rFib.lcbSttbfffn
7258 // read all font information
7259 nFFn
= rSt
.ReadBytes(aA
.data(), nFFn
);
7260 sal_uInt8
* const pEnd
= aA
.data() + nFFn
;
7261 const sal_uInt16 nCalcMax
= calcMaxFonts(aA
.data(), nFFn
);
7263 if (eVersion
< ww::eWW8
)
7267 //newer versions include supportive count of fonts, so take min of that
7269 nMax
= std::min(nMax
, nCalcMax
);
7274 // allocate Index Array
7275 m_aFontA
.resize(nMax
);
7276 WW8_FFN
* p
= m_aFontA
.data();
7278 if( eVersion
<= ww::eWW2
)
7280 sal_uInt8
const * pVer2
= aA
.data();
7282 for(; i
<nMax
; ++i
, ++p
)
7285 pVer2
, offsetof(WW8_FFN_BASE
, cbFfnM1
), pEnd
,
7286 &p
->aFFNBase
.cbFfnM1
))
7291 p
->aFFNBase
.prg
= 0;
7292 p
->aFFNBase
.fTrueType
= 0;
7295 if (!(readU8(pVer2
, 1, pEnd
, &p
->aFFNBase
.wWeight
)
7296 && readU8(pVer2
, 2, pEnd
, &p
->aFFNBase
.chs
)))
7301 #i8726# 7- seems to encode the name in the same encoding as
7302 the font, e.g load the doc in 97 and save to see the unicode
7303 ver of the asian fontnames in that example to confirm.
7305 rtl_TextEncoding eEnc
= WW8Fib::GetFIBCharset(p
->aFFNBase
.chs
, rFib
.m_lid
);
7306 if ((eEnc
== RTL_TEXTENCODING_SYMBOL
) || (eEnc
== RTL_TEXTENCODING_DONTKNOW
))
7307 eEnc
= RTL_TEXTENCODING_MS_1252
;
7309 const size_t nStringOffset
= 1 + 2;
7310 sal_Int32 n
= getStringLengthWithMax(pVer2
, nStringOffset
, pEnd
, maxStrSize
);
7314 p
->sFontname
= OUString(
7315 reinterpret_cast<char const *>(pVer2
+ nStringOffset
), n
, eEnc
);
7316 pVer2
= pVer2
+ p
->aFFNBase
.cbFfnM1
+ 1;
7320 else if( eVersion
< ww::eWW8
)
7322 sal_uInt8
const * pVer6
= aA
.data();
7324 for(; i
<nMax
; ++i
, ++p
)
7327 pVer6
, offsetof(WW8_FFN_BASE
, cbFfnM1
), pEnd
,
7328 &p
->aFFNBase
.cbFfnM1
))
7333 if (!readU8(pVer6
, 1, pEnd
, &c2
)) {
7337 p
->aFFNBase
.prg
= c2
& 0x02;
7338 p
->aFFNBase
.fTrueType
= (c2
& 0x04) >> 2;
7339 // skip a reserve bit
7340 p
->aFFNBase
.ff
= (c2
& 0x70) >> 4;
7343 pVer6
, offsetof(WW8_FFN_BASE
, wWeight
), pEnd
,
7344 &p
->aFFNBase
.wWeight
)
7346 pVer6
, offsetof(WW8_FFN_BASE
, chs
), pEnd
, &p
->aFFNBase
.chs
)
7348 pVer6
, offsetof(WW8_FFN_BASE
, ibszAlt
), pEnd
,
7349 &p
->aFFNBase
.ibszAlt
)))
7354 #i8726# 7- seems to encode the name in the same encoding as
7355 the font, e.g load the doc in 97 and save to see the unicode
7356 ver of the asian fontnames in that example to confirm.
7358 rtl_TextEncoding eEnc
= WW8Fib::GetFIBCharset(p
->aFFNBase
.chs
, rFib
.m_lid
);
7359 if ((eEnc
== RTL_TEXTENCODING_SYMBOL
) || (eEnc
== RTL_TEXTENCODING_DONTKNOW
))
7360 eEnc
= RTL_TEXTENCODING_MS_1252
;
7361 const size_t nStringOffset
= offsetof(WW8_FFN_Ver6
, szFfn
);
7362 sal_Int32 n
= getStringLengthWithMax(pVer6
, nStringOffset
, pEnd
, maxStrSize
);
7366 p
->sFontname
= OUString(reinterpret_cast<char const*>(pVer6
+ nStringOffset
), n
, eEnc
);
7367 if (p
->aFFNBase
.ibszAlt
&& p
->aFFNBase
.ibszAlt
< maxStrSize
) //don't start after end of string
7369 const size_t nAltStringOffset
= offsetof(WW8_FFN_Ver6
, szFfn
) + p
->aFFNBase
.ibszAlt
;
7370 n
= getStringLengthWithMax(pVer6
, nAltStringOffset
, pEnd
, maxStrSize
);
7374 p
->sFontname
+= ";" + OUString(reinterpret_cast<char const*>(pVer6
+ nAltStringOffset
),
7379 //#i18369# if it's a symbol font set Symbol as fallback
7381 RTL_TEXTENCODING_SYMBOL
== WW8Fib::GetFIBCharset(p
->aFFNBase
.chs
, rFib
.m_lid
)
7382 && p
->sFontname
!="Symbol"
7385 p
->sFontname
+= ";Symbol";
7388 pVer6
= pVer6
+ p
->aFFNBase
.cbFfnM1
+ 1;
7394 //count of bytes in minimum FontFamilyInformation payload
7395 const sal_uInt8 cbMinFFNPayload
= 41;
7396 sal_uInt16 nValidFonts
= 0;
7397 sal_Int32 nRemainingFFn
= nFFn
;
7398 sal_uInt8
* pRaw
= aA
.data();
7399 for (sal_uInt16 i
=0; i
< nMax
&& nRemainingFFn
; ++i
, ++p
)
7401 //pRaw[0] is cbFfnM1, the alleged total length of FFN - 1
7402 //i.e. length after cbFfnM1
7403 sal_uInt8 cbFfnM1
= *pRaw
++;
7406 if (cbFfnM1
> nRemainingFFn
)
7409 if (cbFfnM1
< cbMinFFNPayload
)
7412 p
->aFFNBase
.cbFfnM1
= cbFfnM1
;
7414 sal_uInt8
*pVer8
= pRaw
;
7416 sal_uInt8 c2
= *pVer8
++;
7419 p
->aFFNBase
.prg
= c2
& 0x02;
7420 p
->aFFNBase
.fTrueType
= (c2
& 0x04) >> 2;
7421 // skip a reserve bit
7422 p
->aFFNBase
.ff
= (c2
& 0x70) >> 4;
7424 p
->aFFNBase
.wWeight
= SVBT16ToUInt16(*reinterpret_cast<SVBT16
*>(pVer8
));
7428 p
->aFFNBase
.chs
= *pVer8
++;
7431 p
->aFFNBase
.ibszAlt
= *pVer8
++;
7434 pVer8
+= 10; //PANOSE
7436 pVer8
+= 24; //FONTSIGNATURE
7439 assert(cbFfnM1
>= 2);
7441 sal_uInt8 nMaxNullTerminatedPossible
= cbFfnM1
/2 - 1;
7442 sal_Unicode
*pPrimary
= reinterpret_cast<sal_Unicode
*>(pVer8
);
7443 pPrimary
[nMaxNullTerminatedPossible
] = 0;
7444 #ifdef OSL_BIGENDIAN
7445 swapEndian(pPrimary
);
7447 p
->sFontname
= pPrimary
;
7448 if (p
->aFFNBase
.ibszAlt
&& p
->aFFNBase
.ibszAlt
< nMaxNullTerminatedPossible
)
7450 sal_Unicode
*pSecondary
= pPrimary
+ p
->aFFNBase
.ibszAlt
;
7451 #ifdef OSL_BIGENDIAN
7452 swapEndian(pSecondary
);
7454 p
->sFontname
+= OUString::Concat(";") + pSecondary
;
7457 // #i43762# check font name for illegal characters
7458 lcl_checkFontname( p
->sFontname
);
7460 // set pointer one font back to original array
7461 pRaw
+= p
->aFFNBase
.cbFfnM1
;
7462 nRemainingFFn
-= p
->aFFNBase
.cbFfnM1
;
7465 OSL_ENSURE(nMax
== nValidFonts
, "Font count differs with availability");
7466 nMax
= std::min(nMax
, nValidFonts
);
7469 m_aFontA
.resize(nMax
);
7470 m_aFontA
.shrink_to_fit();
7473 const WW8_FFN
* WW8Fonts::GetFont( sal_uInt16 nNum
) const
7475 if (nNum
>= m_aFontA
.size())
7478 return &m_aFontA
[nNum
];
7481 // Search after a header/footer for an index in the ww list from header/footer
7483 // specials for WinWord6 and -7:
7485 // 1) At the start of reading we must build WWPLCF_HdFt with Fib and Dop
7486 // 2) The main text must be read sequentially over all sections
7487 // 3) For every header/footer in the main text, we must call UpdateIndex()
7488 // exactly once with the parameter from the attribute.
7489 // (per section can be maximally one). This call must take place *after*
7490 // the last call from GetTextPos().
7491 // 4) GetTextPos() can be called with exactly one flag
7492 // out of WW8_{FOOTER,HEADER}_{ODD,EVEN,FIRST} (Do not change!)
7493 // -> maybe we can get a right result then
7495 WW8PLCF_HdFt::WW8PLCF_HdFt( SvStream
* pSt
, WW8Fib
const & rFib
, WW8Dop
const & rDop
)
7496 : m_aPLCF(*pSt
, rFib
.m_fcPlcfhdd
, rFib
.m_lcbPlcfhdd
, 0)
7501 This dop.grpfIhdt has a bit set for each special
7502 footnote *and endnote!!* separator,continuation separator, and
7503 continuation notice entry, the documentation does not mention the
7504 endnote separators, the documentation also gets the index numbers
7505 backwards when specifying which bits to test. The bottom six bits
7506 of this value must be tested and skipped over. Each section's
7507 grpfIhdt is then tested for the existence of the appropriate headers
7508 and footers, at the end of each section the nIdxOffset must be updated
7509 to point to the beginning of the next section's group of headers and
7510 footers in this PLCF, UpdateIndex does that task.
7512 for( sal_uInt8 nI
= 0x1; nI
<= 0x20; nI
<<= 1 )
7513 if( nI
& rDop
.grpfIhdt
) // bit set?
7517 bool WW8PLCF_HdFt::GetTextPos(sal_uInt8 grpfIhdt
, sal_uInt8 nWhich
, WW8_CP
& rStart
,
7520 sal_uInt8 nI
= 0x01;
7521 short nIdx
= m_nIdxOffset
;
7527 nIdx
++; // uninteresting Header / Footer
7528 nI
<<= 1; // text next bit
7530 return false; // not found
7532 // nIdx is HdFt-Index
7536 m_aPLCF
.SetIdx( nIdx
); // Lookup suitable CP
7537 m_aPLCF
.Get( rStart
, nEnd
, pData
);
7540 SAL_WARN("sw.ww8", "End " << nEnd
<< " before Start " << rStart
);
7544 bool bFail
= o3tl::checked_sub(nEnd
, rStart
, rLen
);
7547 SAL_WARN("sw.ww8", "broken offset, ignoring");
7556 void WW8PLCF_HdFt::GetTextPosExact(short nIdx
, WW8_CP
& rStart
, WW8_CP
& rLen
)
7561 m_aPLCF
.SetIdx( nIdx
); // Lookup suitable CP
7562 m_aPLCF
.Get( rStart
, nEnd
, pData
);
7565 SAL_WARN("sw.ww8", "End " << nEnd
<< " before Start " << rStart
);
7569 if (o3tl::checked_sub(nEnd
, rStart
, rLen
))
7571 SAL_WARN("sw.ww8", "GetTextPosExact overflow");
7576 void WW8PLCF_HdFt::UpdateIndex( sal_uInt8 grpfIhdt
)
7578 // Caution: Description is not correct
7579 for( sal_uInt8 nI
= 0x01; nI
<= 0x20; nI
<<= 1 )
7584 WW8Dop::WW8Dop(SvStream
& rSt
, sal_Int16 nFib
, sal_Int32 nPos
, sal_uInt32 nSize
):
7585 fFacingPages(false), fWidowControl(false), fPMHMainDoc(false), grfSuppression(0), fpc(0),
7586 grpfIhdt(0), rncFootnote(0), nFootnote(0), fOutlineDirtySave(false), fOnlyMacPics(false),
7587 fOnlyWinPics(false), fLabelDoc(false), fHyphCapitals(false), fAutoHyphen(false),
7588 fFormNoFields(false), fLinkStyles(false), fRevMarking(false), fBackup(false),
7589 fExactCWords(false), fPagHidden(false), fPagResults(false), fLockAtn(false),
7590 fMirrorMargins(false), fReadOnlyRecommended(false), fDfltTrueType(false),
7591 fPagSuppressTopSpacing(false), fProtEnabled(false), fDispFormFieldSel(false), fRMView(false),
7592 fRMPrint(false), fWriteReservation(false), fLockRev(false), fEmbedFonts(false),
7593 copts_fNoTabForInd(false), copts_fNoSpaceRaiseLower(false), copts_fSuppressSpbfAfterPgBrk(false),
7594 copts_fWrapTrailSpaces(false), copts_fMapPrintTextColor(false), copts_fNoColumnBalance(false),
7595 copts_fConvMailMergeEsc(false), copts_fSuppressTopSpacing(false),
7596 copts_fOrigWordTableRules(false), copts_fTransparentMetafiles(false),
7597 copts_fShowBreaksInFrames(false), copts_fSwapBordersFacingPgs(false), copts_fExpShRtn(false),
7598 rncEdn(0), nEdn(0), epc(0), fPrintFormData(false), fSaveFormData(false), fShadeFormData(false),
7599 fWCFootnoteEdn(false), wvkSaved(0), wScaleSaved(0), zkSaved(0), fRotateFontW6(false),
7600 iGutterPos(false), fNoTabForInd(false), fNoSpaceRaiseLower(false),
7601 fSuppressSpbfAfterPageBreak(false), fWrapTrailSpaces(false), fMapPrintTextColor(false),
7602 fNoColumnBalance(false), fConvMailMergeEsc(false), fSuppressTopSpacing(false),
7603 fOrigWordTableRules(false), fTransparentMetafiles(false), fShowBreaksInFrames(false),
7604 fSwapBordersFacingPgs(false), fCompatibilityOptions_Unknown1_13(false), fExpShRtn(false),
7605 fCompatibilityOptions_Unknown1_15(false), fCompatibilityOptions_Unknown1_16(false),
7606 fSuppressTopSpacingMac5(false), fTruncDxaExpand(false), fPrintBodyBeforeHdr(false),
7607 fNoLeading(false), fCompatibilityOptions_Unknown1_21(false), fMWSmallCaps(false),
7608 fCompatibilityOptions_Unknown1_23(false), fCompatibilityOptions_Unknown1_24(false),
7609 fCompatibilityOptions_Unknown1_25(false), fCompatibilityOptions_Unknown1_26(false),
7610 fCompatibilityOptions_Unknown1_27(false), fCompatibilityOptions_Unknown1_28(false),
7611 fCompatibilityOptions_Unknown1_29(false), fCompatibilityOptions_Unknown1_30(false),
7612 fCompatibilityOptions_Unknown1_31(false), fUsePrinterMetrics(false), lvl(0), fHtmlDoc(false),
7613 fSnapBorder(false), fIncludeHeader(false), fIncludeFooter(false), fForcePageSizePag(false),
7614 fMinFontSizePag(false), fHaveVersions(false), fAutoVersion(false),
7615 fCompatibilityOptions_Unknown2_1(false), fCompatibilityOptions_Unknown2_2(false),
7616 fDontUseHTMLAutoSpacing(false), fCompatibilityOptions_Unknown2_4(false),
7617 fCompatibilityOptions_Unknown2_5(false), fCompatibilityOptions_Unknown2_6(false),
7618 fCompatibilityOptions_Unknown2_7(false), fCompatibilityOptions_Unknown2_8(false),
7619 fCompatibilityOptions_Unknown2_9(false), fCompatibilityOptions_Unknown2_10(false),
7620 fDontBreakWrappedTables(false), fCompatibilityOptions_Unknown2_12(false),
7621 fCompatibilityOptions_Unknown2_13(false), fCompatibilityOptions_Unknown2_14(false),
7622 fCompatibilityOptions_Unknown2_15(false), fCompatibilityOptions_Unknown2_16(false),
7623 fCompatibilityOptions_Unknown2_17(false), fCompatibilityOptions_Unknown2_18(false),
7624 fCompatibilityOptions_Unknown2_19(false), fCompatibilityOptions_Unknown2_20(false),
7625 fCompatibilityOptions_Unknown2_21(false), fCompatibilityOptions_Unknown2_22(false),
7626 fCompatibilityOptions_Unknown2_23(false), fCompatibilityOptions_Unknown2_24(false),
7627 fCompatibilityOptions_Unknown2_25(false), fCompatibilityOptions_Unknown2_26(false),
7628 fCompatibilityOptions_Unknown2_27(false), fCompatibilityOptions_Unknown2_28(false),
7629 fCompatibilityOptions_Unknown2_29(false), fCompatibilityOptions_Unknown2_30(false),
7630 fCompatibilityOptions_Unknown2_31(false), fCompatibilityOptions_Unknown2_32(false),
7631 fUnknown3(0), fUseBackGroundInAllmodes(false), fDoNotEmbedSystemFont(false), fWordCompat(false),
7632 fLiveRecover(false), fEmbedFactoids(false), fFactoidXML(false), fFactoidAllDone(false),
7633 fFolioPrint(false), fReverseFolio(false), iTextLineEnding(0), fHideFcc(false),
7634 fAcetateShowMarkup(false), fAcetateShowAtn(false), fAcetateShowInsDel(false),
7635 fAcetateShowProps(false)
7636 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
7637 // above bit-field member initializations can be moved to the class definition
7639 fDontUseHTMLAutoSpacing
= true; //default
7640 fAcetateShowAtn
= true; //default
7641 const sal_uInt32 nMaxDopSize
= 0x268;
7642 std::unique_ptr
<sal_uInt8
[]> pDataPtr( new sal_uInt8
[ nMaxDopSize
] );
7643 sal_uInt8
* pData
= pDataPtr
.get();
7645 sal_uInt32 nRead
= std::min(nMaxDopSize
, nSize
);
7646 if (nSize
< 2 || !checkSeek(rSt
, nPos
) || nRead
!= rSt
.ReadBytes(pData
, nRead
))
7647 nDopError
= ERR_SWG_READ_ERROR
; // report error
7650 if (nMaxDopSize
> nRead
)
7651 memset( pData
+ nRead
, 0, nMaxDopSize
- nRead
);
7653 // interpret the data
7658 a16Bit
= Get_UShort( pData
); // 0 0x00
7659 fFacingPages
= 0 != ( a16Bit
& 0x0001 ) ;
7660 fWidowControl
= 0 != ( a16Bit
& 0x0002 ) ;
7661 fPMHMainDoc
= 0 != ( a16Bit
& 0x0004 ) ;
7662 grfSuppression
= ( a16Bit
& 0x0018 ) >> 3;
7663 fpc
= ( a16Bit
& 0x0060 ) >> 5;
7664 grpfIhdt
= ( a16Bit
& 0xff00 ) >> 8;
7666 a16Bit
= Get_UShort( pData
); // 2 0x02
7667 rncFootnote
= a16Bit
& 0x0003 ;
7668 nFootnote
= ( a16Bit
& ~0x0003 ) >> 2 ;
7670 a8Bit
= Get_Byte( pData
); // 4 0x04
7671 fOutlineDirtySave
= 0 != ( a8Bit
& 0x01 );
7673 a8Bit
= Get_Byte( pData
); // 5 0x05
7674 fOnlyMacPics
= 0 != ( a8Bit
& 0x01 );
7675 fOnlyWinPics
= 0 != ( a8Bit
& 0x02 );
7676 fLabelDoc
= 0 != ( a8Bit
& 0x04 );
7677 fHyphCapitals
= 0 != ( a8Bit
& 0x08 );
7678 fAutoHyphen
= 0 != ( a8Bit
& 0x10 );
7679 fFormNoFields
= 0 != ( a8Bit
& 0x20 );
7680 fLinkStyles
= 0 != ( a8Bit
& 0x40 );
7681 fRevMarking
= 0 != ( a8Bit
& 0x80 );
7683 a8Bit
= Get_Byte( pData
); // 6 0x06
7684 fBackup
= 0 != ( a8Bit
& 0x01 );
7685 fExactCWords
= 0 != ( a8Bit
& 0x02 );
7686 fPagHidden
= 0 != ( a8Bit
& 0x04 );
7687 fPagResults
= 0 != ( a8Bit
& 0x08 );
7688 fLockAtn
= 0 != ( a8Bit
& 0x10 );
7689 fMirrorMargins
= 0 != ( a8Bit
& 0x20 );
7690 fReadOnlyRecommended
= 0 != ( a8Bit
& 0x40 );
7691 fDfltTrueType
= 0 != ( a8Bit
& 0x80 );
7693 a8Bit
= Get_Byte( pData
); // 7 0x07
7694 fPagSuppressTopSpacing
= 0 != ( a8Bit
& 0x01 );
7695 fProtEnabled
= 0 != ( a8Bit
& 0x02 );
7696 fDispFormFieldSel
= 0 != ( a8Bit
& 0x04 );
7697 fRMView
= 0 != ( a8Bit
& 0x08 );
7698 fRMPrint
= 0 != ( a8Bit
& 0x10 );
7699 fWriteReservation
= 0 != ( a8Bit
& 0x20 );
7700 fLockRev
= 0 != ( a8Bit
& 0x40 );
7701 fEmbedFonts
= 0 != ( a8Bit
& 0x80 );
7703 a8Bit
= Get_Byte( pData
); // 8 0x08
7704 copts_fNoTabForInd
= 0 != ( a8Bit
& 0x01 );
7705 copts_fNoSpaceRaiseLower
= 0 != ( a8Bit
& 0x02 );
7706 copts_fSuppressSpbfAfterPgBrk
= 0 != ( a8Bit
& 0x04 );
7707 copts_fWrapTrailSpaces
= 0 != ( a8Bit
& 0x08 );
7708 copts_fMapPrintTextColor
= 0 != ( a8Bit
& 0x10 );
7709 copts_fNoColumnBalance
= 0 != ( a8Bit
& 0x20 );
7710 copts_fConvMailMergeEsc
= 0 != ( a8Bit
& 0x40 );
7711 copts_fSuppressTopSpacing
= 0 != ( a8Bit
& 0x80 );
7713 a8Bit
= Get_Byte( pData
); // 9 0x09
7714 copts_fOrigWordTableRules
= 0 != ( a8Bit
& 0x01 );
7715 copts_fTransparentMetafiles
= 0 != ( a8Bit
& 0x02 );
7716 copts_fShowBreaksInFrames
= 0 != ( a8Bit
& 0x04 );
7717 copts_fSwapBordersFacingPgs
= 0 != ( a8Bit
& 0x08 );
7718 copts_fExpShRtn
= 0 != ( a8Bit
& 0x20 ); // #i56856#
7720 dxaTab
= Get_Short( pData
); // 10 0x0a
7721 wSpare
= Get_UShort( pData
); // 12 0x0c
7722 dxaHotZ
= Get_UShort( pData
); // 14 0x0e
7723 cConsecHypLim
= Get_UShort( pData
); // 16 0x10
7724 wSpare2
= Get_UShort( pData
); // 18 0x12
7725 dttmCreated
= Get_Long( pData
); // 20 0x14
7726 dttmRevised
= Get_Long( pData
); // 24 0x18
7727 dttmLastPrint
= Get_Long( pData
); // 28 0x1c
7728 nRevision
= Get_Short( pData
); // 32 0x20
7729 tmEdited
= Get_Long( pData
); // 34 0x22
7730 cWords
= Get_Long( pData
); // 38 0x26
7731 cCh
= Get_Long( pData
); // 42 0x2a
7732 cPg
= Get_Short( pData
); // 46 0x2e
7733 cParas
= Get_Long( pData
); // 48 0x30
7735 a16Bit
= Get_UShort( pData
); // 52 0x34
7736 rncEdn
= a16Bit
& 0x0003 ;
7737 nEdn
= ( a16Bit
& ~0x0003 ) >> 2;
7739 a16Bit
= Get_UShort( pData
); // 54 0x36
7740 epc
= a16Bit
& 0x0003 ;
7741 nfcFootnoteRef
= ( a16Bit
& 0x003c ) >> 2;
7742 nfcEdnRef
= ( a16Bit
& 0x03c0 ) >> 6;
7743 fPrintFormData
= 0 != ( a16Bit
& 0x0400 );
7744 fSaveFormData
= 0 != ( a16Bit
& 0x0800 );
7745 fShadeFormData
= 0 != ( a16Bit
& 0x1000 );
7746 fWCFootnoteEdn
= 0 != ( a16Bit
& 0x8000 );
7748 cLines
= Get_Long( pData
); // 56 0x38
7749 cWordsFootnoteEnd
= Get_Long( pData
); // 60 0x3c
7750 cChFootnoteEdn
= Get_Long( pData
); // 64 0x40
7751 cPgFootnoteEdn
= Get_Short( pData
); // 68 0x44
7752 cParasFootnoteEdn
= Get_Long( pData
); // 70 0x46
7753 cLinesFootnoteEdn
= Get_Long( pData
); // 74 0x4a
7754 lKeyProtDoc
= Get_Long( pData
); // 78 0x4e
7756 a16Bit
= Get_UShort( pData
); // 82 0x52
7757 wvkSaved
= a16Bit
& 0x0007 ;
7758 wScaleSaved
= ( a16Bit
& 0x0ff8 ) >> 3 ;
7759 zkSaved
= ( a16Bit
& 0x3000 ) >> 12;
7760 fRotateFontW6
= ( a16Bit
& 0x4000 ) >> 14;
7761 iGutterPos
= ( a16Bit
& 0x8000 ) >> 15;
7763 if (nFib
>= 103) // Word 6/32bit, 95, 97, 2000, 2002, 2003, 2007
7765 a32Bit
= Get_ULong( pData
); // 84 0x54
7766 SetCompatibilityOptions(a32Bit
);
7769 //#i22436#, for all WW7- documents
7770 if (nFib
<= 104) // Word 95
7771 fUsePrinterMetrics
= true;
7773 if (nFib
> 105) // Word 97, 2000, 2002, 2003, 2007
7775 adt
= Get_Short( pData
); // 88 0x58
7777 doptypography
.ReadFromMem(pData
); // 90 0x5a
7779 memcpy( &dogrid
, pData
, sizeof( WW8_DOGRID
)); // 400 0x190
7780 pData
+= sizeof( WW8_DOGRID
);
7782 a16Bit
= Get_UShort( pData
); // 410 0x19a
7783 // the following 9 bit are uninteresting
7784 fHtmlDoc
= ( a16Bit
& 0x0200 ) >> 9 ;
7785 fSnapBorder
= ( a16Bit
& 0x0800 ) >> 11 ;
7786 fIncludeHeader
= ( a16Bit
& 0x1000 ) >> 12 ;
7787 fIncludeFooter
= ( a16Bit
& 0x2000 ) >> 13 ;
7788 fForcePageSizePag
= ( a16Bit
& 0x4000 ) >> 14 ;
7789 fMinFontSizePag
= ( a16Bit
& 0x8000 ) >> 15 ;
7791 a16Bit
= Get_UShort( pData
); // 412 0x19c
7792 fHaveVersions
= 0 != ( a16Bit
& 0x0001 );
7793 fAutoVersion
= 0 != ( a16Bit
& 0x0002 );
7795 pData
+= 12; // 414 0x19e
7797 cChWS
= Get_Long( pData
); // 426 0x1aa
7798 cChWSFootnoteEdn
= Get_Long( pData
); // 430 0x1ae
7799 grfDocEvents
= Get_Long( pData
); // 434 0x1b2
7801 pData
+= 4+30+8; // 438 0x1b6; 442 0x1ba; 472 0x1d8; 476 0x1dc
7803 cDBC
= Get_Long( pData
); // 480 0x1e0
7804 cDBCFootnoteEdn
= Get_Long( pData
); // 484 0x1e4
7806 pData
+= 1 * sizeof( sal_Int32
); // 488 0x1e8
7808 nfcFootnoteRef
= Get_Short( pData
); // 492 0x1ec
7809 nfcEdnRef
= Get_Short( pData
); // 494 0x1ee
7810 hpsZoomFontPag
= Get_Short( pData
); // 496 0x1f0
7811 dywDispPag
= Get_Short( pData
); // 498 0x1f2
7815 //500 -> 508, Appear to be repeated here in 2000+
7816 pData
+= 8; // 500 0x1f4
7817 a32Bit
= Get_Long( pData
); // 508 0x1fc
7818 SetCompatibilityOptions(a32Bit
);
7819 a32Bit
= Get_Long( pData
); // 512 0x200
7822 SetCompatibilityOptions2(a32Bit
);
7827 a16Bit
= Get_UShort( pData
);
7828 fDoNotEmbedSystemFont
= ( a16Bit
& 0x0001 );
7829 fWordCompat
= ( a16Bit
& 0x0002 ) >> 1;
7830 fLiveRecover
= ( a16Bit
& 0x0004 ) >> 2;
7831 fEmbedFactoids
= ( a16Bit
& 0x0008 ) >> 3;
7832 fFactoidXML
= ( a16Bit
& 0x00010 ) >> 4;
7833 fFactoidAllDone
= ( a16Bit
& 0x0020 ) >> 5;
7834 fFolioPrint
= ( a16Bit
& 0x0040 ) >> 6;
7835 fReverseFolio
= ( a16Bit
& 0x0080 ) >> 7;
7836 iTextLineEnding
= ( a16Bit
& 0x0700 ) >> 8;
7837 fHideFcc
= ( a16Bit
& 0x0800 ) >> 11;
7838 fAcetateShowMarkup
= ( a16Bit
& 0x1000 ) >> 12;
7839 fAcetateShowAtn
= ( a16Bit
& 0x2000 ) >> 13;
7840 fAcetateShowInsDel
= ( a16Bit
& 0x4000 ) >> 14;
7841 fAcetateShowProps
= ( a16Bit
& 0x8000 ) >> 15;
7846 a16Bit
= Get_Short(pData
);
7847 fUseBackGroundInAllmodes
= (a16Bit
& 0x0080) >> 7;
7854 fFacingPages(false), fWidowControl(true), fPMHMainDoc(false), grfSuppression(0), fpc(1),
7855 grpfIhdt(0), rncFootnote(0), nFootnote(1), fOutlineDirtySave(true), fOnlyMacPics(false),
7856 fOnlyWinPics(false), fLabelDoc(false), fHyphCapitals(true), fAutoHyphen(false),
7857 fFormNoFields(false), fLinkStyles(false), fRevMarking(false), fBackup(true),
7858 fExactCWords(false), fPagHidden(true), fPagResults(true), fLockAtn(false),
7859 fMirrorMargins(false), fReadOnlyRecommended(false), fDfltTrueType(true),
7860 fPagSuppressTopSpacing(false), fProtEnabled(false), fDispFormFieldSel(false), fRMView(true),
7861 fRMPrint(true), fWriteReservation(false), fLockRev(false), fEmbedFonts(false),
7862 copts_fNoTabForInd(false), copts_fNoSpaceRaiseLower(false), copts_fSuppressSpbfAfterPgBrk(false),
7863 copts_fWrapTrailSpaces(false), copts_fMapPrintTextColor(false), copts_fNoColumnBalance(false),
7864 copts_fConvMailMergeEsc(false), copts_fSuppressTopSpacing(false),
7865 copts_fOrigWordTableRules(false), copts_fTransparentMetafiles(false),
7866 copts_fShowBreaksInFrames(false), copts_fSwapBordersFacingPgs(false), copts_fExpShRtn(false),
7867 dxaTab(0x2d0), dxaHotZ(0x168), nRevision(1),
7868 rncEdn(0), nEdn(1), epc(3), fPrintFormData(false), fSaveFormData(false), fShadeFormData(true),
7869 fWCFootnoteEdn(false), wvkSaved(2), wScaleSaved(100), zkSaved(0), fRotateFontW6(false),
7870 iGutterPos(false), fNoTabForInd(false), fNoSpaceRaiseLower(false),
7871 fSuppressSpbfAfterPageBreak(false), fWrapTrailSpaces(false), fMapPrintTextColor(false),
7872 fNoColumnBalance(false), fConvMailMergeEsc(false), fSuppressTopSpacing(false),
7873 fOrigWordTableRules(false), fTransparentMetafiles(false), fShowBreaksInFrames(false),
7874 fSwapBordersFacingPgs(false), fCompatibilityOptions_Unknown1_13(false), fExpShRtn(false),
7875 fCompatibilityOptions_Unknown1_15(false), fCompatibilityOptions_Unknown1_16(false),
7876 fSuppressTopSpacingMac5(false), fTruncDxaExpand(false), fPrintBodyBeforeHdr(false),
7877 fNoLeading(true), fCompatibilityOptions_Unknown1_21(false), fMWSmallCaps(false),
7878 fCompatibilityOptions_Unknown1_23(false), fCompatibilityOptions_Unknown1_24(false),
7879 fCompatibilityOptions_Unknown1_25(false), fCompatibilityOptions_Unknown1_26(false),
7880 fCompatibilityOptions_Unknown1_27(false), fCompatibilityOptions_Unknown1_28(false),
7881 fCompatibilityOptions_Unknown1_29(false), fCompatibilityOptions_Unknown1_30(false),
7882 fCompatibilityOptions_Unknown1_31(false), fUsePrinterMetrics(true), lvl(9), fHtmlDoc(false),
7883 fSnapBorder(false), fIncludeHeader(true), fIncludeFooter(true), fForcePageSizePag(false),
7884 fMinFontSizePag(false), fHaveVersions(false), fAutoVersion(false),
7885 cChWS(0), cChWSFootnoteEdn(0), cDBC(0), cDBCFootnoteEdn(0), nfcEdnRef(2),
7886 fCompatibilityOptions_Unknown2_1(false), fCompatibilityOptions_Unknown2_2(false),
7887 fDontUseHTMLAutoSpacing(false), fCompatibilityOptions_Unknown2_4(false),
7888 fCompatibilityOptions_Unknown2_5(false), fCompatibilityOptions_Unknown2_6(false),
7889 fCompatibilityOptions_Unknown2_7(false), fCompatibilityOptions_Unknown2_8(false),
7890 fCompatibilityOptions_Unknown2_9(false), fCompatibilityOptions_Unknown2_10(false),
7891 fDontBreakWrappedTables(false), fCompatibilityOptions_Unknown2_12(false),
7892 fCompatibilityOptions_Unknown2_13(false), fCompatibilityOptions_Unknown2_14(false),
7893 fCompatibilityOptions_Unknown2_15(false), fCompatibilityOptions_Unknown2_16(false),
7894 fCompatibilityOptions_Unknown2_17(false), fCompatibilityOptions_Unknown2_18(false),
7895 fCompatibilityOptions_Unknown2_19(false), fCompatibilityOptions_Unknown2_20(false),
7896 fCompatibilityOptions_Unknown2_21(false), fCompatibilityOptions_Unknown2_22(false),
7897 fCompatibilityOptions_Unknown2_23(false), fCompatibilityOptions_Unknown2_24(false),
7898 fCompatibilityOptions_Unknown2_25(false), fCompatibilityOptions_Unknown2_26(false),
7899 fCompatibilityOptions_Unknown2_27(false), fCompatibilityOptions_Unknown2_28(false),
7900 fCompatibilityOptions_Unknown2_29(false), fCompatibilityOptions_Unknown2_30(false),
7901 fCompatibilityOptions_Unknown2_31(false), fCompatibilityOptions_Unknown2_32(false),
7902 fUnknown3(0), fUseBackGroundInAllmodes(false), fDoNotEmbedSystemFont(false), fWordCompat(false),
7903 fLiveRecover(false), fEmbedFactoids(false), fFactoidXML(false), fFactoidAllDone(false),
7904 fFolioPrint(false), fReverseFolio(false), iTextLineEnding(0), fHideFcc(false),
7905 fAcetateShowMarkup(false), fAcetateShowAtn(true), fAcetateShowInsDel(false),
7906 fAcetateShowProps(false)
7907 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
7908 // above bit-field member initializations can be moved to the class definition
7911 Writer acts like this all the time at the moment, ideally we need an
7912 option for these two as well to import word docs that are not like
7915 // put in initialization list
7916 // fNoLeading = true;
7917 //fUsePrinterMetrics = true;
7920 void WW8Dop::SetCompatibilityOptions(sal_uInt32 a32Bit
)
7922 fNoTabForInd
= ( a32Bit
& 0x00000001 ) ;
7923 fNoSpaceRaiseLower
= ( a32Bit
& 0x00000002 ) >> 1 ;
7924 fSuppressSpbfAfterPageBreak
= ( a32Bit
& 0x00000004 ) >> 2 ;
7925 fWrapTrailSpaces
= ( a32Bit
& 0x00000008 ) >> 3 ;
7926 fMapPrintTextColor
= ( a32Bit
& 0x00000010 ) >> 4 ;
7927 fNoColumnBalance
= ( a32Bit
& 0x00000020 ) >> 5 ;
7928 fConvMailMergeEsc
= ( a32Bit
& 0x00000040 ) >> 6 ;
7929 fSuppressTopSpacing
= ( a32Bit
& 0x00000080 ) >> 7 ;
7930 fOrigWordTableRules
= ( a32Bit
& 0x00000100 ) >> 8 ;
7931 fTransparentMetafiles
= ( a32Bit
& 0x00000200 ) >> 9 ;
7932 fShowBreaksInFrames
= ( a32Bit
& 0x00000400 ) >> 10 ;
7933 fSwapBordersFacingPgs
= ( a32Bit
& 0x00000800 ) >> 11 ;
7934 fCompatibilityOptions_Unknown1_13
= ( a32Bit
& 0x00001000 ) >> 12 ;
7935 fExpShRtn
= ( a32Bit
& 0x00002000 ) >> 13 ; // #i56856#
7936 fCompatibilityOptions_Unknown1_15
= ( a32Bit
& 0x00004000 ) >> 14 ;
7937 fCompatibilityOptions_Unknown1_16
= ( a32Bit
& 0x00008000 ) >> 15 ;
7938 fSuppressTopSpacingMac5
= ( a32Bit
& 0x00010000 ) >> 16 ;
7939 fTruncDxaExpand
= ( a32Bit
& 0x00020000 ) >> 17 ;
7940 fPrintBodyBeforeHdr
= ( a32Bit
& 0x00040000 ) >> 18 ;
7941 fNoLeading
= ( a32Bit
& 0x00080000 ) >> 19 ;
7942 fCompatibilityOptions_Unknown1_21
= ( a32Bit
& 0x00100000 ) >> 20 ;
7943 fMWSmallCaps
= ( a32Bit
& 0x00200000 ) >> 21 ;
7944 fCompatibilityOptions_Unknown1_23
= ( a32Bit
& 0x00400000 ) >> 22 ;
7945 fCompatibilityOptions_Unknown1_24
= ( a32Bit
& 0x00800800 ) >> 23 ;
7946 fCompatibilityOptions_Unknown1_25
= ( a32Bit
& 0x01000000 ) >> 24 ;
7947 fCompatibilityOptions_Unknown1_26
= ( a32Bit
& 0x02000000 ) >> 25 ;
7948 fCompatibilityOptions_Unknown1_27
= ( a32Bit
& 0x04000000 ) >> 26 ;
7949 fCompatibilityOptions_Unknown1_28
= ( a32Bit
& 0x08000000 ) >> 27 ;
7950 fCompatibilityOptions_Unknown1_29
= ( a32Bit
& 0x10000000 ) >> 28 ;
7951 fCompatibilityOptions_Unknown1_30
= ( a32Bit
& 0x20000000 ) >> 29 ;
7952 fCompatibilityOptions_Unknown1_31
= ( a32Bit
& 0x40000000 ) >> 30 ;
7954 fUsePrinterMetrics
= ( a32Bit
& 0x80000000 ) >> 31 ;
7957 sal_uInt32
WW8Dop::GetCompatibilityOptions() const
7959 sal_uInt32 a32Bit
= 0;
7960 if (fNoTabForInd
) a32Bit
|= 0x00000001;
7961 if (fNoSpaceRaiseLower
) a32Bit
|= 0x00000002;
7962 if (fSuppressSpbfAfterPageBreak
) a32Bit
|= 0x00000004;
7963 if (fWrapTrailSpaces
) a32Bit
|= 0x00000008;
7964 if (fMapPrintTextColor
) a32Bit
|= 0x00000010;
7965 if (fNoColumnBalance
) a32Bit
|= 0x00000020;
7966 if (fConvMailMergeEsc
) a32Bit
|= 0x00000040;
7967 if (fSuppressTopSpacing
) a32Bit
|= 0x00000080;
7968 if (fOrigWordTableRules
) a32Bit
|= 0x00000100;
7969 if (fTransparentMetafiles
) a32Bit
|= 0x00000200;
7970 if (fShowBreaksInFrames
) a32Bit
|= 0x00000400;
7971 if (fSwapBordersFacingPgs
) a32Bit
|= 0x00000800;
7972 if (fCompatibilityOptions_Unknown1_13
) a32Bit
|= 0x00001000;
7973 if (fExpShRtn
) a32Bit
|= 0x00002000; // #i56856#
7974 if (fCompatibilityOptions_Unknown1_15
) a32Bit
|= 0x00004000;
7975 if (fCompatibilityOptions_Unknown1_16
) a32Bit
|= 0x00008000;
7976 if (fSuppressTopSpacingMac5
) a32Bit
|= 0x00010000;
7977 if (fTruncDxaExpand
) a32Bit
|= 0x00020000;
7978 if (fPrintBodyBeforeHdr
) a32Bit
|= 0x00040000;
7979 if (fNoLeading
) a32Bit
|= 0x00080000;
7980 if (fCompatibilityOptions_Unknown1_21
) a32Bit
|= 0x00100000;
7981 if (fMWSmallCaps
) a32Bit
|= 0x00200000;
7982 if (fCompatibilityOptions_Unknown1_23
) a32Bit
|= 0x00400000;
7983 if (fCompatibilityOptions_Unknown1_24
) a32Bit
|= 0x00800000;
7984 if (fCompatibilityOptions_Unknown1_25
) a32Bit
|= 0x01000000;
7985 if (fCompatibilityOptions_Unknown1_26
) a32Bit
|= 0x02000000;
7986 if (fCompatibilityOptions_Unknown1_27
) a32Bit
|= 0x04000000;
7987 if (fCompatibilityOptions_Unknown1_28
) a32Bit
|= 0x08000000;
7988 if (fCompatibilityOptions_Unknown1_29
) a32Bit
|= 0x10000000;
7989 if (fCompatibilityOptions_Unknown1_30
) a32Bit
|= 0x20000000;
7990 if (fCompatibilityOptions_Unknown1_31
) a32Bit
|= 0x40000000;
7991 if (fUsePrinterMetrics
) a32Bit
|= 0x80000000;
7996 void WW8Dop::SetCompatibilityOptions2(sal_uInt32 a32Bit
)
7998 fCompatibilityOptions_Unknown2_1
= ( a32Bit
& 0x00000001 );
7999 fCompatibilityOptions_Unknown2_2
= ( a32Bit
& 0x00000002 ) >> 1 ;
8000 fDontUseHTMLAutoSpacing
= ( a32Bit
& 0x00000004 ) >> 2 ;
8001 fCompatibilityOptions_Unknown2_4
= ( a32Bit
& 0x00000008 ) >> 3 ;
8002 fCompatibilityOptions_Unknown2_5
= ( a32Bit
& 0x00000010 ) >> 4 ;
8003 fCompatibilityOptions_Unknown2_6
= ( a32Bit
& 0x00000020 ) >> 5 ;
8004 fCompatibilityOptions_Unknown2_7
= ( a32Bit
& 0x00000040 ) >> 6 ;
8005 fCompatibilityOptions_Unknown2_8
= ( a32Bit
& 0x00000080 ) >> 7 ;
8006 fCompatibilityOptions_Unknown2_9
= ( a32Bit
& 0x00000100 ) >> 8 ;
8007 fCompatibilityOptions_Unknown2_10
= ( a32Bit
& 0x00000200 ) >> 9 ;
8008 fDontBreakWrappedTables
= ( a32Bit
& 0x00000400 ) >> 10 ;
8009 fCompatibilityOptions_Unknown2_12
= ( a32Bit
& 0x00000800 ) >> 11 ;
8010 fCompatibilityOptions_Unknown2_13
= ( a32Bit
& 0x00001000 ) >> 12 ;
8011 fCompatibilityOptions_Unknown2_14
= ( a32Bit
& 0x00002000 ) >> 13 ;
8012 fCompatibilityOptions_Unknown2_15
= ( a32Bit
& 0x00004000 ) >> 14 ;
8013 fCompatibilityOptions_Unknown2_16
= ( a32Bit
& 0x00008000 ) >> 15 ;
8014 fCompatibilityOptions_Unknown2_17
= ( a32Bit
& 0x00010000 ) >> 16 ;
8015 fCompatibilityOptions_Unknown2_18
= ( a32Bit
& 0x00020000 ) >> 17 ;
8016 fCompatibilityOptions_Unknown2_19
= ( a32Bit
& 0x00040000 ) >> 18 ;
8017 fCompatibilityOptions_Unknown2_20
= ( a32Bit
& 0x00080000 ) >> 19 ;
8018 fCompatibilityOptions_Unknown2_21
= ( a32Bit
& 0x00100000 ) >> 20 ;
8019 fCompatibilityOptions_Unknown2_22
= ( a32Bit
& 0x00200000 ) >> 21 ;
8020 fCompatibilityOptions_Unknown2_23
= ( a32Bit
& 0x00400000 ) >> 22 ;
8021 fCompatibilityOptions_Unknown2_24
= ( a32Bit
& 0x00800800 ) >> 23 ;
8022 fCompatibilityOptions_Unknown2_25
= ( a32Bit
& 0x01000800 ) >> 24 ;
8023 fCompatibilityOptions_Unknown2_26
= ( a32Bit
& 0x02000800 ) >> 25 ;
8024 fCompatibilityOptions_Unknown2_27
= ( a32Bit
& 0x04000800 ) >> 26 ;
8025 fCompatibilityOptions_Unknown2_28
= ( a32Bit
& 0x08000800 ) >> 27 ;
8026 fCompatibilityOptions_Unknown2_29
= ( a32Bit
& 0x10000800 ) >> 28 ;
8027 fCompatibilityOptions_Unknown2_30
= ( a32Bit
& 0x20000800 ) >> 29 ;
8028 fCompatibilityOptions_Unknown2_31
= ( a32Bit
& 0x40000800 ) >> 30 ;
8029 fCompatibilityOptions_Unknown2_32
= ( a32Bit
& 0x80000000 ) >> 31 ;
8032 sal_uInt32
WW8Dop::GetCompatibilityOptions2() const
8034 sal_uInt32 a32Bit
= 0;
8035 if (fCompatibilityOptions_Unknown2_1
) a32Bit
|= 0x00000001;
8036 if (fCompatibilityOptions_Unknown2_2
) a32Bit
|= 0x00000002;
8037 if (fDontUseHTMLAutoSpacing
) a32Bit
|= 0x00000004;
8038 if (fCompatibilityOptions_Unknown2_4
) a32Bit
|= 0x00000008;
8039 if (fCompatibilityOptions_Unknown2_5
) a32Bit
|= 0x00000010;
8040 if (fCompatibilityOptions_Unknown2_6
) a32Bit
|= 0x00000020;
8041 if (fCompatibilityOptions_Unknown2_7
) a32Bit
|= 0x00000040;
8042 if (fCompatibilityOptions_Unknown2_8
) a32Bit
|= 0x00000080;
8043 if (fCompatibilityOptions_Unknown2_9
) a32Bit
|= 0x00000100;
8044 if (fCompatibilityOptions_Unknown2_10
) a32Bit
|= 0x00000200;
8045 if (fDontBreakWrappedTables
) a32Bit
|= 0x00000400;
8046 if (fCompatibilityOptions_Unknown2_12
) a32Bit
|= 0x00000800;
8047 if (fCompatibilityOptions_Unknown2_13
) a32Bit
|= 0x00001000;
8048 //#i42909# set thai "line breaking rules" compatibility option
8049 // pflin, wonder whether bUseThaiLineBreakingRules is correct
8050 // when importing word document.
8051 if (bUseThaiLineBreakingRules
) a32Bit
|= 0x00002000;
8052 else if (fCompatibilityOptions_Unknown2_14
) a32Bit
|= 0x00002000;
8053 if (fCompatibilityOptions_Unknown2_15
) a32Bit
|= 0x00004000;
8054 if (fCompatibilityOptions_Unknown2_16
) a32Bit
|= 0x00008000;
8055 if (fCompatibilityOptions_Unknown2_17
) a32Bit
|= 0x00010000;
8056 if (fCompatibilityOptions_Unknown2_18
) a32Bit
|= 0x00020000;
8057 if (fCompatibilityOptions_Unknown2_19
) a32Bit
|= 0x00040000;
8058 if (fCompatibilityOptions_Unknown2_20
) a32Bit
|= 0x00080000;
8059 if (fCompatibilityOptions_Unknown2_21
) a32Bit
|= 0x00100000;
8060 if (fCompatibilityOptions_Unknown2_22
) a32Bit
|= 0x00200000;
8061 if (fCompatibilityOptions_Unknown2_23
) a32Bit
|= 0x00400000;
8062 if (fCompatibilityOptions_Unknown2_24
) a32Bit
|= 0x00800000;
8063 if (fCompatibilityOptions_Unknown2_25
) a32Bit
|= 0x01000000;
8064 if (fCompatibilityOptions_Unknown2_26
) a32Bit
|= 0x02000000;
8065 if (fCompatibilityOptions_Unknown2_27
) a32Bit
|= 0x04000000;
8066 if (fCompatibilityOptions_Unknown2_28
) a32Bit
|= 0x08000000;
8067 if (fCompatibilityOptions_Unknown2_29
) a32Bit
|= 0x10000000;
8068 if (fCompatibilityOptions_Unknown2_30
) a32Bit
|= 0x20000000;
8069 if (fCompatibilityOptions_Unknown2_31
) a32Bit
|= 0x40000000;
8070 if (fCompatibilityOptions_Unknown2_32
) a32Bit
|= 0x80000000;
8074 void WW8Dop::Write(SvStream
& rStrm
, WW8Fib
& rFib
) const
8076 const int nMaxDopLen
= 610;
8077 sal_uInt32 nLen
= 8 == rFib
.m_nVersion
? nMaxDopLen
: 84;
8078 rFib
.m_fcDop
= rStrm
.Tell();
8079 rFib
.m_lcbDop
= nLen
;
8081 sal_uInt8 aData
[ nMaxDopLen
] = {};
8082 sal_uInt8
* pData
= aData
;
8088 a16Bit
= 0; // 0 0x00
8095 a16Bit
|= ( 0x0018 & (grfSuppression
<< 3));
8096 a16Bit
|= ( 0x0060 & (fpc
<< 5));
8097 a16Bit
|= ( 0xff00 & (grpfIhdt
<< 8));
8098 Set_UInt16( pData
, a16Bit
);
8100 a16Bit
= 0; // 2 0x02
8101 a16Bit
|= ( 0x0003 & rncFootnote
);
8102 a16Bit
|= ( ~0x0003 & (nFootnote
<< 2));
8103 Set_UInt16( pData
, a16Bit
);
8105 a8Bit
= 0; // 4 0x04
8106 if( fOutlineDirtySave
) a8Bit
|= 0x01;
8107 Set_UInt8( pData
, a8Bit
);
8109 a8Bit
= 0; // 5 0x05
8110 if( fOnlyMacPics
) a8Bit
|= 0x01;
8111 if( fOnlyWinPics
) a8Bit
|= 0x02;
8112 if( fLabelDoc
) a8Bit
|= 0x04;
8113 if( fHyphCapitals
) a8Bit
|= 0x08;
8114 if( fAutoHyphen
) a8Bit
|= 0x10;
8115 if( fFormNoFields
) a8Bit
|= 0x20;
8116 if( fLinkStyles
) a8Bit
|= 0x40;
8117 if( fRevMarking
) a8Bit
|= 0x80;
8118 Set_UInt8( pData
, a8Bit
);
8120 a8Bit
= 0; // 6 0x06
8121 if( fBackup
) a8Bit
|= 0x01;
8122 if( fExactCWords
) a8Bit
|= 0x02;
8123 if( fPagHidden
) a8Bit
|= 0x04;
8124 if( fPagResults
) a8Bit
|= 0x08;
8125 if( fLockAtn
) a8Bit
|= 0x10;
8126 if( fMirrorMargins
) a8Bit
|= 0x20;
8127 if( fReadOnlyRecommended
) a8Bit
|= 0x40;
8128 if( fDfltTrueType
) a8Bit
|= 0x80;
8129 Set_UInt8( pData
, a8Bit
);
8131 a8Bit
= 0; // 7 0x07
8132 if( fPagSuppressTopSpacing
) a8Bit
|= 0x01;
8133 if( fProtEnabled
) a8Bit
|= 0x02;
8134 if( fDispFormFieldSel
) a8Bit
|= 0x04;
8135 if( fRMView
) a8Bit
|= 0x08;
8136 if( fRMPrint
) a8Bit
|= 0x10;
8137 if( fWriteReservation
) a8Bit
|= 0x20;
8138 if( fLockRev
) a8Bit
|= 0x40;
8139 if( fEmbedFonts
) a8Bit
|= 0x80;
8140 Set_UInt8( pData
, a8Bit
);
8142 a8Bit
= 0; // 8 0x08
8143 if( copts_fNoTabForInd
) a8Bit
|= 0x01;
8144 if( copts_fNoSpaceRaiseLower
) a8Bit
|= 0x02;
8145 if( copts_fSuppressSpbfAfterPgBrk
) a8Bit
|= 0x04;
8146 if( copts_fWrapTrailSpaces
) a8Bit
|= 0x08;
8147 if( copts_fMapPrintTextColor
) a8Bit
|= 0x10;
8148 if( copts_fNoColumnBalance
) a8Bit
|= 0x20;
8149 if( copts_fConvMailMergeEsc
) a8Bit
|= 0x40;
8150 if( copts_fSuppressTopSpacing
) a8Bit
|= 0x80;
8151 Set_UInt8( pData
, a8Bit
);
8153 a8Bit
= 0; // 9 0x09
8154 if( copts_fOrigWordTableRules
) a8Bit
|= 0x01;
8155 if( copts_fTransparentMetafiles
) a8Bit
|= 0x02;
8156 if( copts_fShowBreaksInFrames
) a8Bit
|= 0x04;
8157 if( copts_fSwapBordersFacingPgs
) a8Bit
|= 0x08;
8158 if( copts_fExpShRtn
) a8Bit
|= 0x20; // #i56856#
8159 Set_UInt8( pData
, a8Bit
);
8161 Set_UInt16( pData
, dxaTab
); // 10 0x0a
8162 Set_UInt16( pData
, wSpare
); // 12 0x0c
8163 Set_UInt16( pData
, dxaHotZ
); // 14 0x0e
8164 Set_UInt16( pData
, cConsecHypLim
); // 16 0x10
8165 Set_UInt16( pData
, wSpare2
); // 18 0x12
8166 Set_UInt32( pData
, dttmCreated
); // 20 0x14
8167 Set_UInt32( pData
, dttmRevised
); // 24 0x18
8168 Set_UInt32( pData
, dttmLastPrint
); // 28 0x1c
8169 Set_UInt16( pData
, nRevision
); // 32 0x20
8170 Set_UInt32( pData
, tmEdited
); // 34 0x22
8171 Set_UInt32( pData
, cWords
); // 38 0x26
8172 Set_UInt32( pData
, cCh
); // 42 0x2a
8173 Set_UInt16( pData
, cPg
); // 46 0x2e
8174 Set_UInt32( pData
, cParas
); // 48 0x30
8176 a16Bit
= 0; // 52 0x34
8177 a16Bit
|= ( 0x0003 & rncEdn
);
8178 a16Bit
|= (~0x0003 & ( nEdn
<< 2));
8179 Set_UInt16( pData
, a16Bit
);
8181 a16Bit
= 0; // 54 0x36
8182 a16Bit
|= (0x0003 & epc
);
8183 a16Bit
|= (0x003c & (nfcFootnoteRef
<< 2));
8184 a16Bit
|= (0x03c0 & (nfcEdnRef
<< 6));
8185 if( fPrintFormData
) a16Bit
|= 0x0400;
8186 if( fSaveFormData
) a16Bit
|= 0x0800;
8187 if( fShadeFormData
) a16Bit
|= 0x1000;
8188 if( fWCFootnoteEdn
) a16Bit
|= 0x8000;
8189 Set_UInt16( pData
, a16Bit
);
8191 Set_UInt32( pData
, cLines
); // 56 0x38
8192 Set_UInt32( pData
, cWordsFootnoteEnd
); // 60 0x3c
8193 Set_UInt32( pData
, cChFootnoteEdn
); // 64 0x40
8194 Set_UInt16( pData
, cPgFootnoteEdn
); // 68 0x44
8195 Set_UInt32( pData
, cParasFootnoteEdn
); // 70 0x46
8196 Set_UInt32( pData
, cLinesFootnoteEdn
); // 74 0x4a
8197 Set_UInt32( pData
, lKeyProtDoc
); // 78 0x4e
8199 a16Bit
= 0; // 82 0x52
8202 a16Bit
|= (0x0ff8 & (wScaleSaved
<< 3));
8203 a16Bit
|= (0x3000 & (zkSaved
<< 12));
8206 // Last bit: gutter at top.
8209 Set_UInt16( pData
, a16Bit
);
8211 if( 8 == rFib
.m_nVersion
)
8213 Set_UInt32(pData
, GetCompatibilityOptions()); // 84 0x54
8215 Set_UInt16( pData
, adt
); // 88 0x58
8217 doptypography
.WriteToMem(pData
); // 400 0x190
8219 memcpy( pData
, &dogrid
, sizeof( WW8_DOGRID
));
8220 pData
+= sizeof( WW8_DOGRID
);
8222 a16Bit
= 0x12; // set lvl to 9 // 410 0x19a
8223 if( fHtmlDoc
) a16Bit
|= 0x0200;
8224 if( fSnapBorder
) a16Bit
|= 0x0800;
8225 if( fIncludeHeader
) a16Bit
|= 0x1000;
8226 if( fIncludeFooter
) a16Bit
|= 0x2000;
8227 if( fForcePageSizePag
) a16Bit
|= 0x4000;
8228 if( fMinFontSizePag
) a16Bit
|= 0x8000;
8229 Set_UInt16( pData
, a16Bit
);
8231 a16Bit
= 0; // 412 0x19c
8232 if( fHaveVersions
) a16Bit
|= 0x0001;
8233 if( fAutoVersion
) a16Bit
|= 0x0002;
8234 Set_UInt16( pData
, a16Bit
);
8236 pData
+= 12; // 414 0x19e
8238 Set_UInt32( pData
, cChWS
); // 426 0x1aa
8239 Set_UInt32( pData
, cChWSFootnoteEdn
); // 430 0x1ae
8240 Set_UInt32( pData
, grfDocEvents
); // 434 0x1b2
8242 pData
+= 4+30+8; // 438 0x1b6; 442 0x1ba; 472 0x1d8; 476 0x1dc
8244 Set_UInt32( pData
, cDBC
); // 480 0x1e0
8245 Set_UInt32( pData
, cDBCFootnoteEdn
); // 484 0x1e4
8247 pData
+= 1 * sizeof( sal_Int32
); // 488 0x1e8
8249 Set_UInt16( pData
, nfcFootnoteRef
); // 492 0x1ec
8250 Set_UInt16( pData
, nfcEdnRef
); // 494 0x1ee
8251 Set_UInt16( pData
, hpsZoomFontPag
); // 496 0x1f0
8252 Set_UInt16( pData
, dywDispPag
); // 498 0x1f2
8254 //500 -> 508, Appear to be repeated here in 2000+
8256 Set_UInt32(pData
, GetCompatibilityOptions());
8257 Set_UInt32(pData
, GetCompatibilityOptions2());
8263 if (fAcetateShowMarkup
)
8265 //Word XP at least requires fAcetateShowMarkup to honour fAcetateShowAtn
8266 if (fAcetateShowAtn
)
8271 Set_UInt16(pData
, a16Bit
);
8275 Set_UInt16(pData
, a16Bit
);
8277 rStrm
.WriteBytes(aData
, nLen
);
8280 void WW8DopTypography::ReadFromMem(sal_uInt8
*&pData
)
8282 sal_uInt16 a16Bit
= Get_UShort(pData
);
8283 m_fKerningPunct
= (a16Bit
& 0x0001);
8284 m_iJustification
= (a16Bit
& 0x0006) >> 1;
8285 m_iLevelOfKinsoku
= (a16Bit
& 0x0018) >> 3;
8286 m_f2on1
= (a16Bit
& 0x0020) >> 5;
8287 m_reserved1
= (a16Bit
& 0x03C0) >> 6;
8288 m_reserved2
= (a16Bit
& 0xFC00) >> 10;
8290 m_cchFollowingPunct
= Get_Short(pData
);
8291 m_cchLeadingPunct
= Get_Short(pData
);
8294 for (i
=0; i
< nMaxFollowing
; ++i
)
8295 m_rgxchFPunct
[i
] = Get_Short(pData
);
8296 for (i
=0; i
< nMaxLeading
; ++i
)
8297 m_rgxchLPunct
[i
] = Get_Short(pData
);
8299 if (m_cchFollowingPunct
>= 0 && m_cchFollowingPunct
< nMaxFollowing
)
8300 m_rgxchFPunct
[m_cchFollowingPunct
]=0;
8302 m_rgxchFPunct
[nMaxFollowing
- 1]=0;
8304 if (m_cchLeadingPunct
>= 0 && m_cchLeadingPunct
< nMaxLeading
)
8305 m_rgxchLPunct
[m_cchLeadingPunct
]=0;
8307 m_rgxchLPunct
[nMaxLeading
- 1]=0;
8311 void WW8DopTypography::WriteToMem(sal_uInt8
*&pData
) const
8313 sal_uInt16 a16Bit
= sal_uInt16(m_fKerningPunct
);
8314 a16Bit
|= (m_iJustification
<< 1) & 0x0006;
8315 a16Bit
|= (m_iLevelOfKinsoku
<< 3) & 0x0018;
8316 a16Bit
|= (int(m_f2on1
) << 5) & 0x0020;
8317 a16Bit
|= (m_reserved1
<< 6) & 0x03C0;
8318 a16Bit
|= (m_reserved2
<< 10) & 0xFC00;
8319 Set_UInt16(pData
,a16Bit
);
8321 Set_UInt16(pData
,m_cchFollowingPunct
);
8322 Set_UInt16(pData
,m_cchLeadingPunct
);
8325 for (i
=0; i
< nMaxFollowing
; ++i
)
8326 Set_UInt16(pData
,m_rgxchFPunct
[i
]);
8327 for (i
=0; i
< nMaxLeading
; ++i
)
8328 Set_UInt16(pData
,m_rgxchLPunct
[i
]);
8331 LanguageType
WW8DopTypography::GetConvertedLang() const
8334 //I have assumed people's republic/taiwan == simplified/traditional
8336 //This isn't a documented issue, so we might have it all wrong,
8337 //i.e. i.e. what's with the powers of two ?
8340 One example of 3 for reserved1 which was really Japanese, perhaps last bit
8341 is for some other use ?, or redundant. If more examples trigger the assert
8342 we might be able to figure it out.
8344 switch(m_reserved1
& 0xE)
8347 nLang
= LANGUAGE_JAPANESE
;
8349 case 4: //Chinese (People's Republic)
8350 nLang
= LANGUAGE_CHINESE_SIMPLIFIED
;
8353 nLang
= LANGUAGE_KOREAN
;
8355 case 8: //Chinese (Taiwan)
8356 nLang
= LANGUAGE_CHINESE_TRADITIONAL
;
8359 OSL_ENSURE(false, "Unknown MS Asian Typography language, report");
8360 nLang
= LANGUAGE_CHINESE_SIMPLIFIED_LEGACY
;
8363 //And here we have the possibility that it says 2, but it's really
8364 //a bug and only japanese level 2 has been selected after a custom
8365 //version was chosen on last save!
8366 nLang
= LANGUAGE_JAPANESE
;
8374 sal_uInt16
wwSprmParser::GetSprmTailLen(sal_uInt16 nId
, const sal_uInt8
* pSprm
, sal_Int32 nRemLen
)
8377 SprmInfo aSprm
= GetSprmInfo(nId
);
8378 sal_uInt16 nL
= 0; // number of Bytes to read
8385 if( pSprm
[1 + mnDelta
] != 255 )
8386 nL
= static_cast< sal_uInt16
>(pSprm
[1 + mnDelta
] + aSprm
.nLen
);
8389 sal_uInt8 nDelIdx
= 2 + mnDelta
;
8390 sal_uInt8 nDel
= nDelIdx
< nRemLen
? pSprm
[nDelIdx
] : 0;
8391 sal_uInt8 nInsIdx
= 3 + mnDelta
+ 4 * nDel
;
8392 sal_uInt8 nIns
= nInsIdx
< nRemLen
? pSprm
[nInsIdx
] : 0;
8394 nL
= 2 + 4 * nDel
+ 3 * nIns
;
8398 switch (aSprm
.nVari
)
8401 nL
= aSprm
.nLen
; // Excl. Token
8404 // Variable 1-Byte Length
8405 // parameter length (i.e. excluding token and length byte)
8406 nL
= static_cast< sal_uInt16
>(pSprm
[1 + mnDelta
] + aSprm
.nLen
);
8410 // Variable 2-Byte Length
8411 // For sprmTDefTable and sprmTDefTable10, the length of the
8412 // parameter plus 1 is recorded in the two bytes beginning
8413 // at offset (WW7-) 1 or (WW8+) 2
8414 sal_uInt8 nIndex
= 1 + mnDelta
;
8416 if (nIndex
+ 1 >= nRemLen
)
8418 SAL_WARN("sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong");
8423 nCount
= SVBT16ToUInt16(&pSprm
[nIndex
]);
8424 SAL_WARN_IF(nCount
< 1, "sw.ww8", "length should have been at least 1");
8428 nL
= static_cast<sal_uInt16
>(nCount
+ aSprm
.nLen
);
8432 OSL_ENSURE(false, "Unknown sprm variant");
8440 // one or two bytes at the beginning at the sprm id
8441 sal_uInt16
wwSprmParser::GetSprmId(const sal_uInt8
* pSp
) const
8443 OSL_ENSURE(pSp
, "Why GetSprmId with pSp of 0");
8449 if (ww::IsSevenMinus(meVersion
))
8451 nId
= *pSp
; // [0..0xff]
8455 nId
= SVBT16ToUInt16(pSp
);
8463 // with tokens and length byte
8464 sal_Int32
wwSprmParser::GetSprmSize(sal_uInt16 nId
, const sal_uInt8
* pSprm
, sal_Int32 nRemLen
) const
8466 return GetSprmTailLen(nId
, pSprm
, nRemLen
) + 1 + mnDelta
+ SprmDataOfs(nId
);
8469 sal_uInt8
wwSprmParser::SprmDataOfs(sal_uInt16 nId
) const
8471 return GetSprmInfo(nId
).nVari
;
8474 sal_Int32
wwSprmParser::DistanceToData(sal_uInt16 nId
) const
8476 return 1 + mnDelta
+ SprmDataOfs(nId
);
8479 SprmResult
wwSprmParser::findSprmData(sal_uInt16 nId
, sal_uInt8
* pSprms
,
8480 sal_Int32 nLen
) const
8482 while (nLen
>= MinSprmLen())
8484 const sal_uInt16 nCurrentId
= GetSprmId(pSprms
);
8485 // set pointer to data
8486 sal_Int32 nSize
= GetSprmSize(nCurrentId
, pSprms
, nLen
);
8488 bool bValid
= nSize
<= nLen
;
8490 SAL_WARN_IF(!bValid
, "sw.ww8",
8491 "sprm 0x" << std::hex
<< nCurrentId
<< std::dec
<< " longer than remaining bytes, " <<
8492 nSize
<< " vs " << nLen
<< "doc or parser is wrong");
8494 if (nCurrentId
== nId
&& bValid
) // Sprm found
8496 sal_Int32 nFixedLen
= DistanceToData(nId
);
8497 return SprmResult(pSprms
+ nFixedLen
, nSize
- nFixedLen
);
8500 //Clip to available size if wrong
8501 nSize
= std::min(nSize
, nLen
);
8506 return SprmResult();
8510 bkc(2), fTitlePage(0), fAutoPgn(0), nfcPgn(0), fUnlocked(0), cnsPgn(0),
8511 fPgnRestart(0), fEndNote(1), lnc(0), grpfIhdt(0), nLnnMod(0), dxaLnn(0),
8512 dxaPgn(720), dyaPgn(720), fLBetween(0), vjc(0), dmBinFirst(0),
8513 dmBinOther(0), dmPaperReq(0), fPropRMark(0), ibstPropRMark(0),
8514 dttmPropRMark(0), dxtCharSpace(0), dyaLinePitch(0), clm(0), reserved1(0),
8515 dmOrientPage(0), iHeadingPgn(0), pgnStart(1), lnnMin(0), wTextFlow(0),
8516 reserved2(0), pgbApplyTo(0), pgbPageDepth(0), pgbOffsetFrom(0),
8517 xaPage(lLetterWidth
), yaPage(lLetterHeight
), xaPageNUp(lLetterWidth
), yaPageNUp(lLetterHeight
),
8518 dxaLeft(1800), dxaRight(1800), dyaTop(1440), dyaBottom(1440), dzaGutter(0),
8519 dyaHdrTop(720), dyaHdrBottom(720), ccolM1(0), fEvenlySpaced(1),
8520 reserved3(0), fBiDi(0), fFacingCol(0), fRTLGutter(0), fRTLAlignment(0),
8521 dxaColumns(720), dxaColumnWidth(0), dmOrientFirst(0), fLayout(0),
8526 bool checkRead(SvStream
&rSt
, void *pDest
, sal_uInt32 nLength
)
8528 return (rSt
.ReadBytes(pDest
, nLength
) == static_cast<std::size_t>(nLength
));
8531 #ifdef OSL_BIGENDIAN
8532 void swapEndian(sal_Unicode
*pString
)
8534 for (sal_Unicode
*pWork
= pString
; *pWork
; ++pWork
)
8535 *pWork
= OSL_SWAPWORD(*pWork
);
8539 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */