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>
37 #include <comphelper/string.hxx>
38 #include <unotools/localedatawrapper.hxx>
39 #include <i18nlangtag/lang.h>
40 #include <o3tl/safeint.hxx>
41 #include <tools/stream.hxx>
43 #include <vcl/settings.hxx>
44 #include <vcl/svapp.hxx>
46 #ifdef DEBUGSPRMREADER
50 using namespace ::com::sun::star::lang
;
55 winword strings are typically Belt and Braces strings preceded with a
56 pascal style count, and ending with a c style 0 terminator. 16bit chars
57 and count for ww8+ and 8bit chars and count for ww7-. The count and 0
58 can be checked for integrity to catch errors (e.g. lotus created
59 documents) where in error 8bit strings are used instead of 16bits
60 strings for style names.
62 bool TestBeltAndBraces(SvStream
& rStrm
)
65 sal_uInt32 nOldPos
= rStrm
.Tell();
67 rStrm
.ReadUInt16( nBelt
);
68 nBelt
*= sizeof(sal_Unicode
);
69 if (rStrm
.good() && (rStrm
.remainingSize() >= (nBelt
+ sizeof(sal_Unicode
))))
74 sal_Unicode
cBraces(0);
75 rStrm
.ReadUtf16( cBraces
);
76 if (rStrm
.good() && cBraces
== 0)
85 const wwSprmSearcher
*wwSprmParser::GetWW2SprmSearcher()
89 static const SprmInfoRow aSprms
[] =
91 { 0, { 0, L_FIX
} }, // "Default-sprm", will be skipped
92 { 2, { 1, L_FIX
} }, // "sprmPIstd", pap.istd (style code)
93 { 3, { 0, L_VAR
} }, // "sprmPIstdPermute pap.istd permutation
94 { 4, { 1, L_FIX
} }, // "sprmPIncLv1" pap.istddifference
95 { 5, { 1, L_FIX
} }, // "sprmPJc" pap.jc (justification)
96 { 6, { 1, L_FIX
} }, // "sprmPFSideBySide" pap.fSideBySide
97 { 7, { 1, L_FIX
} }, // "sprmPFKeep" pap.fKeep
98 { 8, { 1, L_FIX
} }, // "sprmPFKeepFollow " pap.fKeepFollow
99 { 9, { 1, L_FIX
} }, // "sprmPPageBreakBefore" pap.fPageBreakBefore
100 { 10, { 1, L_FIX
} }, // "sprmPBrcl" pap.brcl
101 { 11, { 1, L_FIX
} }, // "sprmPBrcp" pap.brcp
102 { 12, { 1, L_FIX
} }, // "sprmPNfcSeqNumb" pap.nfcSeqNumb
103 { 13, { 1, L_FIX
} }, // "sprmPNoSeqNumb" pap.nnSeqNumb
104 { 14, { 1, L_FIX
} }, // "sprmPFNoLineNumb" pap.fNoLnn
105 { 15, { 0, L_VAR
} }, // "?sprmPChgTabsPapx" pap.itbdMac, ...
106 { 16, { 2, L_FIX
} }, // "sprmPDxaRight" pap.dxaRight
107 { 17, { 2, L_FIX
} }, // "sprmPDxaLeft" pap.dxaLeft
108 { 18, { 2, L_FIX
} }, // "sprmPNest" pap.dxaLeft
109 { 19, { 2, L_FIX
} }, // "sprmPDxaLeft1" pap.dxaLeft1
110 { 20, { 2, L_FIX
} }, // "sprmPDyaLine" pap.lspd an LSPD
111 { 21, { 2, L_FIX
} }, // "sprmPDyaBefore" pap.dyaBefore
112 { 22, { 2, L_FIX
} }, // "sprmPDyaAfter" pap.dyaAfter
113 { 23, { 0, L_VAR
} }, // "?sprmPChgTabs" pap.itbdMac, pap.rgdxaTab, ...
114 { 24, { 1, L_FIX
} }, // "sprmPFInTable" pap.fInTable
115 { 25, { 1, L_FIX
} }, // "sprmPTtp" pap.fTtp
116 { 26, { 2, L_FIX
} }, // "sprmPDxaAbs" pap.dxaAbs
117 { 27, { 2, L_FIX
} }, // "sprmPDyaAbs" pap.dyaAbs
118 { 28, { 2, L_FIX
} }, // "sprmPDxaWidth" pap.dxaWidth
119 { 29, { 1, L_FIX
} }, // "sprmPPc" pap.pcHorz, pap.pcVert
120 { 30, { 2, L_FIX
} }, // "sprmPBrcTop10" pap.brcTop BRC10
121 { 31, { 2, L_FIX
} }, // "sprmPBrcLeft10" pap.brcLeft BRC10
122 { 32, { 2, L_FIX
} }, // "sprmPBrcBottom10" pap.brcBottom BRC10
123 { 33, { 2, L_FIX
} }, // "sprmPBrcRight10" pap.brcRight BRC10
124 { 34, { 2, L_FIX
} }, // "sprmPBrcBetween10" pap.brcBetween BRC10
125 { 35, { 2, L_FIX
} }, // "sprmPBrcBar10" pap.brcBar BRC10
126 { 36, { 2, L_FIX
} }, // "sprmPFromText10" pap.dxaFromText dxa
127 { 37, { 1, L_FIX
} }, // "sprmPWr" pap.wr wr
128 { 38, { 2, L_FIX
} }, // "sprmPBrcTop" pap.brcTop BRC
129 { 39, { 2, L_FIX
} }, // "sprmPBrcLeft" pap.brcLeft BRC
130 { 40, { 2, L_FIX
} }, // "sprmPBrcBottom" pap.brcBottom BRC
131 { 41, { 2, L_FIX
} }, // "sprmPBrcRight" pap.brcRight BRC
132 { 42, { 2, L_FIX
} }, // "sprmPBrcBetween" pap.brcBetween BRC
133 { 43, { 2, L_FIX
} }, // "sprmPBrcBar" pap.brcBar BRC word
134 { 44, { 1, L_FIX
} }, // "sprmPFNoAutoHyph" pap.fNoAutoHyph
135 { 45, { 2, L_FIX
} }, // "sprmPWHeightAbs" pap.wHeightAbs w
136 { 46, { 2, L_FIX
} }, // "sprmPDcs" pap.dcs DCS
137 { 47, { 2, L_FIX
} }, // "sprmPShd" pap.shd SHD
138 { 48, { 2, L_FIX
} }, // "sprmPDyaFromText" pap.dyaFromText dya
139 { 49, { 2, L_FIX
} }, // "sprmPDxaFromText" pap.dxaFromText dxa
140 { 50, { 1, L_FIX
} }, // "sprmPFBiDi" pap.fBiDi 0 or 1 byte
141 { 51, { 1, L_FIX
} }, // "sprmPFWidowControl" pap.fWidowControl 0 or 1 byte
142 { 52, { 0, L_FIX
} }, // "?sprmPRuler 52"
143 { 53, { 1, L_FIX
} }, // "sprmCFStrikeRM" chp.fRMarkDel 1 or 0 bit
144 { 54, { 1, L_FIX
} }, // "sprmCFRMark" chp.fRMark 1 or 0 bit
145 { 55, { 1, L_FIX
} }, // "sprmCFFieldVanish" chp.fFieldVanish 1 or 0 bit
146 { 57, { 0, L_VAR
} }, // "sprmCDefault" whole CHP
147 { 58, { 0, L_FIX
} }, // "sprmCPlain" whole CHP
148 { 60, { 1, L_FIX
} }, // "sprmCFBold" chp.fBold 0,1, 128, or 129
149 { 61, { 1, L_FIX
} }, // "sprmCFItalic" chp.fItalic 0,1, 128, or 129
150 { 62, { 1, L_FIX
} }, // "sprmCFStrike" chp.fStrike 0,1, 128, or 129
151 { 63, { 1, L_FIX
} }, // "sprmCFOutline" chp.fOutline 0,1, 128, or 129
152 { 64, { 1, L_FIX
} }, // "sprmCFShadow" chp.fShadow 0,1, 128, or 129
153 { 65, { 1, L_FIX
} }, // "sprmCFSmallCaps" chp.fSmallCaps 0,1, 128, or 129
154 { 66, { 1, L_FIX
} }, // "sprmCFCaps" chp.fCaps 0,1, 128, or 129
155 { 67, { 1, L_FIX
} }, // "sprmCFVanish" chp.fVanish 0,1, 128, or 129
156 { 68, { 2, L_FIX
} }, // "sprmCFtc" chp.ftc ftc word
157 { 69, { 1, L_FIX
} }, // "sprmCKul" chp.kul kul byte
158 { 70, { 3, L_FIX
} }, // "sprmCSizePos" chp.hps, chp.hpsPos
159 { 71, { 2, L_FIX
} }, // "sprmCDxaSpace" chp.dxaSpace dxa
160 { 72, { 2, L_FIX
} }, // "sprmCLid" chp.lid LID
161 { 73, { 1, L_FIX
} }, // "sprmCIco" chp.ico ico byte
162 { 74, { 1, L_FIX
} }, // "sprmCHps" chp.hps hps !word!
163 { 75, { 1, L_FIX
} }, // "sprmCHpsInc" chp.hps
164 { 76, { 1, L_FIX
} }, // "sprmCHpsPos" chp.hpsPos hps !word!
165 { 77, { 1, L_FIX
} }, // "sprmCHpsPosAdj" chp.hpsPos hps
166 { 78, { 0, L_VAR
} }, // "?sprmCMajority" chp.fBold, chp.fItalic, ...
167 { 80, { 1, L_FIX
} }, // "sprmCFBoldBi" chp.fBoldBi
168 { 81, { 1, L_FIX
} }, // "sprmCFItalicBi" chp.fItalicBi
169 { 82, { 2, L_FIX
} }, // "sprmCFtcBi" chp.ftcBi
170 { 83, { 2, L_FIX
} }, // "sprmClidBi" chp.lidBi
171 { 84, { 1, L_FIX
} }, // "sprmCIcoBi" chp.icoBi
172 { 85, { 1, L_FIX
} }, // "sprmCHpsBi" chp.hpsBi
173 { 86, { 1, L_FIX
} }, // "sprmCFBiDi" chp.fBiDi
174 { 87, { 1, L_FIX
} }, // "sprmCFDiacColor" chp.fDiacUSico
175 { 94, { 1, L_FIX
} }, // "sprmPicBrcl" pic.brcl brcl (see PIC definition)
176 { 95, {12, L_VAR
} }, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
177 { 96, { 2, L_FIX
} }, // "sprmPicBrcTop" pic.brcTop BRC word
178 { 97, { 2, L_FIX
} }, // "sprmPicBrcLeft" pic.brcLeft BRC word
179 { 98, { 2, L_FIX
} }, // "sprmPicBrcBottom" pic.brcBottom BRC word
180 { 99, { 2, L_FIX
} }, // "sprmPicBrcRight" pic.brcRight BRC word
181 {112, { 1, L_FIX
} }, // "sprmSFRTLGutter", set to one if gutter is on
182 {114, { 1, L_FIX
} }, // "sprmSFBiDi" ;;;
183 {115, { 2, L_FIX
} }, // "sprmSDmBinFirst" sep.dmBinFirst word
184 {116, { 2, L_FIX
} }, // "sprmSDmBinOther" sep.dmBinOther word
185 {117, { 1, L_FIX
} }, // "sprmSBkc" sep.bkc bkc byte
186 {118, { 1, L_FIX
} }, // "sprmSFTitlePage" sep.fTitlePage 0 or 1 byte
187 {119, { 2, L_FIX
} }, // "sprmSCcolumns" sep.ccolM1 # of cols - 1 word
188 {120, { 2, L_FIX
} }, // "sprmSDxaColumns" sep.dxaColumns dxa word
189 {121, { 1, L_FIX
} }, // "sprmSFAutoPgn" sep.fAutoPgn obsolete byte
190 {122, { 1, L_FIX
} }, // "sprmSNfcPgn" sep.nfcPgn nfc byte
191 {123, { 2, L_FIX
} }, // "sprmSDyaPgn" sep.dyaPgn dya short
192 {124, { 2, L_FIX
} }, // "sprmSDxaPgn" sep.dxaPgn dya short
193 {125, { 1, L_FIX
} }, // "sprmSFPgnRestart" sep.fPgnRestart 0 or 1 byte
194 {126, { 1, L_FIX
} }, // "sprmSFEndnote" sep.fEndnote 0 or 1 byte
195 {127, { 1, L_FIX
} }, // "sprmSLnc" sep.lnc lnc byte
196 {128, { 1, L_FIX
} }, // "sprmSGprfIhdt" sep.grpfIhdt grpfihdt
197 {129, { 2, L_FIX
} }, // "sprmSNLnnMod" sep.nLnnMod non-neg int. word
198 {130, { 2, L_FIX
} }, // "sprmSDxaLnn" sep.dxaLnn dxa word
199 {131, { 2, L_FIX
} }, // "sprmSDyaHdrTop" sep.dyaHdrTop dya word
200 {132, { 2, L_FIX
} }, // "sprmSDyaHdrBottom" sep.dyaHdrBottom dya word
201 {133, { 1, L_FIX
} }, // "sprmSLBetween" sep.fLBetween 0 or 1 byte
202 {134, { 1, L_FIX
} }, // "sprmSVjc" sep.vjc vjc byte
203 {135, { 2, L_FIX
} }, // "sprmSLnnMin" sep.lnnMin lnn word
204 {136, { 2, L_FIX
} }, // "sprmSPgnStart" sep.pgnStart pgn word
205 {137, { 1, L_FIX
} }, // "sprmSBOrientation" sep.dmOrientPage dm byte
206 {138, { 1, L_FIX
} }, // "sprmSFFacingCol" ;;;
207 {139, { 2, L_FIX
} }, // "sprmSXaPage" sep.xaPage xa word
208 {140, { 2, L_FIX
} }, // "sprmSYaPage" sep.yaPage ya word
209 {141, { 2, L_FIX
} }, // "sprmSDxaLeft" sep.dxaLeft dxa word
210 {142, { 2, L_FIX
} }, // "sprmSDxaRight" sep.dxaRight dxa word
211 {143, { 2, L_FIX
} }, // "sprmSDyaTop" sep.dyaTop dya word
212 {144, { 2, L_FIX
} }, // "sprmSDyaBottom" sep.dyaBottom dya word
213 {145, { 2, L_FIX
} }, // "sprmSDzaGutter" sep.dzaGutter dza word
214 {146, { 2, L_FIX
} }, // "sprmTJc" tap.jc jc (low order byte is significant)
215 {147, { 2, L_FIX
} }, // "sprmTDxaLeft" tap.rgdxaCenter dxa word
216 {148, { 2, L_FIX
} }, // "sprmTDxaGapHalf" tap.dxaGapHalf, tap.rgdxaCenter
217 {149, { 1, L_FIX
} }, // "sprmTFBiDi" ;;;
218 {152, { 0, L_VAR
} }, // "sprmTDefTable10" tap.rgdxaCenter, tap.rgtc complex
219 {153, { 2, L_FIX
} }, // "sprmTDyaRowHeight" tap.dyaRowHeight dya word
220 {154, { 0, L_VAR2
} },// "sprmTDefTable" tap.rgtc complex
221 {155, { 1, L_VAR
} }, // "sprmTDefTableShd" tap.rgshd complex
222 {157, { 5, L_FIX
} }, // "sprmTSetBrc" tap.rgtc[].rgbrc complex 5 bytes
223 {158, { 4, L_FIX
} }, // "sprmTInsert" tap.rgdxaCenter,tap.rgtc complex
224 {159, { 2, L_FIX
} }, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc complex
225 {160, { 4, L_FIX
} }, // "sprmTDxaCol" tap.rgdxaCenter complex
226 {161, { 2, L_FIX
} }, // "sprmTMerge" tap.fFirstMerged, tap.fMerged complex
227 {162, { 2, L_FIX
} }, // "sprmTSplit" tap.fFirstMerged, tap.fMerged complex
228 {163, { 5, L_FIX
} }, // "sprmTSetBrc10" tap.rgtc[].rgbrc complex 5 bytes
229 {164, { 4, L_FIX
} }, // "sprmTSetShd", tap.rgshd complex 4 bytes
232 static wwSprmSearcher
aSprmSrch(aSprms
, SAL_N_ELEMENTS(aSprms
));
236 const wwSprmSearcher
*wwSprmParser::GetWW6SprmSearcher(const WW8Fib
& rFib
)
240 static const SprmInfoRow aSprms
[] =
242 { 0, { 0, L_FIX
} }, // "Default-sprm", is skipped
243 {NS_sprm::v6::sprmPIstd
, { 2, L_FIX
} }, // pap.istd (style code)
244 {NS_sprm::v6::sprmPIstdPermute
, { 3, L_VAR
} }, // pap.istd permutation
245 {NS_sprm::v6::sprmPIncLv1
, { 1, L_FIX
} }, // pap.istddifference
246 {NS_sprm::v6::sprmPJc
, { 1, L_FIX
} }, // pap.jc (justification)
247 {NS_sprm::v6::sprmPFSideBySide
, { 1, L_FIX
} }, // pap.fSideBySide
248 {NS_sprm::v6::sprmPFKeep
, { 1, L_FIX
} }, // pap.fKeep
249 {NS_sprm::v6::sprmPFKeepFollow
, { 1, L_FIX
} }, // pap.fKeepFollow
250 {NS_sprm::v6::sprmPPageBreakBefore
, { 1, L_FIX
} }, // pap.fPageBreakBefore
251 {NS_sprm::v6::sprmPBrcl
, { 1, L_FIX
} }, // pap.brcl
252 {NS_sprm::v6::sprmPBrcp
, { 1, L_FIX
} }, // pap.brcp
253 {NS_sprm::v6::sprmPAnld
, { 0, L_VAR
} }, // pap.anld (ANLD structure)
254 {NS_sprm::v6::sprmPNLvlAnm
, { 1, L_FIX
} }, // pap.nLvlAnm nn
255 {NS_sprm::v6::sprmPFNoLineNumb
, { 1, L_FIX
} }, // pap.fNoLnn
256 {NS_sprm::v6::sprmPChgTabsPapx
, { 0, L_VAR
} }, // pap.itbdMac, ...
257 {NS_sprm::v6::sprmPDxaRight
, { 2, L_FIX
} }, // pap.dxaRight
258 {NS_sprm::v6::sprmPDxaLeft
, { 2, L_FIX
} }, // pap.dxaLeft
259 {NS_sprm::v6::sprmPNest
, { 2, L_FIX
} }, // pap.dxaLeft
260 {NS_sprm::v6::sprmPDxaLeft1
, { 2, L_FIX
} }, // pap.dxaLeft1
261 {NS_sprm::v6::sprmPDyaLine
, { 4, L_FIX
} }, // pap.lspd an LSPD
262 {NS_sprm::v6::sprmPDyaBefore
, { 2, L_FIX
} }, // pap.dyaBefore
263 {NS_sprm::v6::sprmPDyaAfter
, { 2, L_FIX
} }, // pap.dyaAfter
264 {NS_sprm::v6::sprmPChgTabs
, { 0, L_VAR
} }, // pap.itbdMac, pap.rgdxaTab, ...
265 {NS_sprm::v6::sprmPFInTable
, { 1, L_FIX
} }, // pap.fInTable
266 {NS_sprm::v6::sprmPTtp
, { 1, L_FIX
} }, // pap.fTtp
267 {NS_sprm::v6::sprmPDxaAbs
, { 2, L_FIX
} }, // pap.dxaAbs
268 {NS_sprm::v6::sprmPDyaAbs
, { 2, L_FIX
} }, // pap.dyaAbs
269 {NS_sprm::v6::sprmPDxaWidth
, { 2, L_FIX
} }, // pap.dxaWidth
270 {NS_sprm::v6::sprmPPc
, { 1, L_FIX
} }, // pap.pcHorz, pap.pcVert
271 {NS_sprm::v6::sprmPBrcTop10
, { 2, L_FIX
} }, // pap.brcTop BRC10
272 {NS_sprm::v6::sprmPBrcLeft10
, { 2, L_FIX
} }, // pap.brcLeft BRC10
273 {NS_sprm::v6::sprmPBrcBottom10
, { 2, L_FIX
} }, // pap.brcBottom BRC10
274 {NS_sprm::v6::sprmPBrcRight10
, { 2, L_FIX
} }, // pap.brcRight BRC10
275 {NS_sprm::v6::sprmPBrcBetween10
, { 2, L_FIX
} }, // pap.brcBetween BRC10
276 {NS_sprm::v6::sprmPBrcBar10
, { 2, L_FIX
} }, // pap.brcBar BRC10
277 {NS_sprm::v6::sprmPFromText10
, { 2, L_FIX
} }, // pap.dxaFromText dxa
278 {NS_sprm::v6::sprmPWr
, { 1, L_FIX
} }, // pap.wr wr
279 {NS_sprm::v6::sprmPBrcTop
, { 2, L_FIX
} }, // pap.brcTop BRC
280 {NS_sprm::v6::sprmPBrcLeft
, { 2, L_FIX
} }, // pap.brcLeft BRC
281 {NS_sprm::v6::sprmPBrcBottom
, { 2, L_FIX
} }, // pap.brcBottom BRC
282 {NS_sprm::v6::sprmPBrcRight
, { 2, L_FIX
} }, // pap.brcRight BRC
283 {NS_sprm::v6::sprmPBrcBetween
, { 2, L_FIX
} }, // pap.brcBetween BRC
284 {NS_sprm::v6::sprmPBrcBar
, { 2, L_FIX
} }, // pap.brcBar BRC word
285 {NS_sprm::v6::sprmPFNoAutoHyph
, { 1, L_FIX
} }, // pap.fNoAutoHyph
286 {NS_sprm::v6::sprmPWHeightAbs
, { 2, L_FIX
} }, // pap.wHeightAbs w
287 {NS_sprm::v6::sprmPDcs
, { 2, L_FIX
} }, // pap.dcs DCS
288 {NS_sprm::v6::sprmPShd
, { 2, L_FIX
} }, // pap.shd SHD
289 {NS_sprm::v6::sprmPDyaFromText
, { 2, L_FIX
} }, // pap.dyaFromText dya
290 {NS_sprm::v6::sprmPDxaFromText
, { 2, L_FIX
} }, // pap.dxaFromText dxa
291 {NS_sprm::v6::sprmPFLocked
, { 1, L_FIX
} }, // pap.fLocked 0 or 1 byte
292 {NS_sprm::v6::sprmPFWidowControl
, { 1, L_FIX
} }, // pap.fWidowControl 0 or 1 byte
293 {NS_sprm::v6::sprmPRuler
, { 0, L_FIX
} },
294 { 64, { 0, L_VAR
} }, // rtl property ?
295 {NS_sprm::v6::sprmCFStrikeRM
, { 1, L_FIX
} }, // chp.fRMarkDel 1 or 0 bit
296 {NS_sprm::v6::sprmCFRMark
, { 1, L_FIX
} }, // chp.fRMark 1 or 0 bit
297 {NS_sprm::v6::sprmCFFldVanish
, { 1, L_FIX
} }, // chp.fFieldVanish 1 or 0 bit
298 {NS_sprm::v6::sprmCPicLocation
, { 0, L_VAR
} }, // chp.fcPic and chp.fSpec
299 {NS_sprm::v6::sprmCIbstRMark
, { 2, L_FIX
} }, // chp.ibstRMark index into sttbRMark
300 {NS_sprm::v6::sprmCDttmRMark
, { 4, L_FIX
} }, // chp.dttm DTTM long
301 {NS_sprm::v6::sprmCFData
, { 1, L_FIX
} }, // chp.fData 1 or 0 bit
302 {NS_sprm::v6::sprmCRMReason
, { 2, L_FIX
} }, // chp.idslRMReason an index to a table
303 {NS_sprm::v6::sprmCChse
, { 3, L_FIX
} }, // chp.fChsDiff and chp.chse
304 {NS_sprm::v6::sprmCSymbol
, { 0, L_VAR
} }, // chp.fSpec, chp.chSym and chp.ftcSym
305 {NS_sprm::v6::sprmCFOle2
, { 1, L_FIX
} }, // chp.fOle2 1 or 0 bit
306 { 77, { 0, L_VAR
} }, // unknown
307 { 79, { 0, L_VAR
} }, // unknown
308 {NS_sprm::v6::sprmCIstd
, { 2, L_FIX
} }, // chp.istd istd, see stylesheet definition
309 {NS_sprm::v6::sprmCIstdPermute
, { 0, L_VAR
} }, // chp.istd permutation vector
310 {NS_sprm::v6::sprmCDefault
, { 0, L_VAR
} }, // whole CHP
311 {NS_sprm::v6::sprmCPlain
, { 0, L_FIX
} }, // whole CHP
312 {NS_sprm::v6::sprmCFBold
, { 1, L_FIX
} }, // chp.fBold 0,1, 128, or 129
313 {NS_sprm::v6::sprmCFItalic
, { 1, L_FIX
} }, // chp.fItalic 0,1, 128, or 129
314 {NS_sprm::v6::sprmCFStrike
, { 1, L_FIX
} }, // chp.fStrike 0,1, 128, or 129
315 {NS_sprm::v6::sprmCFOutline
, { 1, L_FIX
} }, // chp.fOutline 0,1, 128, or 129
316 {NS_sprm::v6::sprmCFShadow
, { 1, L_FIX
} }, // chp.fShadow 0,1, 128, or 129
317 {NS_sprm::v6::sprmCFSmallCaps
, { 1, L_FIX
} }, // chp.fSmallCaps 0,1, 128, or 129
318 {NS_sprm::v6::sprmCFCaps
, { 1, L_FIX
} }, // chp.fCaps 0,1, 128, or 129
319 {NS_sprm::v6::sprmCFVanish
, { 1, L_FIX
} }, // chp.fVanish 0,1, 128, or 129
320 {NS_sprm::v6::sprmCFtc
, { 2, L_FIX
} }, // chp.ftc ftc word
321 {NS_sprm::v6::sprmCKul
, { 1, L_FIX
} }, // chp.kul kul byte
322 {NS_sprm::v6::sprmCSizePos
, { 3, L_FIX
} }, // chp.hps, chp.hpsPos
323 {NS_sprm::v6::sprmCDxaSpace
, { 2, L_FIX
} }, // chp.dxaSpace dxa
324 {NS_sprm::v6::sprmCLid
, { 2, L_FIX
} }, // chp.lid LID
325 {NS_sprm::v6::sprmCIco
, { 1, L_FIX
} }, // chp.ico ico byte
326 {NS_sprm::v6::sprmCHps
, { 2, L_FIX
} }, // chp.hps hps !word!
327 {NS_sprm::v6::sprmCHpsInc
, { 1, L_FIX
} }, // chp.hps
328 {NS_sprm::v6::sprmCHpsPos
, { 2, L_FIX
} }, // chp.hpsPos hps !word!
329 {NS_sprm::v6::sprmCHpsPosAdj
, { 1, L_FIX
} }, // chp.hpsPos hps
330 {NS_sprm::v6::sprmCMajority
, { 0, L_VAR
} }, // chp.fBold, chp.fItalic, ...
331 {NS_sprm::v6::sprmCIss
, { 1, L_FIX
} }, // chp.iss iss
332 {NS_sprm::v6::sprmCHpsNew50
, { 0, L_VAR
} }, // chp.hps hps variable width
333 {NS_sprm::v6::sprmCHpsInc1
, { 0, L_VAR
} }, // chp.hps complex
334 {NS_sprm::v6::sprmCHpsKern
, { 2, L_FIX
} }, // chp.hpsKern hps
335 {NS_sprm::v6::sprmCMajority50
, { 0, L_VAR
} }, // chp.fBold, chp.fItalic, ...
336 {NS_sprm::v6::sprmCHpsMul
, { 2, L_FIX
} }, // chp.hps percentage to grow hps
337 {NS_sprm::v6::sprmCCondHyhen
, { 2, L_FIX
} }, // chp.ysri ysri
338 {111, { 0, L_VAR
} }, // sprmCFBoldBi or font code
339 {112, { 0, L_VAR
} }, // sprmCFItalicBi or font code
340 {113, { 0, L_VAR
} }, // ww7 rtl font
341 {114, { 0, L_VAR
} }, // ww7 lid
342 {115, { 0, L_VAR
} }, // ww7 CJK font
343 {116, { 0, L_VAR
} }, // ww7 fontsize
344 {NS_sprm::v6::sprmCFSpec
, { 1, L_FIX
} }, // chp.fSpec 1 or 0 bit
345 {NS_sprm::v6::sprmCFObj
, { 1, L_FIX
} }, // chp.fObj 1 or 0 bit
346 {NS_sprm::v6::sprmPicBrcl
, { 1, L_FIX
} }, // pic.brcl brcl (see PIC definition)
347 {NS_sprm::v6::sprmPicScale
, {12, L_VAR
} }, // pic.mx, pic.my, pic.dxaCropleft,
348 {NS_sprm::v6::sprmPicBrcTop
, { 2, L_FIX
} }, // pic.brcTop BRC word
349 {NS_sprm::v6::sprmPicBrcLeft
, { 2, L_FIX
} }, // pic.brcLeft BRC word
350 {NS_sprm::v6::sprmPicBrcBottom
, { 2, L_FIX
} }, // pic.brcBottom BRC word
351 {NS_sprm::v6::sprmPicBrcRight
, { 2, L_FIX
} }, // pic.brcRight BRC word
352 {NS_sprm::v6::sprmSScnsPgn
, { 1, L_FIX
} }, // sep.cnsPgn cns byte
353 {NS_sprm::v6::sprmSiHeadingPgn
, { 1, L_FIX
} }, // sep.iHeadingPgn
354 {NS_sprm::v6::sprmSOlstAnm
, { 0, L_VAR
} }, // sep.olstAnm OLST variable length
355 {NS_sprm::v6::sprmSDxaColWidth
, { 3, L_FIX
} }, // sep.rgdxaColWidthSpacing complex
356 {NS_sprm::v6::sprmSDxaColSpacing
, { 3, L_FIX
} }, // sep.rgdxaColWidthSpacing
357 {NS_sprm::v6::sprmSFEvenlySpaced
, { 1, L_FIX
} }, // sep.fEvenlySpaced 1 or 0
358 {NS_sprm::v6::sprmSFProtected
, { 1, L_FIX
} }, // sep.fUnlocked 1 or 0 byte
359 {NS_sprm::v6::sprmSDmBinFirst
, { 2, L_FIX
} }, // sep.dmBinFirst word
360 {NS_sprm::v6::sprmSDmBinOther
, { 2, L_FIX
} }, // sep.dmBinOther word
361 {NS_sprm::v6::sprmSBkc
, { 1, L_FIX
} }, // sep.bkc bkc byte
362 {NS_sprm::v6::sprmSFTitlePage
, { 1, L_FIX
} }, // sep.fTitlePage 0 or 1 byte
363 {NS_sprm::v6::sprmSCcolumns
, { 2, L_FIX
} }, // sep.ccolM1 # of cols - 1 word
364 {NS_sprm::v6::sprmSDxaColumns
, { 2, L_FIX
} }, // sep.dxaColumns dxa word
365 {NS_sprm::v6::sprmSFAutoPgn
, { 1, L_FIX
} }, // sep.fAutoPgn obsolete byte
366 {NS_sprm::v6::sprmSNfcPgn
, { 1, L_FIX
} }, // sep.nfcPgn nfc byte
367 {NS_sprm::v6::sprmSDyaPgn
, { 2, L_FIX
} }, // sep.dyaPgn dya short
368 {NS_sprm::v6::sprmSDxaPgn
, { 2, L_FIX
} }, // sep.dxaPgn dya short
369 {NS_sprm::v6::sprmSFPgnRestart
, { 1, L_FIX
} }, // sep.fPgnRestart 0 or 1 byte
370 {NS_sprm::v6::sprmSFEndnote
, { 1, L_FIX
} }, // sep.fEndnote 0 or 1 byte
371 {NS_sprm::v6::sprmSLnc
, { 1, L_FIX
} }, // sep.lnc lnc byte
372 {NS_sprm::v6::sprmSGprfIhdt
, { 1, L_FIX
} }, // sep.grpfIhdt grpfihdt
373 {NS_sprm::v6::sprmSNLnnMod
, { 2, L_FIX
} }, // sep.nLnnMod non-neg int. word
374 {NS_sprm::v6::sprmSDxaLnn
, { 2, L_FIX
} }, // sep.dxaLnn dxa word
375 {NS_sprm::v6::sprmSDyaHdrTop
, { 2, L_FIX
} }, // sep.dyaHdrTop dya word
376 {NS_sprm::v6::sprmSDyaHdrBottom
, { 2, L_FIX
} }, // sep.dyaHdrBottom dya word
377 {NS_sprm::v6::sprmSLBetween
, { 1, L_FIX
} }, // sep.fLBetween 0 or 1 byte
378 {NS_sprm::v6::sprmSVjc
, { 1, L_FIX
} }, // sep.vjc vjc byte
379 {NS_sprm::v6::sprmSLnnMin
, { 2, L_FIX
} }, // sep.lnnMin lnn word
380 {NS_sprm::v6::sprmSPgnStart
, { 2, L_FIX
} }, // sep.pgnStart pgn word
381 {NS_sprm::v6::sprmSBOrientation
, { 1, L_FIX
} }, // sep.dmOrientPage dm byte
382 {NS_sprm::v6::sprmSBCustomize
, { 0, L_FIX
} },
383 {NS_sprm::v6::sprmSXaPage
, { 2, L_FIX
} }, // sep.xaPage xa word
384 {NS_sprm::v6::sprmSYaPage
, { 2, L_FIX
} }, // sep.yaPage ya word
385 {NS_sprm::v6::sprmSDxaLeft
, { 2, L_FIX
} }, // sep.dxaLeft dxa word
386 {NS_sprm::v6::sprmSDxaRight
, { 2, L_FIX
} }, // sep.dxaRight dxa word
387 {NS_sprm::v6::sprmSDyaTop
, { 2, L_FIX
} }, // sep.dyaTop dya word
388 {NS_sprm::v6::sprmSDyaBottom
, { 2, L_FIX
} }, // sep.dyaBottom dya word
389 {NS_sprm::v6::sprmSDzaGutter
, { 2, L_FIX
} }, // sep.dzaGutter dza word
390 {NS_sprm::v6::sprmSDMPaperReq
, { 2, L_FIX
} }, // sep.dmPaperReq dm word
391 {179, { 0, L_VAR
} }, // rtl property ?
392 {181, { 0, L_VAR
} }, // rtl property ?
393 {NS_sprm::v6::sprmTJc
, { 2, L_FIX
} }, // tap.jc jc (low order byte is significant)
394 {NS_sprm::v6::sprmTDxaLeft
, { 2, L_FIX
} }, // tap.rgdxaCenter dxa word
395 {NS_sprm::v6::sprmTDxaGapHalf
, { 2, L_FIX
} }, // tap.dxaGapHalf, tap.rgdxaCenter
396 {NS_sprm::v6::sprmTFCantSplit
, { 1, L_FIX
} }, // tap.fCantSplit 1 or 0 byte
397 {NS_sprm::v6::sprmTTableHeader
, { 1, L_FIX
} }, // tap.fTableHeader 1 or 0 byte
398 {NS_sprm::v6::sprmTTableBorders
, {12, L_FIX
} }, // tap.rgbrcTable complex 12 bytes
399 {NS_sprm::v6::sprmTDefTable10
, { 0, L_VAR
} }, // tap.rgdxaCenter, tap.rgtc complex
400 {NS_sprm::v6::sprmTDyaRowHeight
, { 2, L_FIX
} }, // tap.dyaRowHeight dya word
401 {NS_sprm::v6::sprmTDefTable
, { 0, L_VAR2
} }, // tap.rgtc complex
402 {NS_sprm::v6::sprmTDefTableShd
, { 1, L_VAR
} }, // tap.rgshd complex
403 {NS_sprm::v6::sprmTTlp
, { 4, L_FIX
} }, // tap.tlp TLP 4 bytes
404 {NS_sprm::v6::sprmTSetBrc
, { 5, L_FIX
} }, // tap.rgtc[].rgbrc complex 5 bytes
405 {NS_sprm::v6::sprmTInsert
, { 4, L_FIX
} }, // tap.rgdxaCenter,tap.rgtc complex
406 {NS_sprm::v6::sprmTDelete
, { 2, L_FIX
} }, // tap.rgdxaCenter, tap.rgtc complex
407 {NS_sprm::v6::sprmTDxaCol
, { 4, L_FIX
} }, // tap.rgdxaCenter complex
408 {NS_sprm::v6::sprmTMerge
, { 2, L_FIX
} }, // tap.fFirstMerged, tap.fMerged complex
409 {NS_sprm::v6::sprmTSplit
, { 2, L_FIX
} }, // tap.fFirstMerged, tap.fMerged complex
410 {NS_sprm::v6::sprmTSetBrc10
, { 5, L_FIX
} }, // tap.rgtc[].rgbrc complex 5 bytes
411 {NS_sprm::v6::sprmTSetShd
, { 4, L_FIX
} }, // tap.rgshd complex 4 bytes
412 {207, { 0, L_VAR
} } // rtl property ?
415 if (rFib
.m_wIdent
>= 0xa697 && rFib
.m_wIdent
<= 0xa699)
417 //see Read_AmbiguousSPRM for this oddity
418 static wwSprmSearcher
aSprmSrch(aSprms
, SAL_N_ELEMENTS(aSprms
), true);
422 static wwSprmSearcher
aSprmSrch(aSprms
, SAL_N_ELEMENTS(aSprms
));
426 void wwSprmSearcher::patchCJKVariant()
428 for (sal_uInt16 nId
= 111; nId
<= 113; ++nId
)
430 SprmInfo
& amb1
= map_
[nId
];
432 amb1
.nVari
= wwSprmParser::L_FIX
;
436 template <class Sprm
> static constexpr SprmInfoRow
InfoRow()
438 return { Sprm::val
, { Sprm::len
, Sprm::varlen
? wwSprmParser::L_VAR
: wwSprmParser::L_FIX
} };
441 const wwSprmSearcher
*wwSprmParser::GetWW8SprmSearcher()
445 static const SprmInfoRow aSprms
[] =
447 { 0, { 0, L_FIX
} }, // "Default-sprm"/ is skipped
448 InfoRow
<NS_sprm::PIstd
>(), // pap.istd;istd (style code);short;
449 InfoRow
<NS_sprm::PIstdPermute
>(), // pap.istd;permutation vector
450 InfoRow
<NS_sprm::PIncLvl
>(), // pap.istd, pap.lvl;difference
451 // between istd of base PAP and istd of PAP to be
453 InfoRow
<NS_sprm::PJc80
>(), // pap.jc;jc (justification);byte;
454 {NS_sprm::LN_PFSideBySide
, { 1, L_FIX
} }, // "sprmPFSideBySide" pap.fSideBySide;0 or 1;byte;
455 InfoRow
<NS_sprm::PFKeep
>(), // pap.fKeep;0 or 1;byte;
456 InfoRow
<NS_sprm::PFKeepFollow
>(), // pap.fKeepFollow;0 or 1;byte;
457 InfoRow
<NS_sprm::PFPageBreakBefore
>(), // pap.fPageBreakBefore;
459 {NS_sprm::LN_PBrcl
, { 1, L_FIX
} }, // "sprmPBrcl" pap.brcl;brcl;byte;
460 {NS_sprm::LN_PBrcp
, { 1, L_FIX
} }, // "sprmPBrcp" pap.brcp;brcp;byte;
461 InfoRow
<NS_sprm::PIlvl
>(), // pap.ilvl;ilvl;byte;
462 InfoRow
<NS_sprm::PIlfo
>(), // pap.ilfo;ilfo (list index) ;short;
463 InfoRow
<NS_sprm::PFNoLineNumb
>(), // pap.fNoLnn;0 or 1;byte;
464 InfoRow
<NS_sprm::PChgTabsPapx
>(), // pap.itbdMac, pap.rgdxaTab,
466 InfoRow
<NS_sprm::PDxaRight80
>(), // pap.dxaRight;dxa;word;
467 InfoRow
<NS_sprm::PDxaLeft80
>(), // pap.dxaLeft;dxa;word;
468 InfoRow
<NS_sprm::PNest80
>(), // pap.dxaLeft;dxa
469 InfoRow
<NS_sprm::PDxaLeft180
>(), // pap.dxaLeft1;dxa;word;
470 InfoRow
<NS_sprm::PDyaLine
>(), // pap.lspd;an LSPD, a long word
471 // structure consisting of a short of dyaLine
472 // followed by a short of fMultLinespace
473 InfoRow
<NS_sprm::PDyaBefore
>(), // pap.dyaBefore;dya;word;
474 InfoRow
<NS_sprm::PDyaAfter
>(), // pap.dyaAfter;dya;word;
475 InfoRow
<NS_sprm::PChgTabs
>(), // pap.itbdMac, pap.rgdxaTab,
477 InfoRow
<NS_sprm::PFInTable
>(), // pap.fInTable;0 or 1;byte;
478 InfoRow
<NS_sprm::PFTtp
>(), // pap.fTtp;0 or 1;byte;
479 InfoRow
<NS_sprm::PDxaAbs
>(), // pap.dxaAbs;dxa;word;
480 InfoRow
<NS_sprm::PDyaAbs
>(), // pap.dyaAbs;dya;word;
481 InfoRow
<NS_sprm::PDxaWidth
>(), // pap.dxaWidth;dxa;word;
482 InfoRow
<NS_sprm::PPc
>(), // pap.pcHorz, pap.pcVert;complex
483 {NS_sprm::LN_PBrcTop10
, { 2, L_FIX
} }, // "sprmPBrcTop10" pap.brcTop;BRC10;word;
484 {NS_sprm::LN_PBrcLeft10
, { 2, L_FIX
} }, // "sprmPBrcLeft10" pap.brcLeft;BRC10;word;
485 {NS_sprm::LN_PBrcBottom10
, { 2, L_FIX
} }, // "sprmPBrcBottom10" pap.brcBottom;BRC10;word;
486 {NS_sprm::LN_PBrcRight10
, { 2, L_FIX
} }, // "sprmPBrcRight10" pap.brcRight;BRC10;word;
487 {NS_sprm::LN_PBrcBetween10
, { 2, L_FIX
} }, // "sprmPBrcBetween10" pap.brcBetween;BRC10;word;
488 {NS_sprm::LN_PBrcBar10
, { 2, L_FIX
} }, // "sprmPBrcBar10" pap.brcBar;BRC10;word;
489 {NS_sprm::LN_PDxaFromText10
, { 2, L_FIX
} }, // "sprmPDxaFromText10" pap.dxaFromText;dxa;word;
490 InfoRow
<NS_sprm::PWr
>(), // pap.wr;wr
491 InfoRow
<NS_sprm::PBrcTop80
>(), // pap.brcTop;BRC;long;
492 InfoRow
<NS_sprm::PBrcLeft80
>(), // pap.brcLeft;BRC;long;
493 InfoRow
<NS_sprm::PBrcBottom80
>(), // pap.brcBottom;BRC;long;
494 InfoRow
<NS_sprm::PBrcRight80
>(), // pap.brcRight;BRC;long;
495 InfoRow
<NS_sprm::PBrcBetween80
>(), // pap.brcBetween;BRC;long;
496 InfoRow
<NS_sprm::PBrcBar80
>(), // pap.brcBar;BRC;long;
497 InfoRow
<NS_sprm::PFNoAutoHyph
>(), // pap.fNoAutoHyph;0 or 1;byte;
498 InfoRow
<NS_sprm::PWHeightAbs
>(), // pap.wHeightAbs;w;word;
499 InfoRow
<NS_sprm::PDcs
>(), // pap.dcs;DCS;short;
500 InfoRow
<NS_sprm::PShd80
>(), // pap.shd;SHD;word;
501 InfoRow
<NS_sprm::PDyaFromText
>(), // pap.dyaFromText;dya;word;
502 InfoRow
<NS_sprm::PDxaFromText
>(), // pap.dxaFromText;dxa;word;
503 InfoRow
<NS_sprm::PFLocked
>(), // pap.fLocked;0 or 1;byte;
504 InfoRow
<NS_sprm::PFWidowControl
>(), // pap.fWidowControl;0 or 1
505 {NS_sprm::LN_PRuler
, { 0, L_VAR
} }, // "sprmPRuler" ;;variable length;
506 InfoRow
<NS_sprm::PFKinsoku
>(), // pap.fKinsoku;0 or 1;byte;
507 InfoRow
<NS_sprm::PFWordWrap
>(), // pap.fWordWrap;0 or 1;byte;
508 InfoRow
<NS_sprm::PFOverflowPunct
>(), // pap.fOverflowPunct;0 or 1
509 InfoRow
<NS_sprm::PFTopLinePunct
>(), // pap.fTopLinePunct;0 or 1
510 InfoRow
<NS_sprm::PFAutoSpaceDE
>(), // pap.fAutoSpaceDE;0 or 1
511 InfoRow
<NS_sprm::PFAutoSpaceDN
>(), // pap.fAutoSpaceDN;0 or 1
512 InfoRow
<NS_sprm::PWAlignFont
>(), // pap.wAlignFont;iFa
513 InfoRow
<NS_sprm::PFrameTextFlow
>(), // pap.fVertical pap.fBackward
514 // pap.fRotateFont;complex
515 {NS_sprm::LN_PISnapBaseLine
, { 1, L_FIX
} }, // "sprmPISnapBaseLine" obsolete: not applicable in
516 // Word97 and later versions;
517 {NS_sprm::LN_PAnld
, { 0, L_VAR
} }, // "sprmPAnld" pap.anld;;variable length;
518 {NS_sprm::LN_PPropRMark
, { 0, L_VAR
} }, // "sprmPPropRMark" pap.fPropRMark;complex
519 InfoRow
<NS_sprm::POutLvl
>(), // pap.lvl;has no effect if pap.istd
521 InfoRow
<NS_sprm::PFBiDi
>(), // ;;byte;
522 InfoRow
<NS_sprm::PFNumRMIns
>(), // pap.fNumRMIns;1 or 0;bit;
523 {NS_sprm::LN_PCrLf
, { 1, L_FIX
} }, // "sprmPCrLf" ;;byte;
524 InfoRow
<NS_sprm::PNumRM
>(), // pap.numrm;;variable length;
525 {NS_sprm::LN_PHugePapx
, { 4, L_FIX
} }, // "sprmPHugePapx" fc in the data stream to locate
527 InfoRow
<NS_sprm::PHugePapx
>(), // fc in the data stream to locate
529 InfoRow
<NS_sprm::PFUsePgsuSettings
>(), // pap.fUsePgsuSettings;
531 InfoRow
<NS_sprm::PFAdjustRight
>(), // pap.fAdjustRight;1 or 0;byte;
532 InfoRow
<NS_sprm::CFRMarkDel
>(), // chp.fRMarkDel;1 or 0;bit;
533 InfoRow
<NS_sprm::CFRMarkIns
>(), // chp.fRMark;1 or 0;bit;
534 InfoRow
<NS_sprm::CFFldVanish
>(), // chp.fFieldVanish;1 or 0;bit;
535 InfoRow
<NS_sprm::CPicLocation
>(), // chp.fcPic and chp.fSpec;
536 InfoRow
<NS_sprm::CIbstRMark
>(), // chp.ibstRMark;index into
538 InfoRow
<NS_sprm::CDttmRMark
>(), // chp.dttmRMark;DTTM;long;
539 InfoRow
<NS_sprm::CFData
>(), // chp.fData;1 or 0;bit;
540 InfoRow
<NS_sprm::CIdslRMark
>(), // chp.idslRMReason;an index to a
541 // table of strings defined in Word 6.0
542 // executables;short;
543 {NS_sprm::LN_CChs
, { 1, L_FIX
} }, // "sprmCChs" chp.fChsDiff and chp.chse;
544 InfoRow
<NS_sprm::CSymbol
>(), // chp.fSpec, chp.xchSym and
546 InfoRow
<NS_sprm::CFOle2
>(), // chp.fOle2;1 or 0;bit;
547 {NS_sprm::LN_CIdCharType
, { 0, L_FIX
} }, // "sprmCIdCharType" obsolete: not applicable in
548 // Word97 and later versions;
549 InfoRow
<NS_sprm::CHighlight
>(), // chp.fHighlight,
550 // chp.icoHighlight;ico (fHighlight is set to 1 iff
552 {NS_sprm::LN_CObjLocation
, { 4, L_FIX
} }, // "sprmCObjLocation" chp.fcObj;FC;long;
553 {NS_sprm::LN_CFFtcAsciSymb
, { 0, L_FIX
} }, // "sprmCFFtcAsciSymb" ;;;
554 InfoRow
<NS_sprm::CIstd
>(), // chp.istd;istd, see stylesheet def
555 InfoRow
<NS_sprm::CIstdPermute
>(), // chp.istd;permutation vector
556 {NS_sprm::LN_CDefault
, { 0, L_VAR
} }, // "sprmCDefault" whole CHP;none;variable length;
557 InfoRow
<NS_sprm::CPlain
>(), // whole CHP;none;0;
558 InfoRow
<NS_sprm::CKcd
>(), // ;;;
559 InfoRow
<NS_sprm::CFBold
>(), // chp.fBold;0,1, 128, or 129
560 InfoRow
<NS_sprm::CFItalic
>(), // chp.fItalic;0,1, 128, or 129
561 InfoRow
<NS_sprm::CFStrike
>(), // chp.fStrike;0,1, 128, or 129
562 InfoRow
<NS_sprm::CFOutline
>(), // chp.fOutline;0,1, 128, or 129
563 InfoRow
<NS_sprm::CFShadow
>(), // chp.fShadow;0,1, 128, or 129
564 InfoRow
<NS_sprm::CFSmallCaps
>(), // chp.fSmallCaps;0,1, 128, or 129
565 InfoRow
<NS_sprm::CFCaps
>(), // chp.fCaps;0,1, 128, or 129
566 InfoRow
<NS_sprm::CFVanish
>(), // chp.fVanish;0,1, 128, or 129
567 {NS_sprm::LN_CFtcDefault
, { 2, L_FIX
} }, // "sprmCFtcDefault" ;ftc, only used internally
568 InfoRow
<NS_sprm::CKul
>(), // chp.kul;kul;byte;
569 {NS_sprm::LN_CSizePos
, { 3, L_FIX
} }, // "sprmCSizePos" chp.hps, chp.hpsPos;3 bytes;
570 InfoRow
<NS_sprm::CDxaSpace
>(), // chp.dxaSpace;dxa;word;
571 {NS_sprm::LN_CLid
, { 2, L_FIX
} }, // "sprmCLid" ;only used internally never stored
572 InfoRow
<NS_sprm::CIco
>(), // chp.ico;ico;byte;
573 InfoRow
<NS_sprm::CHps
>(), // chp.hps;hps
574 {NS_sprm::LN_CHpsInc
, { 1, L_FIX
} }, // "sprmCHpsInc" chp.hps;
575 InfoRow
<NS_sprm::CHpsPos
>(), // chp.hpsPos;hps;short; (doc wrong)
576 {NS_sprm::LN_CHpsPosAdj
, { 1, L_FIX
} }, // "sprmCHpsPosAdj" chp.hpsPos;hps
577 InfoRow
<NS_sprm::CMajority
>(), // chp.fBold, chp.fItalic,
578 // chp.fSmallCaps, chp.fVanish, chp.fStrike,
579 // chp.fCaps, chp.rgftc, chp.hps, chp.hpsPos,
580 // chp.kul, chp.dxaSpace, chp.ico,
581 // chp.rglid;complex;variable length, length byte
582 // plus size of following grpprl;
583 InfoRow
<NS_sprm::CIss
>(), // chp.iss;iss;byte;
584 {NS_sprm::LN_CHpsNew50
, { 0, L_VAR
} }, // "sprmCHpsNew50" chp.hps;hps;variable width
585 {NS_sprm::LN_CHpsInc1
, { 0, L_VAR
} }, // "sprmCHpsInc1" chp.hps;complex
586 InfoRow
<NS_sprm::CHpsKern
>(), // chp.hpsKern;hps;short;
587 {NS_sprm::LN_CMajority50
, { 2, L_FIX
} }, // "sprmCMajority50" chp.fBold, chp.fItalic,
588 // chp.fSmallCaps, chp.fVanish, chp.fStrike,
589 // chp.fCaps, chp.ftc, chp.hps, chp.hpsPos, chp.kul,
590 // chp.dxaSpace, chp.ico,;complex
591 {NS_sprm::LN_CHpsMul
, { 2, L_FIX
} }, // "sprmCHpsMul" chp.hps;percentage to grow hps
592 InfoRow
<NS_sprm::CHresi
>(), // chp.ysri;ysri;short;
593 InfoRow
<NS_sprm::CRgFtc0
>(), // chp.rgftc[0];ftc for ASCII text
594 InfoRow
<NS_sprm::CRgFtc1
>(), // chp.rgftc[1];ftc for Far East text
595 InfoRow
<NS_sprm::CRgFtc2
>(), // chp.rgftc[2];ftc for non-FE text
596 InfoRow
<NS_sprm::CCharScale
>(),
597 InfoRow
<NS_sprm::CFDStrike
>(), // chp.fDStrike;;byte;
598 InfoRow
<NS_sprm::CFImprint
>(), // chp.fImprint;1 or 0;bit;
599 InfoRow
<NS_sprm::CFSpec
>(), // chp.fSpec ;1 or 0;bit;
600 InfoRow
<NS_sprm::CFObj
>(), // chp.fObj;1 or 0;bit;
601 InfoRow
<NS_sprm::CPropRMark90
>(), // chp.fPropRMark,
602 // chp.ibstPropRMark, chp.dttmPropRMark;Complex
603 InfoRow
<NS_sprm::CFEmboss
>(), // chp.fEmboss;1 or 0;bit;
604 InfoRow
<NS_sprm::CSfxText
>(), // chp.sfxtText;text animation;byte;
605 InfoRow
<NS_sprm::CFBiDi
>(), // ;;;
606 {NS_sprm::LN_CFDiacColor
, { 1, L_FIX
} }, // "sprmCFDiacColor" ;;;
607 InfoRow
<NS_sprm::CFBoldBi
>(), // ;;;
608 InfoRow
<NS_sprm::CFItalicBi
>(), // ;;;
609 InfoRow
<NS_sprm::CFtcBi
>(),
610 InfoRow
<NS_sprm::CLidBi
>(), // ;;;
611 InfoRow
<NS_sprm::CIcoBi
>(), // ;;;
612 InfoRow
<NS_sprm::CHpsBi
>(), // ;;;
613 InfoRow
<NS_sprm::CDispFldRMark
>(), // chp.fDispFieldRMark,
614 // chp.ibstDispFieldRMark, chp.dttmDispFieldRMark ;
615 InfoRow
<NS_sprm::CIbstRMarkDel
>(), // chp.ibstRMarkDel;index into
617 InfoRow
<NS_sprm::CDttmRMarkDel
>(), // chp.dttmRMarkDel;DTTM;long;
618 InfoRow
<NS_sprm::CBrc80
>(), // chp.brc;BRC;long;
619 InfoRow
<NS_sprm::CShd80
>(), // chp.shd;SHD;short;
620 InfoRow
<NS_sprm::CIdslRMarkDel
>(), // chp.idslRMReasonDel;an index
621 // to a table of strings defined in Word 6.0
622 // executables;short;
623 InfoRow
<NS_sprm::CFUsePgsuSettings
>(),
624 // chp.fUsePgsuSettings;1 or 0
625 {NS_sprm::LN_CCpg
, { 2, L_FIX
} }, // "sprmCCpg" ;;word;
626 InfoRow
<NS_sprm::CRgLid0_80
>(), // chp.rglid[0];LID: for non-FE text
627 InfoRow
<NS_sprm::CRgLid1_80
>(), // chp.rglid[1];LID: for Far East text
628 InfoRow
<NS_sprm::CIdctHint
>(), // chp.idctHint;IDCT:
629 {NS_sprm::LN_PicBrcl
, { 1, L_FIX
} }, // "sprmPicBrcl" pic.brcl;brcl (see PIC definition)
630 {NS_sprm::LN_PicScale
, { 0, L_VAR
} }, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
631 // pic.dyaCropTop pic.dxaCropRight,
632 // pic.dyaCropBottom;Complex
633 InfoRow
<NS_sprm::PicBrcTop80
>(), // pic.brcTop;BRC;long;
634 InfoRow
<NS_sprm::PicBrcLeft80
>(), // pic.brcLeft;BRC;long;
635 InfoRow
<NS_sprm::PicBrcBottom80
>(), // pic.brcBottom;BRC;long;
636 InfoRow
<NS_sprm::PicBrcRight80
>(), // pic.brcRight;BRC;long;
637 InfoRow
<NS_sprm::ScnsPgn
>(), // sep.cnsPgn;cns;byte;
638 InfoRow
<NS_sprm::SiHeadingPgn
>(), // sep.iHeadingPgn;heading number
640 {NS_sprm::LN_SOlstAnm
, { 0, L_VAR
} }, // "sprmSOlstAnm" sep.olstAnm;OLST;variable length;
641 InfoRow
<NS_sprm::SDxaColWidth
>(), // sep.rgdxaColWidthSpacing;
642 InfoRow
<NS_sprm::SDxaColSpacing
>(), // sep.rgdxaColWidthSpacing;
644 InfoRow
<NS_sprm::SFEvenlySpaced
>(), // sep.fEvenlySpaced;1 or 0
645 InfoRow
<NS_sprm::SFProtected
>(), // sep.fUnlocked;1 or 0;byte;
646 InfoRow
<NS_sprm::SDmBinFirst
>(), // sep.dmBinFirst;;word;
647 InfoRow
<NS_sprm::SDmBinOther
>(), // sep.dmBinOther;;word;
648 InfoRow
<NS_sprm::SBkc
>(), // sep.bkc;bkc;byte;
649 InfoRow
<NS_sprm::SFTitlePage
>(), // sep.fTitlePage;0 or 1;byte;
650 InfoRow
<NS_sprm::SCcolumns
>(), // sep.ccolM1;# of cols - 1;word;
651 InfoRow
<NS_sprm::SDxaColumns
>(), // sep.dxaColumns;dxa;word;
652 {NS_sprm::LN_SFAutoPgn
, { 1, L_FIX
} }, // "sprmSFAutoPgn" sep.fAutoPgn;obsolete;byte;
653 InfoRow
<NS_sprm::SNfcPgn
>(), // sep.nfcPgn;nfc;byte;
654 {NS_sprm::LN_SDyaPgn
, { 2, L_FIX
} }, // "sprmSDyaPgn" sep.dyaPgn;dya;short;
655 {NS_sprm::LN_SDxaPgn
, { 2, L_FIX
} }, // "sprmSDxaPgn" sep.dxaPgn;dya;short;
656 InfoRow
<NS_sprm::SFPgnRestart
>(), // sep.fPgnRestart;0 or 1;byte;
657 InfoRow
<NS_sprm::SFEndnote
>(), // sep.fEndnote;0 or 1;byte;
658 InfoRow
<NS_sprm::SLnc
>(), // sep.lnc;lnc;byte;
659 {NS_sprm::LN_SGprfIhdt
, { 1, L_FIX
} }, // "sprmSGprfIhdt" sep.grpfIhdt;grpfihdt
660 InfoRow
<NS_sprm::SNLnnMod
>(), // sep.nLnnMod;non-neg int.;word;
661 InfoRow
<NS_sprm::SDxaLnn
>(), // sep.dxaLnn;dxa;word;
662 InfoRow
<NS_sprm::SDyaHdrTop
>(), // sep.dyaHdrTop;dya;word;
663 InfoRow
<NS_sprm::SDyaHdrBottom
>(), // sep.dyaHdrBottom;dya;word;
664 InfoRow
<NS_sprm::SLBetween
>(), // sep.fLBetween;0 or 1;byte;
665 InfoRow
<NS_sprm::SVjc
>(), // sep.vjc;vjc;byte;
666 InfoRow
<NS_sprm::SLnnMin
>(), // sep.lnnMin;lnn;word;
667 InfoRow
<NS_sprm::SPgnStart97
>(), // sep.pgnStart;pgn;word;
668 InfoRow
<NS_sprm::SBOrientation
>(), // sep.dmOrientPage;dm;byte;
669 {NS_sprm::LN_SBCustomize
, { 1, L_FIX
} }, // "sprmSBCustomize" ;;;
670 InfoRow
<NS_sprm::SXaPage
>(), // sep.xaPage;xa;word;
671 InfoRow
<NS_sprm::SYaPage
>(), // sep.yaPage;ya;word;
672 InfoRow
<NS_sprm::SDxaLeft
>(), // sep.dxaLeft;dxa;word;
673 InfoRow
<NS_sprm::SDxaRight
>(), // sep.dxaRight;dxa;word;
674 InfoRow
<NS_sprm::SDyaTop
>(), // sep.dyaTop;dya;word;
675 InfoRow
<NS_sprm::SDyaBottom
>(), // sep.dyaBottom;dya;word;
676 InfoRow
<NS_sprm::SDzaGutter
>(), // sep.dzaGutter;dza;word;
677 InfoRow
<NS_sprm::SDmPaperReq
>(), // sep.dmPaperReq;dm;word;
678 {NS_sprm::LN_SPropRMark
, { 0, L_VAR
} }, // "sprmSPropRMark" sep.fPropRMark,
679 // sep.ibstPropRMark, sep.dttmPropRMark ;complex
680 InfoRow
<NS_sprm::SFBiDi
>(), // ;;;
681 {NS_sprm::LN_SFFacingCol
, { 1, L_FIX
} }, // "sprmSFFacingCol" ;;;
682 InfoRow
<NS_sprm::SFRTLGutter
>(), //, set to one if gutter is on
684 InfoRow
<NS_sprm::SBrcTop80
>(), // sep.brcTop;BRC;long;
685 InfoRow
<NS_sprm::SBrcLeft80
>(), // sep.brcLeft;BRC;long;
686 InfoRow
<NS_sprm::SBrcBottom80
>(), // sep.brcBottom;BRC;long;
687 InfoRow
<NS_sprm::SBrcRight80
>(), // sep.brcRight;BRC;long;
688 InfoRow
<NS_sprm::SPgbProp
>(), // sep.pgbProp;;word;
689 InfoRow
<NS_sprm::SDxtCharSpace
>(), // sep.dxtCharSpace;dxt;long;
690 InfoRow
<NS_sprm::SDyaLinePitch
>(),
691 // sep.dyaLinePitch;dya; WRONG:long; RIGHT:short; !
692 InfoRow
<NS_sprm::SClm
>(), // ;;;
693 InfoRow
<NS_sprm::STextFlow
>(), // sep.wTextFlow;complex
694 InfoRow
<NS_sprm::TJc90
>(), // tap.jc;jc;word (low order byte is
696 InfoRow
<NS_sprm::TDxaLeft
>(), // tap.rgdxaCenter
697 InfoRow
<NS_sprm::TDxaGapHalf
>(), // tap.dxaGapHalf,
699 InfoRow
<NS_sprm::TFCantSplit90
>(), // tap.fCantSplit90;1 or 0;byte;
700 InfoRow
<NS_sprm::TTableHeader
>(), // tap.fTableHeader;1 or 0;byte;
701 InfoRow
<NS_sprm::TFCantSplit
>(), // tap.fCantSplit;1 or 0;byte;
702 InfoRow
<NS_sprm::TTableBorders80
>(), // tap.rgbrcTable;complex
703 {NS_sprm::LN_TDefTable10
, { 0, L_VAR
} }, // "sprmTDefTable10" tap.rgdxaCenter,
705 InfoRow
<NS_sprm::TDyaRowHeight
>(), // tap.dyaRowHeight;dya;word;
706 InfoRow
<NS_sprm::TDefTable
>(), // tap.rgtc;complex
707 InfoRow
<NS_sprm::TDefTableShd80
>(), // tap.rgshd;complex
708 InfoRow
<NS_sprm::TTlp
>(), // tap.tlp;TLP;4 bytes;
709 InfoRow
<NS_sprm::TFBiDi
>(), // ;;;
710 {NS_sprm::LN_THTMLProps
, { 1, L_FIX
} }, // "sprmTHTMLProps" ;;;
711 InfoRow
<NS_sprm::TSetBrc80
>(), // tap.rgtc[].rgbrc;complex
712 InfoRow
<NS_sprm::TInsert
>(), // tap.rgdxaCenter, tap.rgtc;complex
713 InfoRow
<NS_sprm::TDelete
>(), // tap.rgdxaCenter, tap.rgtc;complex
714 InfoRow
<NS_sprm::TDxaCol
>(), // tap.rgdxaCenter;complex
715 InfoRow
<NS_sprm::TMerge
>(), // tap.fFirstMerged, tap.fMerged;
716 InfoRow
<NS_sprm::TSplit
>(), // tap.fFirstMerged, tap.fMerged;
717 {NS_sprm::LN_TSetBrc10
, { 0, L_VAR
} }, // "sprmTSetBrc10" tap.rgtc[].rgbrc;complex
718 {NS_sprm::LN_TSetShd80
, { 0, L_VAR
} }, // "sprmTSetShd80" tap.rgshd;complex
719 {NS_sprm::LN_TSetShdOdd80
, { 0, L_VAR
} }, // "sprmTSetShdOdd80" tap.rgshd;complex
720 InfoRow
<NS_sprm::TTextFlow
>(), // tap.rgtc[].fVerticaltap,
721 // rgtc[].fBackwardtap, rgtc[].fRotateFont;0 or 10
723 {NS_sprm::LN_TDiagLine
, { 1, L_FIX
} }, // "sprmTDiagLine" ;;;
724 InfoRow
<NS_sprm::TVertMerge
>(), // tap.rgtc[].vertMerge
725 InfoRow
<NS_sprm::TVertAlign
>(), // tap.rgtc[].vertAlign
726 InfoRow
<NS_sprm::CFELayout
>(),
727 InfoRow
<NS_sprm::PItap
>(), // undocumented
728 InfoRow
<NS_sprm::TTableWidth
>(), // undocumented
729 InfoRow
<NS_sprm::TDefTableShd
>(),
730 InfoRow
<NS_sprm::TTableBorders
>(),
731 InfoRow
<NS_sprm::TBrcTopCv
>(), // undocumented
732 InfoRow
<NS_sprm::TBrcLeftCv
>(), // undocumented
733 InfoRow
<NS_sprm::TBrcBottomCv
>(), // undocumented
734 InfoRow
<NS_sprm::TBrcRightCv
>(), // undocumented
735 InfoRow
<NS_sprm::TCellPadding
>(), // undocumented
736 InfoRow
<NS_sprm::TCellPaddingDefault
>(), // undocumented
737 {0xD238, { 0, L_VAR
} }, // undocumented sep
738 InfoRow
<NS_sprm::PBrcTop
>(),
739 InfoRow
<NS_sprm::PBrcLeft
>(),
740 InfoRow
<NS_sprm::PBrcBottom
>(),
741 InfoRow
<NS_sprm::PBrcRight
>(),
742 InfoRow
<NS_sprm::PBrcBetween
>(),
743 InfoRow
<NS_sprm::TWidthIndent
>(), // undocumented
744 InfoRow
<NS_sprm::CRgLid0
>(), // chp.rglid[0];LID: for non-FE text
745 InfoRow
<NS_sprm::CRgLid1
>(), // chp.rglid[1];LID: for Far East text
746 {0x6463, { 4, L_FIX
} }, // undocumented
747 InfoRow
<NS_sprm::PJc
>(), // undoc, must be asian version of "sprmPJc"
748 InfoRow
<NS_sprm::PDxaRight
>(), // undoc, must be asian version of "sprmPDxaRight"
749 InfoRow
<NS_sprm::PDxaLeft
>(), // undoc, must be asian version of "sprmPDxaLeft"
750 InfoRow
<NS_sprm::PDxaLeft1
>(), // undoc, must be asian version of "sprmPDxaLeft1"
751 InfoRow
<NS_sprm::TFAutofit
>(), // undocumented
752 InfoRow
<NS_sprm::TPc
>(), // undocumented
753 InfoRow
<NS_sprm::SRsid
>(), // undocumented, sep, perhaps related to textgrids ?
754 InfoRow
<NS_sprm::SFpc
>(), // undocumented, sep
755 InfoRow
<NS_sprm::PFInnerTableCell
>(), // undocumented, subtable "sprmPFInTable" equiv ?
756 InfoRow
<NS_sprm::PFInnerTtp
>(), // undocumented, subtable "sprmPFTtp" equiv ?
757 InfoRow
<NS_sprm::TDxaAbs
>(), // undocumented
758 InfoRow
<NS_sprm::TDyaAbs
>(), // undocumented
759 InfoRow
<NS_sprm::TDxaFromText
>(), // undocumented
760 InfoRow
<NS_sprm::CRsidProp
>(), // undocumented
761 InfoRow
<NS_sprm::CRsidText
>(), // undocumented
762 InfoRow
<NS_sprm::CCv
>(), // text colour
763 InfoRow
<NS_sprm::PShd
>(), // undocumented, para back colour
764 InfoRow
<NS_sprm::PRsid
>(), // undocumented
765 InfoRow
<NS_sprm::PTableProps
>(), // undocumented
766 InfoRow
<NS_sprm::TWidthBefore
>(), // undocumented
767 InfoRow
<NS_sprm::TSetShdTable
>(), // undocumented, something to do with colour.
768 InfoRow
<NS_sprm::TDefTableShdRaw
>(), // undocumented, something to do with colour.
769 InfoRow
<NS_sprm::CShd
>(), // text backcolour
770 InfoRow
<NS_sprm::SRncFtn
>(), // undocumented, sep
771 InfoRow
<NS_sprm::PFDyaBeforeAuto
>(), // undocumented, para autobefore
772 InfoRow
<NS_sprm::PFDyaAfterAuto
>(), // undocumented, para autoafter
773 // "sprmPFContextualSpacing", don't add space between para of the same style
774 InfoRow
<NS_sprm::PFContextualSpacing
>(),
777 static wwSprmSearcher
aSprmSrch(aSprms
, SAL_N_ELEMENTS(aSprms
));
781 wwSprmParser::wwSprmParser(const WW8Fib
& rFib
) : meVersion(rFib
.GetFIBVersion())
783 OSL_ENSURE((meVersion
>= ww::eWW1
&& meVersion
<= ww::eWW8
),
784 "Impossible value for version");
786 mnDelta
= (ww::IsSevenMinus(meVersion
)) ? 0 : 1;
788 if (meVersion
<= ww::eWW2
)
789 mpKnownSprms
= GetWW2SprmSearcher();
790 else if (meVersion
< ww::eWW8
)
791 mpKnownSprms
= GetWW6SprmSearcher(rFib
);
793 mpKnownSprms
= GetWW8SprmSearcher();
796 SprmInfo
wwSprmParser::GetSprmInfo(sal_uInt16 nId
) const
798 const SprmInfo
* pFound
= mpKnownSprms
->search(nId
);
799 if (pFound
!= nullptr)
804 OSL_ENSURE(ww::IsEightPlus(meVersion
),
805 "Unknown ww7- sprm, dangerous, report to development");
807 //All the unknown ww7 sprms appear to be variable (which makes sense)
808 SprmInfo aSrch
= { 0, L_VAR
};
809 if (ww::IsEightPlus(meVersion
)) //We can recover perfectly in this case
843 static sal_uInt8
Get_Byte( sal_uInt8
*& p
)
850 static sal_uInt16
Get_UShort( sal_uInt8
*& p
)
852 const sal_uInt16 n
= SVBT16ToUInt16( *reinterpret_cast<SVBT16
*>(p
) );
857 static sal_Int16
Get_Short( sal_uInt8
*& p
)
859 return Get_UShort(p
);
862 static sal_uInt32
Get_ULong( sal_uInt8
*& p
)
864 sal_uInt32 n
= SVBT32ToUInt32( *reinterpret_cast<SVBT32
*>(p
) );
869 static sal_Int32
Get_Long( sal_uInt8
*& p
)
874 WW8SprmIter::WW8SprmIter(const sal_uInt8
* pSprms_
, sal_Int32 nLen_
,
875 const wwSprmParser
&rParser
)
876 : mrSprmParser(rParser
), pSprms( pSprms_
), nRemLen( nLen_
)
881 void WW8SprmIter::SetSprms(const sal_uInt8
* pSprms_
, sal_Int32 nLen_
)
888 void WW8SprmIter::advance()
892 sal_uInt16 nSize
= nCurrentSize
;
901 void WW8SprmIter::UpdateMyMembers()
903 bool bValid
= (pSprms
&& nRemLen
>= mrSprmParser
.MinSprmLen());
907 nCurrentId
= mrSprmParser
.GetSprmId(pSprms
);
908 nCurrentSize
= mrSprmParser
.GetSprmSize(nCurrentId
, pSprms
, nRemLen
);
909 pCurrentParams
= pSprms
+ mrSprmParser
.DistanceToData(nCurrentId
);
910 bValid
= nCurrentSize
<= nRemLen
;
911 SAL_WARN_IF(!bValid
, "sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong");
917 pCurrentParams
= nullptr;
923 SprmResult
WW8SprmIter::FindSprm(sal_uInt16 nId
, bool bFindFirst
, const sal_uInt8
* pNextByteMatch
)
929 if (GetCurrentId() == nId
)
931 sal_Int32 nFixedLen
= mrSprmParser
.DistanceToData(nId
);
932 sal_Int32 nL
= mrSprmParser
.GetSprmSize(nId
, GetSprms(), GetRemLen());
933 SprmResult
aSprmResult(GetCurrentParams(), nL
- nFixedLen
);
934 // typically pNextByteMatch is nullptr and we just return the first match
935 // very occasionally we want one with a specific following byte
936 if ( !pNextByteMatch
|| (aSprmResult
.nRemainingData
>= 1 && *aSprmResult
.pSprm
== *pNextByteMatch
) )
950 // WW8PLCFx_PCDAttrs cling to WW8PLCF_Pcd and therefore do not have their own iterators.
951 // All methods relating to iterators are therefore dummies.
952 WW8PLCFx_PCDAttrs::WW8PLCFx_PCDAttrs(const WW8Fib
& rFib
,
953 WW8PLCFx_PCD
* pPLCFx_PCD
, const WW8ScannerBase
* pBase
)
954 : WW8PLCFx(rFib
, true), pPcdI(pPLCFx_PCD
->GetPLCFIter()),
955 pPcd(pPLCFx_PCD
), mrGrpprls(pBase
->m_aPieceGrpprls
)
959 sal_uInt32
WW8PLCFx_PCDAttrs::GetIdx() const
964 void WW8PLCFx_PCDAttrs::SetIdx(sal_uInt32
)
968 bool WW8PLCFx_PCDAttrs::SeekPos(WW8_CP
)
973 void WW8PLCFx_PCDAttrs::advance()
977 WW8_CP
WW8PLCFx_PCDAttrs::Where()
979 return pPcd
? pPcd
->Where() : WW8_CP_MAX
;
982 void WW8PLCFx_PCDAttrs::GetSprms(WW8PLCFxDesc
* p
)
986 p
->bRealLineEnd
= false;
987 if ( !pPcdI
|| !pPcdI
->Get(p
->nStartPos
, p
->nEndPos
, pData
) )
989 // PLCF fully processed
990 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
991 p
->pMemPos
= nullptr;
996 const sal_uInt16 nPrm
= SVBT16ToUInt16( static_cast<WW8_PCD
*>(pData
)->prm
);
1000 const sal_uInt16 nSprmIdx
= nPrm
>> 1;
1002 if( nSprmIdx
>= mrGrpprls
.size() )
1005 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
1006 p
->pMemPos
= nullptr;
1010 const sal_uInt8
* pSprms
= mrGrpprls
[ nSprmIdx
].get();
1012 p
->nSprmsLen
= SVBT16ToUInt16( pSprms
); // Length
1014 p
->pMemPos
= pSprms
; // Position
1018 // SPRM is stored directly into members var
1020 These are the attr that are in the piece-table instead of in the text!
1023 if (IsSevenMinus(GetFIBVersion()))
1025 aShortSprm
[0] = static_cast<sal_uInt8
>( ( nPrm
& 0xfe) >> 1 );
1026 aShortSprm
[1] = static_cast<sal_uInt8
>( nPrm
>> 8 );
1027 p
->nSprmsLen
= nPrm
? 2 : 0; // length
1029 // store Position of internal mini storage in Data Pointer
1030 p
->pMemPos
= aShortSprm
;
1034 p
->pMemPos
= nullptr;
1036 sal_uInt8 nSprmListIdx
= static_cast<sal_uInt8
>((nPrm
& 0xfe) >> 1);
1039 // process Sprm Id Matching as explained in MS Documentation
1041 // ''Property Modifier(variant 1) (PRM)''
1042 // see file: s62f39.htm
1044 // Since Sprm is 7 bits, rgsprmPrm can hold 0x80 entries.
1045 static const sal_uInt16 aSprmId
[0x80] =
1047 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1048 0x0000,0x0000,0x0000,0x0000,
1049 // sprmPIncLvl, sprmPJc, sprmPFSideBySide, sprmPFKeep
1050 0x2402,0x2403,NS_sprm::LN_PFSideBySide
,0x2405,
1051 // sprmPFKeepFollow, sprmPFPageBreakBefore, sprmPBrcl,
1053 0x2406,0x2407,NS_sprm::LN_PBrcl
,NS_sprm::LN_PBrcp
,
1054 // sprmPIlvl, sprmNoop, sprmPFNoLineNumb, sprmNoop
1055 0x260A,0x0000,0x240C,0x0000,
1056 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1057 0x0000,0x0000,0x0000,0x0000,
1058 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1059 0x0000,0x0000,0x0000,0x0000,
1060 // sprmPFInTable, sprmPFTtp, sprmNoop, sprmNoop
1061 0x2416,0x2417,0x0000,0x0000,
1062 // sprmNoop, sprmPPc, sprmNoop, sprmNoop
1063 0x0000,0x261B,0x0000,0x0000,
1064 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1065 0x0000,0x0000,0x0000,0x0000,
1066 // sprmNoop, sprmPWr, sprmNoop, sprmNoop
1067 0x0000,0x2423,0x0000,0x0000,
1068 // sprmNoop, sprmNoop, sprmNoop, sprmNoop
1069 0x0000,0x0000,0x0000,0x0000,
1070 // sprmPFNoAutoHyph, sprmNoop, sprmNoop, sprmNoop
1071 0x242A,0x0000,0x0000,0x0000,
1072 // sprmNoop, sprmNoop, sprmPFLocked, sprmPFWidowControl
1073 0x0000,0x0000,0x2430,0x2431,
1074 // sprmNoop, sprmPFKinsoku, sprmPFWordWrap,
1075 // sprmPFOverflowPunct
1076 0x0000,0x2433,0x2434,0x2435,
1077 // sprmPFTopLinePunct, sprmPFAutoSpaceDE,
1078 // sprmPFAutoSpaceDN, sprmNoop
1079 0x2436,0x2437,0x2438,0x0000,
1080 // sprmNoop, sprmPISnapBaseLine, sprmNoop, sprmNoop
1081 0x0000,NS_sprm::LN_PISnapBaseLine
,0x000,0x0000,
1082 // sprmNoop, sprmCFStrikeRM, sprmCFRMark, sprmCFFieldVanish
1083 0x0000,0x0800,0x0801,0x0802,
1084 // sprmNoop, sprmNoop, sprmNoop, sprmCFData
1085 0x0000,0x0000,0x0000,0x0806,
1086 // sprmNoop, sprmNoop, sprmNoop, sprmCFOle2
1087 0x0000,0x0000,0x0000,0x080A,
1088 // sprmNoop, sprmCHighlight, sprmCFEmboss, sprmCSfxText
1089 0x0000,0x2A0C,0x0858,0x2859,
1090 // sprmNoop, sprmNoop, sprmNoop, sprmCPlain
1091 0x0000,0x0000,0x0000,0x2A33,
1092 // sprmNoop, sprmCFBold, sprmCFItalic, sprmCFStrike
1093 0x0000,0x0835,0x0836,0x0837,
1094 // sprmCFOutline, sprmCFShadow, sprmCFSmallCaps, sprmCFCaps,
1095 0x0838,0x0839,0x083a,0x083b,
1096 // sprmCFVanish, sprmNoop, sprmCKul, sprmNoop,
1097 0x083C,0x0000,0x2A3E,0x0000,
1098 // sprmNoop, sprmNoop, sprmCIco, sprmNoop,
1099 0x0000,0x0000,0x2A42,0x0000,
1100 // sprmCHpsInc, sprmNoop, sprmCHpsPosAdj, sprmNoop,
1101 NS_sprm::LN_CHpsInc
,0x0000,NS_sprm::LN_CHpsPosAdj
,0x0000,
1102 // sprmCIss, sprmNoop, sprmNoop, sprmNoop,
1103 0x2A48,0x0000,0x0000,0x0000,
1104 // sprmNoop, sprmNoop, sprmNoop, sprmNoop,
1105 0x0000,0x0000,0x0000,0x0000,
1106 // sprmNoop, sprmNoop, sprmNoop, sprmCFDStrike,
1107 0x0000,0x0000,0x0000,0x2A53,
1108 // sprmCFImprint, sprmCFSpec, sprmCFObj, sprmPicBrcl,
1109 0x0854,0x0855,0x0856,NS_sprm::LN_PicBrcl
,
1110 // sprmPOutLvl, sprmPFBiDi, sprmNoop, sprmNoop,
1111 0x2640,0x2441,0x0000,0x0000,
1112 // sprmNoop, sprmNoop, sprmPPnbrRMarkNot
1113 0x0000,0x0000,0x0000,0x0000
1116 // find real Sprm Id:
1117 const sal_uInt16 nSprmId
= aSprmId
[ nSprmListIdx
];
1121 // move Sprm Id and Sprm Param to internal mini storage:
1122 aShortSprm
[0] = static_cast<sal_uInt8
>( nSprmId
& 0x00ff) ;
1123 aShortSprm
[1] = static_cast<sal_uInt8
>( ( nSprmId
& 0xff00) >> 8 );
1124 aShortSprm
[2] = static_cast<sal_uInt8
>( nPrm
>> 8 );
1126 // store Sprm Length in member:
1127 p
->nSprmsLen
= nPrm
? 3 : 0;
1129 // store Position of internal mini storage in Data Pointer
1130 p
->pMemPos
= aShortSprm
;
1137 WW8PLCFx_PCD::WW8PLCFx_PCD(const WW8Fib
& rFib
, WW8PLCFpcd
* pPLCFpcd
,
1138 WW8_CP nStartCp
, bool bVer67P
)
1139 : WW8PLCFx(rFib
, false), nClipStart(-1)
1141 // construct own iterator
1142 pPcdI
.reset( new WW8PLCFpcd_Iter(*pPLCFpcd
, nStartCp
) );
1146 WW8PLCFx_PCD::~WW8PLCFx_PCD()
1150 sal_uInt32
WW8PLCFx_PCD::GetIMax() const
1152 return pPcdI
? pPcdI
->GetIMax() : 0;
1155 sal_uInt32
WW8PLCFx_PCD::GetIdx() const
1157 return pPcdI
? pPcdI
->GetIdx() : 0;
1160 void WW8PLCFx_PCD::SetIdx(sal_uInt32 nIdx
)
1163 pPcdI
->SetIdx( nIdx
);
1166 bool WW8PLCFx_PCD::SeekPos(WW8_CP nCpPos
)
1168 return pPcdI
&& pPcdI
->SeekPos( nCpPos
);
1171 WW8_CP
WW8PLCFx_PCD::Where()
1173 return pPcdI
? pPcdI
->Where() : WW8_CP_MAX
;
1176 tools::Long
WW8PLCFx_PCD::GetNoSprms( WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
1181 if ( !pPcdI
|| !pPcdI
->Get(rStart
, rEnd
, pData
) )
1183 rStart
= rEnd
= WW8_CP_MAX
;
1186 return pPcdI
->GetIdx();
1189 void WW8PLCFx_PCD::advance()
1191 OSL_ENSURE(pPcdI
, "missing pPcdI");
1196 WW8_FC
WW8PLCFx_PCD::CurrentPieceStartCp2Fc( WW8_CP nCp
)
1198 WW8_CP nCpStart
, nCpEnd
;
1201 if ( !pPcdI
->Get(nCpStart
, nCpEnd
, pData
) )
1203 OSL_ENSURE( false, "CurrentPieceStartCp2Fc() with false Cp found (1)" );
1207 OSL_ENSURE( nCp
>= nCpStart
&& nCp
< nCpEnd
,
1208 "AktPieceCp2Fc() with false Cp found (2)" );
1210 if( nCp
< nCpStart
)
1215 bool bIsUnicode
= false;
1216 WW8_FC nFC
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
1218 nFC
= WW8PLCFx_PCD::TransformPieceAddress( nFC
, bIsUnicode
);
1221 bool bFail
= o3tl::checked_sub(nCp
, nCpStart
, nDistance
);
1224 SAL_WARN("sw.ww8", "broken offset, ignoring");
1230 bFail
= o3tl::checked_multiply
<WW8_CP
>(nDistance
, 2, nDistance
);
1233 SAL_WARN("sw.ww8", "broken offset, ignoring");
1239 bFail
= o3tl::checked_add(nFC
, nDistance
, nRet
);
1242 SAL_WARN("sw.ww8", "broken offset, ignoring");
1249 void WW8PLCFx_PCD::CurrentPieceFc2Cp( WW8_CP
& rStartPos
, WW8_CP
& rEndPos
,
1250 const WW8ScannerBase
*pSBase
)
1252 //No point going anywhere with this
1253 if ((rStartPos
== WW8_CP_MAX
) && (rEndPos
== WW8_CP_MAX
))
1256 rStartPos
= pSBase
->WW8Fc2Cp( rStartPos
);
1257 rEndPos
= pSBase
->WW8Fc2Cp( rEndPos
);
1260 WW8_CP
WW8PLCFx_PCD::CurrentPieceStartFc2Cp( WW8_FC nStartPos
)
1262 WW8_CP nCpStart
, nCpEnd
;
1264 if ( !pPcdI
->Get( nCpStart
, nCpEnd
, pData
) )
1266 OSL_ENSURE( false, "CurrentPieceStartFc2Cp() - error" );
1269 bool bIsUnicode
= false;
1270 sal_Int32 nFcStart
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
1272 nFcStart
= WW8PLCFx_PCD::TransformPieceAddress( nFcStart
, bIsUnicode
);
1274 sal_Int32 nUnicodeFactor
= bIsUnicode
? 2 : 1;
1276 if( nStartPos
< nFcStart
)
1277 nStartPos
= nFcStart
;
1280 bool bFail
= o3tl::checked_sub(nCpEnd
, nCpStart
, nCpLen
);
1283 SAL_WARN("sw.ww8", "broken offset, ignoring");
1288 bFail
= o3tl::checked_multiply(nCpLen
, nUnicodeFactor
, nCpLenBytes
);
1291 SAL_WARN("sw.ww8", "broken offset, ignoring");
1296 bFail
= o3tl::checked_add(nFcStart
, nCpLenBytes
, nFcLen
);
1299 SAL_WARN("sw.ww8", "broken offset, ignoring");
1304 bFail
= o3tl::checked_add(nFcStart
, nFcLen
, nFcEnd
);
1307 SAL_WARN("sw.ww8", "broken offset, ignoring");
1312 if (nStartPos
>= nFcEnd
)
1313 nStartPos
= nFcEnd
- (1 * nUnicodeFactor
);
1315 WW8_FC nFcDiff
= (nStartPos
- nFcStart
) / nUnicodeFactor
;
1318 bFail
= o3tl::checked_add(nCpStart
, nFcDiff
, nCpRet
);
1321 SAL_WARN("sw.ww8", "broken offset, ignoring");
1328 // Helper routines for all
1330 // Convert BRC from WW6 to WW8 format
1331 WW8_BRC::WW8_BRC(const WW8_BRCVer6
& brcVer6
)
1333 sal_uInt8 _dptLineWidth
= brcVer6
.dxpLineWidth(),
1334 _brcType
= brcVer6
.brcType();
1336 if (_dptLineWidth
> 5) // this signifies dashed(6) or dotted(7) line
1338 _brcType
= _dptLineWidth
;
1341 _dptLineWidth
*= 6; // convert units from 0.75pt to 1/8pt
1343 *this = WW8_BRC(_dptLineWidth
, _brcType
, brcVer6
.ico(), brcVer6
.dxpSpace(),
1344 brcVer6
.fShadow(), false);
1347 // Convert BRC from WW8 to WW9 format
1348 WW8_BRCVer9::WW8_BRCVer9(const WW8_BRC
& brcVer8
)
1350 if (brcVer8
.isNil()) {
1351 UInt32ToSVBT32(0, aBits1
);
1352 UInt32ToSVBT32(0xffffffff, aBits2
);
1356 sal_uInt32 _cv
= brcVer8
.ico() == 0 ? 0xff000000 // "auto" colour
1357 : wwUtility::RGBToBGR(SwWW8ImplReader::GetCol(brcVer8
.ico()));
1358 *this = WW8_BRCVer9(_cv
, brcVer8
.dptLineWidth(), brcVer8
.brcType(),
1359 brcVer8
.dptSpace(), brcVer8
.fShadow(), brcVer8
.fFrame());
1363 short WW8_BRC::DetermineBorderProperties(short *pSpace
) const
1365 WW8_BRCVer9
brcVer9(*this);
1366 return brcVer9
.DetermineBorderProperties(pSpace
);
1369 short WW8_BRCVer9::DetermineBorderProperties(short *pSpace
) const
1372 Word does not factor the width of the border into the width/height
1373 stored in the information for graphic/table/object widths, so we need
1374 to figure out this extra width here and utilize the returned size in
1377 short nMSTotalWidth
;
1379 //Specification in 8ths of a point, 1 Point = 20 Twips, so by 2.5
1380 nMSTotalWidth
= static_cast<short>(dptLineWidth()) * 20 / 8;
1382 //Figure out the real size of the border according to word
1385 //Note that codes over 25 are undocumented, and I can't create
1386 //these 4 here in the wild.
1391 OSL_FAIL("Can't create these from the menus, please report");
1394 case 23: //Only 3pt in the menus, but honours the size setting.
1398 triple line is five times the width of an ordinary line,
1399 except that the smallest 1/4 point size appears to have
1400 exactly the same total border width as a 3/4 point size
1401 ordinary line, i.e. three times the nominal line width. The
1402 second smallest 1/2 point size appears to have exactly the
1403 total border width as a 2 1/4 border, i.e 4.5 times the size.
1405 if (nMSTotalWidth
== 5)
1407 else if (nMSTotalWidth
== 10)
1408 nMSTotalWidth
= nMSTotalWidth
*9/2;
1414 wave, the dimensions appear to be created by the drawing of
1415 the wave, so we have only two possibilities in the menus, 3/4
1416 point is equal to solid 3 point. This calculation seems to
1417 match well to results.
1423 double wave, the dimensions appear to be created by the
1424 drawing of the wave, so we have only one possibilities in the
1425 menus, that of 3/4 point is equal to solid 3 point. This
1426 calculation seems to match well to results.
1428 nMSTotalWidth
+= 45*2;
1433 *pSpace
= static_cast<short>(dptSpace()) * 20; // convert from points to twips
1434 return nMSTotalWidth
;
1438 * WW8Cp2Fc is a good method, a CP always maps to a FC
1439 * WW8Fc2Cp on the other hand is more dubious, a random FC
1440 * may not map to a valid CP. Try and avoid WW8Fc2Cp where
1443 WW8_CP
WW8ScannerBase::WW8Fc2Cp( WW8_FC nFcPos
) const
1445 WW8_CP nFallBackCpEnd
= WW8_CP_MAX
;
1446 if( nFcPos
== WW8_FC_MAX
)
1447 return nFallBackCpEnd
;
1450 if (m_pWw8Fib
->m_nVersion
>= 8)
1453 bIsUnicode
= m_pWw8Fib
->m_fExtChar
;
1455 if( m_pPieceIter
) // Complex File ?
1457 sal_uInt32 nOldPos
= m_pPieceIter
->GetIdx();
1459 for (m_pPieceIter
->SetIdx(0);
1460 m_pPieceIter
->GetIdx() < m_pPieceIter
->GetIMax(); m_pPieceIter
->advance())
1462 WW8_CP nCpStart
, nCpEnd
;
1464 if( !m_pPieceIter
->Get( nCpStart
, nCpEnd
, pData
) )
1465 { // outside PLCFfpcd ?
1466 OSL_ENSURE( false, "PLCFpcd-WW8Fc2Cp() went wrong" );
1469 sal_Int32 nFcStart
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
1470 if (m_pWw8Fib
->m_nVersion
>= 8)
1472 nFcStart
= WW8PLCFx_PCD::TransformPieceAddress( nFcStart
,
1477 bIsUnicode
= m_pWw8Fib
->m_fExtChar
;
1481 if (o3tl::checked_sub(nCpEnd
, nCpStart
, nLen
))
1483 SAL_WARN("sw.ww8", "broken offset, ignoring");
1488 if (o3tl::checked_multiply
<WW8_CP
>(nLen
, 2, nLen
))
1490 SAL_WARN("sw.ww8", "broken offset, ignoring");
1496 If this cp is inside this piece, or it's the last piece and we are
1497 on the very last cp of that piece
1499 if (nFcPos
>= nFcStart
)
1503 if (o3tl::checked_sub(nFcPos
, nFcStart
, nFcDiff
))
1505 SAL_WARN("sw.ww8", "broken offset, ignoring");
1511 if (o3tl::checked_add(nCpStart
, nFcDiff
, nTempCp
))
1513 SAL_WARN("sw.ww8", "broken offset, ignoring");
1517 if (o3tl::checked_add(nFcStart
, nLen
, nFcEnd
))
1519 SAL_WARN("sw.ww8", "broken offset, ignoring");
1522 if (nFcPos
< nFcEnd
)
1524 m_pPieceIter
->SetIdx( nOldPos
);
1527 else if (nFcPos
== nFcEnd
)
1529 //Keep this cp as its on a piece boundary because we might
1530 //need it if tests fail
1531 nFallBackCpEnd
= nTempCp
;
1536 m_pPieceIter
->SetIdx( nOldPos
); // not found
1538 If it was not found, then this is because it has fallen between two
1539 stools, i.e. either it is the last cp/fc of the last piece, or it is
1540 the last cp/fc of a disjoint piece.
1542 return nFallBackCpEnd
;
1546 if (o3tl::checked_sub(nFcPos
, m_pWw8Fib
->m_fcMin
, nFcDiff
))
1548 SAL_WARN("sw.ww8", "broken offset, ignoring");
1554 nFallBackCpEnd
= nFcDiff
;
1556 nFallBackCpEnd
= (nFcDiff
+ 1) / 2;
1558 return nFallBackCpEnd
;
1561 // the fib of WinWord2 has a last entry of cpnBtePap of 2 byte sized type PN at
1563 const int nSmallestPossibleFib
= 326;
1565 WW8_FC
WW8ScannerBase::WW8Cp2Fc(WW8_CP nCpPos
, bool* pIsUnicode
,
1566 WW8_CP
* pNextPieceCp
, bool* pTestFlag
) const
1570 if( WW8_CP_MAX
== nCpPos
)
1575 pIsUnicode
= &bIsUnicode
;
1577 if (m_pWw8Fib
->m_nVersion
>= 8)
1578 *pIsUnicode
= false;
1580 *pIsUnicode
= m_pWw8Fib
->m_fExtChar
;
1588 *pNextPieceCp
= WW8_CP_MAX
;
1590 if( !m_pPieceIter
->SeekPos( nCpPos
) )
1595 OSL_ENSURE( false, "Handed over wrong CP to WW8Cp2Fc()" );
1599 WW8_CP nCpStart
, nCpEnd
;
1601 if( !m_pPieceIter
->Get( nCpStart
, nCpEnd
, pData
) )
1606 OSL_ENSURE( false, "PLCFfpcd-Get went wrong" );
1611 *pNextPieceCp
= nCpEnd
;
1613 nRet
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
1614 if (m_pWw8Fib
->m_nVersion
>= 8)
1615 nRet
= WW8PLCFx_PCD::TransformPieceAddress( nRet
, *pIsUnicode
);
1617 *pIsUnicode
= m_pWw8Fib
->m_fExtChar
;
1620 bool bFail
= o3tl::checked_sub(nCpPos
, nCpStart
, nCpLen
);
1623 SAL_WARN("sw.ww8", "broken offset, ignoring");
1629 bFail
= o3tl::checked_multiply
<WW8_CP
>(nCpLen
, 2, nCpLen
);
1632 SAL_WARN("sw.ww8", "broken offset, ignoring");
1637 bFail
= o3tl::checked_add(nRet
, nCpLen
, nRet
);
1640 SAL_WARN("sw.ww8", "broken offset, ignoring");
1649 const bool bFail
= o3tl::checked_multiply
<WW8_CP
>(nCpPos
, 2, nCpPos
);
1652 SAL_WARN("sw.ww8", "broken offset, ignoring");
1658 const bool bFail
= o3tl::checked_add(m_pWw8Fib
->m_fcMin
, nCpPos
, nRet
);
1661 SAL_WARN("sw.ww8", "broken offset, ignoring");
1665 // the text and the fib share the same stream, if the text is inside the fib
1666 // then it's definitely a bad offset. The smallest FIB supported is that of
1667 // WW2 which is 326 bytes in size
1668 if (nRet
< nSmallestPossibleFib
)
1670 SAL_WARN("sw.ww8", "broken offset, ignoring");
1677 std::unique_ptr
<WW8PLCFpcd
> WW8ScannerBase::OpenPieceTable( SvStream
* pStr
, const WW8Fib
* pWwF
)
1679 if ( ((8 > m_pWw8Fib
->m_nVersion
) && !pWwF
->m_fComplex
) || !pWwF
->m_lcbClx
)
1682 if (pWwF
->m_lcbClx
< 0)
1685 WW8_FC nClxPos
= pWwF
->m_fcClx
;
1687 if (!checkSeek(*pStr
, nClxPos
))
1690 sal_Int32 nClxLen
= pWwF
->m_lcbClx
;
1691 sal_Int32 nLeft
= nClxLen
;
1696 pStr
->ReadUChar( clxt
);
1698 if( 2 == clxt
) // PLCFfpcd ?
1699 break; // PLCFfpcd found
1701 pStr
->ReadUInt16( nLen
);
1704 return nullptr; // gone wrong
1705 if( 1 == clxt
) // clxtGrpprl ?
1707 if (m_aPieceGrpprls
.size() == SHRT_MAX
)
1709 if (nLen
> pStr
->remainingSize())
1711 std::unique_ptr
<sal_uInt8
[]> p(new sal_uInt8
[nLen
+2]); // allocate
1712 ShortToSVBT16(nLen
, p
.get()); // add length
1713 if (!checkRead(*pStr
, p
.get()+2, nLen
)) // read grpprl
1717 m_aPieceGrpprls
.push_back(std::move(p
)); // add to array
1721 nLen
= std::min
<sal_uInt64
>(nLen
, pStr
->remainingSize());
1722 pStr
->Seek(pStr
->Tell() + nLen
); // non-Grpprl left
1726 // read Piece Table PLCF
1727 sal_Int32
nPLCFfLen(0);
1728 if (pWwF
->GetFIBVersion() <= ww::eWW2
)
1730 sal_Int16
nWordTwoLen(0);
1731 pStr
->ReadInt16( nWordTwoLen
);
1732 nPLCFfLen
= nWordTwoLen
;
1735 pStr
->ReadInt32( nPLCFfLen
);
1736 OSL_ENSURE( 65536 > nPLCFfLen
, "PLCFfpcd above 64 k" );
1737 return std::make_unique
<WW8PLCFpcd
>( pStr
, pStr
->Tell(), nPLCFfLen
, 8 );
1740 WW8ScannerBase::WW8ScannerBase( SvStream
* pSt
, SvStream
* pTableSt
,
1741 SvStream
* pDataSt
, WW8Fib
* pWwFib
)
1744 m_pPiecePLCF
= OpenPieceTable( pTableSt
, m_pWw8Fib
); // Complex
1747 m_pPieceIter
.reset(new WW8PLCFpcd_Iter( *m_pPiecePLCF
));
1748 m_pPLCFx_PCD
.reset( new WW8PLCFx_PCD(*pWwFib
, m_pPiecePLCF
.get(), 0,
1749 IsSevenMinus(m_pWw8Fib
->GetFIBVersion())));
1750 m_pPLCFx_PCDAttrs
.reset(new WW8PLCFx_PCDAttrs(*pWwFib
,
1751 m_pPLCFx_PCD
.get(), this));
1755 m_pPieceIter
= nullptr;
1756 m_pPLCFx_PCD
= nullptr;
1757 m_pPLCFx_PCDAttrs
= nullptr;
1760 // pChpPLCF and pPapPLCF may NOT be created before pPLCFx_PCD !!
1761 m_pChpPLCF
.reset(new WW8PLCFx_Cp_FKP( pSt
, pTableSt
, pDataSt
, *this, CHP
)); // CHPX
1762 m_pPapPLCF
.reset(new WW8PLCFx_Cp_FKP( pSt
, pTableSt
, pDataSt
, *this, PAP
)); // PAPX
1764 m_pSepPLCF
.reset(new WW8PLCFx_SEPX( pSt
, pTableSt
, *pWwFib
, 0 )); // SEPX
1767 m_pFootnotePLCF
.reset(new WW8PLCFx_SubDoc( pTableSt
, *pWwFib
, 0,
1768 pWwFib
->m_fcPlcffndRef
, pWwFib
->m_lcbPlcffndRef
, pWwFib
->m_fcPlcffndText
,
1769 pWwFib
->m_lcbPlcffndText
, 2 ));
1771 m_pEdnPLCF
.reset(new WW8PLCFx_SubDoc( pTableSt
, *pWwFib
, 0,
1772 pWwFib
->m_fcPlcfendRef
, pWwFib
->m_lcbPlcfendRef
, pWwFib
->m_fcPlcfendText
,
1773 pWwFib
->m_lcbPlcfendText
, 2 ));
1775 m_pAndPLCF
.reset(new WW8PLCFx_SubDoc( pTableSt
, *pWwFib
, 0,
1776 pWwFib
->m_fcPlcfandRef
, pWwFib
->m_lcbPlcfandRef
, pWwFib
->m_fcPlcfandText
,
1777 pWwFib
->m_lcbPlcfandText
, IsSevenMinus(pWwFib
->GetFIBVersion()) ? 20 : 30));
1780 m_pFieldPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_MAINTEXT
));
1781 // Fields Header / Footer
1782 m_pFieldHdFtPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_HDFT
));
1784 m_pFieldFootnotePLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_FTN
));
1786 m_pFieldEdnPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_EDN
));
1788 m_pFieldAndPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_AND
));
1789 // Fields in Textboxes in Main Text
1790 m_pFieldTxbxPLCF
.reset(new WW8PLCFx_FLD(pTableSt
, *pWwFib
, MAN_TXBX
));
1791 // Fields in Textboxes in Header / Footer
1792 m_pFieldTxbxHdFtPLCF
.reset(new WW8PLCFx_FLD(pTableSt
,*pWwFib
,MAN_TXBX_HDFT
));
1794 // Note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
1795 switch( m_pWw8Fib
->m_nVersion
)
1799 if( pWwFib
->m_fcPlcfdoaMom
&& pWwFib
->m_lcbPlcfdoaMom
)
1801 m_pMainFdoa
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfdoaMom
,
1802 pWwFib
->m_lcbPlcfdoaMom
, 6 ));
1804 if( pWwFib
->m_fcPlcfdoaHdr
&& pWwFib
->m_lcbPlcfdoaHdr
)
1806 m_pHdFtFdoa
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfdoaHdr
,
1807 pWwFib
->m_lcbPlcfdoaHdr
, 6 ));
1811 if( pWwFib
->m_fcPlcfspaMom
&& pWwFib
->m_lcbPlcfspaMom
)
1813 m_pMainFdoa
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfspaMom
,
1814 pWwFib
->m_lcbPlcfspaMom
, 26 ));
1816 if( pWwFib
->m_fcPlcfspaHdr
&& pWwFib
->m_lcbPlcfspaHdr
)
1818 m_pHdFtFdoa
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfspaHdr
,
1819 pWwFib
->m_lcbPlcfspaHdr
, 26 ));
1821 // PLCF for TextBox break-descriptors in the main text
1822 if( pWwFib
->m_fcPlcftxbxBkd
&& pWwFib
->m_lcbPlcftxbxBkd
)
1824 m_pMainTxbxBkd
.reset(new WW8PLCFspecial( pTableSt
,
1825 pWwFib
->m_fcPlcftxbxBkd
, pWwFib
->m_lcbPlcftxbxBkd
, 0));
1827 // PLCF for TextBox break-descriptors in Header/Footer range
1828 if( pWwFib
->m_fcPlcfHdrtxbxBkd
&& pWwFib
->m_lcbPlcfHdrtxbxBkd
)
1830 m_pHdFtTxbxBkd
.reset(new WW8PLCFspecial( pTableSt
,
1831 pWwFib
->m_fcPlcfHdrtxbxBkd
, pWwFib
->m_lcbPlcfHdrtxbxBkd
, 0));
1833 // Sub table cp positions
1834 if (pWwFib
->m_fcPlcfTch
&& pWwFib
->m_lcbPlcfTch
)
1836 m_pMagicTables
.reset(new WW8PLCFspecial( pTableSt
,
1837 pWwFib
->m_fcPlcfTch
, pWwFib
->m_lcbPlcfTch
, 4));
1839 // Sub document cp positions
1840 if (pWwFib
->m_fcPlcfwkb
&& pWwFib
->m_lcbPlcfwkb
)
1842 m_pSubdocs
.reset(new WW8PLCFspecial( pTableSt
,
1843 pWwFib
->m_fcPlcfwkb
, pWwFib
->m_lcbPlcfwkb
, 12));
1846 if (pWwFib
->m_fcAtrdExtra
&& pWwFib
->m_lcbAtrdExtra
)
1848 sal_uInt64
const nOldPos
= pTableSt
->Tell();
1849 if (checkSeek(*pTableSt
, pWwFib
->m_fcAtrdExtra
) && (pTableSt
->remainingSize() >= pWwFib
->m_lcbAtrdExtra
))
1851 m_pExtendedAtrds
.reset( new sal_uInt8
[pWwFib
->m_lcbAtrdExtra
] );
1852 pWwFib
->m_lcbAtrdExtra
= pTableSt
->ReadBytes(m_pExtendedAtrds
.get(), pWwFib
->m_lcbAtrdExtra
);
1855 pWwFib
->m_lcbAtrdExtra
= 0;
1856 pTableSt
->Seek(nOldPos
);
1861 OSL_ENSURE( false, "nVersion not implemented!" );
1865 // PLCF for TextBox stories in main text
1866 sal_uInt32 nLenTxBxS
= (8 > m_pWw8Fib
->m_nVersion
) ? 0 : 22;
1867 if( pWwFib
->m_fcPlcftxbxText
&& pWwFib
->m_lcbPlcftxbxText
)
1869 m_pMainTxbx
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcftxbxText
,
1870 pWwFib
->m_lcbPlcftxbxText
, nLenTxBxS
));
1873 // PLCF for TextBox stories in Header/Footer range
1874 if( pWwFib
->m_fcPlcfHdrtxbxText
&& pWwFib
->m_lcbPlcfHdrtxbxText
)
1876 m_pHdFtTxbx
.reset(new WW8PLCFspecial( pTableSt
, pWwFib
->m_fcPlcfHdrtxbxText
,
1877 pWwFib
->m_lcbPlcfHdrtxbxText
, nLenTxBxS
));
1880 m_pBook
.reset(new WW8PLCFx_Book(pTableSt
, *pWwFib
));
1881 m_pAtnBook
.reset(new WW8PLCFx_AtnBook(pTableSt
, *pWwFib
));
1882 m_pFactoidBook
.reset(new WW8PLCFx_FactoidBook(pTableSt
, *pWwFib
));
1885 WW8ScannerBase::~WW8ScannerBase()
1887 m_aPieceGrpprls
.clear();
1888 m_pPLCFx_PCDAttrs
.reset();
1889 m_pPLCFx_PCD
.reset();
1890 m_pPieceIter
.reset();
1891 m_pPiecePLCF
.reset();
1892 m_pFactoidBook
.reset();
1895 m_pFieldEdnPLCF
.reset();
1896 m_pFieldFootnotePLCF
.reset();
1897 m_pFieldAndPLCF
.reset();
1898 m_pFieldHdFtPLCF
.reset();
1899 m_pFieldPLCF
.reset();
1900 m_pFieldTxbxPLCF
.reset();
1901 m_pFieldTxbxHdFtPLCF
.reset();
1903 m_pFootnotePLCF
.reset();
1908 m_pMainFdoa
.reset();
1909 m_pHdFtFdoa
.reset();
1910 m_pMainTxbx
.reset();
1911 m_pMainTxbxBkd
.reset();
1912 m_pHdFtTxbx
.reset();
1913 m_pHdFtTxbxBkd
.reset();
1914 m_pMagicTables
.reset();
1920 static bool WW8SkipField(WW8PLCFspecial
& rPLCF
)
1925 if (!rPLCF
.Get(nP
, pData
)) // End of PLCFspecial?
1930 if((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) != 0x13 ) // No beginning?
1931 return true; // Do not terminate on error
1933 if( !rPLCF
.Get( nP
, pData
) )
1936 while((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x13 )
1938 // still new (nested) beginnings ?
1939 WW8SkipField( rPLCF
); // nested Field in description
1940 if( !rPLCF
.Get( nP
, pData
) )
1944 if((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x14 )
1947 // Field Separator ?
1950 if( !rPLCF
.Get( nP
, pData
) )
1953 while ((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x13)
1955 // still new (nested) beginnings?
1956 WW8SkipField( rPLCF
); // nested Field in Results
1957 if( !rPLCF
.Get( nP
, pData
) )
1966 static bool WW8GetFieldPara(WW8PLCFspecial
& rPLCF
, WW8FieldDesc
& rF
)
1969 sal_uInt32 nOldIdx
= rPLCF
.GetIdx();
1971 rF
.nLen
= rF
.nId
= rF
.nOpt
= 0;
1972 rF
.bCodeNest
= rF
.bResNest
= false;
1974 if (!rPLCF
.Get(rF
.nSCode
, pData
) || rF
.nSCode
< 0) // end of PLCFspecial?
1979 if (!pData
|| (static_cast<sal_uInt8
*>(pData
)[0] & 0x1f) != 0x13) // No beginning?
1982 rF
.nId
= static_cast<sal_uInt8
*>(pData
)[1];
1984 if( !rPLCF
.Get( rF
.nLCode
, pData
) )
1987 if (rF
.nLCode
< rF
.nSCode
)
1990 rF
.nSRes
= rF
.nLCode
; // Default
1991 rF
.nSCode
++; // without markers
1992 rF
.nLCode
-= rF
.nSCode
; // Pos -> length
1994 while((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x13 )
1996 // still new (nested) beginnings ?
1997 WW8SkipField( rPLCF
); // nested Field in description
1998 rF
.bCodeNest
= true;
1999 if (!rPLCF
.Get(rF
.nSRes
, pData
) || rF
.nSRes
< 0)
2003 if ((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x14 ) // Field Separator?
2007 if (!rPLCF
.Get(rF
.nLRes
, pData
) || rF
.nLRes
< 0)
2010 while((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x13 )
2012 // still new (nested) beginnings ?
2013 WW8SkipField( rPLCF
); // nested Field in results
2015 if (!rPLCF
.Get(rF
.nLRes
, pData
) || rF
.nLRes
< 0)
2019 if (o3tl::checked_sub
<WW8_CP
>(rF
.nLRes
, rF
.nSCode
, nTmp
))
2024 if (o3tl::checked_add
<WW8_CP
>(nTmp
, 2, rF
.nLen
)) // nLRes is still the final position
2029 rF
.nLRes
-= rF
.nSRes
; // now: nLRes = length
2030 if (o3tl::checked_add
<WW8_CP
>(rF
.nSRes
, 1, rF
.nSRes
)) // Endpos including Markers
2037 rF
.nLRes
= 0; // no result found
2039 if (o3tl::checked_sub
<WW8_CP
>(rF
.nSRes
, rF
.nSCode
, nTmp
))
2044 if (o3tl::checked_add
<WW8_CP
>(nTmp
, 2, rF
.nLen
)) // total length
2058 if((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f ) == 0x15 )
2061 // INDEX-Field has set Bit7?
2062 rF
.nOpt
= static_cast<sal_uInt8
*>(pData
)[1]; // yes -> copy flags
2064 rF
.nId
= 0; // no -> Field invalid
2067 rPLCF
.SetIdx( nOldIdx
);
2070 rPLCF
.SetIdx( nOldIdx
);
2074 OUString
read_uInt8_BeltAndBracesString(SvStream
& rStrm
, rtl_TextEncoding eEnc
)
2076 const OUString aRet
= read_uInt8_lenPrefixed_uInt8s_ToOUString(rStrm
, eEnc
);
2077 rStrm
.SeekRel(sizeof(sal_uInt8
)); // skip null-byte at end
2081 OUString
read_uInt16_BeltAndBracesString(SvStream
& rStrm
)
2083 const OUString aRet
= read_uInt16_PascalString(rStrm
);
2084 rStrm
.SeekRel(sizeof(sal_Unicode
)); // skip null-byte at end
2088 sal_Int32
WW8ScannerBase::WW8ReadString( SvStream
& rStrm
, OUString
& rStr
,
2089 WW8_CP nCurrentStartCp
, tools::Long nTotalLen
, rtl_TextEncoding eEnc
) const
2091 // Read in plain text, which can extend over several pieces
2094 if (nCurrentStartCp
< 0 || nTotalLen
< 0)
2097 WW8_CP nBehindTextCp
= nCurrentStartCp
+ nTotalLen
;
2098 WW8_CP nNextPieceCp
= nBehindTextCp
; // Initialization, important for Ver6
2099 tools::Long nTotalRead
= 0;
2102 bool bIsUnicode(false), bPosOk(false);
2103 WW8_FC fcAct
= WW8Cp2Fc(nCurrentStartCp
,&bIsUnicode
,&nNextPieceCp
,&bPosOk
);
2105 // Probably aimed beyond file end, doesn't matter!
2109 bool bValid
= checkSeek(rStrm
, fcAct
);
2113 WW8_CP nEnd
= (nNextPieceCp
< nBehindTextCp
) ? nNextPieceCp
2116 const bool bFail
= o3tl::checked_sub(nEnd
, nCurrentStartCp
, nLen
);
2124 ? read_uInt16s_ToOUString(rStrm
, nLen
)
2125 : read_uInt8s_ToOUString(rStrm
, nLen
, eEnc
);
2128 nCurrentStartCp
+= nLen
;
2129 if ( nTotalRead
!= rStr
.getLength() )
2132 while( nTotalRead
< nTotalLen
);
2134 return rStr
.getLength();
2137 WW8PLCFspecial::WW8PLCFspecial(SvStream
* pSt
, sal_uInt32 nFilePos
,
2138 sal_uInt32 nPLCF
, sal_uInt32 nStruct
)
2139 : nIdx(0), nStru(nStruct
)
2141 const sal_uInt32 nValidMin
=4;
2143 sal_uInt64
const nOldPos
= pSt
->Tell();
2145 bool bValid
= checkSeek(*pSt
, nFilePos
);
2146 std::size_t nRemainingSize
= pSt
->remainingSize();
2147 if( nRemainingSize
< nValidMin
|| nPLCF
< nValidMin
)
2149 nPLCF
= bValid
? std::min(nRemainingSize
, static_cast<std::size_t>(nPLCF
)) : nValidMin
;
2151 // Pointer to Pos- and Struct-array
2152 pPLCF_PosArray
.reset( new sal_Int32
[ ( nPLCF
+ 3 ) / 4 ] );
2153 pPLCF_PosArray
[0] = 0;
2155 nPLCF
= bValid
? pSt
->ReadBytes(pPLCF_PosArray
.get(), nPLCF
) : nValidMin
;
2157 nPLCF
= std::max(nPLCF
, nValidMin
);
2159 nIMax
= ( nPLCF
- 4 ) / ( 4 + nStruct
);
2160 #ifdef OSL_BIGENDIAN
2161 for( nIdx
= 0; nIdx
<= nIMax
; nIdx
++ )
2162 pPLCF_PosArray
[nIdx
] = OSL_SWAPDWORD( pPLCF_PosArray
[nIdx
] );
2164 #endif // OSL_BIGENDIAN
2165 if( nStruct
) // Pointer to content array
2166 pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&pPLCF_PosArray
[nIMax
+ 1]);
2168 pPLCF_Contents
= nullptr; // no content
2173 // WW8PLCFspecial::SeekPos() sets WW8PLCFspecial to position nPos, while also the entry is used
2174 // that begins before nPos and ends after nPos.
2175 // Suitable for normal attributes. However, the beginning of the attribute is not corrected onto
2176 // the position nPos.
2177 bool WW8PLCFspecial::SeekPos(tools::Long nP
)
2179 if( nP
< pPLCF_PosArray
[0] )
2182 return false; // Not found: nP less than smallest entry
2185 // Search from beginning?
2186 if ((nIdx
< 1) || (nP
< pPLCF_PosArray
[nIdx
- 1]))
2189 tools::Long nI
= nIdx
;
2190 tools::Long nEnd
= nIMax
;
2192 for(int n
= (1==nIdx
? 1 : 2); n
; --n
)
2194 for( ; nI
<=nEnd
; ++nI
)
2195 { // search with an index that is incremented by 1
2196 if( nP
< pPLCF_PosArray
[nI
] )
2198 nIdx
= nI
- 1; // nI - 1 is the correct index
2199 return true; // done
2205 nIdx
= nIMax
; // not found, greater than all entries
2209 // WW8PLCFspecial::SeekPosExact() like SeekPos(), but it is ensured that no attribute is cut,
2210 // i.e. the next given attribute begins at or after nPos.
2211 // Is used for fields and bookmarks.
2212 bool WW8PLCFspecial::SeekPosExact(tools::Long nP
)
2214 if( nP
< pPLCF_PosArray
[0] )
2217 return false; // Not found: nP less than smallest entry
2219 // Search from beginning?
2220 if( nP
<=pPLCF_PosArray
[nIdx
] )
2223 tools::Long nI
= nIdx
? nIdx
-1 : 0;
2224 tools::Long nEnd
= nIMax
;
2226 for(int n
= (0==nIdx
? 1 : 2); n
; --n
)
2228 for( ; nI
< nEnd
; ++nI
)
2230 if( nP
<=pPLCF_PosArray
[nI
] )
2232 nIdx
= nI
; // nI is the correct index
2233 return true; // done
2239 nIdx
= nIMax
; // Not found, greater than all entries
2243 bool WW8PLCFspecial::Get(WW8_CP
& rPos
, void*& rpValue
) const
2245 return GetData( nIdx
, rPos
, rpValue
);
2248 bool WW8PLCFspecial::GetData(tools::Long nInIdx
, WW8_CP
& rPos
, void*& rpValue
) const
2250 if ( nInIdx
>= nIMax
)
2255 rPos
= pPLCF_PosArray
[nInIdx
];
2256 rpValue
= pPLCF_Contents
? static_cast<void*>(&pPLCF_Contents
[nInIdx
* nStru
]) : nullptr;
2260 // WW8PLCF e.g. for SEPX
2261 // Ctor for *others* than Fkps
2262 // With nStartPos < 0, the first element of PLCFs will be taken
2263 WW8PLCF::WW8PLCF(SvStream
& rSt
, WW8_FC nFilePos
, sal_Int32 nPLCF
, int nStruct
,
2264 WW8_CP nStartPos
) : nIdx(0), nStru(nStruct
)
2268 SAL_WARN("sw.ww8", "broken WW8PLCF, ignoring");
2272 nIMax
= (nPLCF
- 4) / (4 + nStruct
);
2274 ReadPLCF(rSt
, nFilePos
, nPLCF
);
2276 if( nStartPos
>= 0 )
2277 SeekPos( nStartPos
);
2280 // Ctor *only* for Fkps
2281 // The last 2 parameters are needed for PLCF.Chpx and PLCF.Papx.
2282 // If ncpN != 0, then an incomplete PLCF will be completed. This is always required for WW6 with
2283 // lack of resources and for WordPad (W95).
2284 // With nStartPos < 0, the first element of the PLCFs is taken.
2285 WW8PLCF::WW8PLCF(SvStream
& rSt
, WW8_FC nFilePos
, sal_Int32 nPLCF
, int nStruct
,
2286 WW8_CP nStartPos
, sal_Int32 nPN
, sal_Int32 ncpN
): nIdx(0),
2291 SAL_WARN("sw.ww8", "broken WW8PLCF, ignoring");
2292 nIMax
= SAL_MAX_INT32
;
2295 nIMax
= (nPLCF
- 4) / (4 + nStruct
);
2298 ReadPLCF(rSt
, nFilePos
, nPLCF
);
2300 GeneratePLCF(rSt
, nPN
, ncpN
);
2302 if( nStartPos
>= 0 )
2303 SeekPos( nStartPos
);
2306 void WW8PLCF::ReadPLCF(SvStream
& rSt
, WW8_FC nFilePos
, sal_uInt32 nPLCF
)
2308 sal_uInt64
const nOldPos
= rSt
.Tell();
2309 bool bValid
= nPLCF
!= 0 && checkSeek(rSt
, nFilePos
)
2310 && (rSt
.remainingSize() >= nPLCF
);
2314 // Pointer to Pos-array
2315 pPLCF_PosArray
.reset( new WW8_CP
[ ( nPLCF
+ 3 ) / 4 ] );
2316 bValid
= checkRead(rSt
, pPLCF_PosArray
.get(), nPLCF
);
2321 #ifdef OSL_BIGENDIAN
2322 for( nIdx
= 0; nIdx
<= nIMax
; nIdx
++ )
2323 pPLCF_PosArray
[nIdx
] = OSL_SWAPDWORD( pPLCF_PosArray
[nIdx
] );
2325 #endif // OSL_BIGENDIAN
2326 // Pointer to content array
2327 pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&pPLCF_PosArray
[nIMax
+ 1]);
2329 TruncToSortedRange();
2332 OSL_ENSURE(bValid
, "Document has corrupt PLCF, ignoring it");
2340 void WW8PLCF::MakeFailedPLCF()
2343 pPLCF_PosArray
.reset( new WW8_CP
[2] );
2344 pPLCF_PosArray
[0] = pPLCF_PosArray
[1] = WW8_CP_MAX
;
2345 pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&pPLCF_PosArray
[nIMax
+ 1]);
2350 sal_Int32
TruncToSortedRange(const sal_Int32
* pPLCF_PosArray
, sal_Int32 nIMax
)
2352 //Docs state that: ... all Plcs ... are sorted in ascending order.
2353 //So ensure that here for broken documents.
2354 for (auto nI
= 0; nI
< nIMax
; ++nI
)
2356 if (pPLCF_PosArray
[nI
] > pPLCF_PosArray
[nI
+1])
2358 SAL_WARN("sw.ww8", "Document has unsorted PLCF, truncated to sorted portion");
2367 void WW8PLCFpcd::TruncToSortedRange()
2369 nIMax
= ::TruncToSortedRange(pPLCF_PosArray
.get(), nIMax
);
2372 void WW8PLCF::TruncToSortedRange()
2374 nIMax
= ::TruncToSortedRange(pPLCF_PosArray
.get(), nIMax
);
2377 void WW8PLCF::GeneratePLCF(SvStream
& rSt
, sal_Int32 nPN
, sal_Int32 ncpN
)
2379 OSL_ENSURE( nIMax
< ncpN
, "Pcl.Fkp: Why is PLCF too big?" );
2381 bool failure
= false;
2384 if ((nIMax
< 1) || (nIMax
> (WW8_CP_MAX
- 4) / (4 + nStru
)) || nPN
< 0)
2389 // Check arguments to ShortToSVBT16 in loop below will all be valid:
2391 failure
= o3tl::checked_add(nPN
, ncpN
, nResult
) || nResult
> SAL_MAX_UINT16
;
2396 size_t nSiz
= (4 + nStru
) * nIMax
+ 4;
2397 size_t nElems
= ( nSiz
+ 3 ) / 4;
2398 pPLCF_PosArray
.reset( new WW8_CP
[ nElems
] ); // Pointer to Pos-array
2400 for (sal_Int32 i
= 0; i
< ncpN
&& !failure
; ++i
)
2403 // construct FC entries
2404 // first FC entry of each Fkp
2405 if (!checkSeek(rSt
, (nPN
+ i
) << 9))
2409 rSt
.ReadInt32( nFc
);
2410 pPLCF_PosArray
[i
] = nFc
;
2412 failure
= bool(rSt
.GetError());
2422 std::size_t nLastFkpPos
= nPN
+ nIMax
- 1;
2423 nLastFkpPos
= nLastFkpPos
<< 9;
2424 // number of FC entries of last Fkp
2425 if (!checkSeek(rSt
, nLastFkpPos
+ 511))
2429 rSt
.ReadUChar( nb
);
2430 // last FC entry of last Fkp
2431 if (!checkSeek(rSt
, nLastFkpPos
+ nb
* 4))
2435 rSt
.ReadInt32( nFc
);
2436 pPLCF_PosArray
[nIMax
] = nFc
; // end of the last Fkp
2438 failure
= bool(rSt
.GetError());
2444 // Pointer to content array
2445 pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&pPLCF_PosArray
[nIMax
+ 1]);
2446 sal_uInt8
* p
= pPLCF_Contents
;
2448 for (sal_Int32 i
= 0; i
< ncpN
; ++i
) // construct PNs
2450 ShortToSVBT16(static_cast<sal_uInt16
>(nPN
+ i
), p
);
2455 SAL_WARN_IF(failure
, "sw.ww8", "Document has corrupt PLCF, ignoring it");
2461 bool WW8PLCF::SeekPos(WW8_CP nPos
)
2465 if( nP
< pPLCF_PosArray
[0] )
2468 // not found: nPos less than smallest entry
2472 // Search from beginning?
2473 if ((nIdx
< 1) || (nP
< pPLCF_PosArray
[nIdx
- 1]))
2476 sal_Int32 nI
= nIdx
;
2477 sal_Int32 nEnd
= nIMax
;
2479 for(int n
= (1==nIdx
? 1 : 2); n
; --n
)
2481 for( ; nI
<=nEnd
; ++nI
) // search with an index that is incremented by 1
2483 if( nP
< pPLCF_PosArray
[nI
] ) // found position
2485 nIdx
= nI
- 1; // nI - 1 is the correct index
2486 return true; // done
2493 nIdx
= nIMax
; // not found, greater than all entries
2497 bool WW8PLCF::Get(WW8_CP
& rStart
, WW8_CP
& rEnd
, void*& rpValue
) const
2499 if ( nIdx
>= nIMax
)
2501 rStart
= rEnd
= WW8_CP_MAX
;
2504 rStart
= pPLCF_PosArray
[ nIdx
];
2505 rEnd
= pPLCF_PosArray
[ nIdx
+ 1 ];
2506 rpValue
= static_cast<void*>(&pPLCF_Contents
[nIdx
* nStru
]);
2510 WW8_CP
WW8PLCF::Where() const
2512 if ( nIdx
>= nIMax
)
2515 return pPLCF_PosArray
[nIdx
];
2518 WW8PLCFpcd::WW8PLCFpcd(SvStream
* pSt
, sal_uInt32 nFilePos
,
2519 sal_uInt32 nPLCF
, sal_uInt32 nStruct
)
2522 const sal_uInt32 nValidMin
=4;
2524 sal_uInt64
const nOldPos
= pSt
->Tell();
2526 bool bValid
= checkSeek(*pSt
, nFilePos
);
2527 std::size_t nRemainingSize
= pSt
->remainingSize();
2528 if( nRemainingSize
< nValidMin
|| nPLCF
< nValidMin
)
2530 nPLCF
= bValid
? std::min(nRemainingSize
, static_cast<std::size_t>(nPLCF
)) : nValidMin
;
2532 pPLCF_PosArray
.reset( new WW8_CP
[ ( nPLCF
+ 3 ) / 4 ] ); // Pointer to Pos-array
2533 pPLCF_PosArray
[0] = 0;
2535 nPLCF
= bValid
? pSt
->ReadBytes(pPLCF_PosArray
.get(), nPLCF
) : nValidMin
;
2536 nPLCF
= std::max(nPLCF
, nValidMin
);
2538 nIMax
= ( nPLCF
- 4 ) / ( 4 + nStruct
);
2539 #ifdef OSL_BIGENDIAN
2540 for( tools::Long nI
= 0; nI
<= nIMax
; nI
++ )
2541 pPLCF_PosArray
[nI
] = OSL_SWAPDWORD( pPLCF_PosArray
[nI
] );
2542 #endif // OSL_BIGENDIAN
2544 // Pointer to content array
2545 pPLCF_Contents
= reinterpret_cast<sal_uInt8
*>(&pPLCF_PosArray
[nIMax
+ 1]);
2546 TruncToSortedRange();
2548 pSt
->Seek( nOldPos
);
2551 // If nStartPos < 0, the first element of PLCFs will be taken
2552 WW8PLCFpcd_Iter::WW8PLCFpcd_Iter( WW8PLCFpcd
& rPLCFpcd
, tools::Long nStartPos
)
2553 :rPLCF( rPLCFpcd
), nIdx( 0 )
2555 if( nStartPos
>= 0 )
2556 SeekPos( nStartPos
);
2559 bool WW8PLCFpcd_Iter::SeekPos(tools::Long nPos
)
2561 tools::Long nP
= nPos
;
2563 if( nP
< rPLCF
.pPLCF_PosArray
[0] )
2566 return false; // not found: nPos less than smallest entry
2568 // Search from beginning?
2569 if ((nIdx
< 1) || (nP
< rPLCF
.pPLCF_PosArray
[nIdx
- 1]))
2572 tools::Long nI
= nIdx
;
2573 tools::Long nEnd
= rPLCF
.nIMax
;
2575 for(int n
= (1==nIdx
? 1 : 2); n
; --n
)
2577 for( ; nI
<=nEnd
; ++nI
)
2578 { // search with an index that is incremented by 1
2579 if( nP
< rPLCF
.pPLCF_PosArray
[nI
] )
2581 nIdx
= nI
- 1; // nI - 1 is the correct index
2582 return true; // done
2588 nIdx
= rPLCF
.nIMax
; // not found, greater than all entries
2592 bool WW8PLCFpcd_Iter::Get(WW8_CP
& rStart
, WW8_CP
& rEnd
, void*& rpValue
) const
2594 if( nIdx
>= rPLCF
.nIMax
)
2596 rStart
= rEnd
= WW8_CP_MAX
;
2599 rStart
= rPLCF
.pPLCF_PosArray
[nIdx
];
2600 rEnd
= rPLCF
.pPLCF_PosArray
[nIdx
+ 1];
2601 rpValue
= static_cast<void*>(&rPLCF
.pPLCF_Contents
[nIdx
* rPLCF
.nStru
]);
2605 sal_Int32
WW8PLCFpcd_Iter::Where() const
2607 if ( nIdx
>= rPLCF
.nIMax
)
2608 return SAL_MAX_INT32
;
2610 return rPLCF
.pPLCF_PosArray
[nIdx
];
2613 bool WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator<
2614 (const WW8PLCFx_Fc_FKP::WW8Fkp::Entry
& rSecond
) const
2616 return (mnFC
< rSecond
.mnFC
);
2619 static bool IsReplaceAllSprm(sal_uInt16 nSpId
)
2621 return (NS_sprm::LN_PHugePapx
== nSpId
|| 0x6646 == nSpId
);
2624 static bool IsExpandableSprm(sal_uInt16 nSpId
)
2626 return 0x646B == nSpId
;
2629 void WW8PLCFx_Fc_FKP::WW8Fkp::FillEntry(WW8PLCFx_Fc_FKP::WW8Fkp::Entry
&rEntry
,
2630 std::size_t nDataOffset
, sal_uInt16 nLen
)
2632 bool bValidPos
= (nDataOffset
< sizeof(maRawData
));
2634 OSL_ENSURE(bValidPos
, "sprm sequence offset is out of range, ignoring");
2642 const sal_uInt16 nAvailableData
= sizeof(maRawData
)-nDataOffset
;
2643 OSL_ENSURE(nLen
<= nAvailableData
, "srpm sequence len is out of range, clipping");
2644 rEntry
.mnLen
= std::min(nLen
, nAvailableData
);
2645 rEntry
.mpData
= maRawData
+ nDataOffset
;
2648 WW8PLCFx_Fc_FKP::WW8Fkp::WW8Fkp(const WW8Fib
& rFib
, SvStream
* pSt
,
2649 SvStream
* pDataSt
, tools::Long _nFilePos
, tools::Long nItemSiz
, ePLCFT ePl
,
2651 : nItemSize(nItemSiz
), nFilePos(_nFilePos
), mnIdx(0), ePLCF(ePl
)
2652 , mnMustRemainCached(0), maSprmParser(rFib
)
2654 memset(maRawData
, 0, 512);
2656 const ww::WordVersion eVersion
= rFib
.GetFIBVersion();
2658 sal_uInt64
const nOldPos
= pSt
->Tell();
2660 bool bCouldSeek
= checkSeek(*pSt
, nFilePos
);
2661 bool bCouldRead
= bCouldSeek
&& checkRead(*pSt
, maRawData
, 512);
2663 mnIMax
= bCouldRead
? maRawData
[511] : 0;
2665 sal_uInt8
*pStart
= maRawData
;
2666 // Offset-Location in maRawData
2667 const size_t nRawDataStart
= (mnIMax
+ 1) * 4;
2669 for (mnIdx
= 0; mnIdx
< mnIMax
; ++mnIdx
)
2671 const size_t nRawDataOffset
= nRawDataStart
+ mnIdx
* nItemSize
;
2673 //clip to available data, corrupt fkp
2674 if (nRawDataOffset
>= 511)
2680 unsigned int nOfs
= maRawData
[nRawDataOffset
] * 2;
2681 // nOfs in [0..0xff*2=510]
2683 Entry
aEntry(Get_Long(pStart
));
2691 aEntry
.mnLen
= maRawData
[nOfs
];
2694 std::size_t nDataOffset
= nOfs
+ 1;
2696 FillEntry(aEntry
, nDataOffset
, aEntry
.mnLen
);
2698 if (aEntry
.mnLen
&& eVersion
<= ww::eWW2
)
2700 Word2CHPX aChpx
= ReadWord2Chpx(*pSt
, nFilePos
+ nOfs
+ 1, static_cast< sal_uInt8
>(aEntry
.mnLen
));
2701 std::vector
<sal_uInt8
> aSprms
= ChpxToSprms(aChpx
);
2702 aEntry
.mnLen
= static_cast< sal_uInt16
>(aSprms
.size());
2705 aEntry
.mpData
= new sal_uInt8
[aEntry
.mnLen
];
2706 memcpy(aEntry
.mpData
, aSprms
.data(), aEntry
.mnLen
);
2707 aEntry
.mbMustDelete
= true;
2714 sal_uInt8 nDelta
= 0;
2716 aEntry
.mnLen
= maRawData
[nOfs
];
2717 if (IsEightPlus(eVersion
) && !aEntry
.mnLen
)
2719 aEntry
.mnLen
= maRawData
[nOfs
+1];
2724 //stylecode, std/istd
2725 if (eVersion
<= ww::eWW2
)
2727 if (aEntry
.mnLen
>= 1)
2729 aEntry
.mnIStd
= *(maRawData
+nOfs
+1+nDelta
);
2730 aEntry
.mnLen
--; //style code
2731 if (aEntry
.mnLen
>= 6)
2733 aEntry
.mnLen
-=6; //PHE
2734 //skip stc, len byte + 6 byte PHE
2735 unsigned int nOffset
= nOfs
+ 8;
2736 if (nOffset
>= 511) //Bad offset
2738 if (aEntry
.mnLen
) //start is ok
2740 if (nOffset
+ aEntry
.mnLen
> 512) //Bad end, clip
2741 aEntry
.mnLen
= 512 - nOffset
;
2742 aEntry
.mpData
= maRawData
+ nOffset
;
2746 aEntry
.mnLen
=0; //Too short
2751 if (aEntry
.mnLen
>= 2)
2753 //len byte + optional extra len byte
2754 std::size_t nDataOffset
= nOfs
+ 1 + nDelta
;
2755 aEntry
.mnIStd
= nDataOffset
<= sizeof(maRawData
)-sizeof(aEntry
.mnIStd
) ?
2756 SVBT16ToUInt16(maRawData
+nDataOffset
) : 0;
2757 aEntry
.mnLen
-=2; //istd
2761 nDataOffset
+= sizeof(aEntry
.mnIStd
);
2763 FillEntry(aEntry
, nDataOffset
, aEntry
.mnLen
);
2767 aEntry
.mnLen
=0; //Too short, ignore
2770 const sal_uInt16 nSpId
= aEntry
.mnLen
2771 ? maSprmParser
.GetSprmId(aEntry
.mpData
) : 0;
2774 If we replace then we throw away the old data, if we
2775 are expanding, then we tack the old data onto the end
2778 const bool bExpand
= IsExpandableSprm(nSpId
);
2779 const sal_uInt8
* pStartData
2780 = aEntry
.mpData
== nullptr ? nullptr : aEntry
.mpData
+ 2;
2781 const sal_uInt8
* pLastValidDataPos
= maRawData
+ 512 - sizeof(sal_uInt32
);
2782 if (pStartData
!= nullptr && pStartData
> pLastValidDataPos
)
2783 pStartData
= nullptr;
2784 if ((IsReplaceAllSprm(nSpId
) || bExpand
) && pStartData
)
2786 sal_uInt32 nCurr
= pDataSt
->Tell();
2787 sal_uInt32 nPos
= SVBT32ToUInt32(pStartData
);
2790 bool bOk
= checkSeek(*pDataSt
, nPos
);
2793 pDataSt
->ReadUInt16( nLen
);
2794 bOk
= nLen
<= pDataSt
->remainingSize();
2799 const sal_uInt16 nOrigLen
= bExpand
? aEntry
.mnLen
: 0;
2800 sal_uInt8
*pOrigData
= bExpand
? aEntry
.mpData
: nullptr;
2802 aEntry
.mnLen
= nLen
;
2804 new sal_uInt8
[aEntry
.mnLen
+ nOrigLen
];
2805 aEntry
.mbMustDelete
= true;
2807 pDataSt
->ReadBytes(aEntry
.mpData
, aEntry
.mnLen
);
2809 pDataSt
->Seek( nCurr
);
2813 memcpy(aEntry
.mpData
+ aEntry
.mnLen
,
2814 pOrigData
, nOrigLen
);
2815 aEntry
.mnLen
= aEntry
.mnLen
+ nOrigLen
;
2822 OSL_FAIL("sweet god, what have you done!");
2827 maEntries
.push_back(aEntry
);
2829 #ifdef DEBUGSPRMREADER
2832 sal_uInt8
* pSprms
= GetLenAndIStdAndSprms( nLen
);
2833 WW8SprmIter
aIter(pSprms
, nLen
, maSprmParser
);
2834 while (aIter
.GetSprms())
2836 fprintf(stderr
, "id is %x\n", aIter
.GetCurrentId());
2843 //one more FC than grrpl entries
2844 maEntries
.emplace_back(Get_Long(pStart
));
2846 //we expect them sorted, but it appears possible for them to arrive unsorted
2847 std::stable_sort(maEntries
.begin(), maEntries
.end());
2857 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::Entry(const Entry
&rEntry
)
2858 : mnFC(rEntry
.mnFC
), mnLen(rEntry
.mnLen
), mnIStd(rEntry
.mnIStd
),
2859 mbMustDelete(rEntry
.mbMustDelete
)
2863 mpData
= new sal_uInt8
[mnLen
];
2864 memcpy(mpData
, rEntry
.mpData
, mnLen
);
2867 mpData
= rEntry
.mpData
;
2870 WW8PLCFx_Fc_FKP::WW8Fkp::Entry
&
2871 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator=(const Entry
&rEntry
)
2873 if (this == &rEntry
)
2880 mnLen
= rEntry
.mnLen
;
2881 mnIStd
= rEntry
.mnIStd
;
2882 mbMustDelete
= rEntry
.mbMustDelete
;
2884 if (rEntry
.mbMustDelete
)
2886 mpData
= new sal_uInt8
[mnLen
];
2887 memcpy(mpData
, rEntry
.mpData
, mnLen
);
2890 mpData
= rEntry
.mpData
;
2895 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::~Entry()
2901 void WW8PLCFx_Fc_FKP::WW8Fkp::Reset(WW8_FC nFc
)
2908 bool WW8PLCFx_Fc_FKP::WW8Fkp::SeekPos(WW8_FC nFc
)
2910 if (nFc
< maEntries
[0].mnFC
)
2913 return false; // not found: nPos less than smallest entry
2916 // Search from beginning?
2917 if ((mnIdx
< 1) || (nFc
< maEntries
[mnIdx
- 1].mnFC
))
2920 sal_uInt8 nI
= mnIdx
;
2921 sal_uInt8 nEnd
= mnIMax
;
2923 for(sal_uInt8 n
= (1==mnIdx
? 1 : 2); n
; --n
)
2925 for( ; nI
<=nEnd
; ++nI
)
2926 { // search with an index that is incremented by 1
2927 if (nFc
< maEntries
[nI
].mnFC
)
2929 mnIdx
= nI
- 1; // nI - 1 is the correct index
2930 return true; // done
2936 mnIdx
= mnIMax
; // not found, greater than all entries
2940 sal_uInt8
* WW8PLCFx_Fc_FKP::WW8Fkp::Get(WW8_FC
& rStart
, WW8_FC
& rEnd
, sal_Int32
& rLen
)
2945 if (mnIdx
>= mnIMax
)
2947 rStart
= WW8_FC_MAX
;
2951 rStart
= maEntries
[mnIdx
].mnFC
;
2952 rEnd
= maEntries
[mnIdx
+ 1].mnFC
;
2954 sal_uInt8
* pSprms
= GetLenAndIStdAndSprms( rLen
);
2958 void WW8PLCFx_Fc_FKP::WW8Fkp::SetIdx(sal_uInt8 nI
)
2966 sal_uInt8
* WW8PLCFx_Fc_FKP::WW8Fkp::GetLenAndIStdAndSprms(sal_Int32
& rLen
) const
2968 rLen
= maEntries
[mnIdx
].mnLen
;
2969 return maEntries
[mnIdx
].mpData
;
2972 SprmResult
WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm( sal_uInt16 nId
, bool bFindFirst
)
2974 if (mnIdx
>= mnIMax
)
2975 return SprmResult();
2978 sal_uInt8
* pSprms
= GetLenAndIStdAndSprms( nLen
);
2980 WW8SprmIter
aIter(pSprms
, nLen
, maSprmParser
);
2981 return aIter
.FindSprm(nId
, bFindFirst
);
2984 void WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm(sal_uInt16 nId
,
2985 std::vector
<SprmResult
> &rResult
)
2987 if (mnIdx
>= mnIMax
)
2991 sal_uInt8
* pSprms
= GetLenAndIStdAndSprms( nLen
);
2993 WW8SprmIter
aIter(pSprms
, nLen
, maSprmParser
);
2995 while(aIter
.GetSprms())
2997 if (aIter
.GetCurrentId() == nId
)
2999 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId
);
3000 sal_Int32 nL
= maSprmParser
.GetSprmSize(nId
, aIter
.GetSprms(), aIter
.GetRemLen());
3001 rResult
.emplace_back(aIter
.GetCurrentParams(), nL
- nFixedLen
);
3007 ww::WordVersion
WW8PLCFx::GetFIBVersion() const
3009 return mrFib
.GetFIBVersion();
3012 void WW8PLCFx::GetSprms( WW8PLCFxDesc
* p
)
3014 OSL_ENSURE( false, "Called wrong GetSprms" );
3015 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
3016 p
->pMemPos
= nullptr;
3018 p
->bRealLineEnd
= false;
3021 tools::Long
WW8PLCFx::GetNoSprms( WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
3023 OSL_ENSURE( false, "Called wrong GetNoSprms" );
3024 rStart
= rEnd
= WW8_CP_MAX
;
3029 // ...Idx2: Default: ignore
3030 sal_uInt32
WW8PLCFx::GetIdx2() const
3035 void WW8PLCFx::SetIdx2(sal_uInt32
)
3046 explicit SamePos(tools::Long nPo
) : mnPo(nPo
) {}
3047 bool operator()(const std::unique_ptr
<WW8PLCFx_Fc_FKP::WW8Fkp
>& pFkp
)
3048 {return mnPo
== pFkp
->GetFilePos();}
3053 bool WW8PLCFx_Fc_FKP::NewFkp()
3055 WW8_CP nPLCFStart
, nPLCFEnd
;
3058 static const int WW8FkpSizeTabVer2
[ PLCF_END
] =
3060 1, 1, 0 /*, 0, 0, 0*/
3062 static const int WW8FkpSizeTabVer6
[ PLCF_END
] =
3064 1, 7, 0 /*, 0, 0, 0*/
3066 static const int WW8FkpSizeTabVer8
[ PLCF_END
] =
3068 1, 13, 0 /*, 0, 0, 0*/
3070 const int* pFkpSizeTab
;
3072 switch (GetFIBVersion())
3076 pFkpSizeTab
= WW8FkpSizeTabVer2
;
3080 pFkpSizeTab
= WW8FkpSizeTabVer6
;
3083 pFkpSizeTab
= WW8FkpSizeTabVer8
;
3087 OSL_ENSURE( false, "nVersion not implemented!" );
3091 if (!pPLCF
->Get( nPLCFStart
, nPLCFEnd
, pPage
))
3094 return false; // PLCF completely processed
3097 tools::Long nPo
= SVBT16ToUInt16( static_cast<sal_uInt8
*>(pPage
) );
3098 nPo
<<= 9; // shift as LONG
3100 tools::Long nCurrentFkpFilePos
= pFkp
? pFkp
->GetFilePos() : -1;
3101 if (nCurrentFkpFilePos
== nPo
)
3102 pFkp
->Reset(GetStartFc());
3106 std::find_if(maFkpCache
.begin(), maFkpCache
.end(), SamePos(nPo
));
3107 if (aIter
!= maFkpCache
.end())
3109 pFkp
= aIter
->get();
3110 pFkp
->Reset(GetStartFc());
3114 pFkp
= new WW8Fkp(GetFIB(), pFKPStrm
, pDataStrm
, nPo
,
3115 pFkpSizeTab
[ ePLCF
], ePLCF
, GetStartFc());
3116 maFkpCache
.push_back(std::unique_ptr
<WW8Fkp
>(pFkp
));
3118 if (maFkpCache
.size() > eMaxCache
)
3120 WW8Fkp
* pCachedFkp
= maFkpCache
.front().get();
3121 if (!pCachedFkp
->IsMustRemainCache())
3123 maFkpCache
.pop_front();
3129 SetStartFc( -1 ); // only the first time
3133 WW8PLCFx_Fc_FKP::WW8PLCFx_Fc_FKP(SvStream
* pSt
, SvStream
* pTableSt
,
3134 SvStream
* pDataSt
, const WW8Fib
& rFib
, ePLCFT ePl
, WW8_FC nStartFcL
)
3135 : WW8PLCFx(rFib
, true), pFKPStrm(pSt
), pDataStrm(pDataSt
)
3136 , pFkp(nullptr), ePLCF(ePl
)
3138 SetStartFc(nStartFcL
);
3139 tools::Long nLenStruct
= (8 > rFib
.m_nVersion
) ? 2 : 4;
3142 pPLCF
.reset(new WW8PLCF(*pTableSt
, rFib
.m_fcPlcfbteChpx
, rFib
.m_lcbPlcfbteChpx
,
3143 nLenStruct
, GetStartFc(), rFib
.m_pnChpFirst
, rFib
.m_cpnBteChp
));
3147 pPLCF
.reset(new WW8PLCF(*pTableSt
, rFib
.m_fcPlcfbtePapx
, rFib
.m_lcbPlcfbtePapx
,
3148 nLenStruct
, GetStartFc(), rFib
.m_pnPapFirst
, rFib
.m_cpnBtePap
));
3152 WW8PLCFx_Fc_FKP::~WW8PLCFx_Fc_FKP()
3159 sal_uInt32
WW8PLCFx_Fc_FKP::GetIdx() const
3161 sal_uInt32 u
= pPLCF
->GetIdx() << 8;
3163 u
|= pFkp
->GetIdx();
3167 void WW8PLCFx_Fc_FKP::SetIdx(sal_uInt32 nIdx
)
3169 if( !( nIdx
& 0xffffff00L
) )
3171 pPLCF
->SetIdx( nIdx
>> 8 );
3175 { // there was a Fkp
3176 // Set PLCF one position back to retrieve the address of the Fkp
3177 pPLCF
->SetIdx( ( nIdx
>> 8 ) - 1 );
3178 if (NewFkp()) // read Fkp again
3180 sal_uInt8 nFkpIdx
= static_cast<sal_uInt8
>(nIdx
& 0xff);
3181 pFkp
->SetIdx(nFkpIdx
); // set Fkp-Pos again
3186 bool WW8PLCFx_Fc_FKP::SeekPos(WW8_FC nFcPos
)
3188 // StartPos for next Where()
3189 SetStartFc( nFcPos
);
3191 // find StartPos for next pPLCF->Get()
3192 bool bRet
= pPLCF
->SeekPos(nFcPos
);
3194 // make FKP invalid?
3195 WW8_CP nPLCFStart
, nPLCFEnd
;
3197 if( pFkp
&& pPLCF
->Get( nPLCFStart
, nPLCFEnd
, pPage
) )
3199 tools::Long nPo
= SVBT16ToUInt16( static_cast<sal_uInt8
*>(pPage
) );
3200 nPo
<<= 9; // shift as LONG
3201 if (nPo
!= pFkp
->GetFilePos())
3204 pFkp
->SeekPos( nFcPos
);
3209 WW8_FC
WW8PLCFx_Fc_FKP::Where()
3211 if( !pFkp
&& !NewFkp() )
3213 WW8_FC nP
= pFkp
? pFkp
->Where() : WW8_FC_MAX
;
3214 if( nP
!= WW8_FC_MAX
)
3217 pFkp
= nullptr; // FKP finished -> get new
3218 return Where(); // easiest way: do it recursively
3221 sal_uInt8
* WW8PLCFx_Fc_FKP::GetSprmsAndPos(WW8_FC
& rStart
, WW8_FC
& rEnd
, sal_Int32
& rLen
)
3223 rLen
= 0; // Default
3224 rStart
= rEnd
= WW8_FC_MAX
;
3226 if( !pFkp
) // Fkp not there ?
3232 sal_uInt8
* pPos
= pFkp
? pFkp
->Get( rStart
, rEnd
, rLen
) : nullptr;
3233 if( rStart
== WW8_FC_MAX
) //Not found
3238 void WW8PLCFx_Fc_FKP::advance()
3240 if( !pFkp
&& !NewFkp() )
3247 if( pFkp
->Where() == WW8_FC_MAX
)
3251 sal_uInt16
WW8PLCFx_Fc_FKP::GetIstd() const
3253 return pFkp
? pFkp
->GetIstd() : 0xFFFF;
3256 void WW8PLCFx_Fc_FKP::GetPCDSprms( WW8PLCFxDesc
& rDesc
)
3258 rDesc
.pMemPos
= nullptr;
3259 rDesc
.nSprmsLen
= 0;
3264 OSL_FAIL("+Problem: GetPCDSprms: NewFkp necessary (not possible!)" );
3268 pPCDAttrs
->GetSprms(&rDesc
);
3272 SprmResult
WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId
, bool bFindFirst
)
3274 // const would be nicer, but for that, NewFkp() would need to be replaced or eliminated
3277 OSL_FAIL( "+Motz: HasSprm: NewFkp needed ( no const possible )" );
3278 // happens in BugDoc 31722
3280 return SprmResult();
3284 return SprmResult();
3286 SprmResult aRes
= pFkp
->HasSprm(nId
, bFindFirst
);
3291 GetPCDSprms( aDesc
);
3295 WW8SprmIter
aIter(aDesc
.pMemPos
, aDesc
.nSprmsLen
,
3296 pFkp
->GetSprmParser());
3297 aRes
= aIter
.FindSprm(nId
, bFindFirst
);
3304 void WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId
, std::vector
<SprmResult
> &rResult
)
3306 // const would be nicer, but for that, NewFkp() would need to be replaced or eliminated
3309 OSL_FAIL( "+Motz: HasSprm: NewFkp needed ( no const possible )" );
3310 // happens in BugDoc 31722
3318 pFkp
->HasSprm(nId
, rResult
);
3321 GetPCDSprms( aDesc
);
3326 const wwSprmParser
&rSprmParser
= pFkp
->GetSprmParser();
3327 WW8SprmIter
aIter(aDesc
.pMemPos
, aDesc
.nSprmsLen
, rSprmParser
);
3328 while(aIter
.GetSprms())
3330 if (aIter
.GetCurrentId() == nId
)
3332 sal_Int32 nFixedLen
= rSprmParser
.DistanceToData(nId
);
3333 sal_Int32 nL
= rSprmParser
.GetSprmSize(nId
, aIter
.GetSprms(), aIter
.GetRemLen());
3334 rResult
.emplace_back(aIter
.GetCurrentParams(), nL
- nFixedLen
);
3340 WW8PLCFx_Cp_FKP::WW8PLCFx_Cp_FKP( SvStream
* pSt
, SvStream
* pTableSt
,
3341 SvStream
* pDataSt
, const WW8ScannerBase
& rBase
, ePLCFT ePl
)
3342 : WW8PLCFx_Fc_FKP(pSt
, pTableSt
, pDataSt
, *rBase
.m_pWw8Fib
, ePl
,
3343 rBase
.WW8Cp2Fc(0)), rSBase(rBase
), nAttrStart(-1), nAttrEnd(-1),
3345 bComplex( (7 < rBase
.m_pWw8Fib
->m_nVersion
) || rBase
.m_pWw8Fib
->m_fComplex
)
3347 ResetAttrStartEnd();
3349 if (rSBase
.m_pPiecePLCF
)
3350 pPcd
.reset( new WW8PLCFx_PCD(GetFIB(), rBase
.m_pPiecePLCF
.get(), 0, IsSevenMinus(GetFIBVersion())) );
3353 Make a copy of the piece attributes for so that the calls to HasSprm on a
3354 Fc_FKP will be able to take into account the current piece attributes,
3355 despite the fact that such attributes can only be found through a cp based
3360 pPCDAttrs
.reset( rSBase
.m_pPLCFx_PCDAttrs
? new WW8PLCFx_PCDAttrs(
3361 *rSBase
.m_pWw8Fib
, pPcd
.get(), &rSBase
) : nullptr);
3364 pPieceIter
= rSBase
.m_pPieceIter
.get();
3367 WW8PLCFx_Cp_FKP::~WW8PLCFx_Cp_FKP()
3371 void WW8PLCFx_Cp_FKP::ResetAttrStartEnd()
3378 sal_uInt32
WW8PLCFx_Cp_FKP::GetPCDIdx() const
3380 return pPcd
? pPcd
->GetIdx() : 0;
3383 bool WW8PLCFx_Cp_FKP::SeekPos(WW8_CP nCpPos
)
3385 if( pPcd
) // Complex
3387 if( !pPcd
->SeekPos( nCpPos
) ) // set piece
3389 if (pPCDAttrs
&& !pPCDAttrs
->GetIter()->SeekPos(nCpPos
))
3391 return WW8PLCFx_Fc_FKP::SeekPos(pPcd
->CurrentPieceStartCp2Fc(nCpPos
));
3393 // NO piece table !!!
3394 return WW8PLCFx_Fc_FKP::SeekPos( rSBase
.WW8Cp2Fc(nCpPos
) );
3397 WW8_CP
WW8PLCFx_Cp_FKP::Where()
3399 WW8_FC nFc
= WW8PLCFx_Fc_FKP::Where();
3401 return pPcd
->CurrentPieceStartFc2Cp( nFc
); // identify piece
3402 return rSBase
.WW8Fc2Cp( nFc
); // NO piece table !!!
3405 void WW8PLCFx_Cp_FKP::GetSprms(WW8PLCFxDesc
* p
)
3407 WW8_CP nOrigCp
= p
->nStartPos
;
3409 if (!GetDirty()) //Normal case
3411 p
->pMemPos
= WW8PLCFx_Fc_FKP::GetSprmsAndPos(p
->nStartPos
, p
->nEndPos
,
3417 For the odd case where we have a location in a fastsaved file which
3418 does not have an entry in the FKP, perhaps its para end is in the next
3419 piece, or perhaps the cp just doesn't exist at all in this document.
3420 AdvSprm doesn't know so it sets the PLCF as dirty and we figure out
3421 in this method what the situation is
3423 It doesn't exist then the piece iterator will not be able to find it.
3424 Otherwise our cool fastsave algorithm can be brought to bear on the
3429 const sal_uInt32 nOldPos
= pPieceIter
->GetIdx();
3430 bool bOk
= pPieceIter
->SeekPos(nOrigCp
);
3431 pPieceIter
->SetIdx(nOldPos
);
3436 if( pPcd
) // piece table available
3438 // Init ( no ++ called, yet )
3439 if( (nAttrStart
> nAttrEnd
) || (nAttrStart
== -1) )
3441 p
->bRealLineEnd
= (ePLCF
== PAP
);
3443 if ( ((ePLCF
== PAP
) || (ePLCF
== CHP
)) && (nOrigCp
!= WW8_CP_MAX
) )
3445 bool bIsUnicode
=false;
3447 To find the end of a paragraph for a character in a
3448 complex format file.
3450 It is necessary to know the piece that contains the
3451 character and the FC assigned to the character.
3454 //We set the piece iterator to the piece that contains the
3455 //character, now we have the correct piece for this character
3456 sal_uInt32 nOldPos
= pPieceIter
->GetIdx();
3457 p
->nStartPos
= nOrigCp
;
3458 pPieceIter
->SeekPos( p
->nStartPos
);
3460 //This is the FC assigned to the character, but we already
3461 //have the result of the next stage, so we can skip this step
3462 //WW8_FC nStartFc = rSBase.WW8Cp2Fc(p->nStartPos, &bIsUnicode);
3465 Using the FC of the character, first search the FKP that
3466 describes the character to find the smallest FC in the rgfc
3467 that is larger than the character FC.
3469 //But the search has already been done, the next largest FC is
3471 WW8_FC nOldEndPos
= p
->nEndPos
;
3474 If the FC found in the FKP is less than or equal to the limit
3475 FC of the piece, the end of the paragraph that contains the
3476 character is at the FKP FC minus 1.
3478 WW8_CP nCpStart
, nCpEnd
;
3479 void* pData
=nullptr;
3480 bool bOk
= pPieceIter
->Get(nCpStart
, nCpEnd
, pData
);
3484 pPieceIter
->SetIdx(nOldPos
);
3488 WW8_FC nLimitFC
= SVBT32ToUInt32( static_cast<WW8_PCD
*>(pData
)->fc
);
3489 WW8_FC nBeginLimitFC
= nLimitFC
;
3490 if (IsEightPlus(GetFIBVersion()))
3493 WW8PLCFx_PCD::TransformPieceAddress(nLimitFC
,
3498 bool bFail
= o3tl::checked_sub(nCpEnd
, nCpStart
, nCpLen
);
3501 SAL_WARN("sw.ww8", "broken offset, ignoring");
3502 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3503 pPieceIter
->SetIdx(nOldPos
);
3509 bFail
= o3tl::checked_multiply
<WW8_CP
>(nCpLen
, 2, nCpLen
);
3512 SAL_WARN("sw.ww8", "broken offset, ignoring");
3513 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3514 pPieceIter
->SetIdx(nOldPos
);
3519 bFail
= o3tl::checked_add(nBeginLimitFC
, nCpLen
, nLimitFC
);
3522 SAL_WARN("sw.ww8", "broken offset, ignoring");
3523 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3524 pPieceIter
->SetIdx(nOldPos
);
3528 if (nOldEndPos
<= nLimitFC
)
3530 bFail
= o3tl::checked_sub(nLimitFC
, nOldEndPos
, nCpLen
);
3533 SAL_WARN("sw.ww8", "broken offset, ignoring");
3534 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3535 pPieceIter
->SetIdx(nOldPos
);
3539 nCpLen
/= (bIsUnicode
? 2 : 1);
3541 bFail
= o3tl::checked_sub(nCpEnd
, nCpLen
, p
->nEndPos
);
3544 SAL_WARN("sw.ww8", "broken offset, ignoring");
3545 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3546 pPieceIter
->SetIdx(nOldPos
);
3553 p
->nEndPos
= nCpEnd
;
3557 If the FKP FC that was found was greater than the FC
3558 of the end of the piece, scan piece by piece toward
3559 the end of the document until a piece is found that
3560 contains a paragraph end mark.
3564 It's possible to check if a piece contains a paragraph
3565 mark by using the FC of the beginning of the piece to
3566 search in the FKPs for the smallest FC in the FKP rgfc
3567 that is greater than the FC of the beginning of the
3568 piece. If the FC found is less than or equal to the
3569 limit FC of the piece, then the character that ends
3570 the paragraph is the character immediately before the
3574 pPieceIter
->advance();
3576 for (;pPieceIter
->GetIdx() < pPieceIter
->GetIMax();
3577 pPieceIter
->advance())
3579 if( !pPieceIter
->Get( nCpStart
, nCpEnd
, pData
) )
3581 OSL_ENSURE( false, "piece iter broken!" );
3585 sal_Int32 nFcStart
=SVBT32ToUInt32(static_cast<WW8_PCD
*>(pData
)->fc
);
3587 if (IsEightPlus(GetFIBVersion()))
3590 WW8PLCFx_PCD::TransformPieceAddress(
3591 nFcStart
,bIsUnicode
);
3594 bFail
= o3tl::checked_sub(nCpEnd
, nCpStart
, nCpLen
);
3597 SAL_WARN("sw.ww8", "broken offset, ignoring");
3598 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3604 bFail
= o3tl::checked_multiply
<WW8_CP
>(nCpLen
, 2, nCpLen
);
3607 SAL_WARN("sw.ww8", "broken offset, ignoring");
3608 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3613 bFail
= o3tl::checked_add(nFcStart
, nCpLen
, nLimitFC
);
3616 SAL_WARN("sw.ww8", "broken offset, ignoring");
3617 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3621 //if it doesn't exist, skip it
3622 if (!SeekPos(nCpStart
))
3625 WW8_FC nOne
,nSmallest
;
3626 p
->pMemPos
= WW8PLCFx_Fc_FKP::GetSprmsAndPos(nOne
,
3627 nSmallest
, p
->nSprmsLen
);
3629 if (nSmallest
<= nLimitFC
)
3632 bFail
= o3tl::checked_sub(nLimitFC
, nSmallest
, nCpDiff
);
3635 SAL_WARN("sw.ww8", "broken offset, ignoring");
3636 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3643 bFail
= o3tl::checked_sub(nCpEnd
, nCpDiff
, nEndPos
);
3646 SAL_WARN("sw.ww8", "broken offset, ignoring");
3647 p
->nStartPos
= p
->nEndPos
= WW8_FC_MAX
;
3651 OSL_ENSURE(nEndPos
>= p
->nStartPos
, "EndPos before StartPos");
3653 if (nEndPos
>= p
->nStartPos
)
3654 p
->nEndPos
= nEndPos
;
3661 pPieceIter
->SetIdx( nOldPos
);
3664 WW8PLCFx_PCD::CurrentPieceFc2Cp( p
->nStartPos
, p
->nEndPos
,&rSBase
);
3668 p
->nStartPos
= nAttrStart
;
3669 p
->nEndPos
= nAttrEnd
;
3670 p
->bRealLineEnd
= bLineEnd
;
3673 else // NO piece table !!!
3675 p
->nStartPos
= rSBase
.WW8Fc2Cp( p
->nStartPos
);
3676 p
->nEndPos
= rSBase
.WW8Fc2Cp( p
->nEndPos
);
3677 p
->bRealLineEnd
= ePLCF
== PAP
;
3681 void WW8PLCFx_Cp_FKP::advance()
3683 WW8PLCFx_Fc_FKP::advance();
3684 // !pPcd: emergency break
3685 if ( !bComplex
|| !pPcd
)
3688 if( GetPCDIdx() >= pPcd
->GetIMax() ) // End of PLCF
3690 nAttrStart
= nAttrEnd
= WW8_CP_MAX
;
3694 sal_Int32 nFkpLen
; // Fkp entry
3696 WW8PLCFx_Fc_FKP::GetSprmsAndPos(nAttrStart
, nAttrEnd
, nFkpLen
);
3698 WW8PLCFx_PCD::CurrentPieceFc2Cp( nAttrStart
, nAttrEnd
, &rSBase
);
3699 bLineEnd
= (ePLCF
== PAP
);
3702 WW8PLCFx_SEPX::WW8PLCFx_SEPX(SvStream
* pSt
, SvStream
* pTableSt
,
3703 const WW8Fib
& rFib
, WW8_CP nStartCp
)
3704 : WW8PLCFx(rFib
, true), maSprmParser(rFib
),
3705 pStrm(pSt
), nArrMax(256), nSprmSiz(0)
3707 if (rFib
.m_lcbPlcfsed
)
3708 pPLCF
.reset( new WW8PLCF(*pTableSt
, rFib
.m_fcPlcfsed
, rFib
.m_lcbPlcfsed
,
3709 GetFIBVersion() <= ww::eWW2
? 6 : 12, nStartCp
) );
3711 pSprms
.reset( new sal_uInt8
[nArrMax
] ); // maximum length
3714 WW8PLCFx_SEPX::~WW8PLCFx_SEPX()
3718 sal_uInt32
WW8PLCFx_SEPX::GetIdx() const
3720 return pPLCF
? pPLCF
->GetIdx() : 0;
3723 void WW8PLCFx_SEPX::SetIdx(sal_uInt32 nIdx
)
3725 if( pPLCF
) pPLCF
->SetIdx( nIdx
);
3728 bool WW8PLCFx_SEPX::SeekPos(WW8_CP nCpPos
)
3730 return pPLCF
&& pPLCF
->SeekPos( nCpPos
);
3733 WW8_CP
WW8PLCFx_SEPX::Where()
3735 return pPLCF
? pPLCF
->Where() : 0;
3738 void WW8PLCFx_SEPX::GetSprms(WW8PLCFxDesc
* p
)
3740 if( !pPLCF
) return;
3744 p
->bRealLineEnd
= false;
3745 if (!pPLCF
->Get( p
->nStartPos
, p
->nEndPos
, pData
))
3747 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
; // PLCF completely processed
3748 p
->pMemPos
= nullptr;
3753 sal_uInt32 nPo
= SVBT32ToUInt32( static_cast<sal_uInt8
*>(pData
)+2 );
3754 if (nPo
== 0xFFFFFFFF || !checkSeek(*pStrm
, nPo
))
3756 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
; // Sepx empty
3757 p
->pMemPos
= nullptr;
3763 if (GetFIBVersion() <= ww::eWW2
) // eWW6 ?, docs say yes, but...
3766 pStrm
->ReadUChar( nSiz
);
3771 pStrm
->ReadUInt16( nSprmSiz
);
3774 std::size_t nRemaining
= pStrm
->remainingSize();
3775 if (nSprmSiz
> nRemaining
)
3776 nSprmSiz
= nRemaining
;
3778 if( nSprmSiz
> nArrMax
)
3780 nArrMax
= nSprmSiz
; // Get more memory
3781 pSprms
.reset( new sal_uInt8
[nArrMax
] );
3783 nSprmSiz
= pStrm
->ReadBytes(pSprms
.get(), nSprmSiz
); // read Sprms
3785 p
->nSprmsLen
= nSprmSiz
;
3786 p
->pMemPos
= pSprms
.get(); // return Position
3791 void WW8PLCFx_SEPX::advance()
3797 SprmResult
WW8PLCFx_SEPX::HasSprm(sal_uInt16 nId
) const
3799 return HasSprm(nId
, pSprms
.get(), nSprmSiz
);
3802 SprmResult
WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId
, const sal_uInt8
* pOtherSprms
,
3803 tools::Long nOtherSprmSiz
) const
3808 WW8SprmIter
aIter(pOtherSprms
, nOtherSprmSiz
, maSprmParser
);
3809 aRet
= aIter
.FindSprm(nId
, /*bFindFirst=*/true);
3814 bool WW8PLCFx_SEPX::Find4Sprms(sal_uInt16 nId1
,sal_uInt16 nId2
,sal_uInt16 nId3
,sal_uInt16 nId4
,
3815 SprmResult
& r1
, SprmResult
& r2
, SprmResult
& r3
, SprmResult
& r4
) const
3820 bool bFound
= false;
3822 sal_uInt8
* pSp
= pSprms
.get();
3824 while (i
+ maSprmParser
.MinSprmLen() <= nSprmSiz
)
3827 const sal_uInt16 nCurrentId
= maSprmParser
.GetSprmId(pSp
);
3828 sal_Int32 nRemLen
= nSprmSiz
- i
;
3829 const sal_Int32 x
= maSprmParser
.GetSprmSize(nCurrentId
, pSp
, nRemLen
);
3830 bool bValid
= x
<= nRemLen
;
3833 SAL_WARN("sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong");
3837 if( nCurrentId
== nId1
)
3839 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId1
);
3840 r1
= SprmResult(pSp
+ nFixedLen
, x
- nFixedLen
);
3842 else if( nCurrentId
== nId2
)
3844 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId2
);
3845 r2
= SprmResult(pSp
+ nFixedLen
, x
- nFixedLen
);
3847 else if( nCurrentId
== nId3
)
3849 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId3
);
3850 r3
= SprmResult(pSp
+ nFixedLen
, x
- nFixedLen
);
3852 else if( nCurrentId
== nId4
)
3854 sal_Int32 nFixedLen
= maSprmParser
.DistanceToData(nId4
);
3855 r4
= SprmResult(pSp
+ nFixedLen
, x
- nFixedLen
);
3860 // increment pointer so that it points to next SPRM
3867 SprmResult
WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId
, sal_uInt8 n2nd
) const
3872 WW8SprmIter
aIter(pSprms
.get(), nSprmSiz
, maSprmParser
);
3873 aRet
= aIter
.FindSprm(nId
, /*bFindFirst=*/true, &n2nd
);
3878 WW8PLCFx_SubDoc::WW8PLCFx_SubDoc(SvStream
* pSt
, const WW8Fib
& rFib
,
3879 WW8_CP nStartCp
, tools::Long nFcRef
, tools::Long nLenRef
, tools::Long nFcText
, tools::Long nLenText
,
3880 tools::Long nStruct
)
3881 : WW8PLCFx(rFib
, true)
3883 if( nLenRef
&& nLenText
)
3885 pRef
.reset(new WW8PLCF(*pSt
, nFcRef
, nLenRef
, nStruct
, nStartCp
));
3886 pText
.reset(new WW8PLCF(*pSt
, nFcText
, nLenText
, 0, nStartCp
));
3890 WW8PLCFx_SubDoc::~WW8PLCFx_SubDoc()
3896 sal_uInt32
WW8PLCFx_SubDoc::GetIdx() const
3898 // Probably pText ... no need for it
3900 return ( pRef
->GetIdx() << 16 | pText
->GetIdx() );
3904 void WW8PLCFx_SubDoc::SetIdx(sal_uInt32 nIdx
)
3908 pRef
->SetIdx( nIdx
>> 16 );
3909 // Probably pText ... no need for it
3910 pText
->SetIdx( nIdx
& 0xFFFF );
3914 bool WW8PLCFx_SubDoc::SeekPos( WW8_CP nCpPos
)
3916 return pRef
&& pRef
->SeekPos( nCpPos
);
3919 WW8_CP
WW8PLCFx_SubDoc::Where()
3921 return pRef
? pRef
->Where() : WW8_CP_MAX
;
3924 void WW8PLCFx_SubDoc::GetSprms(WW8PLCFxDesc
* p
)
3926 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
3927 p
->pMemPos
= nullptr;
3929 p
->bRealLineEnd
= false;
3934 sal_uInt32 nNr
= pRef
->GetIdx();
3938 if (!pRef
->Get(p
->nStartPos
, nFoo
, pData
))
3940 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
3944 if (o3tl::checked_add
<WW8_CP
>(p
->nStartPos
, 1, p
->nEndPos
))
3946 SAL_WARN("sw.ww8", "broken offset, ignoring");
3947 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
3956 if (!pText
->Get(p
->nCp2OrIdx
, p
->nSprmsLen
, pData
))
3958 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
3963 if (p
->nCp2OrIdx
< 0 || p
->nCp2OrIdx
> p
->nSprmsLen
)
3965 SAL_WARN("sw.ww8", "Document has invalid Cp or Idx, ignoring it");
3966 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
3971 p
->nSprmsLen
-= p
->nCp2OrIdx
;
3974 void WW8PLCFx_SubDoc::advance()
3984 WW8PLCFx_FLD::WW8PLCFx_FLD( SvStream
* pSt
, const WW8Fib
& rMyFib
, short nType
)
3985 : WW8PLCFx(rMyFib
, true), rFib(rMyFib
)
3993 nFc
= rFib
.m_fcPlcffldHdr
;
3994 nLen
= rFib
.m_lcbPlcffldHdr
;
3997 nFc
= rFib
.m_fcPlcffldFootnote
;
3998 nLen
= rFib
.m_lcbPlcffldFootnote
;
4001 nFc
= rFib
.m_fcPlcffldEdn
;
4002 nLen
= rFib
.m_lcbPlcffldEdn
;
4005 nFc
= rFib
.m_fcPlcffldAtn
;
4006 nLen
= rFib
.m_lcbPlcffldAtn
;
4009 nFc
= rFib
.m_fcPlcffldTxbx
;
4010 nLen
= rFib
.m_lcbPlcffldTxbx
;
4013 nFc
= rFib
.m_fcPlcffldHdrTxbx
;
4014 nLen
= rFib
.m_lcbPlcffldHdrTxbx
;
4017 nFc
= rFib
.m_fcPlcffldMom
;
4018 nLen
= rFib
.m_lcbPlcffldMom
;
4023 pPLCF
.reset( new WW8PLCFspecial( pSt
, nFc
, nLen
, 2 ) );
4026 WW8PLCFx_FLD::~WW8PLCFx_FLD()
4030 sal_uInt32
WW8PLCFx_FLD::GetIdx() const
4032 return pPLCF
? pPLCF
->GetIdx() : 0;
4035 void WW8PLCFx_FLD::SetIdx(sal_uInt32 nIdx
)
4038 pPLCF
->SetIdx( nIdx
);
4041 bool WW8PLCFx_FLD::SeekPos(WW8_CP nCpPos
)
4043 return pPLCF
&& pPLCF
->SeekPosExact( nCpPos
);
4046 WW8_CP
WW8PLCFx_FLD::Where()
4048 return pPLCF
? pPLCF
->Where() : WW8_CP_MAX
;
4051 bool WW8PLCFx_FLD::StartPosIsFieldStart()
4055 return pPLCF
&& pPLCF
->Get(nTest
, pData
) && ((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f) == 0x13);
4058 bool WW8PLCFx_FLD::EndPosIsFieldEnd(WW8_CP
& nCP
)
4064 tools::Long n
= pPLCF
->GetIdx();
4070 if ( pPLCF
->Get(nTest
, pData
) && ((static_cast<sal_uInt8
*>(pData
)[0] & 0x1f) == 0x15) )
4082 void WW8PLCFx_FLD::GetSprms(WW8PLCFxDesc
* p
)
4084 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
4085 p
->pMemPos
= nullptr;
4087 p
->bRealLineEnd
= false;
4091 p
->nStartPos
= WW8_CP_MAX
; // there are no fields
4095 tools::Long n
= pPLCF
->GetIdx();
4099 if (!pPLCF
->Get(nP
, pData
)) // end of PLCFspecial?
4101 p
->nStartPos
= WW8_CP_MAX
; // PLCF completely processed
4108 if (!pPLCF
->Get(nP
, pData
)) // end of PLCFspecial?
4110 p
->nStartPos
= WW8_CP_MAX
; // PLCF completely processed
4118 p
->nCp2OrIdx
= pPLCF
->GetIdx();
4121 void WW8PLCFx_FLD::advance()
4123 SAL_WARN_IF(!pPLCF
, "sw.ww8", "Call without PLCFspecial field");
4129 bool WW8PLCFx_FLD::GetPara(tools::Long nIdx
, WW8FieldDesc
& rF
)
4131 SAL_WARN_IF(!pPLCF
, "sw.ww8", "Call without PLCFspecial field");
4135 tools::Long n
= pPLCF
->GetIdx();
4136 pPLCF
->SetIdx(nIdx
);
4138 bool bOk
= WW8GetFieldPara(*pPLCF
, rF
);
4145 void WW8ReadSTTBF(bool bVer8
, SvStream
& rStrm
, sal_uInt32 nStart
, sal_Int32 nLen
,
4146 sal_uInt16 nExtraLen
, rtl_TextEncoding eCS
, std::vector
<OUString
> &rArray
,
4147 std::vector
<ww::bytes
>* pExtraArray
, std::vector
<OUString
>* pValueArray
)
4149 if (nLen
==0) // Handle Empty STTBF
4152 sal_uInt64
const nOldPos
= rStrm
.Tell();
4153 if (checkSeek(rStrm
, nStart
))
4155 sal_uInt16
nLen2(0);
4156 rStrm
.ReadUInt16( nLen2
); // bVer67: total length of structure
4157 // bVer8 : count of strings
4161 sal_uInt16
nStrings(0);
4162 bool bUnicode
= (0xFFFF == nLen2
);
4164 rStrm
.ReadUInt16( nStrings
);
4168 rStrm
.ReadUInt16( nExtraLen
);
4170 const size_t nMinStringLen
= bUnicode
? sizeof(sal_uInt16
) : sizeof(sal_uInt8
);
4171 const size_t nMinRecordSize
= nExtraLen
+ nMinStringLen
;
4172 const size_t nMaxPossibleStrings
= rStrm
.remainingSize() / nMinRecordSize
;
4173 if (nStrings
> nMaxPossibleStrings
)
4175 SAL_WARN("sw.ww8", "STTBF claims " << nStrings
<< " entries, but only " << nMaxPossibleStrings
<< " are possible");
4176 nStrings
= nMaxPossibleStrings
;
4179 if (nExtraLen
&& nStrings
)
4181 const size_t nMaxExtraLen
= (rStrm
.remainingSize() - (nStrings
* nMinStringLen
)) / nStrings
;
4182 if (nExtraLen
> nMaxExtraLen
)
4184 SAL_WARN("sw.ww8", "STTBF claims " << nMaxExtraLen
<< " extra len, but only " << nMaxExtraLen
<< " are possible");
4185 nExtraLen
= nMaxExtraLen
;
4189 for (sal_uInt16 i
=0; i
< nStrings
; ++i
)
4192 rArray
.push_back(read_uInt16_PascalString(rStrm
));
4195 OString aTmp
= read_uInt8_lenPrefixed_uInt8s_ToOString(rStrm
);
4196 rArray
.push_back(OStringToOUString(aTmp
, eCS
));
4199 // Skip the extra data
4204 ww::bytes
extraData(nExtraLen
);
4205 rStrm
.ReadBytes(extraData
.data(), nExtraLen
);
4206 pExtraArray
->push_back(extraData
);
4209 rStrm
.SeekRel( nExtraLen
);
4212 // read the value of the document variables, if requested.
4215 for (sal_uInt16 i
=0; i
< nStrings
; ++i
)
4218 pValueArray
->push_back(read_uInt16_PascalString(rStrm
));
4221 OString aTmp
= read_uInt8_lenPrefixed_uInt8s_ToOString(rStrm
);
4222 pValueArray
->push_back(OStringToOUString(aTmp
, eCS
));
4231 OSL_ENSURE(nLen2
== nLen
,
4232 "Fib length and read length are different");
4233 if (nLen
> SAL_MAX_UINT16
)
4234 nLen
= SAL_MAX_UINT16
;
4237 nLen2
= static_cast<sal_uInt16
>(nLen
);
4239 sal_uLong nRead
= 0;
4240 for( nLen2
-= 2; nRead
< nLen2
; )
4242 sal_uInt8
nBChar(0);
4243 rStrm
.ReadUChar( nBChar
);
4247 OString aTmp
= read_uInt8s_ToOString(rStrm
, nBChar
);
4248 nRead
+= aTmp
.getLength();
4249 rArray
.push_back(OStringToOUString(aTmp
, eCS
));
4252 rArray
.emplace_back();
4254 // Skip the extra data (for bVer67 versions this must come from
4255 // external knowledge)
4260 ww::bytes
extraData(nExtraLen
);
4261 rStrm
.ReadBytes(extraData
.data(), nExtraLen
);
4262 pExtraArray
->push_back(extraData
);
4265 rStrm
.SeekRel( nExtraLen
);
4271 rStrm
.Seek(nOldPos
);
4274 WW8PLCFx_Book::WW8PLCFx_Book(SvStream
* pTableSt
, const WW8Fib
& rFib
)
4275 : WW8PLCFx(rFib
, false), nIsEnd(0), nBookmarkId(1)
4277 if( !rFib
.m_fcPlcfbkf
|| !rFib
.m_lcbPlcfbkf
|| !rFib
.m_fcPlcfbkl
||
4278 !rFib
.m_lcbPlcfbkl
|| !rFib
.m_fcSttbfbkmk
|| !rFib
.m_lcbSttbfbkmk
)
4284 pBook
[0].reset( new WW8PLCFspecial(pTableSt
,rFib
.m_fcPlcfbkf
,rFib
.m_lcbPlcfbkf
,4) );
4286 pBook
[1].reset( new WW8PLCFspecial(pTableSt
,rFib
.m_fcPlcfbkl
,rFib
.m_lcbPlcfbkl
,0) );
4288 rtl_TextEncoding eStructChrSet
= WW8Fib::GetFIBCharset(rFib
.m_chseTables
, rFib
.m_lid
);
4290 WW8ReadSTTBF( (7 < rFib
.m_nVersion
), *pTableSt
, rFib
.m_fcSttbfbkmk
,
4291 rFib
.m_lcbSttbfbkmk
, 0, eStructChrSet
, aBookNames
);
4293 nIMax
= aBookNames
.size();
4295 if( pBook
[0]->GetIMax() < nIMax
) // Count of Bookmarks
4296 nIMax
= pBook
[0]->GetIMax();
4297 if( pBook
[1]->GetIMax() < nIMax
)
4298 nIMax
= pBook
[1]->GetIMax();
4299 aStatus
.resize(nIMax
);
4303 WW8PLCFx_Book::~WW8PLCFx_Book()
4307 sal_uInt32
WW8PLCFx_Book::GetIdx() const
4309 return nIMax
? pBook
[0]->GetIdx() : 0;
4312 void WW8PLCFx_Book::SetIdx(sal_uInt32 nI
)
4315 pBook
[0]->SetIdx( nI
);
4318 sal_uInt32
WW8PLCFx_Book::GetIdx2() const
4320 return nIMax
? ( pBook
[1]->GetIdx() | ( nIsEnd
? 0x80000000 : 0 ) ) : 0;
4323 void WW8PLCFx_Book::SetIdx2(sal_uInt32 nI
)
4327 pBook
[1]->SetIdx( nI
& 0x7fffffff );
4328 nIsEnd
= static_cast<sal_uInt16
>( ( nI
>> 31 ) & 1 ); // 0 or 1
4332 bool WW8PLCFx_Book::SeekPos(WW8_CP nCpPos
)
4337 bool bOk
= pBook
[0]->SeekPosExact( nCpPos
);
4338 bOk
&= pBook
[1]->SeekPosExact( nCpPos
);
4344 WW8_CP
WW8PLCFx_Book::Where()
4346 return pBook
[nIsEnd
]->Where();
4349 tools::Long
WW8PLCFx_Book::GetNoSprms( WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
4355 if (!pBook
[0] || !pBook
[1] || !nIMax
|| (pBook
[nIsEnd
]->GetIdx()) >= nIMax
)
4357 rStart
= rEnd
= WW8_CP_MAX
;
4361 (void)pBook
[nIsEnd
]->Get( rStart
, pData
); // query position
4362 return pBook
[nIsEnd
]->GetIdx();
4365 // The operator ++ has a pitfall: If 2 bookmarks adjoin each other,
4366 // we should first go to the end of the first one
4367 // and then to the beginning of the second one.
4368 // But if 2 bookmarks with the length of 0 lie on top of each other,
4369 // we *must* first find the start and end of each bookmark.
4373 // is not solved yet.
4374 // Because I must jump back and forth in the start- and end-indices then.
4375 // This would require one more index or bitfield to remember
4376 // the already processed bookmarks.
4378 void WW8PLCFx_Book::advance()
4380 if( !(pBook
[0] && pBook
[1] && nIMax
) )
4383 (*pBook
[nIsEnd
]).advance();
4385 sal_uLong l0
= pBook
[0]->Where();
4386 sal_uLong l1
= pBook
[1]->Where();
4393 const void * p
= pBook
[0]->GetData(pBook
[0]->GetIdx());
4394 tools::Long nPairFor
= (p
== nullptr) ? 0 : SVBT16ToUInt16(*static_cast<SVBT16
const *>(p
));
4395 if (nPairFor
== pBook
[1]->GetIdx())
4398 nIsEnd
= nIsEnd
? 0 : 1;
4402 tools::Long
WW8PLCFx_Book::GetLen() const
4406 OSL_ENSURE( false, "Incorrect call (1) of PLCF_Book::GetLen()" );
4411 if( !pBook
[0]->Get( nStartPos
, p
) )
4413 OSL_ENSURE( false, "Incorrect call (2) of PLCF_Book::GetLen()" );
4416 const sal_uInt16 nEndIdx
= SVBT16ToUInt16( *static_cast<SVBT16
*>(p
) );
4417 tools::Long nNum
= pBook
[1]->GetPos( nEndIdx
);
4422 void WW8PLCFx_Book::SetStatus(sal_uInt16 nIndex
, eBookStatus eStat
)
4424 SAL_WARN_IF(nIndex
>= nIMax
, "sw.ww8",
4425 "bookmark index " << nIndex
<< " invalid");
4426 eBookStatus eStatus
= aStatus
.at(nIndex
);
4427 aStatus
[nIndex
] = static_cast<eBookStatus
>(eStatus
| eStat
);
4430 eBookStatus
WW8PLCFx_Book::GetStatus() const
4432 if (aStatus
.empty())
4434 tools::Long nEndIdx
= GetHandle();
4435 return ( nEndIdx
< nIMax
) ? aStatus
[nEndIdx
] : BOOK_NORMAL
;
4438 tools::Long
WW8PLCFx_Book::GetHandle() const
4440 if( !pBook
[0] || !pBook
[1] )
4444 return pBook
[1]->GetIdx();
4447 if (const void* p
= pBook
[0]->GetData(pBook
[0]->GetIdx()))
4448 return SVBT16ToUInt16( *static_cast<SVBT16
const *>(p
) );
4454 OUString
WW8PLCFx_Book::GetBookmark(tools::Long nStart
,tools::Long nEnd
, sal_uInt16
&nIndex
)
4456 bool bFound
= false;
4458 if (pBook
[0] && pBook
[1])
4460 WW8_CP nStartCurrent
, nEndCurrent
;
4461 while (sal::static_int_cast
<decltype(aBookNames
)::size_type
>(i
) < aBookNames
.size())
4466 if( pBook
[0]->GetData( i
, nStartCurrent
, p
) && p
)
4467 nEndIdx
= SVBT16ToUInt16( *static_cast<SVBT16
*>(p
) );
4470 OSL_ENSURE( false, "Bookmark-EndIdx not readable" );
4474 nEndCurrent
= pBook
[1]->GetPos( nEndIdx
);
4476 if ((nStartCurrent
>= nStart
) && (nEndCurrent
<= nEnd
))
4485 return bFound
? aBookNames
[i
] : OUString();
4488 OUString
WW8PLCFx_Book::GetUniqueBookmarkName(const OUString
&rSuggestedName
)
4490 OUString
aRet(rSuggestedName
.isEmpty() ? OUString("Unnamed") : rSuggestedName
);
4492 while (i
< aBookNames
.size())
4494 if (aRet
== aBookNames
[i
])
4496 sal_Int32 len
= aRet
.getLength();
4497 sal_Int32 p
= len
- 1;
4498 while (p
> 0 && aRet
[p
] >= '0' && aRet
[p
] <= '9')
4500 aRet
= aRet
.subView(0, p
+1) + OUString::number(nBookmarkId
++);
4501 i
= 0; // start search from beginning
4509 void WW8PLCFx_Book::MapName(OUString
& rName
)
4511 if( !pBook
[0] || !pBook
[1] )
4515 while (i
< aBookNames
.size())
4517 if (rName
.equalsIgnoreAsciiCase(aBookNames
[i
]))
4519 rName
= aBookNames
[i
];
4526 const OUString
* WW8PLCFx_Book::GetName() const
4528 const OUString
*pRet
= nullptr;
4529 if (!nIsEnd
&& (pBook
[0]->GetIdx() < nIMax
))
4530 pRet
= &(aBookNames
[pBook
[0]->GetIdx()]);
4534 WW8PLCFx_AtnBook::WW8PLCFx_AtnBook(SvStream
* pTableSt
, const WW8Fib
& rFib
)
4535 : WW8PLCFx(rFib
, /*bSprm=*/false),
4538 if (!rFib
.m_fcPlcfAtnbkf
|| !rFib
.m_lcbPlcfAtnbkf
|| !rFib
.m_fcPlcfAtnbkl
|| !rFib
.m_lcbPlcfAtnbkl
)
4544 m_pBook
[0].reset( new WW8PLCFspecial(pTableSt
, rFib
.m_fcPlcfAtnbkf
, rFib
.m_lcbPlcfAtnbkf
, 4) );
4545 m_pBook
[1].reset( new WW8PLCFspecial(pTableSt
, rFib
.m_fcPlcfAtnbkl
, rFib
.m_lcbPlcfAtnbkl
, 0) );
4547 nIMax
= m_pBook
[0]->GetIMax();
4548 if (m_pBook
[1]->GetIMax() < nIMax
)
4549 nIMax
= m_pBook
[1]->GetIMax();
4553 WW8PLCFx_AtnBook::~WW8PLCFx_AtnBook()
4557 sal_uInt32
WW8PLCFx_AtnBook::GetIdx() const
4559 return nIMax
? m_pBook
[0]->GetIdx() : 0;
4562 void WW8PLCFx_AtnBook::SetIdx(sal_uInt32 nI
)
4565 m_pBook
[0]->SetIdx( nI
);
4568 sal_uInt32
WW8PLCFx_AtnBook::GetIdx2() const
4571 return m_pBook
[1]->GetIdx() | ( m_bIsEnd
? 0x80000000 : 0 );
4576 void WW8PLCFx_AtnBook::SetIdx2(sal_uInt32 nI
)
4580 m_pBook
[1]->SetIdx( nI
& 0x7fffffff );
4581 m_bIsEnd
= static_cast<bool>(( nI
>> 31 ) & 1);
4585 bool WW8PLCFx_AtnBook::SeekPos(WW8_CP nCpPos
)
4590 bool bOk
= m_pBook
[0]->SeekPosExact(nCpPos
);
4591 bOk
&= m_pBook
[1]->SeekPosExact(nCpPos
);
4597 WW8_CP
WW8PLCFx_AtnBook::Where()
4599 return m_pBook
[static_cast<int>(m_bIsEnd
)]->Where();
4602 tools::Long
WW8PLCFx_AtnBook::GetNoSprms( WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
4608 if (!m_pBook
[0] || !m_pBook
[1] || !nIMax
|| (m_pBook
[static_cast<int>(m_bIsEnd
)]->GetIdx()) >= nIMax
)
4610 rStart
= rEnd
= WW8_CP_MAX
;
4614 (void)m_pBook
[static_cast<int>(m_bIsEnd
)]->Get(rStart
, pData
);
4615 return m_pBook
[static_cast<int>(m_bIsEnd
)]->GetIdx();
4618 void WW8PLCFx_AtnBook::advance()
4620 if( !(m_pBook
[0] && m_pBook
[1] && nIMax
) )
4623 (*m_pBook
[static_cast<int>(m_bIsEnd
)]).advance();
4625 sal_uLong l0
= m_pBook
[0]->Where();
4626 sal_uLong l1
= m_pBook
[1]->Where();
4633 const void * p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx());
4634 tools::Long nPairFor
= (p
== nullptr) ? 0 : SVBT16ToUInt16(*static_cast<SVBT16
const *>(p
));
4635 if (nPairFor
== m_pBook
[1]->GetIdx())
4638 m_bIsEnd
= !m_bIsEnd
;
4642 tools::Long
WW8PLCFx_AtnBook::getHandle() const
4644 if (!m_pBook
[0] || !m_pBook
[1])
4648 return m_pBook
[1]->GetIdx();
4651 if (const void* p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx()))
4652 return SVBT16ToUInt16(*static_cast<const SVBT16
*>(p
));
4658 bool WW8PLCFx_AtnBook::getIsEnd() const
4663 WW8PLCFx_FactoidBook::WW8PLCFx_FactoidBook(SvStream
* pTableSt
, const WW8Fib
& rFib
)
4664 : WW8PLCFx(rFib
, /*bSprm=*/false),
4667 if (!rFib
.m_fcPlcfBkfFactoid
|| !rFib
.m_lcbPlcfBkfFactoid
|| !rFib
.m_fcPlcfBklFactoid
|| !rFib
.m_lcbPlcfBklFactoid
)
4673 m_pBook
[0].reset(new WW8PLCFspecial(pTableSt
, rFib
.m_fcPlcfBkfFactoid
, rFib
.m_lcbPlcfBkfFactoid
, 6));
4674 m_pBook
[1].reset(new WW8PLCFspecial(pTableSt
, rFib
.m_fcPlcfBklFactoid
, rFib
.m_lcbPlcfBklFactoid
, 4));
4676 m_nIMax
= m_pBook
[0]->GetIMax();
4677 if (m_pBook
[1]->GetIMax() < m_nIMax
)
4678 m_nIMax
= m_pBook
[1]->GetIMax();
4682 WW8PLCFx_FactoidBook::~WW8PLCFx_FactoidBook()
4686 sal_uInt32
WW8PLCFx_FactoidBook::GetIdx() const
4688 return m_nIMax
? m_pBook
[0]->GetIdx() : 0;
4691 void WW8PLCFx_FactoidBook::SetIdx(sal_uInt32 nI
)
4694 m_pBook
[0]->SetIdx(nI
);
4697 sal_uInt32
WW8PLCFx_FactoidBook::GetIdx2() const
4700 return m_pBook
[1]->GetIdx() | (m_bIsEnd
? 0x80000000 : 0);
4705 void WW8PLCFx_FactoidBook::SetIdx2(sal_uInt32 nI
)
4709 m_pBook
[1]->SetIdx(nI
& 0x7fffffff);
4710 m_bIsEnd
= static_cast<bool>((nI
>> 31) & 1);
4714 bool WW8PLCFx_FactoidBook::SeekPos(WW8_CP nCpPos
)
4719 bool bOk
= m_pBook
[0]->SeekPosExact(nCpPos
);
4720 bOk
&= m_pBook
[1]->SeekPosExact(nCpPos
);
4726 WW8_CP
WW8PLCFx_FactoidBook::Where()
4728 return m_pBook
[static_cast<int>(m_bIsEnd
)]->Where();
4731 tools::Long
WW8PLCFx_FactoidBook::GetNoSprms(WW8_CP
& rStart
, WW8_CP
& rEnd
, sal_Int32
& rLen
)
4737 if (!m_pBook
[0] || !m_pBook
[1] || !m_nIMax
|| (m_pBook
[static_cast<int>(m_bIsEnd
)]->GetIdx()) >= m_nIMax
)
4739 rStart
= rEnd
= WW8_CP_MAX
;
4743 (void)m_pBook
[static_cast<int>(m_bIsEnd
)]->Get(rStart
, pData
);
4744 return m_pBook
[static_cast<int>(m_bIsEnd
)]->GetIdx();
4747 void WW8PLCFx_FactoidBook::advance()
4749 if (!(m_pBook
[0] && m_pBook
[1] && m_nIMax
))
4752 (*m_pBook
[static_cast<int>(m_bIsEnd
)]).advance();
4754 sal_uLong l0
= m_pBook
[0]->Where();
4755 sal_uLong l1
= m_pBook
[1]->Where();
4762 const void * p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx());
4763 tools::Long nPairFor
= (p
== nullptr) ? 0 : SVBT16ToUInt16(*static_cast<SVBT16
const *>(p
));
4764 if (nPairFor
== m_pBook
[1]->GetIdx())
4767 m_bIsEnd
= !m_bIsEnd
;
4771 tools::Long
WW8PLCFx_FactoidBook::getHandle() const
4773 if (!m_pBook
[0] || !m_pBook
[1])
4777 return m_pBook
[1]->GetIdx();
4780 if (const void* p
= m_pBook
[0]->GetData(m_pBook
[0]->GetIdx()))
4781 return SVBT16ToUInt16(*static_cast<const SVBT16
*>(p
));
4787 bool WW8PLCFx_FactoidBook::getIsEnd() const
4792 // In the end of a paragraph in WW6 the attribute extends after the <CR>.
4793 // This will be reset by one character to be used with SW,
4794 // if we don't expect trouble thereby.
4795 void WW8PLCFMan::AdjustEnds( WW8PLCFxDesc
& rDesc
)
4797 // might be necessary to do this for pChp and/or pSep as well,
4798 // but its definitely the case for paragraphs that EndPos > StartPos
4799 // for a well formed paragraph as those always have a paragraph
4801 if (&rDesc
== m_pPap
&& rDesc
.bRealLineEnd
)
4803 if (rDesc
.nStartPos
== rDesc
.nEndPos
&& rDesc
.nEndPos
!= WW8_CP_MAX
)
4805 SAL_WARN("sw.ww8", "WW8PLCFxDesc End same as Start, abandoning to avoid looping");
4806 rDesc
.nEndPos
= WW8_CP_MAX
;
4810 //Store old end position for supercool new property finder that uses
4811 //cp instead of fc's as nature intended
4812 rDesc
.nOrigEndPos
= rDesc
.nEndPos
;
4813 rDesc
.nOrigStartPos
= rDesc
.nStartPos
;
4816 Normally given ^XXX{para end}^ we don't actually insert a para end
4817 character into the document, so we clip the para end property one to the
4818 left to make the para properties end when the paragraph text does. In a
4819 drawing textbox we actually do insert a para end character, so we don't
4820 clip it. Making the para end properties end after the para end char.
4822 if (GetDoingDrawTextBox())
4825 if ( (&rDesc
== m_pPap
) && rDesc
.bRealLineEnd
)
4827 if ( m_pPap
->nEndPos
!= WW8_CP_MAX
) // Para adjust
4829 m_nLineEnd
= m_pPap
->nEndPos
;// nLineEnd points *after* the <CR>
4830 m_pPap
->nEndPos
--; // shorten paragraph end by one character
4832 // Is there already a sep end, which points to the current paragraph end?
4833 // Then we also must shorten by one character
4834 if( m_pSep
->nEndPos
== m_nLineEnd
)
4838 else if (&rDesc
== m_pSep
)
4840 // Sep Adjust if end Char-Attr == paragraph end ...
4841 if( (rDesc
.nEndPos
== m_nLineEnd
) && (rDesc
.nEndPos
> rDesc
.nStartPos
) )
4842 rDesc
.nEndPos
--; // ... then shorten by one character
4846 void WW8PLCFxDesc::ReduceByOffset()
4848 SAL_WARN_IF(WW8_CP_MAX
!= nStartPos
&& nStartPos
> nEndPos
, "sw.ww8",
4849 "End " << nEndPos
<< " before Start " << nStartPos
);
4851 if( nStartPos
!= WW8_CP_MAX
)
4855 Force the property change to happen at the beginning of this
4856 subdocument, same as in GetNewNoSprms, except that the target type is
4857 attributes attached to a piece that might span subdocument boundaries
4859 if (nCpOfs
> nStartPos
)
4862 nStartPos
-= nCpOfs
;
4864 if (nEndPos
!= WW8_CP_MAX
)
4866 if (nCpOfs
> nEndPos
)
4868 SAL_WARN("sw.ww8", "broken subdocument piece entry");
4869 nEndPos
= WW8_CP_MAX
;
4876 void WW8PLCFMan::GetNewSprms( WW8PLCFxDesc
& rDesc
)
4878 rDesc
.pPLCFx
->GetSprms(&rDesc
);
4879 rDesc
.ReduceByOffset();
4881 rDesc
.bFirstSprm
= true;
4882 AdjustEnds( rDesc
);
4883 rDesc
.nOrigSprmsLen
= rDesc
.nSprmsLen
;
4886 void WW8PLCFMan::GetNewNoSprms( WW8PLCFxDesc
& rDesc
)
4888 rDesc
.nCp2OrIdx
= rDesc
.pPLCFx
->GetNoSprms(rDesc
.nStartPos
, rDesc
.nEndPos
,
4891 SAL_WARN_IF(WW8_CP_MAX
!= rDesc
.nStartPos
&& rDesc
.nStartPos
> rDesc
.nEndPos
, "sw.ww8",
4892 "End " << rDesc
.nEndPos
<< " before Start " << rDesc
.nStartPos
);
4894 rDesc
.ReduceByOffset();
4896 rDesc
.bFirstSprm
= true;
4897 rDesc
.nOrigSprmsLen
= rDesc
.nSprmsLen
;
4900 sal_uInt16
WW8PLCFMan::GetId(const WW8PLCFxDesc
* p
) const
4902 sal_uInt16 nId
= 0; // Id = 0 for empty attributes
4906 else if (p
== m_pFootnote
)
4908 else if (p
== m_pEdn
)
4910 else if (p
== m_pAnd
)
4912 else if (p
->nSprmsLen
>= maSprmParser
.MinSprmLen())
4913 nId
= maSprmParser
.GetSprmId(p
->pMemPos
);
4918 WW8PLCFMan::WW8PLCFMan(const WW8ScannerBase
* pBase
, ManTypes nType
, tools::Long nStartCp
,
4919 bool bDoingDrawTextBox
)
4920 : maSprmParser(*pBase
->m_pWw8Fib
),
4921 m_nLineEnd(WW8_CP_MAX
),
4922 mbDoingDrawTextBox(bDoingDrawTextBox
)
4924 m_pWwFib
= pBase
->m_pWw8Fib
;
4928 if( MAN_MAINTEXT
== nType
)
4930 // search order of the attributes
4931 m_nPLCF
= MAN_PLCF_COUNT
;
4932 m_pField
= &m_aD
[0];
4935 m_pFootnote
= &m_aD
[3];
4938 m_pPcd
= pBase
->m_pPLCFx_PCD
? &m_aD
[5] : nullptr;
4939 //pPcdA index == pPcd index + 1
4940 m_pPcdA
= pBase
->m_pPLCFx_PCDAttrs
? &m_aD
[6] : nullptr;
4945 m_pAtnBkm
= &m_aD
[10];
4946 m_pFactoidBkm
= &m_aD
[11];
4948 m_pSep
->pPLCFx
= pBase
->m_pSepPLCF
.get();
4949 m_pFootnote
->pPLCFx
= pBase
->m_pFootnotePLCF
.get();
4950 m_pEdn
->pPLCFx
= pBase
->m_pEdnPLCF
.get();
4951 m_pBkm
->pPLCFx
= pBase
->m_pBook
.get();
4952 m_pAnd
->pPLCFx
= pBase
->m_pAndPLCF
.get();
4953 m_pAtnBkm
->pPLCFx
= pBase
->m_pAtnBook
.get();
4954 m_pFactoidBkm
->pPLCFx
= pBase
->m_pFactoidBook
.get();
4959 // search order of the attributes
4961 m_pField
= &m_aD
[0];
4962 m_pBkm
= pBase
->m_pBook
? &m_aD
[1] : nullptr;
4964 m_pPcd
= pBase
->m_pPLCFx_PCD
? &m_aD
[2] : nullptr;
4965 //pPcdA index == pPcd index + 1
4966 m_pPcdA
= pBase
->m_pPLCFx_PCDAttrs
? &m_aD
[3] : nullptr;
4970 m_pSep
= &m_aD
[6]; // Dummy
4972 m_pAnd
= m_pAtnBkm
= m_pFactoidBkm
= m_pFootnote
= m_pEdn
= nullptr; // not used at SpezText
4975 m_pChp
->pPLCFx
= pBase
->m_pChpPLCF
.get();
4976 m_pPap
->pPLCFx
= pBase
->m_pPapPLCF
.get();
4978 m_pPcd
->pPLCFx
= pBase
->m_pPLCFx_PCD
.get();
4980 m_pPcdA
->pPLCFx
= pBase
->m_pPLCFx_PCDAttrs
.get();
4982 m_pBkm
->pPLCFx
= pBase
->m_pBook
.get();
4984 m_pMagicTables
= pBase
->m_pMagicTables
.get();
4985 m_pSubdocs
= pBase
->m_pSubdocs
.get();
4986 m_pExtendedAtrds
= pBase
->m_pExtendedAtrds
.get();
4988 switch( nType
) // field initialization
4991 m_pField
->pPLCFx
= pBase
->m_pFieldHdFtPLCF
.get();
4992 m_pFdoa
= pBase
->m_pHdFtFdoa
.get();
4993 m_pTxbx
= pBase
->m_pHdFtTxbx
.get();
4994 m_pTxbxBkd
= pBase
->m_pHdFtTxbxBkd
.get();
4997 m_pField
->pPLCFx
= pBase
->m_pFieldFootnotePLCF
.get();
4998 m_pFdoa
= m_pTxbx
= m_pTxbxBkd
= nullptr;
5001 m_pField
->pPLCFx
= pBase
->m_pFieldEdnPLCF
.get();
5002 m_pFdoa
= m_pTxbx
= m_pTxbxBkd
= nullptr;
5005 m_pField
->pPLCFx
= pBase
->m_pFieldAndPLCF
.get();
5006 m_pFdoa
= m_pTxbx
= m_pTxbxBkd
= nullptr;
5009 m_pField
->pPLCFx
= pBase
->m_pFieldTxbxPLCF
.get();
5010 m_pTxbx
= pBase
->m_pMainTxbx
.get();
5011 m_pTxbxBkd
= pBase
->m_pMainTxbxBkd
.get();
5015 m_pField
->pPLCFx
= pBase
->m_pFieldTxbxHdFtPLCF
.get();
5016 m_pTxbx
= pBase
->m_pHdFtTxbx
.get();
5017 m_pTxbxBkd
= pBase
->m_pHdFtTxbxBkd
.get();
5021 m_pField
->pPLCFx
= pBase
->m_pFieldPLCF
.get();
5022 m_pFdoa
= pBase
->m_pMainFdoa
.get();
5023 m_pTxbx
= pBase
->m_pMainTxbx
.get();
5024 m_pTxbxBkd
= pBase
->m_pMainTxbxBkd
.get();
5029 m_pWwFib
->GetBaseCp(nType
, &cp
); //TODO: check return value
5032 if( nStartCp
|| m_nCpO
)
5033 SeekPos( nStartCp
); // adjust PLCFe at text StartPos
5035 // initialization to the member vars Low-Level
5036 GetChpPLCF()->ResetAttrStartEnd();
5037 GetPapPLCF()->ResetAttrStartEnd();
5038 for( sal_uInt16 i
=0; i
< m_nPLCF
; ++i
)
5040 WW8PLCFxDesc
* p
= &m_aD
[i
];
5044 For subdocuments we modify the cp of properties to be relative to
5045 the beginning of subdocuments, we should also do the same for
5046 piecetable changes, and piecetable properties, otherwise a piece
5047 change that happens in a subdocument is lost.
5049 p
->nCpOfs
= ( p
== m_pChp
|| p
== m_pPap
|| p
== m_pBkm
|| p
== m_pPcd
||
5050 p
== m_pPcdA
) ? m_nCpO
: 0;
5053 p
->bFirstSprm
= false;
5054 p
->pIdStack
= nullptr;
5056 if ((p
== m_pChp
) || (p
== m_pPap
))
5057 p
->nStartPos
= p
->nEndPos
= nStartCp
;
5059 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
5062 // initialization to the member vars High-Level
5063 for( sal_uInt16 i
=0; i
<m_nPLCF
; ++i
){
5064 WW8PLCFxDesc
* p
= &m_aD
[i
];
5068 p
->nStartPos
= p
->nEndPos
= WW8_CP_MAX
;
5072 if( p
->pPLCFx
->IsSprm() )
5074 // Careful: nEndPos must be
5075 p
->pIdStack
= new std::stack
<sal_uInt16
>;
5076 if ((p
== m_pChp
) || (p
== m_pPap
))
5078 WW8_CP nTemp
= p
->nEndPos
+p
->nCpOfs
;
5079 p
->pMemPos
= nullptr;
5081 p
->nStartPos
= nTemp
;
5082 if (!(*p
->pPLCFx
).SeekPos(p
->nStartPos
))
5083 p
->nEndPos
= p
->nStartPos
= WW8_CP_MAX
;
5088 GetNewSprms( *p
); // initialized at all PLCFs
5090 else if( p
->pPLCFx
)
5091 GetNewNoSprms( *p
);
5095 WW8PLCFMan::~WW8PLCFMan()
5097 for( sal_uInt16 i
=0; i
<m_nPLCF
; i
++)
5098 delete m_aD
[i
].pIdStack
;
5101 // 0. which attr class,
5102 // 1. if it's an attr start,
5103 // 2. CP, where is next attr change
5104 sal_uInt16
WW8PLCFMan::WhereIdx(bool *const pbStart
, WW8_CP
*const pPos
) const
5106 OSL_ENSURE(m_nPLCF
,"What the hell");
5107 WW8_CP nNext
= WW8_CP_MAX
; // search order:
5108 sal_uInt16 nNextIdx
= m_nPLCF
;// first ending found ( CHP, PAP, ( SEP ) ),
5109 bool bStart
= true; // now find beginnings ( ( SEP ), PAP, CHP )
5110 const WW8PLCFxDesc
* pD
;
5111 for (sal_uInt16 i
=0; i
< m_nPLCF
; ++i
)
5116 if( (pD
->nEndPos
< nNext
) && (pD
->nStartPos
== WW8_CP_MAX
) )
5118 // otherwise start = end
5119 nNext
= pD
->nEndPos
;
5125 for (sal_uInt16 i
=m_nPLCF
; i
> 0; --i
)
5128 if (pD
!= m_pPcdA
&& pD
->nStartPos
< nNext
)
5130 nNext
= pD
->nStartPos
;
5142 // gives the CP pos of the next attr change
5143 WW8_CP
WW8PLCFMan::Where() const
5146 WhereIdx(nullptr, &l
);
5150 void WW8PLCFMan::SeekPos( tools::Long nNewCp
)
5152 m_pChp
->pPLCFx
->SeekPos( nNewCp
+ m_nCpO
); // create new attr
5153 m_pPap
->pPLCFx
->SeekPos( nNewCp
+ m_nCpO
);
5154 m_pField
->pPLCFx
->SeekPos( nNewCp
);
5156 m_pPcd
->pPLCFx
->SeekPos( nNewCp
+ m_nCpO
);
5158 m_pBkm
->pPLCFx
->SeekPos( nNewCp
+ m_nCpO
);
5161 void WW8PLCFMan::SaveAllPLCFx( WW8PLCFxSaveAll
& rSave
) const
5165 m_pPcd
->Save( rSave
.aS
[n
++] );
5167 m_pPcdA
->Save( rSave
.aS
[n
++] );
5169 for(sal_uInt16 i
=0; i
<m_nPLCF
; ++i
)
5170 if( m_pPcd
!= &m_aD
[i
] && m_pPcdA
!= &m_aD
[i
] )
5171 m_aD
[i
].Save( rSave
.aS
[n
++] );
5174 void WW8PLCFMan::RestoreAllPLCFx( const WW8PLCFxSaveAll
& rSave
)
5178 m_pPcd
->Restore( rSave
.aS
[n
++] );
5180 m_pPcdA
->Restore( rSave
.aS
[n
++] );
5182 for(sal_uInt16 i
=0; i
<m_nPLCF
; ++i
)
5183 if( m_pPcd
!= &m_aD
[i
] && m_pPcdA
!= &m_aD
[i
] )
5184 m_aD
[i
].Restore( rSave
.aS
[n
++] );
5189 bool IsSizeLegal(tools::Long nSprmLen
, sal_Int32 nSprmsLen
)
5191 if (nSprmLen
> nSprmsLen
)
5193 SAL_WARN("sw.ww8", "Short sprm, len " << nSprmLen
<< " claimed, max possible is " << nSprmsLen
);
5200 bool WW8PLCFMan::IsSprmLegalForCategory(sal_uInt16 nSprmId
, short nIdx
) const
5202 const WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5203 if (p
!= m_pSep
) // just check sep for now
5207 ww::WordVersion eVersion
= maSprmParser
.GetFIBVersion();
5208 if (eVersion
<= ww::eWW2
)
5209 bRet
= nSprmId
>= 112 && nSprmId
<= 145;
5210 else if (eVersion
< ww::eWW8
)
5211 bRet
= nSprmId
>= NS_sprm::v6::sprmSScnsPgn
&& nSprmId
<= NS_sprm::v6::sprmSDMPaperReq
;
5215 Sprm bits: 10-12 sgc sprm group; type of sprm (PAP, CHP, etc)
5217 sgc value type of sprm
5224 auto nSGC
= ((nSprmId
& 0x1C00) >> 10);
5227 SAL_WARN_IF(!bRet
, "sw.ww8", "sprm, id " << nSprmId
<< " wrong category for section properties");
5231 void WW8PLCFMan::GetSprmStart( short nIdx
, WW8PLCFManResult
* pRes
) const
5233 memset( pRes
, 0, sizeof( WW8PLCFManResult
) );
5239 const WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5241 // first Sprm in a Group
5245 pRes
->nFlags
|= MAN_MASK_NEW_PAP
;
5246 else if( p
== m_pSep
)
5247 pRes
->nFlags
|= MAN_MASK_NEW_SEP
;
5249 pRes
->pMemPos
= p
->pMemPos
;
5250 pRes
->nSprmId
= GetId(p
);
5251 pRes
->nCp2OrIdx
= p
->nCp2OrIdx
;
5252 if ((p
== m_pFootnote
) || (p
== m_pEdn
) || (p
== m_pAnd
))
5253 pRes
->nMemLen
= p
->nSprmsLen
;
5254 else if (p
->nSprmsLen
>= maSprmParser
.MinSprmLen()) //normal
5256 // Length of actual sprm
5257 pRes
->nMemLen
= maSprmParser
.GetSprmSize(pRes
->nSprmId
, pRes
->pMemPos
, p
->nSprmsLen
);
5258 if (!IsSizeLegal(pRes
->nMemLen
, p
->nSprmsLen
) || !IsSprmLegalForCategory(pRes
->nSprmId
, nIdx
))
5265 void WW8PLCFMan::GetSprmEnd( short nIdx
, WW8PLCFManResult
* pRes
) const
5267 memset( pRes
, 0, sizeof( WW8PLCFManResult
) );
5269 const WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5271 if (!(p
->pIdStack
->empty()))
5272 pRes
->nSprmId
= p
->pIdStack
->top(); // get end position
5275 OSL_ENSURE( false, "No Id on the Stack" );
5280 void WW8PLCFMan::GetNoSprmStart( short nIdx
, WW8PLCFManResult
* pRes
) const
5282 const WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5284 pRes
->nCpPos
= p
->nStartPos
;
5285 pRes
->nMemLen
= p
->nSprmsLen
;
5286 pRes
->nCp2OrIdx
= p
->nCp2OrIdx
;
5289 pRes
->nSprmId
= eFLD
;
5290 else if( p
== m_pFootnote
)
5291 pRes
->nSprmId
= eFTN
;
5292 else if( p
== m_pEdn
)
5293 pRes
->nSprmId
= eEDN
;
5294 else if( p
== m_pBkm
)
5295 pRes
->nSprmId
= eBKN
;
5296 else if (p
== m_pAtnBkm
)
5297 pRes
->nSprmId
= eATNBKN
;
5298 else if (p
== m_pFactoidBkm
)
5299 pRes
->nSprmId
= eFACTOIDBKN
;
5300 else if( p
== m_pAnd
)
5301 pRes
->nSprmId
= eAND
;
5302 else if( p
== m_pPcd
)
5304 //We slave the piece table attributes to the piece table, the piece
5305 //table attribute iterator contains the sprms for this piece.
5306 GetSprmStart( nIdx
+1, pRes
);
5309 pRes
->nSprmId
= 0; // default: not found
5312 void WW8PLCFMan::GetNoSprmEnd( short nIdx
, WW8PLCFManResult
* pRes
) const
5314 pRes
->nMemLen
= -1; // end tag
5316 if( &m_aD
[nIdx
] == m_pBkm
)
5317 pRes
->nSprmId
= eBKN
;
5318 else if (&m_aD
[nIdx
] == m_pAtnBkm
)
5319 pRes
->nSprmId
= eATNBKN
;
5320 else if (&m_aD
[nIdx
] == m_pFactoidBkm
)
5321 pRes
->nSprmId
= eFACTOIDBKN
;
5322 else if( &m_aD
[nIdx
] == m_pPcd
)
5324 //We slave the piece table attributes to the piece table, the piece
5325 //table attribute iterator contains the sprms for this piece.
5326 GetSprmEnd( nIdx
+1, pRes
);
5332 void WW8PLCFMan::TransferOpenSprms(std::stack
<sal_uInt16
> &rStack
)
5334 for (sal_uInt16 i
= 0; i
< m_nPLCF
; ++i
)
5336 WW8PLCFxDesc
* p
= &m_aD
[i
];
5337 if (!p
|| !p
->pIdStack
)
5339 while (!p
->pIdStack
->empty())
5341 rStack
.push(p
->pIdStack
->top());
5347 void WW8PLCFMan::AdvSprm(short nIdx
, bool bStart
)
5349 WW8PLCFxDesc
* p
= &m_aD
[nIdx
]; // determine sprm class(!)
5351 p
->bFirstSprm
= false;
5354 const sal_uInt16 nLastId
= GetId(p
);
5356 const sal_uInt16 nLastAttribStarted
= IsSprmLegalForCategory(nLastId
, nIdx
) ? nLastId
: 0;
5358 p
->pIdStack
->push(nLastAttribStarted
); // remember Id for attribute end
5362 Check, if we have to process more sprm(s).
5366 // Length of last sprm
5367 const sal_Int32 nSprmL
= maSprmParser
.GetSprmSize(nLastId
, p
->pMemPos
, p
->nSprmsLen
);
5369 // Reduce length of all sprms by length of last sprm
5370 p
->nSprmsLen
-= nSprmL
;
5372 // pos of next possible sprm
5373 if (p
->nSprmsLen
< maSprmParser
.MinSprmLen())
5375 // preventively set to 0, because the end follows!
5376 p
->pMemPos
= nullptr;
5380 p
->pMemPos
+= nSprmL
;
5385 if (p
->nSprmsLen
< maSprmParser
.MinSprmLen())
5386 p
->nStartPos
= WW8_CP_MAX
; // the ending follows
5390 if (!(p
->pIdStack
->empty()))
5392 if (p
->pIdStack
->empty())
5394 if ( (p
== m_pChp
) || (p
== m_pPap
) )
5396 p
->pMemPos
= nullptr;
5398 p
->nStartPos
= p
->nOrigEndPos
+p
->nCpOfs
;
5401 On failed seek we have run out of sprms, probably. But if its
5402 a fastsaved file (has pPcd) then we may be just in a sprm free
5403 gap between pieces that have them, so set dirty flag in sprm
5404 finder to consider than.
5406 if (!(*p
->pPLCFx
).SeekPos(p
->nStartPos
))
5408 p
->nEndPos
= WW8_CP_MAX
;
5409 p
->pPLCFx
->SetDirty(true);
5411 if (!p
->pPLCFx
->GetDirty() || m_pPcd
)
5413 p
->pPLCFx
->SetDirty(false);
5417 To get the character and paragraph properties you first get
5418 the pap and chp and then apply the fastsaved pPcd properties
5419 to the range. If a pap or chp starts inside the pPcd range
5420 then we must bring the current pPcd range to a halt so as to
5421 end those sprms, then the pap/chp will be processed, and then
5422 we must force a restart of the pPcd on that pap/chp starting
5423 boundary. Doing that effectively means that the pPcd sprms will
5424 be applied to the new range. Not doing it means that the pPcd
5425 sprms will only be applied to the first pap/chp set of
5426 properties contained in the pap/chp range.
5428 So we bring the pPcd to a halt on this location here, by
5429 settings its end to the current start, then store the starting
5430 position of the current range to clipstart. The pPcd sprms
5431 will end as normal (albeit earlier than originally expected),
5432 and the existence of a clipstart will force the pPcd iterator
5433 to reread the current set of sprms instead of advancing to its
5434 next set. Then the clipstart will be set as the starting
5435 position which will force them to be applied directly after
5438 if (m_pPcd
&& ((p
->nStartPos
> m_pPcd
->nStartPos
) ||
5439 (m_pPcd
->nStartPos
== WW8_CP_MAX
)) &&
5440 (m_pPcd
->nEndPos
!= p
->nStartPos
))
5442 m_pPcd
->nEndPos
= p
->nStartPos
;
5443 static_cast<WW8PLCFx_PCD
*>(m_pPcd
->pPLCFx
)->SetClipStart(
5450 p
->pPLCFx
->advance(); // next Group of Sprms
5451 p
->pMemPos
= nullptr; // !!!
5455 SAL_WARN_IF(p
->nStartPos
> p
->nEndPos
, "sw.ww8",
5456 "End " << p
->nEndPos
<< " before Start " << p
->nStartPos
);
5461 void WW8PLCFMan::AdvNoSprm(short nIdx
, bool bStart
)
5464 For the case of a piece table we slave the piece table attribute iterator
5465 to the piece table and access it through that only. They are two separate
5466 structures, but act together as one logical one. The attributes only go
5467 to the next entry when the piece changes
5469 WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5473 AdvSprm(nIdx
+1,bStart
);
5475 p
->nStartPos
= m_aD
[nIdx
+1].nStartPos
;
5478 if (m_aD
[nIdx
+1].pIdStack
->empty())
5480 WW8PLCFx_PCD
*pTemp
= static_cast<WW8PLCFx_PCD
*>(m_pPcd
->pPLCFx
);
5483 As per normal, go on to the next set of properties, i.e. we
5484 have traversed over to the next piece. With a clipstart set
5485 we are being told to reread the current piece sprms so as to
5486 reapply them to a new chp or pap range.
5488 if (pTemp
->GetClipStart() == -1)
5489 p
->pPLCFx
->advance();
5490 p
->pMemPos
= nullptr;
5492 GetNewSprms( m_aD
[nIdx
+1] );
5493 GetNewNoSprms( *p
);
5494 if (pTemp
->GetClipStart() != -1)
5497 #i2325#, now we will force our starting position to the
5498 clipping start so as to force the application of these
5499 sprms after the current pap/chp sprms so as to apply the
5500 fastsave sprms to the current range.
5502 p
->nStartPos
= pTemp
->GetClipStart();
5503 pTemp
->SetClipStart(-1);
5509 { // NoSprm without end
5510 p
->pPLCFx
->advance();
5511 p
->pMemPos
= nullptr; // MemPos invalid
5513 GetNewNoSprms( *p
);
5517 void WW8PLCFMan::advance()
5520 const sal_uInt16 nIdx
= WhereIdx(&bStart
);
5523 WW8PLCFxDesc
* p
= &m_aD
[nIdx
];
5525 p
->bFirstSprm
= true; // Default
5527 if( p
->pPLCFx
->IsSprm() )
5528 AdvSprm( nIdx
, bStart
);
5530 AdvNoSprm( nIdx
, bStart
);
5534 // return true for the beginning of an attribute or error,
5535 // false for the end of an attribute
5536 // remaining return values are delivered to the caller from WW8PclxManResults.
5537 bool WW8PLCFMan::Get(WW8PLCFManResult
* pRes
) const
5539 memset( pRes
, 0, sizeof( WW8PLCFManResult
) );
5541 const sal_uInt16 nIdx
= WhereIdx(&bStart
);
5543 if( nIdx
>= m_nPLCF
)
5545 OSL_ENSURE( false, "Position not found" );
5549 if( m_aD
[nIdx
].pPLCFx
->IsSprm() )
5553 GetSprmStart( nIdx
, pRes
);
5558 GetSprmEnd( nIdx
, pRes
);
5566 GetNoSprmStart( nIdx
, pRes
);
5571 GetNoSprmEnd( nIdx
, pRes
);
5577 sal_uInt16
WW8PLCFMan::GetColl() const
5579 if( m_pPap
->pPLCFx
)
5580 return m_pPap
->pPLCFx
->GetIstd();
5583 OSL_ENSURE( false, "GetColl without PLCF_Pap" );
5588 WW8PLCFx_FLD
* WW8PLCFMan::GetField() const
5590 return static_cast<WW8PLCFx_FLD
*>(m_pField
->pPLCFx
);
5593 SprmResult
WW8PLCFMan::HasParaSprm( sal_uInt16 nId
) const
5595 return static_cast<WW8PLCFx_Cp_FKP
*>(m_pPap
->pPLCFx
)->HasSprm( nId
);
5598 SprmResult
WW8PLCFMan::HasCharSprm( sal_uInt16 nId
) const
5600 return static_cast<WW8PLCFx_Cp_FKP
*>(m_pChp
->pPLCFx
)->HasSprm( nId
);
5603 void WW8PLCFMan::HasCharSprm(sal_uInt16 nId
,
5604 std::vector
<SprmResult
> &rResult
) const
5606 static_cast<WW8PLCFx_Cp_FKP
*>(m_pChp
->pPLCFx
)->HasSprm(nId
, rResult
);
5609 void WW8PLCFx::Save( WW8PLCFxSave1
& rSave
) const
5611 rSave
.nPLCFxPos
= GetIdx();
5612 rSave
.nPLCFxPos2
= GetIdx2();
5613 rSave
.nPLCFxMemOfs
= 0;
5614 rSave
.nStartFC
= GetStartFc();
5617 void WW8PLCFx::Restore( const WW8PLCFxSave1
& rSave
)
5619 SetIdx( rSave
.nPLCFxPos
);
5620 SetIdx2( rSave
.nPLCFxPos2
);
5621 SetStartFc( rSave
.nStartFC
);
5624 sal_uInt32
WW8PLCFx_Cp_FKP::GetIdx2() const
5629 void WW8PLCFx_Cp_FKP::SetIdx2(sal_uInt32 nIdx
)
5632 pPcd
->SetIdx( nIdx
);
5635 void WW8PLCFx_Cp_FKP::Save( WW8PLCFxSave1
& rSave
) const
5638 pFkp
->IncMustRemainCache();
5639 WW8PLCFx::Save( rSave
);
5641 rSave
.nAttrStart
= nAttrStart
;
5642 rSave
.nAttrEnd
= nAttrEnd
;
5643 rSave
.bLineEnd
= bLineEnd
;
5646 void WW8PLCFx_Cp_FKP::Restore( const WW8PLCFxSave1
& rSave
)
5648 WW8PLCFx::Restore( rSave
);
5650 nAttrStart
= rSave
.nAttrStart
;
5651 nAttrEnd
= rSave
.nAttrEnd
;
5652 bLineEnd
= rSave
.bLineEnd
;
5655 pFkp
->DecMustRemainCache();
5658 void WW8PLCFxDesc::Save( WW8PLCFxSave1
& rSave
) const
5663 pPLCFx
->Save( rSave
);
5664 if( !pPLCFx
->IsSprm() )
5668 aD
.nStartPos
= nOrigStartPos
+nCpOfs
;
5669 aD
.nCpOfs
= rSave
.nCpOfs
= nCpOfs
;
5670 if (!(pPLCFx
->SeekPos(aD
.nStartPos
)))
5672 aD
.nEndPos
= WW8_CP_MAX
;
5673 pPLCFx
->SetDirty(true);
5675 pPLCFx
->GetSprms(&aD
);
5676 pPLCFx
->SetDirty(false);
5677 aD
.ReduceByOffset();
5678 rSave
.nStartCp
= aD
.nStartPos
;
5679 rSave
.nPLCFxMemOfs
= nOrigSprmsLen
- nSprmsLen
;
5682 void WW8PLCFxDesc::Restore( const WW8PLCFxSave1
& rSave
)
5687 pPLCFx
->Restore( rSave
);
5688 if( !pPLCFx
->IsSprm() )
5692 aD
.nStartPos
= rSave
.nStartCp
+rSave
.nCpOfs
;
5693 nCpOfs
= aD
.nCpOfs
= rSave
.nCpOfs
;
5694 if (!(pPLCFx
->SeekPos(aD
.nStartPos
)))
5696 aD
.nEndPos
= WW8_CP_MAX
;
5697 pPLCFx
->SetDirty(true);
5699 pPLCFx
->GetSprms(&aD
);
5700 pPLCFx
->SetDirty(false);
5701 aD
.ReduceByOffset();
5703 if (nOrigSprmsLen
> aD
.nSprmsLen
)
5705 //two entries exist for the same offset, cut and run
5706 SAL_WARN("sw.ww8", "restored properties don't match saved properties, bailing out");
5712 nSprmsLen
= nOrigSprmsLen
- rSave
.nPLCFxMemOfs
;
5713 pMemPos
= aD
.pMemPos
== nullptr ? nullptr : aD
.pMemPos
+ rSave
.nPLCFxMemOfs
;
5719 sal_uInt32
Readcb(SvStream
& rSt
, ww::WordVersion eVer
)
5721 if (eVer
<= ww::eWW2
)
5723 sal_uInt16
nShort(0);
5724 rSt
.ReadUInt16(nShort
);
5729 sal_uInt32
nLong(0);
5730 rSt
.ReadUInt32(nLong
);
5736 bool WW8Fib::GetBaseCp(ManTypes nType
, WW8_CP
* cp
) const
5738 assert(cp
!= nullptr);
5744 if (m_ccpTxbx
< 0) {
5747 nOffset
= m_ccpTxbx
;
5750 if (m_ccpEdn
< 0 || m_ccpEdn
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5753 nOffset
+= m_ccpEdn
;
5756 if (m_ccpAtn
< 0 || m_ccpAtn
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5759 nOffset
+= m_ccpAtn
;
5762 if (m_ccpMcr
< 0 || m_ccpMcr
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5765 nOffset
+= m_ccpMcr
;
5769 A subdocument of this kind (MAN_MACRO) probably exists in some defunct
5770 version of MSWord, but now ccpMcr is always 0. If some example that
5771 uses this comes to light, this is the likely calculation required
5775 if (m_ccpHdr
< 0 || m_ccpHdr
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5778 nOffset
+= m_ccpHdr
;
5781 if (m_ccpFootnote
< 0 || m_ccpFootnote
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5784 nOffset
+= m_ccpFootnote
;
5787 if (m_ccpText
< 0 || m_ccpText
> std::numeric_limits
<WW8_CP
>::max() - nOffset
) {
5790 nOffset
+= m_ccpText
;
5799 ww::WordVersion
WW8Fib::GetFIBVersion() const
5801 ww::WordVersion eVer
= ww::eWW8
;
5803 * Word for Windows 2 I think (1.X might work too if anyone has an example.
5805 * 0xA59B for Word 1 for Windows
5806 * 0xA59C for Word 1 for OS/2 "PM Word"
5808 * Various pages claim that the fileformats of Word 1 and 2 for Windows are
5809 * equivalent to Word for Macintosh 4 and 5. On the other hand
5811 * wIdents for Word for Mac versions...
5814 * 0xFE37 for Word 4 et 5.
5817 * http://cmsdoc.cern.ch/documents/docformat/CMS_CERN_LetterHead.word is
5818 * claimed to be "Word 5 for Mac" by Office etc and has that wIdent, but
5819 * its format isn't the same as that of Word 2 for windows. Nor is it
5820 * the same as that of Word for DOS/PCWord 5
5822 if (m_wIdent
== 0xa59b || m_wIdent
== 0xa59c)
5824 else if (m_wIdent
== 0xa5db)
5844 WW8Fib::WW8Fib(SvStream
& rSt
, sal_uInt8 nWantedVersion
, sal_uInt32 nOffset
):
5845 m_fDot(false), m_fGlsy(false), m_fComplex(false), m_fHasPic(false), m_cQuickSaves(0),
5846 m_fEncrypted(false), m_fWhichTableStm(false), m_fReadOnlyRecommended(false),
5847 m_fWriteReservation(false), m_fExtChar(false), m_fFarEast(false), m_fObfuscated(false),
5848 m_fMac(false), m_fEmptySpecial(false), m_fLoadOverridePage(false), m_fFuturesavedUndo(false),
5849 m_fWord97Saved(false), m_fWord2000Saved(false)
5850 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
5851 // above bit-field member initializations can be moved to the class definition
5853 // See [MS-DOC] 2.5.15 "How to read the FIB".
5856 sal_uInt8 aVer8Bits1
; // only used starting with WinWord 8
5857 rSt
.Seek( nOffset
);
5859 note desired number, identify file version number
5860 and check against desired number!
5862 m_nVersion
= nWantedVersion
;
5863 rSt
.ReadUInt16( m_wIdent
);
5864 rSt
.ReadUInt16( m_nFib
);
5865 rSt
.ReadUInt16( m_nProduct
);
5866 if( ERRCODE_NONE
!= rSt
.GetError() )
5870 // note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
5871 switch( m_nVersion
)
5874 nFibMin
= 0x0065; // from 101 WinWord 6.0
5876 // and 103 WinWord 6.0 for Macintosh
5878 nFibMax
= 0x0069; // to 105 WinWord 95
5881 nFibMin
= 0x0069; // from 105 WinWord 95
5882 nFibMax
= 0x0069; // to 105 WinWord 95
5885 nFibMin
= 0x006A; // from 106 WinWord 97
5886 nFibMax
= 0x00c1; // to 193 WinWord 97 (?)
5889 nFibMin
= 0; // program error!
5892 OSL_ENSURE( false, "nVersion not implemented!" );
5895 if ( (m_nFib
< nFibMin
) || (m_nFib
> nFibMax
) )
5897 m_nFibError
= ERR_SWG_READ_ERROR
; // report error
5902 ww::WordVersion eVer
= GetFIBVersion();
5904 // helper vars for Ver67:
5905 sal_Int16 pnChpFirst_Ver67
=0;
5906 sal_Int16 pnPapFirst_Ver67
=0;
5907 sal_Int16 cpnBteChp_Ver67
=0;
5908 sal_Int16 cpnBtePap_Ver67
=0;
5911 sal_uInt16 nTmpLid
= 0;
5912 rSt
.ReadUInt16(nTmpLid
);
5913 m_lid
= LanguageType(nTmpLid
);
5914 rSt
.ReadInt16( m_pnNext
);
5915 rSt
.ReadUChar( aBits1
);
5916 rSt
.ReadUChar( aBits2
);
5917 rSt
.ReadUInt16( m_nFibBack
);
5918 rSt
.ReadUInt16( m_nHash
);
5919 rSt
.ReadUInt16( m_nKey
);
5920 rSt
.ReadUChar( m_envr
);
5921 rSt
.ReadUChar( aVer8Bits1
); // only have an empty reserve field under Ver67
5922 // content from aVer8Bits1
5924 // sal_uInt8 fMac :1;
5925 // sal_uInt8 fEmptySpecial :1;
5926 // sal_uInt8 fLoadOverridePage :1;
5927 // sal_uInt8 fFuturesavedUndo :1;
5928 // sal_uInt8 fWord97Saved :1;
5930 rSt
.ReadUInt16( m_chse
);
5931 rSt
.ReadUInt16( m_chseTables
);
5932 rSt
.ReadInt32( m_fcMin
);
5933 rSt
.ReadInt32( m_fcMac
);
5935 // insertion for WW8
5936 if (IsEightPlus(eVer
))
5938 rSt
.ReadUInt16( m_csw
);
5940 // Marke: "rgsw" Beginning of the array of shorts
5941 rSt
.ReadUInt16( m_wMagicCreated
);
5942 rSt
.ReadUInt16( m_wMagicRevised
);
5943 rSt
.ReadUInt16( m_wMagicCreatedPrivate
);
5944 rSt
.ReadUInt16( m_wMagicRevisedPrivate
);
5945 rSt
.SeekRel( 9 * sizeof( sal_Int16
) );
5948 // these are the 9 unused fields:
5949 && (bVer67 || WW8ReadINT16( rSt, pnFbpChpFirst_W6 )) // 1
5950 && (bVer67 || WW8ReadINT16( rSt, pnChpFirst_W6 )) // 2
5951 && (bVer67 || WW8ReadINT16( rSt, cpnBteChp_W6 )) // 3
5952 && (bVer67 || WW8ReadINT16( rSt, pnFbpPapFirst_W6 )) // 4
5953 && (bVer67 || WW8ReadINT16( rSt, pnPapFirst_W6 )) // 5
5954 && (bVer67 || WW8ReadINT16( rSt, cpnBtePap_W6 )) // 6
5955 && (bVer67 || WW8ReadINT16( rSt, pnFbpLvcFirst_W6 )) // 7
5956 && (bVer67 || WW8ReadINT16( rSt, pnLvcFirst_W6 )) // 8
5957 && (bVer67 || WW8ReadINT16( rSt, cpnBteLvc_W6 )) // 9
5959 sal_uInt16 nTmpFE
= 0;
5960 rSt
.ReadUInt16(nTmpFE
);
5961 m_lidFE
= LanguageType(nTmpFE
);
5962 rSt
.ReadUInt16( m_clw
);
5965 // end of the insertion for WW8
5967 // Marke: "rglw" Beginning of the array of longs
5968 rSt
.ReadInt32( m_cbMac
);
5970 // ignore 2 longs, because they are unimportant
5971 rSt
.SeekRel( 2 * sizeof( sal_Int32
) );
5973 // skipping 2 more longs only at Ver67
5974 if (IsSevenMinus(eVer
))
5975 rSt
.SeekRel( 2 * sizeof( sal_Int32
) );
5977 rSt
.ReadInt32( m_ccpText
);
5978 rSt
.ReadInt32( m_ccpFootnote
);
5979 rSt
.ReadInt32( m_ccpHdr
);
5980 rSt
.ReadInt32( m_ccpMcr
);
5981 rSt
.ReadInt32( m_ccpAtn
);
5982 rSt
.ReadInt32( m_ccpEdn
);
5983 rSt
.ReadInt32( m_ccpTxbx
);
5984 rSt
.ReadInt32( m_ccpHdrTxbx
);
5986 // only skip one more long at Ver67
5987 if (IsSevenMinus(eVer
))
5988 rSt
.SeekRel( 1 * sizeof( sal_Int32
) );
5991 // insertion for WW8
5992 rSt
.ReadInt32( m_pnFbpChpFirst
);
5993 rSt
.ReadInt32( m_pnChpFirst
);
5994 rSt
.ReadInt32( m_cpnBteChp
);
5995 rSt
.ReadInt32( m_pnFbpPapFirst
);
5996 rSt
.ReadInt32( m_pnPapFirst
);
5997 rSt
.ReadInt32( m_cpnBtePap
);
5998 rSt
.ReadInt32( m_pnFbpLvcFirst
);
5999 rSt
.ReadInt32( m_pnLvcFirst
);
6000 rSt
.ReadInt32( m_cpnBteLvc
);
6001 rSt
.ReadInt32( m_fcIslandFirst
);
6002 rSt
.ReadInt32( m_fcIslandLim
);
6003 rSt
.ReadUInt16( m_cfclcb
);
6005 // Read cswNew to find out if nFib should be ignored.
6006 sal_uInt32 nPos
= rSt
.Tell();
6007 rSt
.SeekRel(m_cfclcb
* 8);
6010 rSt
.ReadUInt16(m_cswNew
);
6015 // end of the insertion for WW8
6017 // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
6018 rSt
.ReadInt32( m_fcStshfOrig
);
6019 m_lcbStshfOrig
= Readcb(rSt
, eVer
);
6020 rSt
.ReadInt32( m_fcStshf
);
6021 m_lcbStshf
= Readcb(rSt
, eVer
);
6022 rSt
.ReadInt32( m_fcPlcffndRef
);
6023 m_lcbPlcffndRef
= Readcb(rSt
, eVer
);
6024 rSt
.ReadInt32( m_fcPlcffndText
);
6025 m_lcbPlcffndText
= Readcb(rSt
, eVer
);
6026 rSt
.ReadInt32( m_fcPlcfandRef
);
6027 m_lcbPlcfandRef
= Readcb(rSt
, eVer
);
6028 rSt
.ReadInt32( m_fcPlcfandText
);
6029 m_lcbPlcfandText
= Readcb(rSt
, eVer
);
6030 rSt
.ReadInt32( m_fcPlcfsed
);
6031 m_lcbPlcfsed
= Readcb(rSt
, eVer
);
6032 rSt
.ReadInt32( m_fcPlcfpad
);
6033 m_lcbPlcfpad
= Readcb(rSt
, eVer
);
6034 rSt
.ReadInt32( m_fcPlcfphe
);
6035 m_lcbPlcfphe
= Readcb(rSt
, eVer
);
6036 rSt
.ReadInt32( m_fcSttbfglsy
);
6037 m_lcbSttbfglsy
= Readcb(rSt
, eVer
);
6038 rSt
.ReadInt32( m_fcPlcfglsy
);
6039 m_lcbPlcfglsy
= Readcb(rSt
, eVer
);
6040 rSt
.ReadInt32( m_fcPlcfhdd
);
6041 m_lcbPlcfhdd
= Readcb(rSt
, eVer
);
6042 rSt
.ReadInt32( m_fcPlcfbteChpx
);
6043 m_lcbPlcfbteChpx
= Readcb(rSt
, eVer
);
6044 rSt
.ReadInt32( m_fcPlcfbtePapx
);
6045 m_lcbPlcfbtePapx
= Readcb(rSt
, eVer
);
6046 rSt
.ReadInt32( m_fcPlcfsea
);
6047 m_lcbPlcfsea
= Readcb(rSt
, eVer
);
6048 rSt
.ReadInt32( m_fcSttbfffn
);
6049 m_lcbSttbfffn
= Readcb(rSt
, eVer
);
6050 rSt
.ReadInt32( m_fcPlcffldMom
);
6051 m_lcbPlcffldMom
= Readcb(rSt
, eVer
);
6052 rSt
.ReadInt32( m_fcPlcffldHdr
);
6053 m_lcbPlcffldHdr
= Readcb(rSt
, eVer
);
6054 rSt
.ReadInt32( m_fcPlcffldFootnote
);
6055 m_lcbPlcffldFootnote
= Readcb(rSt
, eVer
);
6056 rSt
.ReadInt32( m_fcPlcffldAtn
);
6057 m_lcbPlcffldAtn
= Readcb(rSt
, eVer
);
6058 rSt
.ReadInt32( m_fcPlcffldMcr
);
6059 m_lcbPlcffldMcr
= Readcb(rSt
, eVer
);
6060 rSt
.ReadInt32( m_fcSttbfbkmk
);
6061 m_lcbSttbfbkmk
= Readcb(rSt
, eVer
);
6062 rSt
.ReadInt32( m_fcPlcfbkf
);
6063 m_lcbPlcfbkf
= Readcb(rSt
, eVer
);
6064 rSt
.ReadInt32( m_fcPlcfbkl
);
6065 m_lcbPlcfbkl
= Readcb(rSt
, eVer
);
6066 rSt
.ReadInt32( m_fcCmds
);
6067 m_lcbCmds
= Readcb(rSt
, eVer
);
6068 rSt
.ReadInt32( m_fcPlcfmcr
);
6069 m_lcbPlcfmcr
= Readcb(rSt
, eVer
);
6070 rSt
.ReadInt32( m_fcSttbfmcr
);
6071 m_lcbSttbfmcr
= Readcb(rSt
, eVer
);
6072 if (eVer
>= ww::eWW2
)
6074 rSt
.ReadInt32( m_fcPrDrvr
);
6075 m_lcbPrDrvr
= Readcb(rSt
, eVer
);
6076 rSt
.ReadInt32( m_fcPrEnvPort
);
6077 m_lcbPrEnvPort
= Readcb(rSt
, eVer
);
6078 rSt
.ReadInt32( m_fcPrEnvLand
);
6079 m_lcbPrEnvLand
= Readcb(rSt
, eVer
);
6083 rSt
.ReadInt32( m_fcPrEnvPort
);
6084 m_lcbPrEnvPort
= Readcb(rSt
, eVer
);
6086 rSt
.ReadInt32( m_fcWss
);
6087 m_lcbWss
= Readcb(rSt
, eVer
);
6088 rSt
.ReadInt32( m_fcDop
);
6089 m_lcbDop
= Readcb(rSt
, eVer
);
6090 rSt
.ReadInt32( m_fcSttbfAssoc
);
6091 m_lcbSttbfAssoc
= Readcb(rSt
, eVer
);
6092 rSt
.ReadInt32( m_fcClx
);
6093 m_lcbClx
= Readcb(rSt
, eVer
);
6094 rSt
.ReadInt32( m_fcPlcfpgdFootnote
);
6095 m_lcbPlcfpgdFootnote
= Readcb(rSt
, eVer
);
6096 rSt
.ReadInt32( m_fcAutosaveSource
);
6097 m_lcbAutosaveSource
= Readcb(rSt
, eVer
);
6098 rSt
.ReadInt32( m_fcGrpStAtnOwners
);
6099 m_lcbGrpStAtnOwners
= Readcb(rSt
, eVer
);
6100 rSt
.ReadInt32( m_fcSttbfAtnbkmk
);
6101 m_lcbSttbfAtnbkmk
= Readcb(rSt
, eVer
);
6103 // only skip more shot at Ver67
6104 if (IsSevenMinus(eVer
))
6106 if (eVer
== ww::eWW1
)
6107 rSt
.SeekRel(1*sizeof(sal_Int32
));
6108 rSt
.SeekRel(1*sizeof(sal_Int16
));
6110 if (eVer
>= ww::eWW2
)
6112 rSt
.ReadInt16(pnChpFirst_Ver67
);
6113 rSt
.ReadInt16(pnPapFirst_Ver67
);
6115 rSt
.ReadInt16(cpnBteChp_Ver67
);
6116 rSt
.ReadInt16(cpnBtePap_Ver67
);
6119 if (eVer
> ww::eWW2
)
6121 rSt
.ReadInt32( m_fcPlcfdoaMom
);
6122 rSt
.ReadInt32( m_lcbPlcfdoaMom
);
6123 rSt
.ReadInt32( m_fcPlcfdoaHdr
);
6124 rSt
.ReadInt32( m_lcbPlcfdoaHdr
);
6125 rSt
.ReadInt32( m_fcPlcfspaMom
);
6126 rSt
.ReadInt32( m_lcbPlcfspaMom
);
6127 rSt
.ReadInt32( m_fcPlcfspaHdr
);
6128 rSt
.ReadInt32( m_lcbPlcfspaHdr
);
6130 rSt
.ReadInt32( m_fcPlcfAtnbkf
);
6131 rSt
.ReadInt32( m_lcbPlcfAtnbkf
);
6132 rSt
.ReadInt32( m_fcPlcfAtnbkl
);
6133 rSt
.ReadInt32( m_lcbPlcfAtnbkl
);
6134 rSt
.ReadInt32( m_fcPms
);
6135 rSt
.ReadInt32( m_lcbPMS
);
6136 rSt
.ReadInt32( m_fcFormFieldSttbf
);
6137 rSt
.ReadInt32( m_lcbFormFieldSttbf
);
6138 rSt
.ReadInt32( m_fcPlcfendRef
);
6139 rSt
.ReadInt32( m_lcbPlcfendRef
);
6140 rSt
.ReadInt32( m_fcPlcfendText
);
6141 rSt
.ReadInt32( m_lcbPlcfendText
);
6142 rSt
.ReadInt32( m_fcPlcffldEdn
);
6143 rSt
.ReadInt32( m_lcbPlcffldEdn
);
6144 rSt
.ReadInt32( m_fcPlcfpgdEdn
);
6145 rSt
.ReadInt32( m_lcbPlcfpgdEdn
);
6146 rSt
.ReadInt32( m_fcDggInfo
);
6147 rSt
.ReadInt32( m_lcbDggInfo
);
6148 rSt
.ReadInt32( m_fcSttbfRMark
);
6149 rSt
.ReadInt32( m_lcbSttbfRMark
);
6150 rSt
.ReadInt32( m_fcSttbfCaption
);
6151 rSt
.ReadInt32( m_lcbSttbfCaption
);
6152 rSt
.ReadInt32( m_fcSttbAutoCaption
);
6153 rSt
.ReadInt32( m_lcbSttbAutoCaption
);
6154 rSt
.ReadInt32( m_fcPlcfwkb
);
6155 rSt
.ReadInt32( m_lcbPlcfwkb
);
6156 rSt
.ReadInt32( m_fcPlcfspl
);
6157 rSt
.ReadInt32( m_lcbPlcfspl
);
6158 rSt
.ReadInt32( m_fcPlcftxbxText
);
6159 rSt
.ReadInt32( m_lcbPlcftxbxText
);
6160 rSt
.ReadInt32( m_fcPlcffldTxbx
);
6161 rSt
.ReadInt32( m_lcbPlcffldTxbx
);
6162 rSt
.ReadInt32( m_fcPlcfHdrtxbxText
);
6163 rSt
.ReadInt32( m_lcbPlcfHdrtxbxText
);
6164 rSt
.ReadInt32( m_fcPlcffldHdrTxbx
);
6165 rSt
.ReadInt32( m_lcbPlcffldHdrTxbx
);
6166 rSt
.ReadInt32( m_fcStwUser
);
6167 rSt
.ReadUInt32( m_lcbStwUser
);
6168 rSt
.ReadInt32( m_fcSttbttmbd
);
6169 rSt
.ReadUInt32( m_lcbSttbttmbd
);
6172 if( ERRCODE_NONE
== rSt
.GetError() )
6175 m_fDot
= aBits1
& 0x01 ;
6176 m_fGlsy
= ( aBits1
& 0x02 ) >> 1;
6177 m_fComplex
= ( aBits1
& 0x04 ) >> 2;
6178 m_fHasPic
= ( aBits1
& 0x08 ) >> 3;
6179 m_cQuickSaves
= ( aBits1
& 0xf0 ) >> 4;
6180 m_fEncrypted
= aBits2
& 0x01 ;
6181 m_fWhichTableStm
= ( aBits2
& 0x02 ) >> 1;
6182 m_fReadOnlyRecommended
= (aBits2
& 0x4) >> 2;
6183 m_fWriteReservation
= (aBits2
& 0x8) >> 3;
6184 m_fExtChar
= ( aBits2
& 0x10 ) >> 4;
6185 // dummy = ( aBits2 & 0x20 ) >> 5;
6186 m_fFarEast
= ( aBits2
& 0x40 ) >> 6; // #i90932#
6187 // dummy = ( aBits2 & 0x80 ) >> 7;
6190 p.r.n. fill targeted variable with xxx_Ver67
6193 if (IsSevenMinus(eVer
))
6195 m_pnChpFirst
= pnChpFirst_Ver67
;
6196 m_pnPapFirst
= pnPapFirst_Ver67
;
6197 m_cpnBteChp
= cpnBteChp_Ver67
;
6198 m_cpnBtePap
= cpnBtePap_Ver67
;
6200 else if (IsEightPlus(eVer
))
6202 m_fMac
= aVer8Bits1
& 0x01 ;
6203 m_fEmptySpecial
= ( aVer8Bits1
& 0x02 ) >> 1;
6204 m_fLoadOverridePage
= ( aVer8Bits1
& 0x04 ) >> 2;
6205 m_fFuturesavedUndo
= ( aVer8Bits1
& 0x08 ) >> 3;
6206 m_fWord97Saved
= ( aVer8Bits1
& 0x10 ) >> 4;
6207 m_fWord2000Saved
= ( aVer8Bits1
& 0x20 ) >> 5;
6211 identify the values for PLCF and PLF LFO
6212 and PLCF for the textbox break descriptors
6214 tools::Long nOldPos
= rSt
.Tell();
6217 rSt
.ReadInt32( m_fcSttbFnm
);
6218 rSt
.ReadInt32( m_lcbSttbFnm
);
6219 rSt
.ReadInt32( m_fcPlcfLst
);
6220 rSt
.ReadInt32( m_lcbPlcfLst
);
6221 rSt
.ReadInt32( m_fcPlfLfo
);
6222 rSt
.ReadInt32( m_lcbPlfLfo
);
6223 rSt
.ReadInt32( m_fcPlcftxbxBkd
);
6224 rSt
.ReadInt32( m_lcbPlcftxbxBkd
);
6225 rSt
.ReadInt32( m_fcPlcfHdrtxbxBkd
);
6226 rSt
.ReadInt32( m_lcbPlcfHdrtxbxBkd
);
6227 if( ERRCODE_NONE
!= rSt
.GetError() )
6229 m_nFibError
= ERR_SWG_READ_ERROR
;
6232 rSt
.Seek( 0x372 ); // fcSttbListNames
6233 rSt
.ReadInt32( m_fcSttbListNames
);
6234 rSt
.ReadInt32( m_lcbSttbListNames
);
6238 rSt
.Seek( 0x382 ); // MagicTables
6239 rSt
.ReadInt32( m_fcPlcfTch
);
6240 rSt
.ReadInt32( m_lcbPlcfTch
);
6245 rSt
.Seek( 0x41A ); // new ATRD
6246 rSt
.ReadInt32( m_fcAtrdExtra
);
6247 rSt
.ReadUInt32( m_lcbAtrdExtra
);
6250 // Factoid bookmarks
6254 rSt
.ReadInt32(m_fcPlcfBkfFactoid
);
6255 rSt
.ReadUInt32(m_lcbPlcfBkfFactoid
);
6258 rSt
.ReadInt32(m_fcPlcfBklFactoid
);
6259 rSt
.ReadUInt32(m_lcbPlcfBklFactoid
);
6262 rSt
.ReadInt32(m_fcFactoidData
);
6263 rSt
.ReadUInt32(m_lcbFactoidData
);
6266 if( ERRCODE_NONE
!= rSt
.GetError() )
6267 m_nFibError
= ERR_SWG_READ_ERROR
;
6269 rSt
.Seek( 0x5bc ); // Actual nFib introduced in Word 2003
6270 rSt
.ReadUInt16( m_nFib_actual
);
6272 rSt
.Seek( nOldPos
);
6277 m_nFibError
= ERR_SWG_READ_ERROR
; // report error
6281 WW8Fib::WW8Fib(sal_uInt8 nVer
, bool bDot
):
6282 m_nVersion(nVer
), m_fDot(false), m_fGlsy(false), m_fComplex(false), m_fHasPic(false), m_cQuickSaves(0),
6283 m_fEncrypted(false), m_fWhichTableStm(false), m_fReadOnlyRecommended(false),
6284 m_fWriteReservation(false), m_fExtChar(false), m_fFarEast(false), m_fObfuscated(false),
6285 m_fMac(false), m_fEmptySpecial(false), m_fLoadOverridePage(false), m_fFuturesavedUndo(false),
6286 m_fWord97Saved(false), m_fWord2000Saved(false)
6287 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
6288 // above bit-field member initializations can be moved to the class definition
6296 m_nProduct
= 0x204D;
6299 m_csw
= 0x0e; // Is this really necessary???
6300 m_cfclcb
= 0x88; // -""-
6301 m_clw
= 0x16; // -""-
6302 m_pnFbpChpFirst
= m_pnFbpPapFirst
= m_pnFbpLvcFirst
= 0x000fffff;
6304 m_fWord97Saved
= m_fWord2000Saved
= true;
6306 // Just a fancy way to write 'Caolan80'.
6307 m_wMagicCreated
= 0x6143;
6308 m_wMagicRevised
= 0x6C6F;
6309 m_wMagicCreatedPrivate
= 0x6E61;
6310 m_wMagicRevisedPrivate
= 0x3038;
6316 m_nFib
= m_nFibBack
= 0x65;
6317 m_nProduct
= 0xc02d;
6320 //If nFib is 0x00D9 or greater, then cQuickSaves MUST be 0xF
6321 m_cQuickSaves
= m_nFib
>= 0x00D9 ? 0xF : 0;
6324 m_lid
= LanguageType(0x409); // LANGUAGE_ENGLISH_US
6326 LanguageType nLang
= Application::GetSettings().GetLanguageTag().getLanguageType();
6327 m_fFarEast
= MsLangId::isCJK(nLang
);
6333 LanguageTag
aLanguageTag( m_lid
);
6334 LocaleDataWrapper
aLocaleWrapper( aLanguageTag
);
6335 m_nNumDecimalSep
= aLocaleWrapper
.getNumDecimalSep()[0];
6339 void WW8Fib::WriteHeader(SvStream
& rStrm
)
6341 bool bVer8
= 8 == m_nVersion
;
6343 size_t nUnencryptedHdr
= bVer8
? 0x44 : 0x24;
6344 std::unique_ptr
<sal_uInt8
[]> pDataPtr( new sal_uInt8
[ nUnencryptedHdr
] );
6345 sal_uInt8
*pData
= pDataPtr
.get();
6346 memset( pData
, 0, nUnencryptedHdr
);
6348 m_cbMac
= rStrm
.TellEnd();
6350 Set_UInt16( pData
, m_wIdent
);
6351 Set_UInt16( pData
, m_nFib
);
6352 Set_UInt16( pData
, m_nProduct
);
6353 Set_UInt16( pData
, static_cast<sal_uInt16
>(m_lid
) );
6354 Set_UInt16( pData
, m_pnNext
);
6356 sal_uInt16 nBits16
= 0;
6357 if( m_fDot
) nBits16
|= 0x0001;
6358 if( m_fGlsy
) nBits16
|= 0x0002;
6359 if( m_fComplex
) nBits16
|= 0x0004;
6360 if( m_fHasPic
) nBits16
|= 0x0008;
6361 nBits16
|= (0xf0 & ( m_cQuickSaves
<< 4 ));
6362 if( m_fEncrypted
) nBits16
|= 0x0100;
6363 if( m_fWhichTableStm
) nBits16
|= 0x0200;
6365 if (m_fReadOnlyRecommended
)
6367 if (m_fWriteReservation
)
6370 if( m_fExtChar
) nBits16
|= 0x1000;
6371 if( m_fFarEast
) nBits16
|= 0x4000; // #i90932#
6372 if( m_fObfuscated
) nBits16
|= 0x8000;
6373 Set_UInt16( pData
, nBits16
);
6375 Set_UInt16( pData
, m_nFibBack
);
6376 Set_UInt16( pData
, m_nHash
);
6377 Set_UInt16( pData
, m_nKey
);
6378 Set_UInt8( pData
, m_envr
);
6380 sal_uInt8 nBits8
= 0;
6383 if( m_fMac
) nBits8
|= 0x0001;
6384 if( m_fEmptySpecial
) nBits8
|= 0x0002;
6385 if( m_fLoadOverridePage
) nBits8
|= 0x0004;
6386 if( m_fFuturesavedUndo
) nBits8
|= 0x0008;
6387 if( m_fWord97Saved
) nBits8
|= 0x0010;
6388 if( m_fWord2000Saved
) nBits8
|= 0x0020;
6390 // under Ver67 these are only reserved
6391 Set_UInt8( pData
, nBits8
);
6393 Set_UInt16( pData
, m_chse
);
6394 Set_UInt16( pData
, m_chseTables
);
6395 Set_UInt32( pData
, m_fcMin
);
6396 Set_UInt32( pData
, m_fcMac
);
6398 // insertion for WW8
6400 // Marke: "rgsw" Beginning of the array of shorts
6403 Set_UInt16( pData
, m_csw
);
6404 Set_UInt16( pData
, m_wMagicCreated
);
6405 Set_UInt16( pData
, m_wMagicRevised
);
6406 Set_UInt16( pData
, m_wMagicCreatedPrivate
);
6407 Set_UInt16( pData
, m_wMagicRevisedPrivate
);
6408 pData
+= 9 * sizeof( sal_Int16
);
6409 Set_UInt16( pData
, static_cast<sal_uInt16
>(m_lidFE
) );
6410 Set_UInt16( pData
, m_clw
);
6413 // end of the insertion for WW8
6415 // Marke: "rglw" Beginning of the array of longs
6416 Set_UInt32( pData
, m_cbMac
);
6418 rStrm
.WriteBytes(pDataPtr
.get(), nUnencryptedHdr
);
6421 void WW8Fib::Write(SvStream
& rStrm
)
6423 bool bVer8
= 8 == m_nVersion
;
6425 WriteHeader( rStrm
);
6427 size_t nUnencryptedHdr
= bVer8
? 0x44 : 0x24;
6429 std::unique_ptr
<sal_uInt8
[]> pDataPtr( new sal_uInt8
[ m_fcMin
- nUnencryptedHdr
] );
6430 sal_uInt8
*pData
= pDataPtr
.get();
6431 memset( pData
, 0, m_fcMin
- nUnencryptedHdr
);
6433 m_cbMac
= rStrm
.TellEnd();
6435 // ignore 2 longs, because they are unimportant
6436 pData
+= 2 * sizeof( sal_Int32
);
6438 // skipping 2 more longs only at Ver67
6440 pData
+= 2 * sizeof( sal_Int32
);
6442 Set_UInt32( pData
, m_ccpText
);
6443 Set_UInt32( pData
, m_ccpFootnote
);
6444 Set_UInt32( pData
, m_ccpHdr
);
6445 Set_UInt32( pData
, m_ccpMcr
);
6446 Set_UInt32( pData
, m_ccpAtn
);
6447 Set_UInt32( pData
, m_ccpEdn
);
6448 Set_UInt32( pData
, m_ccpTxbx
);
6449 Set_UInt32( pData
, m_ccpHdrTxbx
);
6451 // only skip one more long at Ver67
6453 pData
+= 1 * sizeof( sal_Int32
);
6455 // insertion for WW8
6458 Set_UInt32( pData
, m_pnFbpChpFirst
);
6459 Set_UInt32( pData
, m_pnChpFirst
);
6460 Set_UInt32( pData
, m_cpnBteChp
);
6461 Set_UInt32( pData
, m_pnFbpPapFirst
);
6462 Set_UInt32( pData
, m_pnPapFirst
);
6463 Set_UInt32( pData
, m_cpnBtePap
);
6464 Set_UInt32( pData
, m_pnFbpLvcFirst
);
6465 Set_UInt32( pData
, m_pnLvcFirst
);
6466 Set_UInt32( pData
, m_cpnBteLvc
);
6467 Set_UInt32( pData
, m_fcIslandFirst
);
6468 Set_UInt32( pData
, m_fcIslandLim
);
6469 Set_UInt16( pData
, m_cfclcb
);
6471 // end of the insertion for WW8
6473 // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
6474 Set_UInt32( pData
, m_fcStshfOrig
);
6475 Set_UInt32( pData
, m_lcbStshfOrig
);
6476 Set_UInt32( pData
, m_fcStshf
);
6477 Set_UInt32( pData
, m_lcbStshf
);
6478 Set_UInt32( pData
, m_fcPlcffndRef
);
6479 Set_UInt32( pData
, m_lcbPlcffndRef
);
6480 Set_UInt32( pData
, m_fcPlcffndText
);
6481 Set_UInt32( pData
, m_lcbPlcffndText
);
6482 Set_UInt32( pData
, m_fcPlcfandRef
);
6483 Set_UInt32( pData
, m_lcbPlcfandRef
);
6484 Set_UInt32( pData
, m_fcPlcfandText
);
6485 Set_UInt32( pData
, m_lcbPlcfandText
);
6486 Set_UInt32( pData
, m_fcPlcfsed
);
6487 Set_UInt32( pData
, m_lcbPlcfsed
);
6488 Set_UInt32( pData
, m_fcPlcfpad
);
6489 Set_UInt32( pData
, m_lcbPlcfpad
);
6490 Set_UInt32( pData
, m_fcPlcfphe
);
6491 Set_UInt32( pData
, m_lcbPlcfphe
);
6492 Set_UInt32( pData
, m_fcSttbfglsy
);
6493 Set_UInt32( pData
, m_lcbSttbfglsy
);
6494 Set_UInt32( pData
, m_fcPlcfglsy
);
6495 Set_UInt32( pData
, m_lcbPlcfglsy
);
6496 Set_UInt32( pData
, m_fcPlcfhdd
);
6497 Set_UInt32( pData
, m_lcbPlcfhdd
);
6498 Set_UInt32( pData
, m_fcPlcfbteChpx
);
6499 Set_UInt32( pData
, m_lcbPlcfbteChpx
);
6500 Set_UInt32( pData
, m_fcPlcfbtePapx
);
6501 Set_UInt32( pData
, m_lcbPlcfbtePapx
);
6502 Set_UInt32( pData
, m_fcPlcfsea
);
6503 Set_UInt32( pData
, m_lcbPlcfsea
);
6504 Set_UInt32( pData
, m_fcSttbfffn
);
6505 Set_UInt32( pData
, m_lcbSttbfffn
);
6506 Set_UInt32( pData
, m_fcPlcffldMom
);
6507 Set_UInt32( pData
, m_lcbPlcffldMom
);
6508 Set_UInt32( pData
, m_fcPlcffldHdr
);
6509 Set_UInt32( pData
, m_lcbPlcffldHdr
);
6510 Set_UInt32( pData
, m_fcPlcffldFootnote
);
6511 Set_UInt32( pData
, m_lcbPlcffldFootnote
);
6512 Set_UInt32( pData
, m_fcPlcffldAtn
);
6513 Set_UInt32( pData
, m_lcbPlcffldAtn
);
6514 Set_UInt32( pData
, m_fcPlcffldMcr
);
6515 Set_UInt32( pData
, m_lcbPlcffldMcr
);
6516 Set_UInt32( pData
, m_fcSttbfbkmk
);
6517 Set_UInt32( pData
, m_lcbSttbfbkmk
);
6518 Set_UInt32( pData
, m_fcPlcfbkf
);
6519 Set_UInt32( pData
, m_lcbPlcfbkf
);
6520 Set_UInt32( pData
, m_fcPlcfbkl
);
6521 Set_UInt32( pData
, m_lcbPlcfbkl
);
6522 Set_UInt32( pData
, m_fcCmds
);
6523 Set_UInt32( pData
, m_lcbCmds
);
6524 Set_UInt32( pData
, m_fcPlcfmcr
);
6525 Set_UInt32( pData
, m_lcbPlcfmcr
);
6526 Set_UInt32( pData
, m_fcSttbfmcr
);
6527 Set_UInt32( pData
, m_lcbSttbfmcr
);
6528 Set_UInt32( pData
, m_fcPrDrvr
);
6529 Set_UInt32( pData
, m_lcbPrDrvr
);
6530 Set_UInt32( pData
, m_fcPrEnvPort
);
6531 Set_UInt32( pData
, m_lcbPrEnvPort
);
6532 Set_UInt32( pData
, m_fcPrEnvLand
);
6533 Set_UInt32( pData
, m_lcbPrEnvLand
);
6534 Set_UInt32( pData
, m_fcWss
);
6535 Set_UInt32( pData
, m_lcbWss
);
6536 Set_UInt32( pData
, m_fcDop
);
6537 Set_UInt32( pData
, m_lcbDop
);
6538 Set_UInt32( pData
, m_fcSttbfAssoc
);
6539 Set_UInt32( pData
, m_lcbSttbfAssoc
);
6540 Set_UInt32( pData
, m_fcClx
);
6541 Set_UInt32( pData
, m_lcbClx
);
6542 Set_UInt32( pData
, m_fcPlcfpgdFootnote
);
6543 Set_UInt32( pData
, m_lcbPlcfpgdFootnote
);
6544 Set_UInt32( pData
, m_fcAutosaveSource
);
6545 Set_UInt32( pData
, m_lcbAutosaveSource
);
6546 Set_UInt32( pData
, m_fcGrpStAtnOwners
);
6547 Set_UInt32( pData
, m_lcbGrpStAtnOwners
);
6548 Set_UInt32( pData
, m_fcSttbfAtnbkmk
);
6549 Set_UInt32( pData
, m_lcbSttbfAtnbkmk
);
6551 // only skip one more short at Ver67
6554 pData
+= 1*sizeof( sal_Int16
);
6555 Set_UInt16( pData
, static_cast<sal_uInt16
>(m_pnChpFirst
) );
6556 Set_UInt16( pData
, static_cast<sal_uInt16
>(m_pnPapFirst
) );
6557 Set_UInt16( pData
, static_cast<sal_uInt16
>(m_cpnBteChp
) );
6558 Set_UInt16( pData
, static_cast<sal_uInt16
>(m_cpnBtePap
) );
6561 Set_UInt32( pData
, m_fcPlcfdoaMom
); // only at Ver67, in Ver8 unused
6562 Set_UInt32( pData
, m_lcbPlcfdoaMom
); // only at Ver67, in Ver8 unused
6563 Set_UInt32( pData
, m_fcPlcfdoaHdr
); // only at Ver67, in Ver8 unused
6564 Set_UInt32( pData
, m_lcbPlcfdoaHdr
); // only at Ver67, in Ver8 unused
6566 Set_UInt32( pData
, m_fcPlcfspaMom
); // in Ver67 empty reserve
6567 Set_UInt32( pData
, m_lcbPlcfspaMom
); // in Ver67 empty reserve
6568 Set_UInt32( pData
, m_fcPlcfspaHdr
); // in Ver67 empty reserve
6569 Set_UInt32( pData
, m_lcbPlcfspaHdr
); // in Ver67 empty reserve
6571 Set_UInt32( pData
, m_fcPlcfAtnbkf
);
6572 Set_UInt32( pData
, m_lcbPlcfAtnbkf
);
6573 Set_UInt32( pData
, m_fcPlcfAtnbkl
);
6574 Set_UInt32( pData
, m_lcbPlcfAtnbkl
);
6575 Set_UInt32( pData
, m_fcPms
);
6576 Set_UInt32( pData
, m_lcbPMS
);
6577 Set_UInt32( pData
, m_fcFormFieldSttbf
);
6578 Set_UInt32( pData
, m_lcbFormFieldSttbf
);
6579 Set_UInt32( pData
, m_fcPlcfendRef
);
6580 Set_UInt32( pData
, m_lcbPlcfendRef
);
6581 Set_UInt32( pData
, m_fcPlcfendText
);
6582 Set_UInt32( pData
, m_lcbPlcfendText
);
6583 Set_UInt32( pData
, m_fcPlcffldEdn
);
6584 Set_UInt32( pData
, m_lcbPlcffldEdn
);
6585 Set_UInt32( pData
, m_fcPlcfpgdEdn
);
6586 Set_UInt32( pData
, m_lcbPlcfpgdEdn
);
6587 Set_UInt32( pData
, m_fcDggInfo
); // in Ver67 empty reserve
6588 Set_UInt32( pData
, m_lcbDggInfo
); // in Ver67 empty reserve
6589 Set_UInt32( pData
, m_fcSttbfRMark
);
6590 Set_UInt32( pData
, m_lcbSttbfRMark
);
6591 Set_UInt32( pData
, m_fcSttbfCaption
);
6592 Set_UInt32( pData
, m_lcbSttbfCaption
);
6593 Set_UInt32( pData
, m_fcSttbAutoCaption
);
6594 Set_UInt32( pData
, m_lcbSttbAutoCaption
);
6595 Set_UInt32( pData
, m_fcPlcfwkb
);
6596 Set_UInt32( pData
, m_lcbPlcfwkb
);
6597 Set_UInt32( pData
, m_fcPlcfspl
); // in Ver67 empty reserve
6598 Set_UInt32( pData
, m_lcbPlcfspl
); // in Ver67 empty reserve
6599 Set_UInt32( pData
, m_fcPlcftxbxText
);
6600 Set_UInt32( pData
, m_lcbPlcftxbxText
);
6601 Set_UInt32( pData
, m_fcPlcffldTxbx
);
6602 Set_UInt32( pData
, m_lcbPlcffldTxbx
);
6603 Set_UInt32( pData
, m_fcPlcfHdrtxbxText
);
6604 Set_UInt32( pData
, m_lcbPlcfHdrtxbxText
);
6605 Set_UInt32( pData
, m_fcPlcffldHdrTxbx
);
6606 Set_UInt32( pData
, m_lcbPlcffldHdrTxbx
);
6610 pData
+= 0x2da - 0x27a; // Pos + Offset (fcPlcfLst - fcStwUser)
6611 Set_UInt32( pData
, m_fcSttbFnm
);
6612 Set_UInt32( pData
, m_lcbSttbFnm
);
6613 Set_UInt32( pData
, m_fcPlcfLst
);
6614 Set_UInt32( pData
, m_lcbPlcfLst
);
6615 Set_UInt32( pData
, m_fcPlfLfo
);
6616 Set_UInt32( pData
, m_lcbPlfLfo
);
6617 Set_UInt32( pData
, m_fcPlcftxbxBkd
);
6618 Set_UInt32( pData
, m_lcbPlcftxbxBkd
);
6619 Set_UInt32( pData
, m_fcPlcfHdrtxbxBkd
);
6620 Set_UInt32( pData
, m_lcbPlcfHdrtxbxBkd
);
6622 pData
+= 0x372 - 0x302; // Pos + Offset (fcSttbListNames - fcDocUndo)
6623 Set_UInt32( pData
, m_fcSttbListNames
);
6624 Set_UInt32( pData
, m_lcbSttbListNames
);
6626 pData
+= 0x382 - 0x37A;
6627 Set_UInt32( pData
, m_fcPlcfTch
);
6628 Set_UInt32( pData
, m_lcbPlcfTch
);
6630 pData
+= 0x3FA - 0x38A;
6631 Set_UInt16( pData
, sal_uInt16(0x0002));
6632 Set_UInt16( pData
, sal_uInt16(0x00D9));
6634 pData
+= 0x41A - 0x3FE;
6635 Set_UInt32( pData
, m_fcAtrdExtra
);
6636 Set_UInt32( pData
, m_lcbAtrdExtra
);
6638 pData
+= 0x42a - 0x422;
6639 Set_UInt32(pData
, m_fcSttbfBkmkFactoid
);
6640 Set_UInt32(pData
, m_lcbSttbfBkmkFactoid
);
6641 Set_UInt32(pData
, m_fcPlcfBkfFactoid
);
6642 Set_UInt32(pData
, m_lcbPlcfBkfFactoid
);
6644 pData
+= 0x442 - 0x43A;
6645 Set_UInt32(pData
, m_fcPlcfBklFactoid
);
6646 Set_UInt32(pData
, m_lcbPlcfBklFactoid
);
6647 Set_UInt32(pData
, m_fcFactoidData
);
6648 Set_UInt32(pData
, m_lcbFactoidData
);
6650 pData
+= 0x4BA - 0x452;
6651 Set_UInt32(pData
, m_fcPlcffactoid
);
6652 Set_UInt32(pData
, m_lcbPlcffactoid
);
6654 pData
+= 0x4DA - 0x4c2;
6655 Set_UInt32( pData
, m_fcHplxsdr
);
6656 Set_UInt32( pData
, 0);
6659 rStrm
.WriteBytes(pDataPtr
.get(), m_fcMin
- nUnencryptedHdr
);
6662 rtl_TextEncoding
WW8Fib::GetFIBCharset(sal_uInt16 chs
, LanguageType nLidLocale
)
6664 OSL_ENSURE(chs
<= 0x100, "overflowed winword charset set");
6666 return RTL_TEXTENCODING_APPLE_ROMAN
;
6667 if (chs
== 0 && static_cast<sal_uInt16
>(nLidLocale
) >= 999)
6671 language stamp -- localized version In pre-WinWord 2.0 files this
6672 value was the nLocale. If value is < 999, then it is the nLocale,
6673 otherwise it is the lid.
6675 css::lang::Locale
aLocale(LanguageTag::convertToLocale(nLidLocale
));
6676 return msfilter::util::getBestTextEncodingFromLocale(aLocale
);
6678 return rtl_getTextEncodingFromWindowsCharset(static_cast<sal_uInt8
>(chs
));
6681 MSOFactoidType::MSOFactoidType()
6686 namespace MSOPBString
6688 static OUString
Read(SvStream
& rStream
)
6693 rStream
.ReadUInt16(nBuf
);
6694 sal_uInt16 nCch
= nBuf
& 0x7fff; // Bits 1..15.
6695 bool bAnsiString
= (nBuf
& (1 << 15)) >> 15; // 16th bit.
6697 aRet
= OStringToOUString(read_uInt8s_ToOString(rStream
, nCch
), RTL_TEXTENCODING_ASCII_US
);
6699 aRet
= read_uInt16s_ToOUString(rStream
, nCch
);
6704 static void Write(const OUString
& rString
, SvStream
& rStream
)
6706 sal_uInt16 nBuf
= 0;
6707 nBuf
|= rString
.getLength(); // cch, 0..14th bits.
6708 nBuf
|= 0x8000; // fAnsiString, 15th bit.
6709 rStream
.WriteUInt16(nBuf
);
6710 SwWW8Writer::WriteString8(rStream
, rString
, false, RTL_TEXTENCODING_ASCII_US
);
6714 void MSOFactoidType::Read(SvStream
& rStream
)
6716 sal_uInt32
cbFactoid(0);
6717 rStream
.ReadUInt32(cbFactoid
);
6718 rStream
.ReadUInt32(m_nId
);
6719 m_aUri
= MSOPBString::Read(rStream
);
6720 m_aTag
= MSOPBString::Read(rStream
);
6721 MSOPBString::Read(rStream
); // rgbDownloadURL
6724 void MSOFactoidType::Write(WW8Export
& rExport
)
6726 SvStream
& rStream
= *rExport
.pTableStrm
;
6728 SvMemoryStream aStream
;
6729 aStream
.WriteUInt32(m_nId
); // id
6730 MSOPBString::Write(m_aUri
, aStream
);
6731 MSOPBString::Write(m_aTag
, aStream
);
6732 MSOPBString::Write("", aStream
); // rgbDownloadURL
6733 rStream
.WriteUInt32(aStream
.Tell());
6735 rStream
.WriteStream(aStream
);
6738 void MSOPropertyBagStore::Read(SvStream
& rStream
)
6740 sal_uInt32
cFactoidType(0);
6741 rStream
.ReadUInt32(cFactoidType
);
6742 for (sal_uInt32 i
= 0; i
< cFactoidType
&& rStream
.good(); ++i
)
6744 MSOFactoidType aFactoidType
;
6745 aFactoidType
.Read(rStream
);
6746 m_aFactoidTypes
.push_back(aFactoidType
);
6748 sal_uInt16
cbHdr(0);
6749 rStream
.ReadUInt16(cbHdr
);
6750 SAL_WARN_IF(cbHdr
!= 0xc, "sw.ww8", "MSOPropertyBagStore::Read: unexpected cbHdr");
6752 rStream
.ReadUInt16(nVer
);
6753 SAL_WARN_IF(nVer
!= 0x0100, "sw.ww8", "MSOPropertyBagStore::Read: unexpected nVer");
6754 rStream
.SeekRel(4); // cfactoid
6755 sal_uInt32
nCste(0);
6756 rStream
.ReadUInt32(nCste
);
6758 //each string has a 2 byte len record at the start
6759 const size_t nMaxPossibleRecords
= rStream
.remainingSize() / sizeof(sal_uInt16
);
6760 if (nCste
> nMaxPossibleRecords
)
6762 SAL_WARN("sw.ww8", nCste
<< " records claimed, but max possible is " << nMaxPossibleRecords
);
6763 nCste
= nMaxPossibleRecords
;
6766 for (sal_uInt32 i
= 0; i
< nCste
; ++i
)
6768 OUString aString
= MSOPBString::Read(rStream
);
6769 m_aStringTable
.push_back(aString
);
6773 void MSOPropertyBagStore::Write(WW8Export
& rExport
)
6775 SvStream
& rStream
= *rExport
.pTableStrm
;
6776 rStream
.WriteUInt32(m_aFactoidTypes
.size()); // cFactoidType
6777 for (MSOFactoidType
& rType
: m_aFactoidTypes
)
6778 rType
.Write(rExport
);
6779 rStream
.WriteUInt16(0xc); // cbHdr
6780 rStream
.WriteUInt16(0x0100); // sVer
6781 rStream
.WriteUInt32(0); // cfactoid
6782 rStream
.WriteUInt32(m_aStringTable
.size()); // cste
6783 for (const OUString
& rString
: m_aStringTable
)
6784 MSOPBString::Write(rString
, rStream
);
6787 MSOProperty::MSOProperty()
6793 void MSOProperty::Read(SvStream
& rStream
)
6795 rStream
.ReadUInt32(m_nKey
);
6796 rStream
.ReadUInt32(m_nValue
);
6799 void MSOProperty::Write(SvStream
& rStream
)
6801 rStream
.WriteUInt32(m_nKey
);
6802 rStream
.WriteUInt32(m_nValue
);
6805 MSOPropertyBag::MSOPropertyBag()
6810 bool MSOPropertyBag::Read(SvStream
& rStream
)
6812 rStream
.ReadUInt16(m_nId
);
6813 sal_uInt16
cProp(0);
6814 rStream
.ReadUInt16(cProp
);
6815 if (!rStream
.good())
6817 rStream
.SeekRel(2); // cbUnknown
6818 //each MSOProperty is 8 bytes in size
6819 const size_t nMaxPossibleRecords
= rStream
.remainingSize() / 8;
6820 if (cProp
> nMaxPossibleRecords
)
6822 SAL_WARN("sw.ww8", cProp
<< " records claimed, but max possible is " << nMaxPossibleRecords
);
6823 cProp
= nMaxPossibleRecords
;
6825 for (sal_uInt16 i
= 0; i
< cProp
&& rStream
.good(); ++i
)
6827 MSOProperty aProperty
;
6828 aProperty
.Read(rStream
);
6829 m_aProperties
.push_back(aProperty
);
6831 return rStream
.good();
6834 void MSOPropertyBag::Write(WW8Export
& rExport
)
6836 SvStream
& rStream
= *rExport
.pTableStrm
;
6837 rStream
.WriteUInt16(m_nId
);
6838 rStream
.WriteUInt16(m_aProperties
.size());
6839 rStream
.WriteUInt16(0); // cbUnknown
6840 for (MSOProperty
& rProperty
: m_aProperties
)
6841 rProperty
.Write(rStream
);
6844 void WW8SmartTagData::Read(SvStream
& rStream
, WW8_FC fcFactoidData
, sal_uInt32 lcbFactoidData
)
6846 sal_uInt64 nOldPosition
= rStream
.Tell();
6847 if (!checkSeek(rStream
, fcFactoidData
))
6850 m_aPropBagStore
.Read(rStream
);
6851 while (rStream
.good() && rStream
.Tell() < fcFactoidData
+ lcbFactoidData
)
6853 MSOPropertyBag aPropertyBag
;
6854 if (!aPropertyBag
.Read(rStream
))
6856 m_aPropBags
.push_back(aPropertyBag
);
6859 rStream
.Seek(nOldPosition
);
6862 void WW8SmartTagData::Write(WW8Export
& rExport
)
6864 m_aPropBagStore
.Write(rExport
);
6865 for (MSOPropertyBag
& rPropertyBag
: m_aPropBags
)
6866 rPropertyBag
.Write(rExport
);
6869 WW8Style::WW8Style(SvStream
& rStream
, WW8Fib
& rFibPara
)
6870 : m_rFib(rFibPara
), m_rStream(rStream
), m_cstd(0), m_cbSTDBaseInFile(0), m_fStdStylenamesWritten(0)
6871 , m_stiMaxWhenSaved(0), m_istdMaxFixedWhenSaved(0), m_nVerBuiltInNamesWhenSaved(0)
6872 , m_ftcAsci(0), m_ftcFE(0), m_ftcOther(0), m_ftcBi(0)
6874 if (!checkSeek(m_rStream
, m_rFib
.m_fcStshf
))
6877 sal_uInt16 cbStshi
= 0; // 2 bytes size of the following STSHI structure
6878 sal_uInt32 nRemaining
= m_rFib
.m_lcbStshf
;
6879 const sal_uInt32 nMinValidStshi
= 4;
6881 if (m_rFib
.GetFIBVersion() <= ww::eWW2
)
6888 if (m_rFib
.m_nFib
< 67) // old Version ? (need to find this again to fix)
6889 cbStshi
= nMinValidStshi
;
6892 if (nRemaining
< sizeof(cbStshi
))
6894 // reads the length of the structure in the file
6895 m_rStream
.ReadUInt16( cbStshi
);
6900 cbStshi
= std::min(static_cast<sal_uInt32
>(cbStshi
), nRemaining
);
6901 if (cbStshi
< nMinValidStshi
)
6904 const sal_uInt16 nRead
= cbStshi
;
6907 m_rStream
.ReadUInt16( m_cstd
);
6909 m_rStream
.ReadUInt16( m_cbSTDBaseInFile
);
6911 if( 6 > nRead
) break;
6914 m_rStream
.ReadUInt16( a16Bit
);
6915 m_fStdStylenamesWritten
= a16Bit
& 0x0001;
6917 if( 8 > nRead
) break;
6918 m_rStream
.ReadUInt16( m_stiMaxWhenSaved
);
6920 if( 10 > nRead
) break;
6921 m_rStream
.ReadUInt16( m_istdMaxFixedWhenSaved
);
6923 if( 12 > nRead
) break;
6924 m_rStream
.ReadUInt16( m_nVerBuiltInNamesWhenSaved
);
6926 if( 14 > nRead
) break;
6927 m_rStream
.ReadUInt16( m_ftcAsci
);
6929 if( 16 > nRead
) break;
6930 m_rStream
.ReadUInt16( m_ftcFE
);
6932 if ( 18 > nRead
) break;
6933 m_rStream
.ReadUInt16( m_ftcOther
);
6935 m_ftcBi
= m_ftcOther
;
6937 if ( 20 > nRead
) break;
6938 m_rStream
.ReadUInt16( m_ftcBi
);
6940 // p.r.n. ignore the rest
6942 m_rStream
.SeekRel( nRead
-20 );
6944 while( false ); // trick: the block above will be passed through exactly one time
6945 // and that's why we can early exit with "break".
6947 nRemaining
-= cbStshi
;
6949 //There will be stshi.cstd (cbSTD, STD) pairs in the file following the
6950 //STSHI. Note that styles can be empty, i.e. cbSTD == 0
6951 const sal_uInt32 nMinRecordSize
= sizeof(sal_uInt16
);
6952 const sal_uInt16 nMaxPossibleRecords
= nRemaining
/nMinRecordSize
;
6954 OSL_ENSURE(m_cstd
<= nMaxPossibleRecords
,
6955 "allegedly more styles that available data");
6956 m_cstd
= std::min(m_cstd
, nMaxPossibleRecords
);
6959 // Read1STDFixed() reads a style. If the style is completely existent,
6960 // so it has no empty slot, we should allocate memory and a pointer should
6961 // reference to STD (perhaps filled with 0). If the slot is empty,
6962 // it will return a null pointer.
6963 std::unique_ptr
<WW8_STD
> WW8Style::Read1STDFixed(sal_uInt16
& rSkip
)
6965 std::unique_ptr
<WW8_STD
> pStd
;
6967 sal_uInt16
cbStd(0);
6968 m_rStream
.ReadUInt16(cbStd
); // read length
6970 const sal_uInt16 nRead
= m_cbSTDBaseInFile
;
6971 if( cbStd
>= m_cbSTDBaseInFile
)
6973 // Fixed part completely available
6975 // read fixed part of STD
6976 pStd
.reset(new WW8_STD
);
6977 memset( pStd
.get(), 0, sizeof( *pStd
) );
6981 if( 2 > nRead
) break;
6983 sal_uInt16 a16Bit
= 0;
6984 m_rStream
.ReadUInt16( a16Bit
);
6985 pStd
->sti
= a16Bit
& 0x0fff ;
6986 pStd
->fScratch
= sal_uInt16(0 != ( a16Bit
& 0x1000 ));
6987 pStd
->fInvalHeight
= sal_uInt16(0 != ( a16Bit
& 0x2000 ));
6988 pStd
->fHasUpe
= sal_uInt16(0 != ( a16Bit
& 0x4000 ));
6989 pStd
->fMassCopy
= sal_uInt16(0 != ( a16Bit
& 0x8000 ));
6991 if( 4 > nRead
) break;
6993 m_rStream
.ReadUInt16( a16Bit
);
6994 pStd
->sgc
= a16Bit
& 0x000f ;
6995 pStd
->istdBase
= ( a16Bit
& 0xfff0 ) >> 4;
6997 if( 6 > nRead
) break;
6999 m_rStream
.ReadUInt16( a16Bit
);
7000 pStd
->cupx
= a16Bit
& 0x000f ;
7001 pStd
->istdNext
= ( a16Bit
& 0xfff0 ) >> 4;
7003 if( 8 > nRead
) break;
7004 m_rStream
.ReadUInt16( pStd
->bchUpe
);
7006 // from Ver8 this two fields should be added:
7007 if(10 > nRead
) break;
7009 m_rStream
.ReadUInt16( a16Bit
);
7010 pStd
->fAutoRedef
= a16Bit
& 0x0001 ;
7011 pStd
->fHidden
= ( a16Bit
& 0x0002 ) >> 1;
7012 // You never know: cautionary skipped
7015 auto nSkip
= std::min
<sal_uInt64
>(nRead
- 10, m_rStream
.remainingSize());
7016 m_rStream
.Seek(m_rStream
.Tell() + nSkip
);
7019 while( false ); // trick: the block above will passed through exactly one time
7020 // and can be left early with a "break"
7022 if (!m_rStream
.good() || !nRead
)
7024 pStd
.reset(); // report error with NULL
7027 rSkip
= cbStd
- m_cbSTDBaseInFile
;
7030 { // Fixed part too short
7032 m_rStream
.SeekRel( cbStd
); // skip leftovers
7038 std::unique_ptr
<WW8_STD
> WW8Style::Read1Style(sal_uInt16
& rSkip
, OUString
* pString
)
7040 // Attention: MacWord-Documents have their Stylenames
7041 // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
7043 std::unique_ptr
<WW8_STD
> pStd
= Read1STDFixed(rSkip
); // read STD
7050 sal_Int32 nLenStringBytes
= 0;
7051 switch( m_rFib
.m_nVersion
)
7055 // read pascal string
7056 *pString
= read_uInt8_BeltAndBracesString(m_rStream
, RTL_TEXTENCODING_MS_1252
);
7057 // leading len and trailing zero --> 2
7058 nLenStringBytes
= pString
->getLength() + 2;
7061 // handle Unicode-String with leading length short and
7063 if (TestBeltAndBraces(m_rStream
))
7065 *pString
= read_uInt16_BeltAndBracesString(m_rStream
);
7066 nLenStringBytes
= (pString
->getLength() + 2) * 2;
7072 This is supposed to be impossible, it's just supposed
7073 to be 16 bit count followed by the string and ending
7074 in a 0 short. But "Lotus SmartSuite Product: Word Pro"
7075 is creating invalid style names in ww7- format. So we
7076 use the belt and braces of the ms strings to see if
7077 they are not corrupt. If they are then we try them as
7080 *pString
= read_uInt8_BeltAndBracesString(m_rStream
,RTL_TEXTENCODING_MS_1252
);
7081 // leading len and trailing zero --> 2
7082 nLenStringBytes
= pString
->getLength() + 2;
7086 OSL_ENSURE(false, "It was forgotten to code nVersion!");
7089 if (nLenStringBytes
> rSkip
)
7091 SAL_WARN("sw.ww8", "WW8Style structure corrupt");
7092 nLenStringBytes
= rSkip
;
7094 rSkip
-= nLenStringBytes
;
7097 pString
->clear(); // can not return a name
7103 const sal_uInt16 maxStrSize
= 65;
7109 char szFfn
[maxStrSize
]; // 0x6 or 0x40 from Ver8 on zero terminated string that
7110 // records name of font.
7111 // Maximal size of szFfn is 65 characters.
7112 // Attention: This array can also be smaller!!!
7113 // Possibly followed by a second sz which records the
7114 // name of an alternate font to use if the first named
7115 // font does not exist on this system.
7120 // #i43762# check font name for illegal characters
7121 static void lcl_checkFontname( OUString
& sString
)
7123 // for efficiency, we'd like to use String methods as far as possible.
7125 // 1) convert all invalid chars to \u0001
7126 // 2) then erase all \u0001 chars (if anywhere found), and
7127 // 3) erase leading/trailing ';', in case a font name was
7128 // completely removed
7130 // convert all invalid chars to \u0001
7131 OUStringBuffer
aBuf(sString
);
7132 const sal_Int32 nLen
= aBuf
.getLength();
7133 bool bFound
= false;
7134 for ( sal_Int32 n
= 0; n
< nLen
; ++n
)
7136 if ( aBuf
[n
] < 0x20 )
7142 sString
= aBuf
.makeStringAndClear();
7144 // if anything was found, remove \u0001 + leading/trailing ';'
7147 sString
= comphelper::string::strip(sString
.replaceAll("\001", ""), ';');
7153 sal_uInt16
calcMaxFonts(sal_uInt8
*p
, sal_Int32 nFFn
)
7155 // Figure out the max number of fonts defined here
7156 sal_uInt16 nMax
= 0;
7157 sal_Int32 nRemaining
= nFFn
;
7160 //p[0] is cbFfnM1, the alleged total length of FFN - 1.
7161 //i.e. length after cbFfnM1
7162 const sal_uInt16 cbFfnM1
= *p
++;
7165 if (cbFfnM1
> nRemaining
)
7169 nRemaining
-= cbFfnM1
;
7175 template<typename T
> bool readU8(
7176 sal_uInt8
const * p
, std::size_t offset
, sal_uInt8
const * pEnd
,
7180 assert(value
!= nullptr);
7181 if (offset
>= o3tl::make_unsigned(pEnd
- p
)) {
7189 sal_uInt8
const * p
, std::size_t offset
, sal_uInt8
const * pEnd
,
7193 assert(value
!= nullptr);
7194 if (offset
> o3tl::make_unsigned(pEnd
- p
)
7195 || static_cast<std::size_t>(pEnd
- p
) - offset
< 2)
7199 *value
= unsigned(p
[offset
]) + (unsigned(p
[offset
+ 1]) << 8);
7203 sal_Int32
getStringLength(
7204 sal_uInt8
const * p
, std::size_t offset
, sal_uInt8
const * pEnd
)
7207 assert(pEnd
- p
<= SAL_MAX_INT32
);
7208 if (offset
>= o3tl::make_unsigned(pEnd
- p
)) {
7211 void const * p2
= std::memchr(
7212 p
+ offset
, 0, static_cast<std::size_t>(pEnd
- p
) - offset
);
7213 if (p2
== nullptr) {
7216 return static_cast<sal_uInt8
const *>(p2
) - (p
+ offset
);
7220 WW8Fonts::WW8Fonts( SvStream
& rSt
, WW8Fib
const & rFib
)
7222 // Attention: MacWord-Documents have their Fontnames
7223 // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
7224 if( rFib
.m_lcbSttbfffn
<= 2 )
7226 OSL_ENSURE( false, "font table is broken! (rFib.lcbSttbfffn < 2)" );
7230 if (!checkSeek(rSt
, rFib
.m_fcSttbfffn
))
7233 sal_Int32 nFFn
= rFib
.m_lcbSttbfffn
- 2;
7235 const sal_uInt64 nMaxPossible
= rSt
.remainingSize();
7236 if (o3tl::make_unsigned(nFFn
) > nMaxPossible
)
7238 SAL_WARN("sw.ww8", "FFN structure longer than available data");
7239 nFFn
= nMaxPossible
;
7242 // allocate Font Array
7243 std::vector
<sal_uInt8
> aA(nFFn
);
7244 memset(aA
.data(), 0, nFFn
);
7246 ww::WordVersion eVersion
= rFib
.GetFIBVersion();
7249 if( eVersion
>= ww::eWW8
)
7251 // bVer8: read the count of strings in nMax
7252 rSt
.ReadUInt16(nMax
);
7255 // Ver8: skip undefined uint16
7256 // Ver67: skip the herein stored total byte of structure
7257 // - we already got that information in rFib.lcbSttbfffn
7260 // read all font information
7261 nFFn
= rSt
.ReadBytes(aA
.data(), nFFn
);
7262 sal_uInt8
* const pEnd
= aA
.data() + nFFn
;
7263 const sal_uInt16 nCalcMax
= calcMaxFonts(aA
.data(), nFFn
);
7265 if (eVersion
< ww::eWW8
)
7269 //newer versions include supportive count of fonts, so take min of that
7271 nMax
= std::min(nMax
, nCalcMax
);
7276 // allocate Index Array
7277 m_aFontA
.resize(nMax
);
7278 WW8_FFN
* p
= m_aFontA
.data();
7280 if( eVersion
<= ww::eWW2
)
7282 sal_uInt8
const * pVer2
= aA
.data();
7284 for(; i
<nMax
; ++i
, ++p
)
7287 pVer2
, offsetof(WW8_FFN_BASE
, cbFfnM1
), pEnd
,
7288 &p
->aFFNBase
.cbFfnM1
))
7293 p
->aFFNBase
.prg
= 0;
7294 p
->aFFNBase
.fTrueType
= 0;
7297 if (!(readU8(pVer2
, 1, pEnd
, &p
->aFFNBase
.wWeight
)
7298 && readU8(pVer2
, 2, pEnd
, &p
->aFFNBase
.chs
)))
7303 #i8726# 7- seems to encode the name in the same encoding as
7304 the font, e.g load the doc in 97 and save to see the unicode
7305 ver of the asian fontnames in that example to confirm.
7307 rtl_TextEncoding eEnc
= WW8Fib::GetFIBCharset(p
->aFFNBase
.chs
, rFib
.m_lid
);
7308 if ((eEnc
== RTL_TEXTENCODING_SYMBOL
) || (eEnc
== RTL_TEXTENCODING_DONTKNOW
))
7309 eEnc
= RTL_TEXTENCODING_MS_1252
;
7311 sal_Int32 n
= getStringLength(pVer2
, 1 + 2, pEnd
);
7315 p
->sFontname
= OUString(
7316 reinterpret_cast<char const *>(pVer2
+ 1 + 2), n
, eEnc
);
7317 pVer2
= pVer2
+ p
->aFFNBase
.cbFfnM1
+ 1;
7321 else if( eVersion
< ww::eWW8
)
7323 sal_uInt8
const * pVer6
= aA
.data();
7325 for(; i
<nMax
; ++i
, ++p
)
7328 pVer6
, offsetof(WW8_FFN_BASE
, cbFfnM1
), pEnd
,
7329 &p
->aFFNBase
.cbFfnM1
))
7334 if (!readU8(pVer6
, 1, pEnd
, &c2
)) {
7338 p
->aFFNBase
.prg
= c2
& 0x02;
7339 p
->aFFNBase
.fTrueType
= (c2
& 0x04) >> 2;
7340 // skip a reserve bit
7341 p
->aFFNBase
.ff
= (c2
& 0x70) >> 4;
7344 pVer6
, offsetof(WW8_FFN_BASE
, wWeight
), pEnd
,
7345 &p
->aFFNBase
.wWeight
)
7347 pVer6
, offsetof(WW8_FFN_BASE
, chs
), pEnd
, &p
->aFFNBase
.chs
)
7349 pVer6
, offsetof(WW8_FFN_BASE
, ibszAlt
), pEnd
,
7350 &p
->aFFNBase
.ibszAlt
)))
7355 #i8726# 7- seems to encode the name in the same encoding as
7356 the font, e.g load the doc in 97 and save to see the unicode
7357 ver of the asian fontnames in that example to confirm.
7359 rtl_TextEncoding eEnc
= WW8Fib::GetFIBCharset(p
->aFFNBase
.chs
, rFib
.m_lid
);
7360 if ((eEnc
== RTL_TEXTENCODING_SYMBOL
) || (eEnc
== RTL_TEXTENCODING_DONTKNOW
))
7361 eEnc
= RTL_TEXTENCODING_MS_1252
;
7362 sal_Int32 n
= getStringLength(
7363 pVer6
, offsetof(WW8_FFN_Ver6
, szFfn
), pEnd
);
7367 p
->sFontname
= OUString(
7368 reinterpret_cast<char const *>(
7369 pVer6
+ offsetof(WW8_FFN_Ver6
, szFfn
)),
7371 if (p
->aFFNBase
.ibszAlt
&& p
->aFFNBase
.ibszAlt
< maxStrSize
) //don't start after end of string
7373 n
= getStringLength(
7374 pVer6
, offsetof(WW8_FFN_Ver6
, szFfn
) + p
->aFFNBase
.ibszAlt
,
7379 p
->sFontname
+= ";" + OUString(
7380 reinterpret_cast<char const *>(
7381 pVer6
+ offsetof(WW8_FFN_Ver6
, szFfn
) + p
->aFFNBase
.ibszAlt
),
7386 //#i18369# if it's a symbol font set Symbol as fallback
7388 RTL_TEXTENCODING_SYMBOL
== WW8Fib::GetFIBCharset(p
->aFFNBase
.chs
, rFib
.m_lid
)
7389 && p
->sFontname
!="Symbol"
7392 p
->sFontname
+= ";Symbol";
7395 pVer6
= pVer6
+ p
->aFFNBase
.cbFfnM1
+ 1;
7401 //count of bytes in minimum FontFamilyInformation payload
7402 const sal_uInt8 cbMinFFNPayload
= 41;
7403 sal_uInt16 nValidFonts
= 0;
7404 sal_Int32 nRemainingFFn
= nFFn
;
7405 sal_uInt8
* pRaw
= aA
.data();
7406 for (sal_uInt16 i
=0; i
< nMax
&& nRemainingFFn
; ++i
, ++p
)
7408 //pRaw[0] is cbFfnM1, the alleged total length of FFN - 1
7409 //i.e. length after cbFfnM1
7410 sal_uInt8 cbFfnM1
= *pRaw
++;
7413 if (cbFfnM1
> nRemainingFFn
)
7416 if (cbFfnM1
< cbMinFFNPayload
)
7419 p
->aFFNBase
.cbFfnM1
= cbFfnM1
;
7421 sal_uInt8
*pVer8
= pRaw
;
7423 sal_uInt8 c2
= *pVer8
++;
7426 p
->aFFNBase
.prg
= c2
& 0x02;
7427 p
->aFFNBase
.fTrueType
= (c2
& 0x04) >> 2;
7428 // skip a reserve bit
7429 p
->aFFNBase
.ff
= (c2
& 0x70) >> 4;
7431 p
->aFFNBase
.wWeight
= SVBT16ToUInt16(*reinterpret_cast<SVBT16
*>(pVer8
));
7435 p
->aFFNBase
.chs
= *pVer8
++;
7438 p
->aFFNBase
.ibszAlt
= *pVer8
++;
7441 pVer8
+= 10; //PANOSE
7443 pVer8
+= 24; //FONTSIGNATURE
7446 assert(cbFfnM1
>= 2);
7448 sal_uInt8 nMaxNullTerminatedPossible
= cbFfnM1
/2 - 1;
7449 sal_Unicode
*pPrimary
= reinterpret_cast<sal_Unicode
*>(pVer8
);
7450 pPrimary
[nMaxNullTerminatedPossible
] = 0;
7451 #ifdef OSL_BIGENDIAN
7452 swapEndian(pPrimary
);
7454 p
->sFontname
= pPrimary
;
7455 if (p
->aFFNBase
.ibszAlt
&& p
->aFFNBase
.ibszAlt
< nMaxNullTerminatedPossible
)
7457 sal_Unicode
*pSecondary
= pPrimary
+ p
->aFFNBase
.ibszAlt
;
7458 #ifdef OSL_BIGENDIAN
7459 swapEndian(pSecondary
);
7461 p
->sFontname
+= OUStringLiteral(u
";") + pSecondary
;
7464 // #i43762# check font name for illegal characters
7465 lcl_checkFontname( p
->sFontname
);
7467 // set pointer one font back to original array
7468 pRaw
+= p
->aFFNBase
.cbFfnM1
;
7469 nRemainingFFn
-= p
->aFFNBase
.cbFfnM1
;
7472 OSL_ENSURE(nMax
== nValidFonts
, "Font count differs with availability");
7473 nMax
= std::min(nMax
, nValidFonts
);
7476 m_aFontA
.resize(nMax
);
7477 m_aFontA
.shrink_to_fit();
7480 const WW8_FFN
* WW8Fonts::GetFont( sal_uInt16 nNum
) const
7482 if (nNum
>= m_aFontA
.size())
7485 return &m_aFontA
[nNum
];
7488 // Search after a header/footer for an index in the ww list from header/footer
7490 // specials for WinWord6 and -7:
7492 // 1) At the start of reading we must build WWPLCF_HdFt with Fib and Dop
7493 // 2) The main text must be read sequentially over all sections
7494 // 3) For every header/footer in the main text, we must call UpdateIndex()
7495 // exactly once with the parameter from the attribute.
7496 // (per section can be maximally one). This call must take place *after*
7497 // the last call from GetTextPos().
7498 // 4) GetTextPos() can be called with exactly one flag
7499 // out of WW8_{FOOTER,HEADER}_{ODD,EVEN,FIRST} (Do not change!)
7500 // -> maybe we can get a right result then
7502 WW8PLCF_HdFt::WW8PLCF_HdFt( SvStream
* pSt
, WW8Fib
const & rFib
, WW8Dop
const & rDop
)
7503 : aPLCF(*pSt
, rFib
.m_fcPlcfhdd
, rFib
.m_lcbPlcfhdd
, 0)
7508 This dop.grpfIhdt has a bit set for each special
7509 footnote *and endnote!!* separator,continuation separator, and
7510 continuation notice entry, the documentation does not mention the
7511 endnote separators, the documentation also gets the index numbers
7512 backwards when specifying which bits to test. The bottom six bits
7513 of this value must be tested and skipped over. Each section's
7514 grpfIhdt is then tested for the existence of the appropriate headers
7515 and footers, at the end of each section the nIdxOffset must be updated
7516 to point to the beginning of the next section's group of headers and
7517 footers in this PLCF, UpdateIndex does that task.
7519 for( sal_uInt8 nI
= 0x1; nI
<= 0x20; nI
<<= 1 )
7520 if( nI
& rDop
.grpfIhdt
) // bit set?
7524 bool WW8PLCF_HdFt::GetTextPos(sal_uInt8 grpfIhdt
, sal_uInt8 nWhich
, WW8_CP
& rStart
,
7527 sal_uInt8 nI
= 0x01;
7528 short nIdx
= nIdxOffset
;
7534 nIdx
++; // uninteresting Header / Footer
7535 nI
<<= 1; // text next bit
7537 return false; // not found
7539 // nIdx is HdFt-Index
7543 aPLCF
.SetIdx( nIdx
); // Lookup suitable CP
7544 aPLCF
.Get( rStart
, nEnd
, pData
);
7547 SAL_WARN("sw.ww8", "End " << nEnd
<< " before Start " << rStart
);
7551 bool bFail
= o3tl::checked_sub(nEnd
, rStart
, rLen
);
7554 SAL_WARN("sw.ww8", "broken offset, ignoring");
7563 void WW8PLCF_HdFt::GetTextPosExact(short nIdx
, WW8_CP
& rStart
, WW8_CP
& rLen
)
7568 aPLCF
.SetIdx( nIdx
); // Lookup suitable CP
7569 aPLCF
.Get( rStart
, nEnd
, pData
);
7572 SAL_WARN("sw.ww8", "End " << nEnd
<< " before Start " << rStart
);
7576 if (o3tl::checked_sub(nEnd
, rStart
, rLen
))
7578 SAL_WARN("sw.ww8", "GetTextPosExact overflow");
7583 void WW8PLCF_HdFt::UpdateIndex( sal_uInt8 grpfIhdt
)
7585 // Caution: Description is not correct
7586 for( sal_uInt8 nI
= 0x01; nI
<= 0x20; nI
<<= 1 )
7591 WW8Dop::WW8Dop(SvStream
& rSt
, sal_Int16 nFib
, sal_Int32 nPos
, sal_uInt32 nSize
):
7592 fFacingPages(false), fWidowControl(false), fPMHMainDoc(false), grfSuppression(0), fpc(0),
7593 grpfIhdt(0), rncFootnote(0), nFootnote(0), fOutlineDirtySave(false), fOnlyMacPics(false),
7594 fOnlyWinPics(false), fLabelDoc(false), fHyphCapitals(false), fAutoHyphen(false),
7595 fFormNoFields(false), fLinkStyles(false), fRevMarking(false), fBackup(false),
7596 fExactCWords(false), fPagHidden(false), fPagResults(false), fLockAtn(false),
7597 fMirrorMargins(false), fReadOnlyRecommended(false), fDfltTrueType(false),
7598 fPagSuppressTopSpacing(false), fProtEnabled(false), fDispFormFieldSel(false), fRMView(false),
7599 fRMPrint(false), fWriteReservation(false), fLockRev(false), fEmbedFonts(false),
7600 copts_fNoTabForInd(false), copts_fNoSpaceRaiseLower(false), copts_fSupressSpbfAfterPgBrk(false),
7601 copts_fWrapTrailSpaces(false), copts_fMapPrintTextColor(false), copts_fNoColumnBalance(false),
7602 copts_fConvMailMergeEsc(false), copts_fSupressTopSpacing(false),
7603 copts_fOrigWordTableRules(false), copts_fTransparentMetafiles(false),
7604 copts_fShowBreaksInFrames(false), copts_fSwapBordersFacingPgs(false), copts_fExpShRtn(false),
7605 rncEdn(0), nEdn(0), epc(0), fPrintFormData(false), fSaveFormData(false), fShadeFormData(false),
7606 fWCFootnoteEdn(false), wvkSaved(0), wScaleSaved(0), zkSaved(0), fRotateFontW6(false),
7607 iGutterPos(false), fNoTabForInd(false), fNoSpaceRaiseLower(false),
7608 fSupressSpbfAfterPageBreak(false), fWrapTrailSpaces(false), fMapPrintTextColor(false),
7609 fNoColumnBalance(false), fConvMailMergeEsc(false), fSupressTopSpacing(false),
7610 fOrigWordTableRules(false), fTransparentMetafiles(false), fShowBreaksInFrames(false),
7611 fSwapBordersFacingPgs(false), fCompatibilityOptions_Unknown1_13(false), fExpShRtn(false),
7612 fCompatibilityOptions_Unknown1_15(false), fCompatibilityOptions_Unknown1_16(false),
7613 fSuppressTopSpacingMac5(false), fTruncDxaExpand(false), fPrintBodyBeforeHdr(false),
7614 fNoLeading(false), fCompatibilityOptions_Unknown1_21(false), fMWSmallCaps(false),
7615 fCompatibilityOptions_Unknown1_23(false), fCompatibilityOptions_Unknown1_24(false),
7616 fCompatibilityOptions_Unknown1_25(false), fCompatibilityOptions_Unknown1_26(false),
7617 fCompatibilityOptions_Unknown1_27(false), fCompatibilityOptions_Unknown1_28(false),
7618 fCompatibilityOptions_Unknown1_29(false), fCompatibilityOptions_Unknown1_30(false),
7619 fCompatibilityOptions_Unknown1_31(false), fUsePrinterMetrics(false), lvl(0), fHtmlDoc(false),
7620 fSnapBorder(false), fIncludeHeader(false), fIncludeFooter(false), fForcePageSizePag(false),
7621 fMinFontSizePag(false), fHaveVersions(false), fAutoVersion(false),
7622 fCompatibilityOptions_Unknown2_1(false), fCompatibilityOptions_Unknown2_2(false),
7623 fDontUseHTMLAutoSpacing(false), fCompatibilityOptions_Unknown2_4(false),
7624 fCompatibilityOptions_Unknown2_5(false), fCompatibilityOptions_Unknown2_6(false),
7625 fCompatibilityOptions_Unknown2_7(false), fCompatibilityOptions_Unknown2_8(false),
7626 fCompatibilityOptions_Unknown2_9(false), fCompatibilityOptions_Unknown2_10(false),
7627 fCompatibilityOptions_Unknown2_11(false), fCompatibilityOptions_Unknown2_12(false),
7628 fCompatibilityOptions_Unknown2_13(false), fCompatibilityOptions_Unknown2_14(false),
7629 fCompatibilityOptions_Unknown2_15(false), fCompatibilityOptions_Unknown2_16(false),
7630 fCompatibilityOptions_Unknown2_17(false), fCompatibilityOptions_Unknown2_18(false),
7631 fCompatibilityOptions_Unknown2_19(false), fCompatibilityOptions_Unknown2_20(false),
7632 fCompatibilityOptions_Unknown2_21(false), fCompatibilityOptions_Unknown2_22(false),
7633 fCompatibilityOptions_Unknown2_23(false), fCompatibilityOptions_Unknown2_24(false),
7634 fCompatibilityOptions_Unknown2_25(false), fCompatibilityOptions_Unknown2_26(false),
7635 fCompatibilityOptions_Unknown2_27(false), fCompatibilityOptions_Unknown2_28(false),
7636 fCompatibilityOptions_Unknown2_29(false), fCompatibilityOptions_Unknown2_30(false),
7637 fCompatibilityOptions_Unknown2_31(false), fCompatibilityOptions_Unknown2_32(false),
7638 fUnknown3(0), fUseBackGroundInAllmodes(false), fDoNotEmbedSystemFont(false), fWordCompat(false),
7639 fLiveRecover(false), fEmbedFactoids(false), fFactoidXML(false), fFactoidAllDone(false),
7640 fFolioPrint(false), fReverseFolio(false), iTextLineEnding(0), fHideFcc(false),
7641 fAcetateShowMarkup(false), fAcetateShowAtn(false), fAcetateShowInsDel(false),
7642 fAcetateShowProps(false)
7643 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
7644 // above bit-field member initializations can be moved to the class definition
7646 fDontUseHTMLAutoSpacing
= true; //default
7647 fAcetateShowAtn
= true; //default
7648 const sal_uInt32 nMaxDopSize
= 0x268;
7649 std::unique_ptr
<sal_uInt8
[]> pDataPtr( new sal_uInt8
[ nMaxDopSize
] );
7650 sal_uInt8
* pData
= pDataPtr
.get();
7652 sal_uInt32 nRead
= std::min(nMaxDopSize
, nSize
);
7653 if (nSize
< 2 || !checkSeek(rSt
, nPos
) || nRead
!= rSt
.ReadBytes(pData
, nRead
))
7654 nDopError
= ERR_SWG_READ_ERROR
; // report error
7657 if (nMaxDopSize
> nRead
)
7658 memset( pData
+ nRead
, 0, nMaxDopSize
- nRead
);
7660 // interpret the data
7665 a16Bit
= Get_UShort( pData
); // 0 0x00
7666 fFacingPages
= 0 != ( a16Bit
& 0x0001 ) ;
7667 fWidowControl
= 0 != ( a16Bit
& 0x0002 ) ;
7668 fPMHMainDoc
= 0 != ( a16Bit
& 0x0004 ) ;
7669 grfSuppression
= ( a16Bit
& 0x0018 ) >> 3;
7670 fpc
= ( a16Bit
& 0x0060 ) >> 5;
7671 grpfIhdt
= ( a16Bit
& 0xff00 ) >> 8;
7673 a16Bit
= Get_UShort( pData
); // 2 0x02
7674 rncFootnote
= a16Bit
& 0x0003 ;
7675 nFootnote
= ( a16Bit
& ~0x0003 ) >> 2 ;
7677 a8Bit
= Get_Byte( pData
); // 4 0x04
7678 fOutlineDirtySave
= 0 != ( a8Bit
& 0x01 );
7680 a8Bit
= Get_Byte( pData
); // 5 0x05
7681 fOnlyMacPics
= 0 != ( a8Bit
& 0x01 );
7682 fOnlyWinPics
= 0 != ( a8Bit
& 0x02 );
7683 fLabelDoc
= 0 != ( a8Bit
& 0x04 );
7684 fHyphCapitals
= 0 != ( a8Bit
& 0x08 );
7685 fAutoHyphen
= 0 != ( a8Bit
& 0x10 );
7686 fFormNoFields
= 0 != ( a8Bit
& 0x20 );
7687 fLinkStyles
= 0 != ( a8Bit
& 0x40 );
7688 fRevMarking
= 0 != ( a8Bit
& 0x80 );
7690 a8Bit
= Get_Byte( pData
); // 6 0x06
7691 fBackup
= 0 != ( a8Bit
& 0x01 );
7692 fExactCWords
= 0 != ( a8Bit
& 0x02 );
7693 fPagHidden
= 0 != ( a8Bit
& 0x04 );
7694 fPagResults
= 0 != ( a8Bit
& 0x08 );
7695 fLockAtn
= 0 != ( a8Bit
& 0x10 );
7696 fMirrorMargins
= 0 != ( a8Bit
& 0x20 );
7697 fReadOnlyRecommended
= 0 != ( a8Bit
& 0x40 );
7698 fDfltTrueType
= 0 != ( a8Bit
& 0x80 );
7700 a8Bit
= Get_Byte( pData
); // 7 0x07
7701 fPagSuppressTopSpacing
= 0 != ( a8Bit
& 0x01 );
7702 fProtEnabled
= 0 != ( a8Bit
& 0x02 );
7703 fDispFormFieldSel
= 0 != ( a8Bit
& 0x04 );
7704 fRMView
= 0 != ( a8Bit
& 0x08 );
7705 fRMPrint
= 0 != ( a8Bit
& 0x10 );
7706 fWriteReservation
= 0 != ( a8Bit
& 0x20 );
7707 fLockRev
= 0 != ( a8Bit
& 0x40 );
7708 fEmbedFonts
= 0 != ( a8Bit
& 0x80 );
7710 a8Bit
= Get_Byte( pData
); // 8 0x08
7711 copts_fNoTabForInd
= 0 != ( a8Bit
& 0x01 );
7712 copts_fNoSpaceRaiseLower
= 0 != ( a8Bit
& 0x02 );
7713 copts_fSupressSpbfAfterPgBrk
= 0 != ( a8Bit
& 0x04 );
7714 copts_fWrapTrailSpaces
= 0 != ( a8Bit
& 0x08 );
7715 copts_fMapPrintTextColor
= 0 != ( a8Bit
& 0x10 );
7716 copts_fNoColumnBalance
= 0 != ( a8Bit
& 0x20 );
7717 copts_fConvMailMergeEsc
= 0 != ( a8Bit
& 0x40 );
7718 copts_fSupressTopSpacing
= 0 != ( a8Bit
& 0x80 );
7720 a8Bit
= Get_Byte( pData
); // 9 0x09
7721 copts_fOrigWordTableRules
= 0 != ( a8Bit
& 0x01 );
7722 copts_fTransparentMetafiles
= 0 != ( a8Bit
& 0x02 );
7723 copts_fShowBreaksInFrames
= 0 != ( a8Bit
& 0x04 );
7724 copts_fSwapBordersFacingPgs
= 0 != ( a8Bit
& 0x08 );
7725 copts_fExpShRtn
= 0 != ( a8Bit
& 0x20 ); // #i56856#
7727 dxaTab
= Get_Short( pData
); // 10 0x0a
7728 wSpare
= Get_UShort( pData
); // 12 0x0c
7729 dxaHotZ
= Get_UShort( pData
); // 14 0x0e
7730 cConsecHypLim
= Get_UShort( pData
); // 16 0x10
7731 wSpare2
= Get_UShort( pData
); // 18 0x12
7732 dttmCreated
= Get_Long( pData
); // 20 0x14
7733 dttmRevised
= Get_Long( pData
); // 24 0x18
7734 dttmLastPrint
= Get_Long( pData
); // 28 0x1c
7735 nRevision
= Get_Short( pData
); // 32 0x20
7736 tmEdited
= Get_Long( pData
); // 34 0x22
7737 cWords
= Get_Long( pData
); // 38 0x26
7738 cCh
= Get_Long( pData
); // 42 0x2a
7739 cPg
= Get_Short( pData
); // 46 0x2e
7740 cParas
= Get_Long( pData
); // 48 0x30
7742 a16Bit
= Get_UShort( pData
); // 52 0x34
7743 rncEdn
= a16Bit
& 0x0003 ;
7744 nEdn
= ( a16Bit
& ~0x0003 ) >> 2;
7746 a16Bit
= Get_UShort( pData
); // 54 0x36
7747 epc
= a16Bit
& 0x0003 ;
7748 nfcFootnoteRef
= ( a16Bit
& 0x003c ) >> 2;
7749 nfcEdnRef
= ( a16Bit
& 0x03c0 ) >> 6;
7750 fPrintFormData
= 0 != ( a16Bit
& 0x0400 );
7751 fSaveFormData
= 0 != ( a16Bit
& 0x0800 );
7752 fShadeFormData
= 0 != ( a16Bit
& 0x1000 );
7753 fWCFootnoteEdn
= 0 != ( a16Bit
& 0x8000 );
7755 cLines
= Get_Long( pData
); // 56 0x38
7756 cWordsFootnoteEnd
= Get_Long( pData
); // 60 0x3c
7757 cChFootnoteEdn
= Get_Long( pData
); // 64 0x40
7758 cPgFootnoteEdn
= Get_Short( pData
); // 68 0x44
7759 cParasFootnoteEdn
= Get_Long( pData
); // 70 0x46
7760 cLinesFootnoteEdn
= Get_Long( pData
); // 74 0x4a
7761 lKeyProtDoc
= Get_Long( pData
); // 78 0x4e
7763 a16Bit
= Get_UShort( pData
); // 82 0x52
7764 wvkSaved
= a16Bit
& 0x0007 ;
7765 wScaleSaved
= ( a16Bit
& 0x0ff8 ) >> 3 ;
7766 zkSaved
= ( a16Bit
& 0x3000 ) >> 12;
7767 fRotateFontW6
= ( a16Bit
& 0x4000 ) >> 14;
7768 iGutterPos
= ( a16Bit
& 0x8000 ) >> 15;
7770 if (nFib
>= 103) // Word 6/32bit, 95, 97, 2000, 2002, 2003, 2007
7772 a32Bit
= Get_ULong( pData
); // 84 0x54
7773 SetCompatibilityOptions(a32Bit
);
7776 //#i22436#, for all WW7- documents
7777 if (nFib
<= 104) // Word 95
7778 fUsePrinterMetrics
= true;
7780 if (nFib
> 105) // Word 97, 2000, 2002, 2003, 2007
7782 adt
= Get_Short( pData
); // 88 0x58
7784 doptypography
.ReadFromMem(pData
); // 90 0x5a
7786 memcpy( &dogrid
, pData
, sizeof( WW8_DOGRID
)); // 400 0x190
7787 pData
+= sizeof( WW8_DOGRID
);
7789 a16Bit
= Get_UShort( pData
); // 410 0x19a
7790 // the following 9 bit are uninteresting
7791 fHtmlDoc
= ( a16Bit
& 0x0200 ) >> 9 ;
7792 fSnapBorder
= ( a16Bit
& 0x0800 ) >> 11 ;
7793 fIncludeHeader
= ( a16Bit
& 0x1000 ) >> 12 ;
7794 fIncludeFooter
= ( a16Bit
& 0x2000 ) >> 13 ;
7795 fForcePageSizePag
= ( a16Bit
& 0x4000 ) >> 14 ;
7796 fMinFontSizePag
= ( a16Bit
& 0x8000 ) >> 15 ;
7798 a16Bit
= Get_UShort( pData
); // 412 0x19c
7799 fHaveVersions
= 0 != ( a16Bit
& 0x0001 );
7800 fAutoVersion
= 0 != ( a16Bit
& 0x0002 );
7802 pData
+= 12; // 414 0x19e
7804 cChWS
= Get_Long( pData
); // 426 0x1aa
7805 cChWSFootnoteEdn
= Get_Long( pData
); // 430 0x1ae
7806 grfDocEvents
= Get_Long( pData
); // 434 0x1b2
7808 pData
+= 4+30+8; // 438 0x1b6; 442 0x1ba; 472 0x1d8; 476 0x1dc
7810 cDBC
= Get_Long( pData
); // 480 0x1e0
7811 cDBCFootnoteEdn
= Get_Long( pData
); // 484 0x1e4
7813 pData
+= 1 * sizeof( sal_Int32
); // 488 0x1e8
7815 nfcFootnoteRef
= Get_Short( pData
); // 492 0x1ec
7816 nfcEdnRef
= Get_Short( pData
); // 494 0x1ee
7817 hpsZoomFontPag
= Get_Short( pData
); // 496 0x1f0
7818 dywDispPag
= Get_Short( pData
); // 498 0x1f2
7822 //500 -> 508, Appear to be repeated here in 2000+
7823 pData
+= 8; // 500 0x1f4
7824 a32Bit
= Get_Long( pData
); // 508 0x1fc
7825 SetCompatibilityOptions(a32Bit
);
7826 a32Bit
= Get_Long( pData
); // 512 0x200
7829 SetCompatibilityOptions2(a32Bit
);
7834 a16Bit
= Get_UShort( pData
);
7835 fDoNotEmbedSystemFont
= ( a16Bit
& 0x0001 );
7836 fWordCompat
= ( a16Bit
& 0x0002 ) >> 1;
7837 fLiveRecover
= ( a16Bit
& 0x0004 ) >> 2;
7838 fEmbedFactoids
= ( a16Bit
& 0x0008 ) >> 3;
7839 fFactoidXML
= ( a16Bit
& 0x00010 ) >> 4;
7840 fFactoidAllDone
= ( a16Bit
& 0x0020 ) >> 5;
7841 fFolioPrint
= ( a16Bit
& 0x0040 ) >> 6;
7842 fReverseFolio
= ( a16Bit
& 0x0080 ) >> 7;
7843 iTextLineEnding
= ( a16Bit
& 0x0700 ) >> 8;
7844 fHideFcc
= ( a16Bit
& 0x0800 ) >> 11;
7845 fAcetateShowMarkup
= ( a16Bit
& 0x1000 ) >> 12;
7846 fAcetateShowAtn
= ( a16Bit
& 0x2000 ) >> 13;
7847 fAcetateShowInsDel
= ( a16Bit
& 0x4000 ) >> 14;
7848 fAcetateShowProps
= ( a16Bit
& 0x8000 ) >> 15;
7853 a16Bit
= Get_Short(pData
);
7854 fUseBackGroundInAllmodes
= (a16Bit
& 0x0080) >> 7;
7861 fFacingPages(false), fWidowControl(true), fPMHMainDoc(false), grfSuppression(0), fpc(1),
7862 grpfIhdt(0), rncFootnote(0), nFootnote(1), fOutlineDirtySave(true), fOnlyMacPics(false),
7863 fOnlyWinPics(false), fLabelDoc(false), fHyphCapitals(true), fAutoHyphen(false),
7864 fFormNoFields(false), fLinkStyles(false), fRevMarking(false), fBackup(true),
7865 fExactCWords(false), fPagHidden(true), fPagResults(true), fLockAtn(false),
7866 fMirrorMargins(false), fReadOnlyRecommended(false), fDfltTrueType(true),
7867 fPagSuppressTopSpacing(false), fProtEnabled(false), fDispFormFieldSel(false), fRMView(true),
7868 fRMPrint(true), fWriteReservation(false), fLockRev(false), fEmbedFonts(false),
7869 copts_fNoTabForInd(false), copts_fNoSpaceRaiseLower(false), copts_fSupressSpbfAfterPgBrk(false),
7870 copts_fWrapTrailSpaces(false), copts_fMapPrintTextColor(false), copts_fNoColumnBalance(false),
7871 copts_fConvMailMergeEsc(false), copts_fSupressTopSpacing(false),
7872 copts_fOrigWordTableRules(false), copts_fTransparentMetafiles(false),
7873 copts_fShowBreaksInFrames(false), copts_fSwapBordersFacingPgs(false), copts_fExpShRtn(false),
7874 dxaTab(0x2d0), dxaHotZ(0x168), nRevision(1),
7875 rncEdn(0), nEdn(1), epc(3), fPrintFormData(false), fSaveFormData(false), fShadeFormData(true),
7876 fWCFootnoteEdn(false), wvkSaved(2), wScaleSaved(100), zkSaved(0), fRotateFontW6(false),
7877 iGutterPos(false), fNoTabForInd(false), fNoSpaceRaiseLower(false),
7878 fSupressSpbfAfterPageBreak(false), fWrapTrailSpaces(false), fMapPrintTextColor(false),
7879 fNoColumnBalance(false), fConvMailMergeEsc(false), fSupressTopSpacing(false),
7880 fOrigWordTableRules(false), fTransparentMetafiles(false), fShowBreaksInFrames(false),
7881 fSwapBordersFacingPgs(false), fCompatibilityOptions_Unknown1_13(false), fExpShRtn(false),
7882 fCompatibilityOptions_Unknown1_15(false), fCompatibilityOptions_Unknown1_16(false),
7883 fSuppressTopSpacingMac5(false), fTruncDxaExpand(false), fPrintBodyBeforeHdr(false),
7884 fNoLeading(true), fCompatibilityOptions_Unknown1_21(false), fMWSmallCaps(false),
7885 fCompatibilityOptions_Unknown1_23(false), fCompatibilityOptions_Unknown1_24(false),
7886 fCompatibilityOptions_Unknown1_25(false), fCompatibilityOptions_Unknown1_26(false),
7887 fCompatibilityOptions_Unknown1_27(false), fCompatibilityOptions_Unknown1_28(false),
7888 fCompatibilityOptions_Unknown1_29(false), fCompatibilityOptions_Unknown1_30(false),
7889 fCompatibilityOptions_Unknown1_31(false), fUsePrinterMetrics(true), lvl(9), fHtmlDoc(false),
7890 fSnapBorder(false), fIncludeHeader(true), fIncludeFooter(true), fForcePageSizePag(false),
7891 fMinFontSizePag(false), fHaveVersions(false), fAutoVersion(false),
7892 cChWS(0), cChWSFootnoteEdn(0), cDBC(0), cDBCFootnoteEdn(0), nfcEdnRef(2),
7893 fCompatibilityOptions_Unknown2_1(false), fCompatibilityOptions_Unknown2_2(false),
7894 fDontUseHTMLAutoSpacing(false), fCompatibilityOptions_Unknown2_4(false),
7895 fCompatibilityOptions_Unknown2_5(false), fCompatibilityOptions_Unknown2_6(false),
7896 fCompatibilityOptions_Unknown2_7(false), fCompatibilityOptions_Unknown2_8(false),
7897 fCompatibilityOptions_Unknown2_9(false), fCompatibilityOptions_Unknown2_10(false),
7898 fCompatibilityOptions_Unknown2_11(false), fCompatibilityOptions_Unknown2_12(false),
7899 fCompatibilityOptions_Unknown2_13(false), fCompatibilityOptions_Unknown2_14(false),
7900 fCompatibilityOptions_Unknown2_15(false), fCompatibilityOptions_Unknown2_16(false),
7901 fCompatibilityOptions_Unknown2_17(false), fCompatibilityOptions_Unknown2_18(false),
7902 fCompatibilityOptions_Unknown2_19(false), fCompatibilityOptions_Unknown2_20(false),
7903 fCompatibilityOptions_Unknown2_21(false), fCompatibilityOptions_Unknown2_22(false),
7904 fCompatibilityOptions_Unknown2_23(false), fCompatibilityOptions_Unknown2_24(false),
7905 fCompatibilityOptions_Unknown2_25(false), fCompatibilityOptions_Unknown2_26(false),
7906 fCompatibilityOptions_Unknown2_27(false), fCompatibilityOptions_Unknown2_28(false),
7907 fCompatibilityOptions_Unknown2_29(false), fCompatibilityOptions_Unknown2_30(false),
7908 fCompatibilityOptions_Unknown2_31(false), fCompatibilityOptions_Unknown2_32(false),
7909 fUnknown3(0), fUseBackGroundInAllmodes(false), fDoNotEmbedSystemFont(false), fWordCompat(false),
7910 fLiveRecover(false), fEmbedFactoids(false), fFactoidXML(false), fFactoidAllDone(false),
7911 fFolioPrint(false), fReverseFolio(false), iTextLineEnding(0), fHideFcc(false),
7912 fAcetateShowMarkup(false), fAcetateShowAtn(true), fAcetateShowInsDel(false),
7913 fAcetateShowProps(false)
7914 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
7915 // above bit-field member initializations can be moved to the class definition
7918 Writer acts like this all the time at the moment, ideally we need an
7919 option for these two as well to import word docs that are not like
7922 // put in initialization list
7923 // fNoLeading = true;
7924 //fUsePrinterMetrics = true;
7927 void WW8Dop::SetCompatibilityOptions(sal_uInt32 a32Bit
)
7929 fNoTabForInd
= ( a32Bit
& 0x00000001 ) ;
7930 fNoSpaceRaiseLower
= ( a32Bit
& 0x00000002 ) >> 1 ;
7931 fSupressSpbfAfterPageBreak
= ( a32Bit
& 0x00000004 ) >> 2 ;
7932 fWrapTrailSpaces
= ( a32Bit
& 0x00000008 ) >> 3 ;
7933 fMapPrintTextColor
= ( a32Bit
& 0x00000010 ) >> 4 ;
7934 fNoColumnBalance
= ( a32Bit
& 0x00000020 ) >> 5 ;
7935 fConvMailMergeEsc
= ( a32Bit
& 0x00000040 ) >> 6 ;
7936 fSupressTopSpacing
= ( a32Bit
& 0x00000080 ) >> 7 ;
7937 fOrigWordTableRules
= ( a32Bit
& 0x00000100 ) >> 8 ;
7938 fTransparentMetafiles
= ( a32Bit
& 0x00000200 ) >> 9 ;
7939 fShowBreaksInFrames
= ( a32Bit
& 0x00000400 ) >> 10 ;
7940 fSwapBordersFacingPgs
= ( a32Bit
& 0x00000800 ) >> 11 ;
7941 fCompatibilityOptions_Unknown1_13
= ( a32Bit
& 0x00001000 ) >> 12 ;
7942 fExpShRtn
= ( a32Bit
& 0x00002000 ) >> 13 ; // #i56856#
7943 fCompatibilityOptions_Unknown1_15
= ( a32Bit
& 0x00004000 ) >> 14 ;
7944 fCompatibilityOptions_Unknown1_16
= ( a32Bit
& 0x00008000 ) >> 15 ;
7945 fSuppressTopSpacingMac5
= ( a32Bit
& 0x00010000 ) >> 16 ;
7946 fTruncDxaExpand
= ( a32Bit
& 0x00020000 ) >> 17 ;
7947 fPrintBodyBeforeHdr
= ( a32Bit
& 0x00040000 ) >> 18 ;
7948 fNoLeading
= ( a32Bit
& 0x00080000 ) >> 19 ;
7949 fCompatibilityOptions_Unknown1_21
= ( a32Bit
& 0x00100000 ) >> 20 ;
7950 fMWSmallCaps
= ( a32Bit
& 0x00200000 ) >> 21 ;
7951 fCompatibilityOptions_Unknown1_23
= ( a32Bit
& 0x00400000 ) >> 22 ;
7952 fCompatibilityOptions_Unknown1_24
= ( a32Bit
& 0x00800800 ) >> 23 ;
7953 fCompatibilityOptions_Unknown1_25
= ( a32Bit
& 0x01000000 ) >> 24 ;
7954 fCompatibilityOptions_Unknown1_26
= ( a32Bit
& 0x02000000 ) >> 25 ;
7955 fCompatibilityOptions_Unknown1_27
= ( a32Bit
& 0x04000000 ) >> 26 ;
7956 fCompatibilityOptions_Unknown1_28
= ( a32Bit
& 0x08000000 ) >> 27 ;
7957 fCompatibilityOptions_Unknown1_29
= ( a32Bit
& 0x10000000 ) >> 28 ;
7958 fCompatibilityOptions_Unknown1_30
= ( a32Bit
& 0x20000000 ) >> 29 ;
7959 fCompatibilityOptions_Unknown1_31
= ( a32Bit
& 0x40000000 ) >> 30 ;
7961 fUsePrinterMetrics
= ( a32Bit
& 0x80000000 ) >> 31 ;
7964 sal_uInt32
WW8Dop::GetCompatibilityOptions() const
7966 sal_uInt32 a32Bit
= 0;
7967 if (fNoTabForInd
) a32Bit
|= 0x00000001;
7968 if (fNoSpaceRaiseLower
) a32Bit
|= 0x00000002;
7969 if (fSupressSpbfAfterPageBreak
) a32Bit
|= 0x00000004;
7970 if (fWrapTrailSpaces
) a32Bit
|= 0x00000008;
7971 if (fMapPrintTextColor
) a32Bit
|= 0x00000010;
7972 if (fNoColumnBalance
) a32Bit
|= 0x00000020;
7973 if (fConvMailMergeEsc
) a32Bit
|= 0x00000040;
7974 if (fSupressTopSpacing
) a32Bit
|= 0x00000080;
7975 if (fOrigWordTableRules
) a32Bit
|= 0x00000100;
7976 if (fTransparentMetafiles
) a32Bit
|= 0x00000200;
7977 if (fShowBreaksInFrames
) a32Bit
|= 0x00000400;
7978 if (fSwapBordersFacingPgs
) a32Bit
|= 0x00000800;
7979 if (fCompatibilityOptions_Unknown1_13
) a32Bit
|= 0x00001000;
7980 if (fExpShRtn
) a32Bit
|= 0x00002000; // #i56856#
7981 if (fCompatibilityOptions_Unknown1_15
) a32Bit
|= 0x00004000;
7982 if (fCompatibilityOptions_Unknown1_16
) a32Bit
|= 0x00008000;
7983 if (fSuppressTopSpacingMac5
) a32Bit
|= 0x00010000;
7984 if (fTruncDxaExpand
) a32Bit
|= 0x00020000;
7985 if (fPrintBodyBeforeHdr
) a32Bit
|= 0x00040000;
7986 if (fNoLeading
) a32Bit
|= 0x00080000;
7987 if (fCompatibilityOptions_Unknown1_21
) a32Bit
|= 0x00100000;
7988 if (fMWSmallCaps
) a32Bit
|= 0x00200000;
7989 if (fCompatibilityOptions_Unknown1_23
) a32Bit
|= 0x00400000;
7990 if (fCompatibilityOptions_Unknown1_24
) a32Bit
|= 0x00800000;
7991 if (fCompatibilityOptions_Unknown1_25
) a32Bit
|= 0x01000000;
7992 if (fCompatibilityOptions_Unknown1_26
) a32Bit
|= 0x02000000;
7993 if (fCompatibilityOptions_Unknown1_27
) a32Bit
|= 0x04000000;
7994 if (fCompatibilityOptions_Unknown1_28
) a32Bit
|= 0x08000000;
7995 if (fCompatibilityOptions_Unknown1_29
) a32Bit
|= 0x10000000;
7996 if (fCompatibilityOptions_Unknown1_30
) a32Bit
|= 0x20000000;
7997 if (fCompatibilityOptions_Unknown1_31
) a32Bit
|= 0x40000000;
7998 if (fUsePrinterMetrics
) a32Bit
|= 0x80000000;
8003 void WW8Dop::SetCompatibilityOptions2(sal_uInt32 a32Bit
)
8005 fCompatibilityOptions_Unknown2_1
= ( a32Bit
& 0x00000001 );
8006 fCompatibilityOptions_Unknown2_2
= ( a32Bit
& 0x00000002 ) >> 1 ;
8007 fDontUseHTMLAutoSpacing
= ( a32Bit
& 0x00000004 ) >> 2 ;
8008 fCompatibilityOptions_Unknown2_4
= ( a32Bit
& 0x00000008 ) >> 3 ;
8009 fCompatibilityOptions_Unknown2_5
= ( a32Bit
& 0x00000010 ) >> 4 ;
8010 fCompatibilityOptions_Unknown2_6
= ( a32Bit
& 0x00000020 ) >> 5 ;
8011 fCompatibilityOptions_Unknown2_7
= ( a32Bit
& 0x00000040 ) >> 6 ;
8012 fCompatibilityOptions_Unknown2_8
= ( a32Bit
& 0x00000080 ) >> 7 ;
8013 fCompatibilityOptions_Unknown2_9
= ( a32Bit
& 0x00000100 ) >> 8 ;
8014 fCompatibilityOptions_Unknown2_10
= ( a32Bit
& 0x00000200 ) >> 9 ;
8015 fCompatibilityOptions_Unknown2_11
= ( a32Bit
& 0x00000400 ) >> 10 ;
8016 fCompatibilityOptions_Unknown2_12
= ( a32Bit
& 0x00000800 ) >> 11 ;
8017 fCompatibilityOptions_Unknown2_13
= ( a32Bit
& 0x00001000 ) >> 12 ;
8018 fCompatibilityOptions_Unknown2_14
= ( a32Bit
& 0x00002000 ) >> 13 ;
8019 fCompatibilityOptions_Unknown2_15
= ( a32Bit
& 0x00004000 ) >> 14 ;
8020 fCompatibilityOptions_Unknown2_16
= ( a32Bit
& 0x00008000 ) >> 15 ;
8021 fCompatibilityOptions_Unknown2_17
= ( a32Bit
& 0x00010000 ) >> 16 ;
8022 fCompatibilityOptions_Unknown2_18
= ( a32Bit
& 0x00020000 ) >> 17 ;
8023 fCompatibilityOptions_Unknown2_19
= ( a32Bit
& 0x00040000 ) >> 18 ;
8024 fCompatibilityOptions_Unknown2_20
= ( a32Bit
& 0x00080000 ) >> 19 ;
8025 fCompatibilityOptions_Unknown2_21
= ( a32Bit
& 0x00100000 ) >> 20 ;
8026 fCompatibilityOptions_Unknown2_22
= ( a32Bit
& 0x00200000 ) >> 21 ;
8027 fCompatibilityOptions_Unknown2_23
= ( a32Bit
& 0x00400000 ) >> 22 ;
8028 fCompatibilityOptions_Unknown2_24
= ( a32Bit
& 0x00800800 ) >> 23 ;
8029 fCompatibilityOptions_Unknown2_25
= ( a32Bit
& 0x01000800 ) >> 24 ;
8030 fCompatibilityOptions_Unknown2_26
= ( a32Bit
& 0x02000800 ) >> 25 ;
8031 fCompatibilityOptions_Unknown2_27
= ( a32Bit
& 0x04000800 ) >> 26 ;
8032 fCompatibilityOptions_Unknown2_28
= ( a32Bit
& 0x08000800 ) >> 27 ;
8033 fCompatibilityOptions_Unknown2_29
= ( a32Bit
& 0x10000800 ) >> 28 ;
8034 fCompatibilityOptions_Unknown2_30
= ( a32Bit
& 0x20000800 ) >> 29 ;
8035 fCompatibilityOptions_Unknown2_31
= ( a32Bit
& 0x40000800 ) >> 30 ;
8036 fCompatibilityOptions_Unknown2_32
= ( a32Bit
& 0x80000000 ) >> 31 ;
8039 sal_uInt32
WW8Dop::GetCompatibilityOptions2() const
8041 sal_uInt32 a32Bit
= 0;
8042 if (fCompatibilityOptions_Unknown2_1
) a32Bit
|= 0x00000001;
8043 if (fCompatibilityOptions_Unknown2_2
) a32Bit
|= 0x00000002;
8044 if (fDontUseHTMLAutoSpacing
) a32Bit
|= 0x00000004;
8045 if (fCompatibilityOptions_Unknown2_4
) a32Bit
|= 0x00000008;
8046 if (fCompatibilityOptions_Unknown2_5
) a32Bit
|= 0x00000010;
8047 if (fCompatibilityOptions_Unknown2_6
) a32Bit
|= 0x00000020;
8048 if (fCompatibilityOptions_Unknown2_7
) a32Bit
|= 0x00000040;
8049 if (fCompatibilityOptions_Unknown2_8
) a32Bit
|= 0x00000080;
8050 if (fCompatibilityOptions_Unknown2_9
) a32Bit
|= 0x00000100;
8051 if (fCompatibilityOptions_Unknown2_10
) a32Bit
|= 0x00000200;
8052 if (fCompatibilityOptions_Unknown2_11
) a32Bit
|= 0x00000400;
8053 if (fCompatibilityOptions_Unknown2_12
) a32Bit
|= 0x00000800;
8054 if (fCompatibilityOptions_Unknown2_13
) a32Bit
|= 0x00001000;
8055 //#i42909# set thai "line breaking rules" compatibility option
8056 // pflin, wonder whether bUseThaiLineBreakingRules is correct
8057 // when importing word document.
8058 if (bUseThaiLineBreakingRules
) a32Bit
|= 0x00002000;
8059 else if (fCompatibilityOptions_Unknown2_14
) a32Bit
|= 0x00002000;
8060 if (fCompatibilityOptions_Unknown2_15
) a32Bit
|= 0x00004000;
8061 if (fCompatibilityOptions_Unknown2_16
) a32Bit
|= 0x00008000;
8062 if (fCompatibilityOptions_Unknown2_17
) a32Bit
|= 0x00010000;
8063 if (fCompatibilityOptions_Unknown2_18
) a32Bit
|= 0x00020000;
8064 if (fCompatibilityOptions_Unknown2_19
) a32Bit
|= 0x00040000;
8065 if (fCompatibilityOptions_Unknown2_20
) a32Bit
|= 0x00080000;
8066 if (fCompatibilityOptions_Unknown2_21
) a32Bit
|= 0x00100000;
8067 if (fCompatibilityOptions_Unknown2_22
) a32Bit
|= 0x00200000;
8068 if (fCompatibilityOptions_Unknown2_23
) a32Bit
|= 0x00400000;
8069 if (fCompatibilityOptions_Unknown2_24
) a32Bit
|= 0x00800000;
8070 if (fCompatibilityOptions_Unknown2_25
) a32Bit
|= 0x01000000;
8071 if (fCompatibilityOptions_Unknown2_26
) a32Bit
|= 0x02000000;
8072 if (fCompatibilityOptions_Unknown2_27
) a32Bit
|= 0x04000000;
8073 if (fCompatibilityOptions_Unknown2_28
) a32Bit
|= 0x08000000;
8074 if (fCompatibilityOptions_Unknown2_29
) a32Bit
|= 0x10000000;
8075 if (fCompatibilityOptions_Unknown2_30
) a32Bit
|= 0x20000000;
8076 if (fCompatibilityOptions_Unknown2_31
) a32Bit
|= 0x40000000;
8077 if (fCompatibilityOptions_Unknown2_32
) a32Bit
|= 0x80000000;
8081 void WW8Dop::Write(SvStream
& rStrm
, WW8Fib
& rFib
) const
8083 const int nMaxDopLen
= 610;
8084 sal_uInt32 nLen
= 8 == rFib
.m_nVersion
? nMaxDopLen
: 84;
8085 rFib
.m_fcDop
= rStrm
.Tell();
8086 rFib
.m_lcbDop
= nLen
;
8088 sal_uInt8 aData
[ nMaxDopLen
] = {};
8089 sal_uInt8
* pData
= aData
;
8095 a16Bit
= 0; // 0 0x00
8102 a16Bit
|= ( 0x0018 & (grfSuppression
<< 3));
8103 a16Bit
|= ( 0x0060 & (fpc
<< 5));
8104 a16Bit
|= ( 0xff00 & (grpfIhdt
<< 8));
8105 Set_UInt16( pData
, a16Bit
);
8107 a16Bit
= 0; // 2 0x02
8108 a16Bit
|= ( 0x0003 & rncFootnote
);
8109 a16Bit
|= ( ~0x0003 & (nFootnote
<< 2));
8110 Set_UInt16( pData
, a16Bit
);
8112 a8Bit
= 0; // 4 0x04
8113 if( fOutlineDirtySave
) a8Bit
|= 0x01;
8114 Set_UInt8( pData
, a8Bit
);
8116 a8Bit
= 0; // 5 0x05
8117 if( fOnlyMacPics
) a8Bit
|= 0x01;
8118 if( fOnlyWinPics
) a8Bit
|= 0x02;
8119 if( fLabelDoc
) a8Bit
|= 0x04;
8120 if( fHyphCapitals
) a8Bit
|= 0x08;
8121 if( fAutoHyphen
) a8Bit
|= 0x10;
8122 if( fFormNoFields
) a8Bit
|= 0x20;
8123 if( fLinkStyles
) a8Bit
|= 0x40;
8124 if( fRevMarking
) a8Bit
|= 0x80;
8125 Set_UInt8( pData
, a8Bit
);
8127 a8Bit
= 0; // 6 0x06
8128 if( fBackup
) a8Bit
|= 0x01;
8129 if( fExactCWords
) a8Bit
|= 0x02;
8130 if( fPagHidden
) a8Bit
|= 0x04;
8131 if( fPagResults
) a8Bit
|= 0x08;
8132 if( fLockAtn
) a8Bit
|= 0x10;
8133 if( fMirrorMargins
) a8Bit
|= 0x20;
8134 if( fReadOnlyRecommended
) a8Bit
|= 0x40;
8135 if( fDfltTrueType
) a8Bit
|= 0x80;
8136 Set_UInt8( pData
, a8Bit
);
8138 a8Bit
= 0; // 7 0x07
8139 if( fPagSuppressTopSpacing
) a8Bit
|= 0x01;
8140 if( fProtEnabled
) a8Bit
|= 0x02;
8141 if( fDispFormFieldSel
) a8Bit
|= 0x04;
8142 if( fRMView
) a8Bit
|= 0x08;
8143 if( fRMPrint
) a8Bit
|= 0x10;
8144 if( fWriteReservation
) a8Bit
|= 0x20;
8145 if( fLockRev
) a8Bit
|= 0x40;
8146 if( fEmbedFonts
) a8Bit
|= 0x80;
8147 Set_UInt8( pData
, a8Bit
);
8149 a8Bit
= 0; // 8 0x08
8150 if( copts_fNoTabForInd
) a8Bit
|= 0x01;
8151 if( copts_fNoSpaceRaiseLower
) a8Bit
|= 0x02;
8152 if( copts_fSupressSpbfAfterPgBrk
) a8Bit
|= 0x04;
8153 if( copts_fWrapTrailSpaces
) a8Bit
|= 0x08;
8154 if( copts_fMapPrintTextColor
) a8Bit
|= 0x10;
8155 if( copts_fNoColumnBalance
) a8Bit
|= 0x20;
8156 if( copts_fConvMailMergeEsc
) a8Bit
|= 0x40;
8157 if( copts_fSupressTopSpacing
) a8Bit
|= 0x80;
8158 Set_UInt8( pData
, a8Bit
);
8160 a8Bit
= 0; // 9 0x09
8161 if( copts_fOrigWordTableRules
) a8Bit
|= 0x01;
8162 if( copts_fTransparentMetafiles
) a8Bit
|= 0x02;
8163 if( copts_fShowBreaksInFrames
) a8Bit
|= 0x04;
8164 if( copts_fSwapBordersFacingPgs
) a8Bit
|= 0x08;
8165 if( copts_fExpShRtn
) a8Bit
|= 0x20; // #i56856#
8166 Set_UInt8( pData
, a8Bit
);
8168 Set_UInt16( pData
, dxaTab
); // 10 0x0a
8169 Set_UInt16( pData
, wSpare
); // 12 0x0c
8170 Set_UInt16( pData
, dxaHotZ
); // 14 0x0e
8171 Set_UInt16( pData
, cConsecHypLim
); // 16 0x10
8172 Set_UInt16( pData
, wSpare2
); // 18 0x12
8173 Set_UInt32( pData
, dttmCreated
); // 20 0x14
8174 Set_UInt32( pData
, dttmRevised
); // 24 0x18
8175 Set_UInt32( pData
, dttmLastPrint
); // 28 0x1c
8176 Set_UInt16( pData
, nRevision
); // 32 0x20
8177 Set_UInt32( pData
, tmEdited
); // 34 0x22
8178 Set_UInt32( pData
, cWords
); // 38 0x26
8179 Set_UInt32( pData
, cCh
); // 42 0x2a
8180 Set_UInt16( pData
, cPg
); // 46 0x2e
8181 Set_UInt32( pData
, cParas
); // 48 0x30
8183 a16Bit
= 0; // 52 0x34
8184 a16Bit
|= ( 0x0003 & rncEdn
);
8185 a16Bit
|= (~0x0003 & ( nEdn
<< 2));
8186 Set_UInt16( pData
, a16Bit
);
8188 a16Bit
= 0; // 54 0x36
8189 a16Bit
|= (0x0003 & epc
);
8190 a16Bit
|= (0x003c & (nfcFootnoteRef
<< 2));
8191 a16Bit
|= (0x03c0 & (nfcEdnRef
<< 6));
8192 if( fPrintFormData
) a16Bit
|= 0x0400;
8193 if( fSaveFormData
) a16Bit
|= 0x0800;
8194 if( fShadeFormData
) a16Bit
|= 0x1000;
8195 if( fWCFootnoteEdn
) a16Bit
|= 0x8000;
8196 Set_UInt16( pData
, a16Bit
);
8198 Set_UInt32( pData
, cLines
); // 56 0x38
8199 Set_UInt32( pData
, cWordsFootnoteEnd
); // 60 0x3c
8200 Set_UInt32( pData
, cChFootnoteEdn
); // 64 0x40
8201 Set_UInt16( pData
, cPgFootnoteEdn
); // 68 0x44
8202 Set_UInt32( pData
, cParasFootnoteEdn
); // 70 0x46
8203 Set_UInt32( pData
, cLinesFootnoteEdn
); // 74 0x4a
8204 Set_UInt32( pData
, lKeyProtDoc
); // 78 0x4e
8206 a16Bit
= 0; // 82 0x52
8209 a16Bit
|= (0x0ff8 & (wScaleSaved
<< 3));
8210 a16Bit
|= (0x3000 & (zkSaved
<< 12));
8211 Set_UInt16( pData
, a16Bit
);
8213 if( 8 == rFib
.m_nVersion
)
8215 Set_UInt32(pData
, GetCompatibilityOptions()); // 84 0x54
8217 Set_UInt16( pData
, adt
); // 88 0x58
8219 doptypography
.WriteToMem(pData
); // 400 0x190
8221 memcpy( pData
, &dogrid
, sizeof( WW8_DOGRID
));
8222 pData
+= sizeof( WW8_DOGRID
);
8224 a16Bit
= 0x12; // set lvl to 9 // 410 0x19a
8225 if( fHtmlDoc
) a16Bit
|= 0x0200;
8226 if( fSnapBorder
) a16Bit
|= 0x0800;
8227 if( fIncludeHeader
) a16Bit
|= 0x1000;
8228 if( fIncludeFooter
) a16Bit
|= 0x2000;
8229 if( fForcePageSizePag
) a16Bit
|= 0x4000;
8230 if( fMinFontSizePag
) a16Bit
|= 0x8000;
8231 Set_UInt16( pData
, a16Bit
);
8233 a16Bit
= 0; // 412 0x19c
8234 if( fHaveVersions
) a16Bit
|= 0x0001;
8235 if( fAutoVersion
) a16Bit
|= 0x0002;
8236 Set_UInt16( pData
, a16Bit
);
8238 pData
+= 12; // 414 0x19e
8240 Set_UInt32( pData
, cChWS
); // 426 0x1aa
8241 Set_UInt32( pData
, cChWSFootnoteEdn
); // 430 0x1ae
8242 Set_UInt32( pData
, grfDocEvents
); // 434 0x1b2
8244 pData
+= 4+30+8; // 438 0x1b6; 442 0x1ba; 472 0x1d8; 476 0x1dc
8246 Set_UInt32( pData
, cDBC
); // 480 0x1e0
8247 Set_UInt32( pData
, cDBCFootnoteEdn
); // 484 0x1e4
8249 pData
+= 1 * sizeof( sal_Int32
); // 488 0x1e8
8251 Set_UInt16( pData
, nfcFootnoteRef
); // 492 0x1ec
8252 Set_UInt16( pData
, nfcEdnRef
); // 494 0x1ee
8253 Set_UInt16( pData
, hpsZoomFontPag
); // 496 0x1f0
8254 Set_UInt16( pData
, dywDispPag
); // 498 0x1f2
8256 //500 -> 508, Appear to be repeated here in 2000+
8258 Set_UInt32(pData
, GetCompatibilityOptions());
8259 Set_UInt32(pData
, GetCompatibilityOptions2());
8265 if (fAcetateShowMarkup
)
8267 //Word XP at least requires fAcetateShowMarkup to honour fAcetateShowAtn
8268 if (fAcetateShowAtn
)
8273 Set_UInt16(pData
, a16Bit
);
8277 Set_UInt16(pData
, a16Bit
);
8279 rStrm
.WriteBytes(aData
, nLen
);
8282 void WW8DopTypography::ReadFromMem(sal_uInt8
*&pData
)
8284 sal_uInt16 a16Bit
= Get_UShort(pData
);
8285 m_fKerningPunct
= (a16Bit
& 0x0001);
8286 m_iJustification
= (a16Bit
& 0x0006) >> 1;
8287 m_iLevelOfKinsoku
= (a16Bit
& 0x0018) >> 3;
8288 m_f2on1
= (a16Bit
& 0x0020) >> 5;
8289 m_reserved1
= (a16Bit
& 0x03C0) >> 6;
8290 m_reserved2
= (a16Bit
& 0xFC00) >> 10;
8292 m_cchFollowingPunct
= Get_Short(pData
);
8293 m_cchLeadingPunct
= Get_Short(pData
);
8296 for (i
=0; i
< nMaxFollowing
; ++i
)
8297 m_rgxchFPunct
[i
] = Get_Short(pData
);
8298 for (i
=0; i
< nMaxLeading
; ++i
)
8299 m_rgxchLPunct
[i
] = Get_Short(pData
);
8301 if (m_cchFollowingPunct
>= 0 && m_cchFollowingPunct
< nMaxFollowing
)
8302 m_rgxchFPunct
[m_cchFollowingPunct
]=0;
8304 m_rgxchFPunct
[nMaxFollowing
- 1]=0;
8306 if (m_cchLeadingPunct
>= 0 && m_cchLeadingPunct
< nMaxLeading
)
8307 m_rgxchLPunct
[m_cchLeadingPunct
]=0;
8309 m_rgxchLPunct
[nMaxLeading
- 1]=0;
8313 void WW8DopTypography::WriteToMem(sal_uInt8
*&pData
) const
8315 sal_uInt16 a16Bit
= sal_uInt16(m_fKerningPunct
);
8316 a16Bit
|= (m_iJustification
<< 1) & 0x0006;
8317 a16Bit
|= (m_iLevelOfKinsoku
<< 3) & 0x0018;
8318 a16Bit
|= (int(m_f2on1
) << 5) & 0x0020;
8319 a16Bit
|= (m_reserved1
<< 6) & 0x03C0;
8320 a16Bit
|= (m_reserved2
<< 10) & 0xFC00;
8321 Set_UInt16(pData
,a16Bit
);
8323 Set_UInt16(pData
,m_cchFollowingPunct
);
8324 Set_UInt16(pData
,m_cchLeadingPunct
);
8327 for (i
=0; i
< nMaxFollowing
; ++i
)
8328 Set_UInt16(pData
,m_rgxchFPunct
[i
]);
8329 for (i
=0; i
< nMaxLeading
; ++i
)
8330 Set_UInt16(pData
,m_rgxchLPunct
[i
]);
8333 LanguageType
WW8DopTypography::GetConvertedLang() const
8336 //I have assumed people's republic/taiwan == simplified/traditional
8338 //This isn't a documented issue, so we might have it all wrong,
8339 //i.e. i.e. what's with the powers of two ?
8342 One example of 3 for reserved1 which was really Japanese, perhaps last bit
8343 is for some other use ?, or redundant. If more examples trigger the assert
8344 we might be able to figure it out.
8346 switch(m_reserved1
& 0xE)
8349 nLang
= LANGUAGE_JAPANESE
;
8351 case 4: //Chinese (People's Republic)
8352 nLang
= LANGUAGE_CHINESE_SIMPLIFIED
;
8355 nLang
= LANGUAGE_KOREAN
;
8357 case 8: //Chinese (Taiwan)
8358 nLang
= LANGUAGE_CHINESE_TRADITIONAL
;
8361 OSL_ENSURE(false, "Unknown MS Asian Typography language, report");
8362 nLang
= LANGUAGE_CHINESE_SIMPLIFIED_LEGACY
;
8365 //And here we have the possibility that it says 2, but it's really
8366 //a bug and only japanese level 2 has been selected after a custom
8367 //version was chosen on last save!
8368 nLang
= LANGUAGE_JAPANESE
;
8376 sal_uInt16
wwSprmParser::GetSprmTailLen(sal_uInt16 nId
, const sal_uInt8
* pSprm
, sal_Int32 nRemLen
)
8379 SprmInfo aSprm
= GetSprmInfo(nId
);
8380 sal_uInt16 nL
= 0; // number of Bytes to read
8387 if( pSprm
[1 + mnDelta
] != 255 )
8388 nL
= static_cast< sal_uInt16
>(pSprm
[1 + mnDelta
] + aSprm
.nLen
);
8391 sal_uInt8 nDelIdx
= 2 + mnDelta
;
8392 sal_uInt8 nDel
= nDelIdx
< nRemLen
? pSprm
[nDelIdx
] : 0;
8393 sal_uInt8 nInsIdx
= 3 + mnDelta
+ 4 * nDel
;
8394 sal_uInt8 nIns
= nInsIdx
< nRemLen
? pSprm
[nInsIdx
] : 0;
8396 nL
= 2 + 4 * nDel
+ 3 * nIns
;
8401 sal_uInt8 nIndex
= 1 + mnDelta
;
8402 if (nIndex
+ 1 >= nRemLen
)
8404 SAL_WARN("sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong");
8408 nL
= SVBT16ToUInt16(&pSprm
[nIndex
]);
8412 switch (aSprm
.nVari
)
8415 nL
= aSprm
.nLen
; // Excl. Token
8418 // Variable 1-Byte Length?
8419 // Excl. Token + Var-Lengthbyte
8420 nL
= static_cast< sal_uInt16
>(pSprm
[1 + mnDelta
] + aSprm
.nLen
);
8424 // Variable 2-Byte Length?
8425 // Excl. Token + Var-Lengthbyte
8426 sal_uInt8 nIndex
= 1 + mnDelta
;
8428 if (nIndex
+ 1 >= nRemLen
)
8430 SAL_WARN("sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong");
8434 nCount
= SVBT16ToUInt16(&pSprm
[nIndex
]);
8435 nL
= static_cast< sal_uInt16
>(nCount
+ aSprm
.nLen
- 1);
8439 OSL_ENSURE(false, "Unknown sprm variant");
8447 // one or two bytes at the beginning at the sprm id
8448 sal_uInt16
wwSprmParser::GetSprmId(const sal_uInt8
* pSp
) const
8450 OSL_ENSURE(pSp
, "Why GetSprmId with pSp of 0");
8456 if (ww::IsSevenMinus(meVersion
))
8458 nId
= *pSp
; // [0..0xff]
8462 nId
= SVBT16ToUInt16(pSp
);
8470 // with tokens and length byte
8471 sal_Int32
wwSprmParser::GetSprmSize(sal_uInt16 nId
, const sal_uInt8
* pSprm
, sal_Int32 nRemLen
) const
8473 return GetSprmTailLen(nId
, pSprm
, nRemLen
) + 1 + mnDelta
+ SprmDataOfs(nId
);
8476 sal_uInt8
wwSprmParser::SprmDataOfs(sal_uInt16 nId
) const
8478 return GetSprmInfo(nId
).nVari
;
8481 sal_Int32
wwSprmParser::DistanceToData(sal_uInt16 nId
) const
8483 return 1 + mnDelta
+ SprmDataOfs(nId
);
8486 SprmResult
wwSprmParser::findSprmData(sal_uInt16 nId
, sal_uInt8
* pSprms
,
8487 sal_Int32 nLen
) const
8489 while (nLen
>= MinSprmLen())
8491 const sal_uInt16 nCurrentId
= GetSprmId(pSprms
);
8492 // set pointer to data
8493 sal_Int32 nSize
= GetSprmSize(nCurrentId
, pSprms
, nLen
);
8495 bool bValid
= nSize
<= nLen
;
8497 SAL_WARN_IF(!bValid
, "sw.ww8",
8498 "sprm 0x" << std::hex
<< nCurrentId
<< std::dec
<< " longer than remaining bytes, " <<
8499 nSize
<< " vs " << nLen
<< "doc or parser is wrong");
8501 if (nCurrentId
== nId
&& bValid
) // Sprm found
8503 sal_Int32 nFixedLen
= DistanceToData(nId
);
8504 return SprmResult(pSprms
+ nFixedLen
, nSize
- nFixedLen
);
8507 //Clip to available size if wrong
8508 nSize
= std::min(nSize
, nLen
);
8513 return SprmResult();
8517 bkc(2), fTitlePage(0), fAutoPgn(0), nfcPgn(0), fUnlocked(0), cnsPgn(0),
8518 fPgnRestart(0), fEndNote(1), lnc(0), grpfIhdt(0), nLnnMod(0), dxaLnn(0),
8519 dxaPgn(720), dyaPgn(720), fLBetween(0), vjc(0), dmBinFirst(0),
8520 dmBinOther(0), dmPaperReq(0), fPropRMark(0), ibstPropRMark(0),
8521 dttmPropRMark(0), dxtCharSpace(0), dyaLinePitch(0), clm(0), reserved1(0),
8522 dmOrientPage(0), iHeadingPgn(0), pgnStart(1), lnnMin(0), wTextFlow(0),
8523 reserved2(0), pgbApplyTo(0), pgbPageDepth(0), pgbOffsetFrom(0),
8524 xaPage(lLetterWidth
), yaPage(lLetterHeight
), xaPageNUp(lLetterWidth
), yaPageNUp(lLetterHeight
),
8525 dxaLeft(1800), dxaRight(1800), dyaTop(1440), dyaBottom(1440), dzaGutter(0),
8526 dyaHdrTop(720), dyaHdrBottom(720), ccolM1(0), fEvenlySpaced(1),
8527 reserved3(0), fBiDi(0), fFacingCol(0), fRTLGutter(0), fRTLAlignment(0),
8528 dxaColumns(720), dxaColumnWidth(0), dmOrientFirst(0), fLayout(0),
8533 bool checkRead(SvStream
&rSt
, void *pDest
, sal_uInt32 nLength
)
8535 return (rSt
.ReadBytes(pDest
, nLength
) == static_cast<std::size_t>(nLength
));
8538 #ifdef OSL_BIGENDIAN
8539 void swapEndian(sal_Unicode
*pString
)
8541 for (sal_Unicode
*pWork
= pString
; *pWork
; ++pWork
)
8542 *pWork
= OSL_SWAPWORD(*pWork
);
8546 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */