Bug Summary

File:home/maarten/src/libreoffice/core/include/tools/solar.h
Warning:line 48, column 79
Array access (from variable 'p') results in a null pointer dereference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ww8scan.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/oox/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx

/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <memory>
21#include "ww8scan.hxx"
22#include "ww8par.hxx"
23
24#include <cassert>
25#include <cstddef>
26#include <cstring>
27#include <algorithm>
28
29#include <i18nlangtag/mslangid.hxx>
30#include "sprmids.hxx"
31#include <rtl/tencinfo.h>
32#include <sal/macros.h>
33#include <sal/log.hxx>
34
35#include <swerror.h>
36
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>
42
43#include <vcl/settings.hxx>
44#include <vcl/svapp.hxx>
45
46#ifdef DEBUGSPRMREADER
47#include <stdio.h>
48#endif
49
50using namespace ::com::sun::star::lang;
51
52namespace
53{
54 /**
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.
61 */
62 bool TestBeltAndBraces(SvStream& rStrm)
63 {
64 bool bRet = false;
65 sal_uInt32 nOldPos = rStrm.Tell();
66 sal_uInt16 nBelt(0);
67 rStrm.ReadUInt16( nBelt );
68 nBelt *= sizeof(sal_Unicode);
69 if (rStrm.good() && (rStrm.remainingSize() >= (nBelt + sizeof(sal_Unicode))))
70 {
71 rStrm.SeekRel(nBelt);
72 if (rStrm.good())
73 {
74 sal_Unicode cBraces(0);
75 rStrm.ReadUtf16( cBraces );
76 if (rStrm.good() && cBraces == 0)
77 bRet = true;
78 }
79 }
80 rStrm.Seek(nOldPos);
81 return bRet;
82 }
83}
84
85const wwSprmSearcher *wwSprmParser::GetWW2SprmSearcher()
86{
87 //double lock me
88 // WW2 Sprms
89 static const SprmInfoRow aSprms[] =
90 {
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
230 };
231
232 static wwSprmSearcher aSprmSrch(aSprms, SAL_N_ELEMENTS(aSprms)(sizeof(sal_n_array_size(aSprms))));
233 return &aSprmSrch;
234};
235
236const wwSprmSearcher *wwSprmParser::GetWW6SprmSearcher(const WW8Fib& rFib)
237{
238 //double lock me
239 // WW7- Sprms
240 static const SprmInfoRow aSprms[] =
241 {
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 ?
413 };
414
415 if (rFib.m_wIdent >= 0xa697 && rFib.m_wIdent <= 0xa699)
416 {
417 //see Read_AmbiguousSPRM for this oddity
418 static wwSprmSearcher aSprmSrch(aSprms, SAL_N_ELEMENTS(aSprms)(sizeof(sal_n_array_size(aSprms))), true);
419 return &aSprmSrch;
420 }
421
422 static wwSprmSearcher aSprmSrch(aSprms, SAL_N_ELEMENTS(aSprms)(sizeof(sal_n_array_size(aSprms))));
423 return &aSprmSrch;
424};
425
426void wwSprmSearcher::patchCJKVariant()
427{
428 for (sal_uInt16 nId = 111; nId <= 113; ++nId)
429 {
430 SprmInfo& amb1 = map_[nId];
431 amb1.nLen = 2;
432 amb1.nVari = wwSprmParser::L_FIX;
433 }
434}
435
436template <class Sprm> static constexpr SprmInfoRow InfoRow()
437{
438 return { Sprm::val, { Sprm::len, Sprm::varlen ? wwSprmParser::L_VAR : wwSprmParser::L_FIX } };
439}
440
441const wwSprmSearcher *wwSprmParser::GetWW8SprmSearcher()
442{
443 //double lock me
444 //WW8+ Sprms
445 static const SprmInfoRow aSprms[] =
446 {
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
452 // produced
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;
458 // 0 or 1
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,
465 // pap.rgtbd;complex
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,
476 // pap.rgtbd;complex
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
520 // is < 1 or is > 9
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
526 // the huge grpprl
527 InfoRow<NS_sprm::PHugePapx>(), // fc in the data stream to locate
528 // the huge grpprl
529 InfoRow<NS_sprm::PFUsePgsuSettings>(), // pap.fUsePgsuSettings;
530 // 1 or 0
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
537 // sttbRMark
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
545 // chp.ftcSym
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
551 // ico is not 0)
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
616 // sttbRMark;short;
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
639 // level;byte;
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;
643 // complex
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
683 // right
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
695 // significant);
696 InfoRow<NS_sprm::TDxaLeft>(), // tap.rgdxaCenter
697 InfoRow<NS_sprm::TDxaGapHalf>(), // tap.dxaGapHalf,
698 // tap.rgdxaCenter
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,
704 // tap.rgtc;complex
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
722 // or 10 or 1;word;
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>(),
775 };
776
777 static wwSprmSearcher aSprmSrch(aSprms, SAL_N_ELEMENTS(aSprms)(sizeof(sal_n_array_size(aSprms))));
778 return &aSprmSrch;
779};
780
781wwSprmParser::wwSprmParser(const WW8Fib& rFib) : meVersion(rFib.GetFIBVersion())
782{
783 OSL_ENSURE((meVersion >= ww::eWW1 && meVersion <= ww::eWW8),do { if (true && (!((meVersion >= ww::eWW1 &&
meVersion <= ww::eWW8)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "784" ": "), "%s", "Impossible value for version"); } } while
(false)
784 "Impossible value for version")do { if (true && (!((meVersion >= ww::eWW1 &&
meVersion <= ww::eWW8)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "784" ": "), "%s", "Impossible value for version"); } } while
(false)
;
785
786 mnDelta = (ww::IsSevenMinus(meVersion)) ? 0 : 1;
787
788 if (meVersion <= ww::eWW2)
789 mpKnownSprms = GetWW2SprmSearcher();
790 else if (meVersion < ww::eWW8)
791 mpKnownSprms = GetWW6SprmSearcher(rFib);
792 else
793 mpKnownSprms = GetWW8SprmSearcher();
794}
795
796SprmInfo wwSprmParser::GetSprmInfo(sal_uInt16 nId) const
797{
798 const SprmInfo* pFound = mpKnownSprms->search(nId);
799 if (pFound != nullptr)
800 {
801 return *pFound;
802 }
803
804 OSL_ENSURE(ww::IsEightPlus(meVersion),do { if (true && (!(ww::IsEightPlus(meVersion)))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "805" ": "), "%s", "Unknown ww7- sprm, dangerous, report to development"
); } } while (false)
805 "Unknown ww7- sprm, dangerous, report to development")do { if (true && (!(ww::IsEightPlus(meVersion)))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "805" ": "), "%s", "Unknown ww7- sprm, dangerous, report to development"
); } } while (false)
;
806
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
810 {
811 aSrch.nVari = L_FIX;
812 switch (nId >> 13)
813 {
814 case 0:
815 case 1:
816 aSrch.nLen = 1;
817 break;
818 case 2:
819 aSrch.nLen = 2;
820 break;
821 case 3:
822 aSrch.nLen = 4;
823 break;
824 case 4:
825 case 5:
826 aSrch.nLen = 2;
827 break;
828 case 6:
829 aSrch.nLen = 0;
830 aSrch.nVari = L_VAR;
831 break;
832 case 7:
833 default:
834 aSrch.nLen = 3;
835 break;
836 }
837 }
838 return aSrch;
839}
840
841//-end
842
843static sal_uInt8 Get_Byte( sal_uInt8 *& p )
844{
845 sal_uInt8 n = *p;
846 p += 1;
847 return n;
848}
849
850static sal_uInt16 Get_UShort( sal_uInt8 *& p )
851{
852 const sal_uInt16 n = SVBT16ToUInt16( *reinterpret_cast<SVBT16*>(p) );
853 p += 2;
854 return n;
855}
856
857static sal_Int16 Get_Short( sal_uInt8 *& p )
858{
859 return Get_UShort(p);
860}
861
862static sal_uInt32 Get_ULong( sal_uInt8 *& p )
863{
864 sal_uInt32 n = SVBT32ToUInt32( *reinterpret_cast<SVBT32*>(p) );
865 p += 4;
866 return n;
867}
868
869static sal_Int32 Get_Long( sal_uInt8 *& p )
870{
871 return Get_ULong(p);
872}
873
874WW8SprmIter::WW8SprmIter(const sal_uInt8* pSprms_, sal_Int32 nLen_,
875 const wwSprmParser &rParser)
876 : mrSprmParser(rParser), pSprms( pSprms_), nRemLen( nLen_)
877{
878 UpdateMyMembers();
879}
880
881void WW8SprmIter::SetSprms(const sal_uInt8* pSprms_, sal_Int32 nLen_)
882{
883 pSprms = pSprms_;
884 nRemLen = nLen_;
885 UpdateMyMembers();
886}
887
888void WW8SprmIter::advance()
889{
890 if (nRemLen > 0 )
891 {
892 sal_uInt16 nSize = nCurrentSize;
893 if (nSize > nRemLen)
894 nSize = nRemLen;
895 pSprms += nSize;
896 nRemLen -= nSize;
897 UpdateMyMembers();
898 }
899}
900
901void WW8SprmIter::UpdateMyMembers()
902{
903 bool bValid = (pSprms && nRemLen >= mrSprmParser.MinSprmLen());
904
905 if (bValid)
906 {
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")do { if (true && (!bValid)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "sprm longer than remaining bytes, doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "911" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "sprm longer than remaining bytes, doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm longer than remaining bytes, doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "911" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "sprm longer than remaining bytes, doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "911" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "sprm longer than remaining bytes, doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm longer than remaining bytes, doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "911" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
912 }
913
914 if (!bValid)
915 {
916 nCurrentId = 0;
917 pCurrentParams = nullptr;
918 nCurrentSize = 0;
919 nRemLen = 0;
920 }
921}
922
923SprmResult WW8SprmIter::FindSprm(sal_uInt16 nId, bool bFindFirst, const sal_uInt8* pNextByteMatch)
924{
925 SprmResult aRet;
926
927 while (GetSprms())
928 {
929 if (GetCurrentId() == nId)
930 {
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) )
937 {
938 if ( bFindFirst )
939 return aSprmResult;
940 aRet = aSprmResult;
941 }
942 }
943 advance();
944 }
945
946 return aRet;
947}
948
949// temporary test
950// WW8PLCFx_PCDAttrs cling to WW8PLCF_Pcd and therefore do not have their own iterators.
951// All methods relating to iterators are therefore dummies.
952WW8PLCFx_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)
956{
957}
958
959sal_uInt32 WW8PLCFx_PCDAttrs::GetIdx() const
960{
961 return 0;
962}
963
964void WW8PLCFx_PCDAttrs::SetIdx(sal_uInt32)
965{
966}
967
968bool WW8PLCFx_PCDAttrs::SeekPos(WW8_CP )
969{
970 return true;
971}
972
973void WW8PLCFx_PCDAttrs::advance()
974{
975}
976
977WW8_CP WW8PLCFx_PCDAttrs::Where()
978{
979 return pPcd ? pPcd->Where() : WW8_CP_MAX;
980}
981
982void WW8PLCFx_PCDAttrs::GetSprms(WW8PLCFxDesc* p)
983{
984 void* pData;
985
986 p->bRealLineEnd = false;
987 if ( !pPcdI || !pPcdI->Get(p->nStartPos, p->nEndPos, pData) )
988 {
989 // PLCF fully processed
990 p->nStartPos = p->nEndPos = WW8_CP_MAX;
991 p->pMemPos = nullptr;
992 p->nSprmsLen = 0;
993 return;
994 }
995
996 const sal_uInt16 nPrm = SVBT16ToUInt16( static_cast<WW8_PCD*>(pData)->prm );
997 if ( nPrm & 1 )
998 {
999 // PRM Variant 2
1000 const sal_uInt16 nSprmIdx = nPrm >> 1;
1001
1002 if( nSprmIdx >= mrGrpprls.size() )
1003 {
1004 // Invalid Index
1005 p->nStartPos = p->nEndPos = WW8_CP_MAX;
1006 p->pMemPos = nullptr;
1007 p->nSprmsLen = 0;
1008 return;
1009 }
1010 const sal_uInt8* pSprms = mrGrpprls[ nSprmIdx ].get();
1011
1012 p->nSprmsLen = SVBT16ToUInt16( pSprms ); // Length
1013 pSprms += 2;
1014 p->pMemPos = pSprms; // Position
1015 }
1016 else
1017 {
1018 // SPRM is stored directly into members var
1019 /*
1020 These are the attr that are in the piece-table instead of in the text!
1021 */
1022
1023 if (IsSevenMinus(GetFIBVersion()))
1024 {
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
1028
1029 // store Position of internal mini storage in Data Pointer
1030 p->pMemPos = aShortSprm;
1031 }
1032 else
1033 {
1034 p->pMemPos = nullptr;
1035 p->nSprmsLen = 0;
1036 sal_uInt8 nSprmListIdx = static_cast<sal_uInt8>((nPrm & 0xfe) >> 1);
1037 if( nSprmListIdx )
1038 {
1039 // process Sprm Id Matching as explained in MS Documentation
1040
1041 // ''Property Modifier(variant 1) (PRM)''
1042 // see file: s62f39.htm
1043
1044 // Since Sprm is 7 bits, rgsprmPrm can hold 0x80 entries.
1045 static const sal_uInt16 aSprmId[0x80] =
1046 {
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,
1052 // sprmPBrcp
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
1114 };
1115
1116 // find real Sprm Id:
1117 const sal_uInt16 nSprmId = aSprmId[ nSprmListIdx ];
1118
1119 if( nSprmId )
1120 {
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 );
1125
1126 // store Sprm Length in member:
1127 p->nSprmsLen = nPrm ? 3 : 0;
1128
1129 // store Position of internal mini storage in Data Pointer
1130 p->pMemPos = aShortSprm;
1131 }
1132 }
1133 }
1134 }
1135}
1136
1137WW8PLCFx_PCD::WW8PLCFx_PCD(const WW8Fib& rFib, WW8PLCFpcd* pPLCFpcd,
1138 WW8_CP nStartCp, bool bVer67P)
1139 : WW8PLCFx(rFib, false), nClipStart(-1)
1140{
1141 // construct own iterator
1142 pPcdI.reset( new WW8PLCFpcd_Iter(*pPLCFpcd, nStartCp) );
1143 bVer67= bVer67P;
1144}
1145
1146WW8PLCFx_PCD::~WW8PLCFx_PCD()
1147{
1148}
1149
1150sal_uInt32 WW8PLCFx_PCD::GetIMax() const
1151{
1152 return pPcdI ? pPcdI->GetIMax() : 0;
1153}
1154
1155sal_uInt32 WW8PLCFx_PCD::GetIdx() const
1156{
1157 return pPcdI ? pPcdI->GetIdx() : 0;
1158}
1159
1160void WW8PLCFx_PCD::SetIdx(sal_uInt32 nIdx)
1161{
1162 if (pPcdI)
1163 pPcdI->SetIdx( nIdx );
1164}
1165
1166bool WW8PLCFx_PCD::SeekPos(WW8_CP nCpPos)
1167{
1168 return pPcdI && pPcdI->SeekPos( nCpPos );
1169}
1170
1171WW8_CP WW8PLCFx_PCD::Where()
1172{
1173 return pPcdI ? pPcdI->Where() : WW8_CP_MAX;
1174}
1175
1176long WW8PLCFx_PCD::GetNoSprms( WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen )
1177{
1178 void* pData;
1179 rLen = 0;
1180
1181 if ( !pPcdI || !pPcdI->Get(rStart, rEnd, pData) )
1182 {
1183 rStart = rEnd = WW8_CP_MAX;
1184 return -1;
1185 }
1186 return pPcdI->GetIdx();
1187}
1188
1189void WW8PLCFx_PCD::advance()
1190{
1191 OSL_ENSURE(pPcdI , "missing pPcdI")do { if (true && (!(pPcdI))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1191" ": "), "%s", "missing pPcdI"); } } while (false)
;
1192 if (pPcdI)
1193 pPcdI->advance();
1194}
1195
1196WW8_FC WW8PLCFx_PCD::CurrentPieceStartCp2Fc( WW8_CP nCp )
1197{
1198 WW8_CP nCpStart, nCpEnd;
1199 void* pData;
1200
1201 if ( !pPcdI->Get(nCpStart, nCpEnd, pData) )
1202 {
1203 OSL_ENSURE( false, "CurrentPieceStartCp2Fc() with false Cp found (1)" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1203" ": "), "%s", "CurrentPieceStartCp2Fc() with false Cp found (1)"
); } } while (false)
;
1204 return WW8_FC_MAX;
1205 }
1206
1207 OSL_ENSURE( nCp >= nCpStart && nCp < nCpEnd,do { if (true && (!(nCp >= nCpStart && nCp
< nCpEnd))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1208" ": "), "%s", "AktPieceCp2Fc() with false Cp found (2)"
); } } while (false)
1208 "AktPieceCp2Fc() with false Cp found (2)" )do { if (true && (!(nCp >= nCpStart && nCp
< nCpEnd))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1208" ": "), "%s", "AktPieceCp2Fc() with false Cp found (2)"
); } } while (false)
;
1209
1210 if( nCp < nCpStart )
1211 nCp = nCpStart;
1212 if( nCp >= nCpEnd )
1213 nCp = nCpEnd - 1;
1214
1215 bool bIsUnicode = false;
1216 WW8_FC nFC = SVBT32ToUInt32( static_cast<WW8_PCD*>(pData)->fc );
1217 if( !bVer67 )
1218 nFC = WW8PLCFx_PCD::TransformPieceAddress( nFC, bIsUnicode );
1219
1220 WW8_CP nDistance;
1221 bool bFail = o3tl::checked_sub(nCp, nCpStart, nDistance);
1222 if (bFail)
1223 {
1224 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1224" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1224" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1224" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1224" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1225 return WW8_FC_MAX;
1226 }
1227
1228 if (bIsUnicode)
1229 {
1230 bFail = o3tl::checked_multiply<WW8_CP>(nDistance, 2, nDistance);
1231 if (bFail)
1232 {
1233 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1233" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1233" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1233" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1233" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1234 return WW8_FC_MAX;
1235 }
1236 }
1237
1238 WW8_FC nRet;
1239 bFail = o3tl::checked_add(nFC, nDistance, nRet);
1240 if (bFail)
1241 {
1242 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1242" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1242" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1242" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1242" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1243 return WW8_FC_MAX;
1244 }
1245
1246 return nRet;
1247}
1248
1249void WW8PLCFx_PCD::CurrentPieceFc2Cp( WW8_CP& rStartPos, WW8_CP& rEndPos,
1250 const WW8ScannerBase *pSBase )
1251{
1252 //No point going anywhere with this
1253 if ((rStartPos == WW8_CP_MAX) && (rEndPos == WW8_CP_MAX))
1254 return;
1255
1256 rStartPos = pSBase->WW8Fc2Cp( rStartPos );
1257 rEndPos = pSBase->WW8Fc2Cp( rEndPos );
1258}
1259
1260WW8_CP WW8PLCFx_PCD::CurrentPieceStartFc2Cp( WW8_FC nStartPos )
1261{
1262 WW8_CP nCpStart, nCpEnd;
1263 void* pData;
1264 if ( !pPcdI->Get( nCpStart, nCpEnd, pData ) )
1265 {
1266 OSL_ENSURE( false, "CurrentPieceStartFc2Cp() - error" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1266" ": "), "%s", "CurrentPieceStartFc2Cp() - error");
} } while (false)
;
1267 return WW8_CP_MAX;
1268 }
1269 bool bIsUnicode = false;
1270 sal_Int32 nFcStart = SVBT32ToUInt32( static_cast<WW8_PCD*>(pData)->fc );
1271 if( !bVer67 )
1272 nFcStart = WW8PLCFx_PCD::TransformPieceAddress( nFcStart, bIsUnicode );
1273
1274 sal_Int32 nUnicodeFactor = bIsUnicode ? 2 : 1;
1275
1276 if( nStartPos < nFcStart )
1277 nStartPos = nFcStart;
1278
1279 WW8_CP nCpLen;
1280 bool bFail = o3tl::checked_sub(nCpEnd, nCpStart, nCpLen);
1281 if (bFail)
1282 {
1283 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1283" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1283" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1283" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1283" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1284 return WW8_CP_MAX;
1285 }
1286
1287 WW8_CP nCpLenBytes;
1288 bFail = o3tl::checked_multiply(nCpLen, nUnicodeFactor, nCpLenBytes);
1289 if (bFail)
1290 {
1291 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1291" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1291" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1291" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1291" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1292 return WW8_CP_MAX;
1293 }
1294
1295 WW8_FC nFcLen;
1296 bFail = o3tl::checked_add(nFcStart, nCpLenBytes, nFcLen);
1297 if (bFail)
1298 {
1299 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1299" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1299" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1299" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1299" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1300 return WW8_CP_MAX;
1301 }
1302
1303 WW8_FC nFcEnd;
1304 bFail = o3tl::checked_add(nFcStart, nFcLen, nFcEnd);
1305 if (bFail)
1306 {
1307 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1307" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1307" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1307" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1307" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1308 return WW8_CP_MAX;
1309 }
1310
1311
1312 if (nStartPos >= nFcEnd)
1313 nStartPos = nFcEnd - (1 * nUnicodeFactor);
1314
1315 WW8_FC nFcDiff = (nStartPos - nFcStart) / nUnicodeFactor;
1316
1317 WW8_FC nCpRet;
1318 bFail = o3tl::checked_add(nCpStart, nFcDiff, nCpRet);
1319 if (bFail)
1320 {
1321 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1321" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1321" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1321" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1321" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1322 return WW8_CP_MAX;
1323 }
1324
1325 return nCpRet;
1326}
1327
1328// Helper routines for all
1329
1330// Convert BRC from WW6 to WW8 format
1331WW8_BRC::WW8_BRC(const WW8_BRCVer6& brcVer6)
1332{
1333 sal_uInt8 _dptLineWidth = brcVer6.dxpLineWidth(),
1334 _brcType = brcVer6.brcType();
1335
1336 if (_dptLineWidth > 5) // this signifies dashed(6) or dotted(7) line
1337 {
1338 _brcType = _dptLineWidth;
1339 _dptLineWidth = 1;
1340 }
1341 _dptLineWidth *= 6; // convert units from 0.75pt to 1/8pt
1342
1343 *this = WW8_BRC(_dptLineWidth, _brcType, brcVer6.ico(), brcVer6.dxpSpace(),
1344 brcVer6.fShadow(), false);
1345}
1346
1347// Convert BRC from WW8 to WW9 format
1348WW8_BRCVer9::WW8_BRCVer9(const WW8_BRC& brcVer8)
1349{
1350 if (brcVer8.isNil()) {
1351 UInt32ToSVBT32(0, aBits1);
1352 UInt32ToSVBT32(0xffffffff, aBits2);
1353 }
1354 else
1355 {
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());
1360 }
1361}
1362
1363short WW8_BRC::DetermineBorderProperties(short *pSpace) const
1364{
1365 WW8_BRCVer9 brcVer9(*this);
1366 return brcVer9.DetermineBorderProperties(pSpace);
1367}
1368
1369short WW8_BRCVer9::DetermineBorderProperties(short *pSpace) const
1370{
1371 /*
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
1375 our calculations
1376 */
1377 short nMSTotalWidth;
1378
1379 //Specification in 8ths of a point, 1 Point = 20 Twips, so by 2.5
1380 nMSTotalWidth = static_cast<short>(dptLineWidth()) * 20 / 8;
1381
1382 //Figure out the real size of the border according to word
1383 switch (brcType())
1384 {
1385 //Note that codes over 25 are undocumented, and I can't create
1386 //these 4 here in the wild.
1387 case 2:
1388 case 4:
1389 case 5:
1390 case 22:
1391 OSL_FAIL("Can't create these from the menus, please report")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1391" ": "), "%s", "Can't create these from the menus, please report"
); } } while (false)
;
1392 break;
1393 default:
1394 case 23: //Only 3pt in the menus, but honours the size setting.
1395 break;
1396 case 10:
1397 /*
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.
1404 */
1405 if (nMSTotalWidth == 5)
1406 nMSTotalWidth*=3;
1407 else if (nMSTotalWidth == 10)
1408 nMSTotalWidth = nMSTotalWidth*9/2;
1409 else
1410 nMSTotalWidth*=5;
1411 break;
1412 case 20:
1413 /*
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.
1418 */
1419 nMSTotalWidth +=45;
1420 break;
1421 case 21:
1422 /*
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.
1427 */
1428 nMSTotalWidth += 45*2;
1429 break;
1430 }
1431
1432 if (pSpace)
1433 *pSpace = static_cast<short>(dptSpace()) * 20; // convert from points to twips
1434 return nMSTotalWidth;
1435}
1436
1437/*
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
1441 * possible
1442 */
1443WW8_CP WW8ScannerBase::WW8Fc2Cp( WW8_FC nFcPos ) const
1444{
1445 WW8_CP nFallBackCpEnd = WW8_CP_MAX;
1446 if( nFcPos == WW8_FC_MAX )
1447 return nFallBackCpEnd;
1448
1449 bool bIsUnicode;
1450 if (m_pWw8Fib->m_nVersion >= 8)
1451 bIsUnicode = false;
1452 else
1453 bIsUnicode = m_pWw8Fib->m_fExtChar;
1454
1455 if( m_pPieceIter ) // Complex File ?
1456 {
1457 sal_uInt32 nOldPos = m_pPieceIter->GetIdx();
1458
1459 for (m_pPieceIter->SetIdx(0);
1460 m_pPieceIter->GetIdx() < m_pPieceIter->GetIMax(); m_pPieceIter->advance())
1461 {
1462 WW8_CP nCpStart, nCpEnd;
1463 void* pData;
1464 if( !m_pPieceIter->Get( nCpStart, nCpEnd, pData ) )
1465 { // outside PLCFfpcd ?
1466 OSL_ENSURE( false, "PLCFpcd-WW8Fc2Cp() went wrong" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1466" ": "), "%s", "PLCFpcd-WW8Fc2Cp() went wrong"); } }
while (false)
;
1467 break;
1468 }
1469 sal_Int32 nFcStart = SVBT32ToUInt32( static_cast<WW8_PCD*>(pData)->fc );
1470 if (m_pWw8Fib->m_nVersion >= 8)
1471 {
1472 nFcStart = WW8PLCFx_PCD::TransformPieceAddress( nFcStart,
1473 bIsUnicode );
1474 }
1475 else
1476 {
1477 bIsUnicode = m_pWw8Fib->m_fExtChar;
1478 }
1479
1480 sal_Int32 nLen;
1481 if (o3tl::checked_sub(nCpEnd, nCpStart, nLen))
1482 {
1483 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1483" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1483" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1483" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1483" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1484 return WW8_CP_MAX;
1485 }
1486 if (bIsUnicode)
1487 {
1488 if (o3tl::checked_multiply<WW8_CP>(nLen, 2, nLen))
1489 {
1490 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1490" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1490" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1490" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1490" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1491 return WW8_CP_MAX;
1492 }
1493 }
1494
1495 /*
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
1498 */
1499 if (nFcPos >= nFcStart)
1500 {
1501 // found
1502 WW8_FC nFcDiff;
1503 if (o3tl::checked_sub(nFcPos, nFcStart, nFcDiff))
1504 {
1505 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1505" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1505" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1505" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1505" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1506 return WW8_CP_MAX;
1507 }
1508 if (bIsUnicode)
1509 nFcDiff /= 2;
1510 WW8_CP nTempCp;
1511 if (o3tl::checked_add(nCpStart, nFcDiff, nTempCp))
1512 {
1513 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1513" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1513" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1513" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1513" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1514 return WW8_CP_MAX;
1515 }
1516 WW8_FC nFcEnd;
1517 if (o3tl::checked_add(nFcStart, nLen, nFcEnd))
1518 {
1519 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1519" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1519" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1519" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1519" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1520 return WW8_CP_MAX;
1521 }
1522 if (nFcPos < nFcEnd)
1523 {
1524 m_pPieceIter->SetIdx( nOldPos );
1525 return nTempCp;
1526 }
1527 else if (nFcPos == nFcEnd)
1528 {
1529 //Keep this cp as its on a piece boundary because we might
1530 //need it if tests fail
1531 nFallBackCpEnd = nTempCp;
1532 }
1533 }
1534 }
1535 // not found
1536 m_pPieceIter->SetIdx( nOldPos ); // not found
1537 /*
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.
1541 */
1542 return nFallBackCpEnd;
1543 }
1544
1545 WW8_FC nFcDiff;
1546 if (o3tl::checked_sub(nFcPos, m_pWw8Fib->m_fcMin, nFcDiff))
1547 {
1548 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1548" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1548" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1548" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1548" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1549 return WW8_CP_MAX;
1550 }
1551
1552 // No complex file
1553 if (!bIsUnicode)
1554 nFallBackCpEnd = nFcDiff;
1555 else
1556 nFallBackCpEnd = (nFcDiff + 1) / 2;
1557
1558 return nFallBackCpEnd;
1559}
1560
1561// the fib of WinWord2 has a last entry of cpnBtePap of 2 byte sized type PN at
1562// offset 324
1563const int nSmallestPossibleFib = 326;
1564
1565WW8_FC WW8ScannerBase::WW8Cp2Fc(WW8_CP nCpPos, bool* pIsUnicode,
1566 WW8_CP* pNextPieceCp, bool* pTestFlag) const
1567{
1568 if( pTestFlag )
1569 *pTestFlag = true;
1570 if( WW8_CP_MAX == nCpPos )
1571 return WW8_CP_MAX;
1572
1573 bool bIsUnicode;
1574 if( !pIsUnicode )
1575 pIsUnicode = &bIsUnicode;
1576
1577 if (m_pWw8Fib->m_nVersion >= 8)
1578 *pIsUnicode = false;
1579 else
1580 *pIsUnicode = m_pWw8Fib->m_fExtChar;
1581
1582 WW8_FC nRet;
1583
1584 if( m_pPieceIter )
1585 {
1586 // Complex File
1587 if( pNextPieceCp )
1588 *pNextPieceCp = WW8_CP_MAX;
1589
1590 if( !m_pPieceIter->SeekPos( nCpPos ) )
1591 {
1592 if( pTestFlag )
1593 *pTestFlag = false;
1594 else {
1595 OSL_ENSURE( false, "Handed over wrong CP to WW8Cp2Fc()" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1595" ": "), "%s", "Handed over wrong CP to WW8Cp2Fc()"
); } } while (false)
;
1596 }
1597 return WW8_FC_MAX;
1598 }
1599 WW8_CP nCpStart, nCpEnd;
1600 void* pData;
1601 if( !m_pPieceIter->Get( nCpStart, nCpEnd, pData ) )
1602 {
1603 if( pTestFlag )
1604 *pTestFlag = false;
1605 else {
1606 OSL_ENSURE( false, "PLCFfpcd-Get went wrong" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1606" ": "), "%s", "PLCFfpcd-Get went wrong"); } } while
(false)
;
1607 }
1608 return WW8_FC_MAX;
1609 }
1610 if( pNextPieceCp )
1611 *pNextPieceCp = nCpEnd;
1612
1613 nRet = SVBT32ToUInt32( static_cast<WW8_PCD*>(pData)->fc );
1614 if (m_pWw8Fib->m_nVersion >= 8)
1615 nRet = WW8PLCFx_PCD::TransformPieceAddress( nRet, *pIsUnicode );
1616 else
1617 *pIsUnicode = m_pWw8Fib->m_fExtChar;
1618
1619 WW8_CP nCpLen;
1620 bool bFail = o3tl::checked_sub(nCpPos, nCpStart, nCpLen);
1621 if (bFail)
1622 {
1623 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1623" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1623" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1623" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1623" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1624 return WW8_CP_MAX;
1625 }
1626
1627 if (*pIsUnicode)
1628 {
1629 bFail = o3tl::checked_multiply<WW8_CP>(nCpLen, 2, nCpLen);
1630 if (bFail)
1631 {
1632 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1632" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1632" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1632" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1632" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1633 return WW8_CP_MAX;
1634 }
1635 }
1636
1637 bFail = o3tl::checked_add(nRet, nCpLen, nRet);
1638 if (bFail)
1639 {
1640 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1640" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1640" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1640" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1640" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1641 return WW8_CP_MAX;
1642 }
1643
1644 return nRet;
1645 }
1646
1647 if (*pIsUnicode)
1648 {
1649 const bool bFail = o3tl::checked_multiply<WW8_CP>(nCpPos, 2, nCpPos);
1650 if (bFail)
1651 {
1652 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1652" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1652" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1652" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1652" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1653 return WW8_CP_MAX;
1654 }
1655 }
1656
1657 // No complex file
1658 const bool bFail = o3tl::checked_add(m_pWw8Fib->m_fcMin, nCpPos, nRet);
1659 if (bFail)
1660 {
1661 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1661" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1661" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1661" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1661" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1662 return WW8_CP_MAX;
1663 }
1664
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)
1669 {
1670 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1670" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1670" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1670" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1670" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1671 return WW8_CP_MAX;
1672 }
1673
1674 return nRet;
1675}
1676
1677std::unique_ptr<WW8PLCFpcd> WW8ScannerBase::OpenPieceTable( SvStream* pStr, const WW8Fib* pWwF )
1678{
1679 if ( ((8 > m_pWw8Fib->m_nVersion) && !pWwF->m_fComplex) || !pWwF->m_lcbClx )
1680 return nullptr;
1681
1682 if (pWwF->m_lcbClx < 0)
1683 return nullptr;
1684
1685 WW8_FC nClxPos = pWwF->m_fcClx;
1686
1687 if (!checkSeek(*pStr, nClxPos))
1688 return nullptr;
1689
1690 sal_Int32 nClxLen = pWwF->m_lcbClx;
1691 sal_Int32 nLeft = nClxLen;
1692
1693 while (true)
1694 {
1695 sal_uInt8 clxt(2);
1696 pStr->ReadUChar( clxt );
1697 nLeft--;
1698 if( 2 == clxt) // PLCFfpcd ?
1699 break; // PLCFfpcd found
1700 sal_uInt16 nLen(0);
1701 pStr->ReadUInt16( nLen );
1702 nLeft -= 2 + nLen;
1703 if( nLeft < 0 )
1704 return nullptr; // gone wrong
1705 if( 1 == clxt ) // clxtGrpprl ?
1706 {
1707 if (m_aPieceGrpprls.size() == SHRT_MAX32767)
1708 return nullptr;
1709 if (nLen > pStr->remainingSize())
1710 return nullptr;
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
1714 {
1715 return nullptr;
1716 }
1717 m_aPieceGrpprls.push_back(std::move(p)); // add to array
1718 }
1719 else
1720 {
1721 nLen = std::min<sal_uInt64>(nLen, pStr->remainingSize());
1722 pStr->Seek(pStr->Tell() + nLen); // non-Grpprl left
1723 }
1724 }
1725
1726 // read Piece Table PLCF
1727 sal_Int32 nPLCFfLen(0);
1728 if (pWwF->GetFIBVersion() <= ww::eWW2)
1729 {
1730 sal_Int16 nWordTwoLen(0);
1731 pStr->ReadInt16( nWordTwoLen );
1732 nPLCFfLen = nWordTwoLen;
1733 }
1734 else
1735 pStr->ReadInt32( nPLCFfLen );
1736 OSL_ENSURE( 65536 > nPLCFfLen, "PLCFfpcd above 64 k" )do { if (true && (!(65536 > nPLCFfLen))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1736" ": "), "%s", "PLCFfpcd above 64 k"); } } while (false
)
;
1737 return std::make_unique<WW8PLCFpcd>( pStr, pStr->Tell(), nPLCFfLen, 8 );
1738}
1739
1740WW8ScannerBase::WW8ScannerBase( SvStream* pSt, SvStream* pTableSt,
1741 SvStream* pDataSt, WW8Fib* pWwFib )
1742 : m_pWw8Fib(pWwFib)
1743{
1744 m_pPiecePLCF = OpenPieceTable( pTableSt, m_pWw8Fib ); // Complex
1745 if( m_pPiecePLCF )
1746 {
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));
1752 }
1753 else
1754 {
1755 m_pPieceIter = nullptr;
1756 m_pPLCFx_PCD = nullptr;
1757 m_pPLCFx_PCDAttrs = nullptr;
1758 }
1759
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
1763
1764 m_pSepPLCF.reset(new WW8PLCFx_SEPX( pSt, pTableSt, *pWwFib, 0 )); // SEPX
1765
1766 // Footnotes
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 ));
1770 // Endnotes
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 ));
1774 // Comments
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));
1778
1779 // Fields Main Text
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));
1783 // Fields Footnote
1784 m_pFieldFootnotePLCF.reset(new WW8PLCFx_FLD(pTableSt, *pWwFib, MAN_FTN));
1785 // Fields Endnote
1786 m_pFieldEdnPLCF.reset(new WW8PLCFx_FLD(pTableSt, *pWwFib, MAN_EDN));
1787 // Fields Comments
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));
1793
1794 // Note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
1795 switch( m_pWw8Fib->m_nVersion )
1796 {
1797 case 6:
1798 case 7:
1799 if( pWwFib->m_fcPlcfdoaMom && pWwFib->m_lcbPlcfdoaMom )
1800 {
1801 m_pMainFdoa.reset(new WW8PLCFspecial( pTableSt, pWwFib->m_fcPlcfdoaMom,
1802 pWwFib->m_lcbPlcfdoaMom, 6 ));
1803 }
1804 if( pWwFib->m_fcPlcfdoaHdr && pWwFib->m_lcbPlcfdoaHdr )
1805 {
1806 m_pHdFtFdoa.reset(new WW8PLCFspecial( pTableSt, pWwFib->m_fcPlcfdoaHdr,
1807 pWwFib->m_lcbPlcfdoaHdr, 6 ));
1808 }
1809 break;
1810 case 8:
1811 if( pWwFib->m_fcPlcfspaMom && pWwFib->m_lcbPlcfspaMom )
1812 {
1813 m_pMainFdoa.reset(new WW8PLCFspecial( pTableSt, pWwFib->m_fcPlcfspaMom,
1814 pWwFib->m_lcbPlcfspaMom, 26 ));
1815 }
1816 if( pWwFib->m_fcPlcfspaHdr && pWwFib->m_lcbPlcfspaHdr )
1817 {
1818 m_pHdFtFdoa.reset(new WW8PLCFspecial( pTableSt, pWwFib->m_fcPlcfspaHdr,
1819 pWwFib->m_lcbPlcfspaHdr, 26 ));
1820 }
1821 // PLCF for TextBox break-descriptors in the main text
1822 if( pWwFib->m_fcPlcftxbxBkd && pWwFib->m_lcbPlcftxbxBkd )
1823 {
1824 m_pMainTxbxBkd.reset(new WW8PLCFspecial( pTableSt,
1825 pWwFib->m_fcPlcftxbxBkd, pWwFib->m_lcbPlcftxbxBkd, 0));
1826 }
1827 // PLCF for TextBox break-descriptors in Header/Footer range
1828 if( pWwFib->m_fcPlcfHdrtxbxBkd && pWwFib->m_lcbPlcfHdrtxbxBkd )
1829 {
1830 m_pHdFtTxbxBkd.reset(new WW8PLCFspecial( pTableSt,
1831 pWwFib->m_fcPlcfHdrtxbxBkd, pWwFib->m_lcbPlcfHdrtxbxBkd, 0));
1832 }
1833 // Sub table cp positions
1834 if (pWwFib->m_fcPlcfTch && pWwFib->m_lcbPlcfTch)
1835 {
1836 m_pMagicTables.reset(new WW8PLCFspecial( pTableSt,
1837 pWwFib->m_fcPlcfTch, pWwFib->m_lcbPlcfTch, 4));
1838 }
1839 // Sub document cp positions
1840 if (pWwFib->m_fcPlcfwkb && pWwFib->m_lcbPlcfwkb)
1841 {
1842 m_pSubdocs.reset(new WW8PLCFspecial( pTableSt,
1843 pWwFib->m_fcPlcfwkb, pWwFib->m_lcbPlcfwkb, 12));
1844 }
1845 // Extended ATRD
1846 if (pWwFib->m_fcAtrdExtra && pWwFib->m_lcbAtrdExtra)
1847 {
1848 sal_uInt64 const nOldPos = pTableSt->Tell();
1849 if (checkSeek(*pTableSt, pWwFib->m_fcAtrdExtra) && (pTableSt->remainingSize() >= pWwFib->m_lcbAtrdExtra))
1850 {
1851 m_pExtendedAtrds.reset( new sal_uInt8[pWwFib->m_lcbAtrdExtra] );
1852 pWwFib->m_lcbAtrdExtra = pTableSt->ReadBytes(m_pExtendedAtrds.get(), pWwFib->m_lcbAtrdExtra);
1853 }
1854 else
1855 pWwFib->m_lcbAtrdExtra = 0;
1856 pTableSt->Seek(nOldPos);
1857 }
1858
1859 break;
1860 default:
1861 OSL_ENSURE( false, "nVersion not implemented!" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "1861" ": "), "%s", "nVersion not implemented!"); } } while
(false)
;
1862 break;
1863 }
1864
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 )
1868 {
1869 m_pMainTxbx.reset(new WW8PLCFspecial( pTableSt, pWwFib->m_fcPlcftxbxText,
1870 pWwFib->m_lcbPlcftxbxText, nLenTxBxS ));
1871 }
1872
1873 // PLCF for TextBox stories in Header/Footer range
1874 if( pWwFib->m_fcPlcfHdrtxbxText && pWwFib->m_lcbPlcfHdrtxbxText )
1875 {
1876 m_pHdFtTxbx.reset(new WW8PLCFspecial( pTableSt, pWwFib->m_fcPlcfHdrtxbxText,
1877 pWwFib->m_lcbPlcfHdrtxbxText, nLenTxBxS ));
1878 }
1879
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));
1883}
1884
1885WW8ScannerBase::~WW8ScannerBase()
1886{
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();
1893 m_pAtnBook.reset();
1894 m_pBook.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();
1902 m_pEdnPLCF.reset();
1903 m_pFootnotePLCF.reset();
1904 m_pAndPLCF.reset();
1905 m_pSepPLCF.reset();
1906 m_pPapPLCF.reset();
1907 m_pChpPLCF.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();
1915 m_pSubdocs.reset();
1916}
1917
1918// Fields
1919
1920static bool WW8SkipField(WW8PLCFspecial& rPLCF)
1921{
1922 void* pData;
1923 WW8_CP nP;
1924
1925 if (!rPLCF.Get(nP, pData)) // End of PLCFspecial?
1926 return false;
1927
1928 rPLCF.advance();
1929
1930 if((static_cast<sal_uInt8*>(pData)[0] & 0x1f ) != 0x13 ) // No beginning?
1931 return true; // Do not terminate on error
1932
1933 if( !rPLCF.Get( nP, pData ) )
1934 return false;
1935
1936 while((static_cast<sal_uInt8*>(pData)[0] & 0x1f ) == 0x13 )
1937 {
1938 // still new (nested) beginnings ?
1939 WW8SkipField( rPLCF ); // nested Field in description
1940 if( !rPLCF.Get( nP, pData ) )
1941 return false;
1942 }
1943
1944 if((static_cast<sal_uInt8*>(pData)[0] & 0x1f ) == 0x14 )
1945 {
1946
1947 // Field Separator ?
1948 rPLCF.advance();
1949
1950 if( !rPLCF.Get( nP, pData ) )
1951 return false;
1952
1953 while ((static_cast<sal_uInt8*>(pData)[0] & 0x1f ) == 0x13)
1954 {
1955 // still new (nested) beginnings?
1956 WW8SkipField( rPLCF ); // nested Field in Results
1957 if( !rPLCF.Get( nP, pData ) )
1958 return false;
1959 }
1960 }
1961 rPLCF.advance();
1962
1963 return true;
1964}
1965
1966static bool WW8GetFieldPara(WW8PLCFspecial& rPLCF, WW8FieldDesc& rF)
1967{
1968 void* pData;
1969 sal_uInt32 nOldIdx = rPLCF.GetIdx();
1970
1971 rF.nLen = rF.nId = rF.nOpt = 0;
1972 rF.bCodeNest = rF.bResNest = false;
1973
1974 if (!rPLCF.Get(rF.nSCode, pData) || rF.nSCode < 0) // end of PLCFspecial?
1975 goto Err;
1976
1977 rPLCF.advance();
1978
1979 if (!pData || (static_cast<sal_uInt8*>(pData)[0] & 0x1f) != 0x13) // No beginning?
1980 goto Err;
1981
1982 rF.nId = static_cast<sal_uInt8*>(pData)[1];
1983
1984 if( !rPLCF.Get( rF.nLCode, pData ) )
1985 goto Err;
1986
1987 if (rF.nLCode < rF.nSCode)
1988 goto Err;
1989
1990 rF.nSRes = rF.nLCode; // Default
1991 rF.nSCode++; // without markers
1992 rF.nLCode -= rF.nSCode; // Pos -> length
1993
1994 while((static_cast<sal_uInt8*>(pData)[0] & 0x1f ) == 0x13 )
1995 {
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)
2000 goto Err;
2001 }
2002
2003 if ((static_cast<sal_uInt8*>(pData)[0] & 0x1f ) == 0x14 ) // Field Separator?
2004 {
2005 rPLCF.advance();
2006
2007 if (!rPLCF.Get(rF.nLRes, pData) || rF.nLRes < 0)
2008 goto Err;
2009
2010 while((static_cast<sal_uInt8*>(pData)[0] & 0x1f ) == 0x13 )
2011 {
2012 // still new (nested) beginnings ?
2013 WW8SkipField( rPLCF ); // nested Field in results
2014 rF.bResNest = true;
2015 if (!rPLCF.Get(rF.nLRes, pData) || rF.nLRes < 0)
2016 goto Err;
2017 }
2018 WW8_CP nTmp;
2019 if (o3tl::checked_sub<WW8_CP>(rF.nLRes, rF.nSCode, nTmp))
2020 {
2021 rF.nLen = 0;
2022 goto Err;
2023 }
2024 if (o3tl::checked_add<WW8_CP>(nTmp, 2, rF.nLen)) // nLRes is still the final position
2025 {
2026 rF.nLen = 0;
2027 goto Err;
2028 }
2029 rF.nLRes -= rF.nSRes; // now: nLRes = length
2030 if (o3tl::checked_add<WW8_CP>(rF.nSRes, 1, rF.nSRes)) // Endpos including Markers
2031 {
2032 rF.nLen = 0;
2033 goto Err;
2034 }
2035 rF.nLRes--;
2036 }else{
2037 rF.nLRes = 0; // no result found
2038 WW8_CP nTmp;
2039 if (o3tl::checked_sub<WW8_CP>(rF.nSRes, rF.nSCode, nTmp))
2040 {
2041 rF.nLen = 0;
2042 goto Err;
2043 }
2044 if (o3tl::checked_add<WW8_CP>(nTmp, 2, rF.nLen)) // total length
2045 {
2046 rF.nLen = 0;
2047 goto Err;
2048 }
2049 }
2050
2051 if (rF.nLen < 0)
2052 {
2053 rF.nLen = 0;
2054 goto Err;
2055 }
2056
2057 rPLCF.advance();
2058 if((static_cast<sal_uInt8*>(pData)[0] & 0x1f ) == 0x15 )
2059 {
2060 // Field end ?
2061 // INDEX-Field has set Bit7?
2062 rF.nOpt = static_cast<sal_uInt8*>(pData)[1]; // yes -> copy flags
2063 }else{
2064 rF.nId = 0; // no -> Field invalid
2065 }
2066
2067 rPLCF.SetIdx( nOldIdx );
2068 return true;
2069Err:
2070 rPLCF.SetIdx( nOldIdx );
2071 return false;
2072}
2073
2074OUString read_uInt8_BeltAndBracesString(SvStream& rStrm, rtl_TextEncoding eEnc)
2075{
2076 const OUString aRet = read_uInt8_lenPrefixed_uInt8s_ToOUString(rStrm, eEnc);
2077 rStrm.SeekRel(sizeof(sal_uInt8)); // skip null-byte at end
2078 return aRet;
2079}
2080
2081OUString read_uInt16_BeltAndBracesString(SvStream& rStrm)
2082{
2083 const OUString aRet = read_uInt16_PascalString(rStrm);
2084 rStrm.SeekRel(sizeof(sal_Unicode)); // skip null-byte at end
2085 return aRet;
2086}
2087
2088sal_Int32 WW8ScannerBase::WW8ReadString( SvStream& rStrm, OUString& rStr,
2089 WW8_CP nCurrentStartCp, long nTotalLen, rtl_TextEncoding eEnc ) const
2090{
2091 // Read in plain text, which can extend over several pieces
2092 rStr.clear();
2093
2094 if (nCurrentStartCp < 0 || nTotalLen < 0)
2095 return 0;
2096
2097 WW8_CP nBehindTextCp = nCurrentStartCp + nTotalLen;
2098 WW8_CP nNextPieceCp = nBehindTextCp; // Initialization, important for Ver6
2099 long nTotalRead = 0;
2100 do
2101 {
2102 bool bIsUnicode(false), bPosOk(false);
2103 WW8_FC fcAct = WW8Cp2Fc(nCurrentStartCp,&bIsUnicode,&nNextPieceCp,&bPosOk);
2104
2105 // Probably aimed beyond file end, doesn't matter!
2106 if( !bPosOk )
2107 break;
2108
2109 bool bValid = checkSeek(rStrm, fcAct);
2110 if (!bValid)
2111 break;
2112
2113 WW8_CP nEnd = (nNextPieceCp < nBehindTextCp) ? nNextPieceCp
2114 : nBehindTextCp;
2115 WW8_CP nLen;
2116 const bool bFail = o3tl::checked_sub(nEnd, nCurrentStartCp, nLen);
2117 if (bFail)
2118 break;
2119
2120 if( 0 >= nLen )
2121 break;
2122
2123 rStr += bIsUnicode
2124 ? read_uInt16s_ToOUString(rStrm, nLen)
2125 : read_uInt8s_ToOUString(rStrm, nLen, eEnc);
2126
2127 nTotalRead += nLen;
2128 nCurrentStartCp += nLen;
2129 if ( nTotalRead != rStr.getLength() )
2130 break;
2131 }
2132 while( nTotalRead < nTotalLen );
2133
2134 return rStr.getLength();
2135}
2136
2137WW8PLCFspecial::WW8PLCFspecial(SvStream* pSt, sal_uInt32 nFilePos,
2138 sal_uInt32 nPLCF, sal_uInt32 nStruct)
2139 : nIdx(0), nStru(nStruct)
2140{
2141 const sal_uInt32 nValidMin=4;
2142
2143 sal_uInt64 const nOldPos = pSt->Tell();
2144
2145 bool bValid = checkSeek(*pSt, nFilePos);
2146 std::size_t nRemainingSize = pSt->remainingSize();
2147 if( nRemainingSize < nValidMin || nPLCF < nValidMin )
2148 bValid = false;
2149 nPLCF = bValid ? std::min(nRemainingSize, static_cast<std::size_t>(nPLCF)) : nValidMin;
2150
2151 // Pointer to Pos- and Struct-array
2152 pPLCF_PosArray.reset( new sal_Int32[ ( nPLCF + 3 ) / 4 ] );
2153 pPLCF_PosArray[0] = 0;
2154
2155 nPLCF = bValid ? pSt->ReadBytes(pPLCF_PosArray.get(), nPLCF) : nValidMin;
2156
2157 nPLCF = std::max(nPLCF, nValidMin);
2158
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] )((sal_uInt32)((((sal_uInt16)((sal_uInt16)((((sal_uInt8)(((sal_uInt16
)(((sal_uInt16)(((sal_uInt32)(pPLCF_PosArray[nIdx]) >> 16
) & 0xFFFF))) >> 8) & 0xFF))) & 0xFF) | (((
sal_uInt16)(((sal_uInt8)((sal_uInt16)(((sal_uInt16)(((sal_uInt32
)(pPLCF_PosArray[nIdx]) >> 16) & 0xFFFF))) & 0xFF
))) & 0xFF) << 8)))) & 0xFFFF) | (((sal_uInt32)
(((sal_uInt16)((sal_uInt16)((((sal_uInt8)(((sal_uInt16)(((sal_uInt16
)((sal_uInt32)(pPLCF_PosArray[nIdx]) & 0xFFFF))) >>
8) & 0xFF))) & 0xFF) | (((sal_uInt16)(((sal_uInt8)((
sal_uInt16)(((sal_uInt16)((sal_uInt32)(pPLCF_PosArray[nIdx]) &
0xFFFF))) & 0xFF))) & 0xFF) << 8)))) & 0xFFFF
) << 16))
;
2163 nIdx = 0;
2164#endif // OSL_BIGENDIAN
2165 if( nStruct ) // Pointer to content array
2166 pPLCF_Contents = reinterpret_cast<sal_uInt8*>(&pPLCF_PosArray[nIMax + 1]);
2167 else
2168 pPLCF_Contents = nullptr; // no content
2169
2170 pSt->Seek(nOldPos);
2171}
2172
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.
2177bool WW8PLCFspecial::SeekPos(long nP)
2178{
2179 if( nP < pPLCF_PosArray[0] )
2180 {
2181 nIdx = 0;
2182 return false; // Not found: nP less than smallest entry
2183 }
2184
2185 // Search from beginning?
2186 if ((nIdx < 1) || (nP < pPLCF_PosArray[nIdx - 1]))
2187 nIdx = 1;
2188
2189 long nI = nIdx;
2190 long nEnd = nIMax;
2191
2192 for(int n = (1==nIdx ? 1 : 2); n; --n )
2193 {
2194 for( ; nI <=nEnd; ++nI)
2195 { // search with an index that is incremented by 1
2196 if( nP < pPLCF_PosArray[nI] )
2197 { // found position
2198 nIdx = nI - 1; // nI - 1 is the correct index
2199 return true; // done
2200 }
2201 }
2202 nI = 1;
2203 nEnd = nIdx-1;
2204 }
2205 nIdx = nIMax; // not found, greater than all entries
2206 return false;
2207}
2208
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.
2212bool WW8PLCFspecial::SeekPosExact(long nP)
2213{
2214 if( nP < pPLCF_PosArray[0] )
2215 {
2216 nIdx = 0;
2217 return false; // Not found: nP less than smallest entry
2218 }
2219 // Search from beginning?
2220 if( nP <=pPLCF_PosArray[nIdx] )
2221 nIdx = 0;
2222
2223 long nI = nIdx ? nIdx-1 : 0;
2224 long nEnd = nIMax;
2225
2226 for(int n = (0==nIdx ? 1 : 2); n; --n )
2227 {
2228 for( ; nI < nEnd; ++nI)
2229 {
2230 if( nP <=pPLCF_PosArray[nI] )
2231 { // found position
2232 nIdx = nI; // nI is the correct index
2233 return true; // done
2234 }
2235 }
2236 nI = 0;
2237 nEnd = nIdx;
2238 }
2239 nIdx = nIMax; // Not found, greater than all entries
2240 return false;
2241}
2242
2243bool WW8PLCFspecial::Get(WW8_CP& rPos, void*& rpValue) const
2244{
2245 return GetData( nIdx, rPos, rpValue );
4
Calling 'WW8PLCFspecial::GetData'
10
Returning from 'WW8PLCFspecial::GetData'
11
Returning the value 1, which participates in a condition later
2246}
2247
2248bool WW8PLCFspecial::GetData(long nInIdx, WW8_CP& rPos, void*& rpValue) const
2249{
2250 if ( nInIdx >= nIMax )
5
Assuming 'nInIdx' is < field 'nIMax'
6
Taking false branch
2251 {
2252 rPos = WW8_CP_MAX;
2253 return false;
2254 }
2255 rPos = pPLCF_PosArray[nInIdx];
2256 rpValue = pPLCF_Contents ? static_cast<void*>(&pPLCF_Contents[nInIdx * nStru]) : nullptr;
7
Assuming field 'pPLCF_Contents' is null
8
'?' condition is false
2257 return true;
9
Returning the value 1, which participates in a condition later
2258}
2259
2260// WW8PLCF e.g. for SEPX
2261// Ctor for *others* than Fkps
2262// With nStartPos < 0, the first element of PLCFs will be taken
2263WW8PLCF::WW8PLCF(SvStream& rSt, WW8_FC nFilePos, sal_Int32 nPLCF, int nStruct,
2264 WW8_CP nStartPos) : nIdx(0), nStru(nStruct)
2265{
2266 if (nPLCF < 0)
2267 {
2268 SAL_WARN("sw.ww8", "broken WW8PLCF, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken WW8PLCF, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2268" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken WW8PLCF, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken WW8PLCF, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2268" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken WW8PLCF, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2268" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken WW8PLCF, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken WW8PLCF, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2268" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2269 nPLCF = 0;
2270 }
2271 else
2272 nIMax = (nPLCF - 4) / (4 + nStruct);
2273
2274 ReadPLCF(rSt, nFilePos, nPLCF);
2275
2276 if( nStartPos >= 0 )
2277 SeekPos( nStartPos );
2278}
2279
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.
2285WW8PLCF::WW8PLCF(SvStream& rSt, WW8_FC nFilePos, sal_Int32 nPLCF, int nStruct,
2286 WW8_CP nStartPos, sal_Int32 nPN, sal_Int32 ncpN): nIdx(0),
2287 nStru(nStruct)
2288{
2289 if (nPLCF < 0)
2290 {
2291 SAL_WARN("sw.ww8", "broken WW8PLCF, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken WW8PLCF, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2291" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken WW8PLCF, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken WW8PLCF, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2291" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken WW8PLCF, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2291" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken WW8PLCF, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken WW8PLCF, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2291" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2292 nIMax = SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF);
2293 }
2294 else
2295 nIMax = (nPLCF - 4) / (4 + nStruct);
2296
2297 if( nIMax >= ncpN )
2298 ReadPLCF(rSt, nFilePos, nPLCF);
2299 else
2300 GeneratePLCF(rSt, nPN, ncpN);
2301
2302 if( nStartPos >= 0 )
2303 SeekPos( nStartPos );
2304}
2305
2306void WW8PLCF::ReadPLCF(SvStream& rSt, WW8_FC nFilePos, sal_uInt32 nPLCF)
2307{
2308 sal_uInt64 const nOldPos = rSt.Tell();
2309 bool bValid = nPLCF != 0 && checkSeek(rSt, nFilePos)
2310 && (rSt.remainingSize() >= nPLCF);
2311
2312 if (bValid)
2313 {
2314 // Pointer to Pos-array
2315 pPLCF_PosArray.reset( new WW8_CP[ ( nPLCF + 3 ) / 4 ] );
2316 bValid = checkRead(rSt, pPLCF_PosArray.get(), nPLCF);
2317 }
2318
2319 if (bValid)
2320 {
2321#ifdef OSL_BIGENDIAN
2322 for( nIdx = 0; nIdx <= nIMax; nIdx++ )
2323 pPLCF_PosArray[nIdx] = OSL_SWAPDWORD( pPLCF_PosArray[nIdx] )((sal_uInt32)((((sal_uInt16)((sal_uInt16)((((sal_uInt8)(((sal_uInt16
)(((sal_uInt16)(((sal_uInt32)(pPLCF_PosArray[nIdx]) >> 16
) & 0xFFFF))) >> 8) & 0xFF))) & 0xFF) | (((
sal_uInt16)(((sal_uInt8)((sal_uInt16)(((sal_uInt16)(((sal_uInt32
)(pPLCF_PosArray[nIdx]) >> 16) & 0xFFFF))) & 0xFF
))) & 0xFF) << 8)))) & 0xFFFF) | (((sal_uInt32)
(((sal_uInt16)((sal_uInt16)((((sal_uInt8)(((sal_uInt16)(((sal_uInt16
)((sal_uInt32)(pPLCF_PosArray[nIdx]) & 0xFFFF))) >>
8) & 0xFF))) & 0xFF) | (((sal_uInt16)(((sal_uInt8)((
sal_uInt16)(((sal_uInt16)((sal_uInt32)(pPLCF_PosArray[nIdx]) &
0xFFFF))) & 0xFF))) & 0xFF) << 8)))) & 0xFFFF
) << 16))
;
2324 nIdx = 0;
2325#endif // OSL_BIGENDIAN
2326 // Pointer to content array
2327 pPLCF_Contents = reinterpret_cast<sal_uInt8*>(&pPLCF_PosArray[nIMax + 1]);
2328
2329 TruncToSortedRange();
2330 }
2331
2332 OSL_ENSURE(bValid, "Document has corrupt PLCF, ignoring it")do { if (true && (!(bValid))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2332" ": "), "%s", "Document has corrupt PLCF, ignoring it"
); } } while (false)
;
2333
2334 if (!bValid)
2335 MakeFailedPLCF();
2336
2337 rSt.Seek(nOldPos);
2338}
2339
2340void WW8PLCF::MakeFailedPLCF()
2341{
2342 nIMax = 0;
2343 pPLCF_PosArray.reset( new sal_Int32[2] );
2344 pPLCF_PosArray[0] = pPLCF_PosArray[1] = WW8_CP_MAX;
2345 pPLCF_Contents = reinterpret_cast<sal_uInt8*>(&pPLCF_PosArray[nIMax + 1]);
2346}
2347
2348void WW8PLCF::TruncToSortedRange()
2349{
2350 //Docs state that: ... all Plcs ... are sorted in ascending order.
2351 //So ensure that here for broken documents.
2352 for (auto nI = 0; nI < nIMax; ++nI)
2353 {
2354 if (pPLCF_PosArray[nI] > pPLCF_PosArray[nI+1])
2355 {
2356 SAL_WARN("sw.ww8", "Document has unsorted PLCF, truncated to sorted portion")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Document has unsorted PLCF, truncated to sorted portion"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2356" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Document has unsorted PLCF, truncated to sorted portion"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Document has unsorted PLCF, truncated to sorted portion"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2356" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Document has unsorted PLCF, truncated to sorted portion"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2356" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Document has unsorted PLCF, truncated to sorted portion"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Document has unsorted PLCF, truncated to sorted portion"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2356" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2357 nIMax = nI;
2358 break;
2359 }
2360 }
2361}
2362
2363void WW8PLCF::GeneratePLCF(SvStream& rSt, sal_Int32 nPN, sal_Int32 ncpN)
2364{
2365 OSL_ENSURE( nIMax < ncpN, "Pcl.Fkp: Why is PLCF too big?" )do { if (true && (!(nIMax < ncpN))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2365" ": "), "%s", "Pcl.Fkp: Why is PLCF too big?"); } }
while (false)
;
2366
2367 bool failure = false;
2368 nIMax = ncpN;
2369
2370 if ((nIMax < 1) || (nIMax > (WW8_CP_MAX - 4) / (4 + nStru)) || nPN < 0)
2371 failure = true;
2372
2373 if (!failure)
2374 {
2375 // Check arguments to ShortToSVBT16 in loop below will all be valid:
2376 sal_Int32 nResult;
2377 failure = o3tl::checked_add(nPN, ncpN, nResult) || nResult > SAL_MAX_UINT16((sal_uInt16) 0xFFFF);
2378 }
2379
2380 if (!failure)
2381 {
2382 size_t nSiz = (4 + nStru) * nIMax + 4;
2383 size_t nElems = ( nSiz + 3 ) / 4;
2384 pPLCF_PosArray.reset( new sal_Int32[ nElems ] ); // Pointer to Pos-array
2385
2386 for (sal_Int32 i = 0; i < ncpN && !failure; ++i)
2387 {
2388 failure = true;
2389 // construct FC entries
2390 // first FC entry of each Fkp
2391 if (!checkSeek(rSt, (nPN + i) << 9))
2392 break;
2393
2394 WW8_CP nFc(0);
2395 rSt.ReadInt32( nFc );
2396 pPLCF_PosArray[i] = nFc;
2397
2398 failure = bool(rSt.GetError());
2399 }
2400 }
2401
2402 if (!failure)
2403 {
2404 do
2405 {
2406 failure = true;
2407
2408 std::size_t nLastFkpPos = nPN + nIMax - 1;
2409 nLastFkpPos = nLastFkpPos << 9;
2410 // number of FC entries of last Fkp
2411 if (!checkSeek(rSt, nLastFkpPos + 511))
2412 break;
2413
2414 sal_uInt8 nb(0);
2415 rSt.ReadUChar( nb );
2416 // last FC entry of last Fkp
2417 if (!checkSeek(rSt, nLastFkpPos + nb * 4))
2418 break;
2419
2420 WW8_CP nFc(0);
2421 rSt.ReadInt32( nFc );
2422 pPLCF_PosArray[nIMax] = nFc; // end of the last Fkp
2423
2424 failure = bool(rSt.GetError());
2425 } while(false);
2426 }
2427
2428 if (!failure)
2429 {
2430 // Pointer to content array
2431 pPLCF_Contents = reinterpret_cast<sal_uInt8*>(&pPLCF_PosArray[nIMax + 1]);
2432 sal_uInt8* p = pPLCF_Contents;
2433
2434 for (sal_Int32 i = 0; i < ncpN; ++i) // construct PNs
2435 {
2436 ShortToSVBT16(static_cast<sal_uInt16>(nPN + i), p);
2437 p += nStru;
2438 }
2439 }
2440
2441 SAL_WARN_IF(failure, "sw.ww8", "Document has corrupt PLCF, ignoring it")do { if (true && (failure)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "Document has corrupt PLCF, ignoring it"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2441" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Document has corrupt PLCF, ignoring it"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Document has corrupt PLCF, ignoring it"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2441" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Document has corrupt PLCF, ignoring it") == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"),
("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2441" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Document has corrupt PLCF, ignoring it"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Document has corrupt PLCF, ignoring it"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2441" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2442
2443 if (failure)
2444 MakeFailedPLCF();
2445}
2446
2447bool WW8PLCF::SeekPos(WW8_CP nPos)
2448{
2449 WW8_CP nP = nPos;
2450
2451 if( nP < pPLCF_PosArray[0] )
2452 {
2453 nIdx = 0;
2454 // not found: nPos less than smallest entry
2455 return false;
2456 }
2457
2458 // Search from beginning?
2459 if ((nIdx < 1) || (nP < pPLCF_PosArray[nIdx - 1]))
2460 nIdx = 1;
2461
2462 sal_Int32 nI = nIdx;
2463 sal_Int32 nEnd = nIMax;
2464
2465 for(int n = (1==nIdx ? 1 : 2); n; --n )
2466 {
2467 for( ; nI <=nEnd; ++nI) // search with an index that is incremented by 1
2468 {
2469 if( nP < pPLCF_PosArray[nI] ) // found position
2470 {
2471 nIdx = nI - 1; // nI - 1 is the correct index
2472 return true; // done
2473 }
2474 }
2475 nI = 1;
2476 nEnd = nIdx-1;
2477 }
2478
2479 nIdx = nIMax; // not found, greater than all entries
2480 return false;
2481}
2482
2483bool WW8PLCF::Get(WW8_CP& rStart, WW8_CP& rEnd, void*& rpValue) const
2484{
2485 if ( nIdx >= nIMax )
2486 {
2487 rStart = rEnd = WW8_CP_MAX;
2488 return false;
2489 }
2490 rStart = pPLCF_PosArray[ nIdx ];
2491 rEnd = pPLCF_PosArray[ nIdx + 1 ];
2492 rpValue = static_cast<void*>(&pPLCF_Contents[nIdx * nStru]);
2493 return true;
2494}
2495
2496WW8_CP WW8PLCF::Where() const
2497{
2498 if ( nIdx >= nIMax )
2499 return WW8_CP_MAX;
2500
2501 return pPLCF_PosArray[nIdx];
2502}
2503
2504WW8PLCFpcd::WW8PLCFpcd(SvStream* pSt, sal_uInt32 nFilePos,
2505 sal_uInt32 nPLCF, sal_uInt32 nStruct)
2506 : nStru( nStruct )
2507{
2508 const sal_uInt32 nValidMin=4;
2509
2510 sal_uInt64 const nOldPos = pSt->Tell();
2511
2512 bool bValid = checkSeek(*pSt, nFilePos);
2513 std::size_t nRemainingSize = pSt->remainingSize();
2514 if( nRemainingSize < nValidMin || nPLCF < nValidMin )
2515 bValid = false;
2516 nPLCF = bValid ? std::min(nRemainingSize, static_cast<std::size_t>(nPLCF)) : nValidMin;
2517
2518 pPLCF_PosArray.reset( new sal_Int32[ ( nPLCF + 3 ) / 4 ] ); // Pointer to Pos-array
2519 pPLCF_PosArray[0] = 0;
2520
2521 nPLCF = bValid ? pSt->ReadBytes(pPLCF_PosArray.get(), nPLCF) : nValidMin;
2522 nPLCF = std::max(nPLCF, nValidMin);
2523
2524 nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
2525#ifdef OSL_BIGENDIAN
2526 for( long nI = 0; nI <= nIMax; nI++ )
2527 pPLCF_PosArray[nI] = OSL_SWAPDWORD( pPLCF_PosArray[nI] )((sal_uInt32)((((sal_uInt16)((sal_uInt16)((((sal_uInt8)(((sal_uInt16
)(((sal_uInt16)(((sal_uInt32)(pPLCF_PosArray[nI]) >> 16
) & 0xFFFF))) >> 8) & 0xFF))) & 0xFF) | (((
sal_uInt16)(((sal_uInt8)((sal_uInt16)(((sal_uInt16)(((sal_uInt32
)(pPLCF_PosArray[nI]) >> 16) & 0xFFFF))) & 0xFF
))) & 0xFF) << 8)))) & 0xFFFF) | (((sal_uInt32)
(((sal_uInt16)((sal_uInt16)((((sal_uInt8)(((sal_uInt16)(((sal_uInt16
)((sal_uInt32)(pPLCF_PosArray[nI]) & 0xFFFF))) >> 8
) & 0xFF))) & 0xFF) | (((sal_uInt16)(((sal_uInt8)((sal_uInt16
)(((sal_uInt16)((sal_uInt32)(pPLCF_PosArray[nI]) & 0xFFFF
))) & 0xFF))) & 0xFF) << 8)))) & 0xFFFF) <<
16))
;
2528#endif // OSL_BIGENDIAN
2529
2530 // Pointer to content array
2531 pPLCF_Contents = reinterpret_cast<sal_uInt8*>(&pPLCF_PosArray[nIMax + 1]);
2532
2533 pSt->Seek( nOldPos );
2534}
2535
2536// If nStartPos < 0, the first element of PLCFs will be taken
2537WW8PLCFpcd_Iter::WW8PLCFpcd_Iter( WW8PLCFpcd& rPLCFpcd, long nStartPos )
2538 :rPLCF( rPLCFpcd ), nIdx( 0 )
2539{
2540 if( nStartPos >= 0 )
2541 SeekPos( nStartPos );
2542}
2543
2544bool WW8PLCFpcd_Iter::SeekPos(long nPos)
2545{
2546 long nP = nPos;
2547
2548 if( nP < rPLCF.pPLCF_PosArray[0] )
2549 {
2550 nIdx = 0;
2551 return false; // not found: nPos less than smallest entry
2552 }
2553 // Search from beginning?
2554 if ((nIdx < 1) || (nP < rPLCF.pPLCF_PosArray[nIdx - 1]))
2555 nIdx = 1;
2556
2557 long nI = nIdx;
2558 long nEnd = rPLCF.nIMax;
2559
2560 for(int n = (1==nIdx ? 1 : 2); n; --n )
2561 {
2562 for( ; nI <=nEnd; ++nI)
2563 { // search with an index that is incremented by 1
2564 if( nP < rPLCF.pPLCF_PosArray[nI] )
2565 { // found position
2566 nIdx = nI - 1; // nI - 1 is the correct index
2567 return true; // done
2568 }
2569 }
2570 nI = 1;
2571 nEnd = nIdx-1;
2572 }
2573 nIdx = rPLCF.nIMax; // not found, greater than all entries
2574 return false;
2575}
2576
2577bool WW8PLCFpcd_Iter::Get(WW8_CP& rStart, WW8_CP& rEnd, void*& rpValue) const
2578{
2579 if( nIdx >= rPLCF.nIMax )
2580 {
2581 rStart = rEnd = WW8_CP_MAX;
2582 return false;
2583 }
2584 rStart = rPLCF.pPLCF_PosArray[nIdx];
2585 rEnd = rPLCF.pPLCF_PosArray[nIdx + 1];
2586 rpValue = static_cast<void*>(&rPLCF.pPLCF_Contents[nIdx * rPLCF.nStru]);
2587 return true;
2588}
2589
2590sal_Int32 WW8PLCFpcd_Iter::Where() const
2591{
2592 if ( nIdx >= rPLCF.nIMax )
2593 return SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF);
2594
2595 return rPLCF.pPLCF_PosArray[nIdx];
2596}
2597
2598bool WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator<
2599 (const WW8PLCFx_Fc_FKP::WW8Fkp::Entry& rSecond) const
2600{
2601 return (mnFC < rSecond.mnFC);
2602}
2603
2604static bool IsReplaceAllSprm(sal_uInt16 nSpId)
2605{
2606 return (NS_sprm::LN_PHugePapx == nSpId || 0x6646 == nSpId);
2607}
2608
2609static bool IsExpandableSprm(sal_uInt16 nSpId)
2610{
2611 return 0x646B == nSpId;
2612}
2613
2614void WW8PLCFx_Fc_FKP::WW8Fkp::FillEntry(WW8PLCFx_Fc_FKP::WW8Fkp::Entry &rEntry,
2615 std::size_t nDataOffset, sal_uInt16 nLen)
2616{
2617 bool bValidPos = (nDataOffset < sizeof(maRawData));
2618
2619 OSL_ENSURE(bValidPos, "sprm sequence offset is out of range, ignoring")do { if (true && (!(bValidPos))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2619" ": "), "%s", "sprm sequence offset is out of range, ignoring"
); } } while (false)
;
2620
2621 if (!bValidPos)
2622 {
2623 rEntry.mnLen = 0;
2624 return;
2625 }
2626
2627 const sal_uInt16 nAvailableData = sizeof(maRawData)-nDataOffset;
2628 OSL_ENSURE(nLen <= nAvailableData, "srpm sequence len is out of range, clipping")do { if (true && (!(nLen <= nAvailableData))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2628" ": "), "%s", "srpm sequence len is out of range, clipping"
); } } while (false)
;
2629 rEntry.mnLen = std::min(nLen, nAvailableData);
2630 rEntry.mpData = maRawData + nDataOffset;
2631}
2632
2633WW8PLCFx_Fc_FKP::WW8Fkp::WW8Fkp(const WW8Fib& rFib, SvStream* pSt,
2634 SvStream* pDataSt, long _nFilePos, long nItemSiz, ePLCFT ePl,
2635 WW8_FC nStartFc)
2636 : nItemSize(nItemSiz), nFilePos(_nFilePos), mnIdx(0), ePLCF(ePl)
2637 , mnMustRemainCached(0), maSprmParser(rFib)
2638{
2639 memset(maRawData, 0, 512);
2640
2641 const ww::WordVersion eVersion = rFib.GetFIBVersion();
2642
2643 sal_uInt64 const nOldPos = pSt->Tell();
2644
2645 bool bCouldSeek = checkSeek(*pSt, nFilePos);
2646 bool bCouldRead = bCouldSeek && checkRead(*pSt, maRawData, 512);
2647
2648 mnIMax = bCouldRead ? maRawData[511] : 0;
2649
2650 sal_uInt8 *pStart = maRawData;
2651 // Offset-Location in maRawData
2652 const size_t nRawDataStart = (mnIMax + 1) * 4;
2653
2654 for (mnIdx = 0; mnIdx < mnIMax; ++mnIdx)
2655 {
2656 const size_t nRawDataOffset = nRawDataStart + mnIdx * nItemSize;
2657
2658 //clip to available data, corrupt fkp
2659 if (nRawDataOffset >= 511)
2660 {
2661 mnIMax = mnIdx;
2662 break;
2663 }
2664
2665 unsigned int nOfs = maRawData[nRawDataOffset] * 2;
2666 // nOfs in [0..0xff*2=510]
2667
2668 Entry aEntry(Get_Long(pStart));
2669
2670 if (nOfs)
2671 {
2672 switch (ePLCF)
2673 {
2674 case CHP:
2675 {
2676 aEntry.mnLen = maRawData[nOfs];
2677
2678 //len byte
2679 std::size_t nDataOffset = nOfs + 1;
2680
2681 FillEntry(aEntry, nDataOffset, aEntry.mnLen);
2682
2683 if (aEntry.mnLen && eVersion <= ww::eWW2)
2684 {
2685 Word2CHPX aChpx = ReadWord2Chpx(*pSt, nFilePos + nOfs + 1, static_cast< sal_uInt8 >(aEntry.mnLen));
2686 std::vector<sal_uInt8> aSprms = ChpxToSprms(aChpx);
2687 aEntry.mnLen = static_cast< sal_uInt16 >(aSprms.size());
2688 if (aEntry.mnLen)
2689 {
2690 aEntry.mpData = new sal_uInt8[aEntry.mnLen];
2691 memcpy(aEntry.mpData, aSprms.data(), aEntry.mnLen);
2692 aEntry.mbMustDelete = true;
2693 }
2694 }
2695 break;
2696 }
2697 case PAP:
2698 {
2699 sal_uInt8 nDelta = 0;
2700
2701 aEntry.mnLen = maRawData[nOfs];
2702 if (IsEightPlus(eVersion) && !aEntry.mnLen)
2703 {
2704 aEntry.mnLen = maRawData[nOfs+1];
2705 nDelta++;
2706 }
2707 aEntry.mnLen *= 2;
2708
2709 //stylecode, std/istd
2710 if (eVersion <= ww::eWW2)
2711 {
2712 if (aEntry.mnLen >= 1)
2713 {
2714 aEntry.mnIStd = *(maRawData+nOfs+1+nDelta);
2715 aEntry.mnLen--; //style code
2716 if (aEntry.mnLen >= 6)
2717 {
2718 aEntry.mnLen-=6; //PHE
2719 //skip stc, len byte + 6 byte PHE
2720 unsigned int nOffset = nOfs + 8;
2721 if (nOffset >= 511) //Bad offset
2722 aEntry.mnLen=0;
2723 if (aEntry.mnLen) //start is ok
2724 {
2725 if (nOffset + aEntry.mnLen > 512) //Bad end, clip
2726 aEntry.mnLen = 512 - nOffset;
2727 aEntry.mpData = maRawData + nOffset;
2728 }
2729 }
2730 else
2731 aEntry.mnLen=0; //Too short
2732 }
2733 }
2734 else
2735 {
2736 if (aEntry.mnLen >= 2)
2737 {
2738 //len byte + optional extra len byte
2739 std::size_t nDataOffset = nOfs + 1 + nDelta;
2740 aEntry.mnIStd = nDataOffset <= sizeof(maRawData)-sizeof(aEntry.mnIStd) ?
2741 SVBT16ToUInt16(maRawData+nDataOffset) : 0;
2742 aEntry.mnLen-=2; //istd
2743 if (aEntry.mnLen)
2744 {
2745 //additional istd
2746 nDataOffset += sizeof(aEntry.mnIStd);
2747
2748 FillEntry(aEntry, nDataOffset, aEntry.mnLen);
2749 }
2750 }
2751 else
2752 aEntry.mnLen=0; //Too short, ignore
2753 }
2754
2755 const sal_uInt16 nSpId = aEntry.mnLen
2756 ? maSprmParser.GetSprmId(aEntry.mpData) : 0;
2757
2758 /*
2759 If we replace then we throw away the old data, if we
2760 are expanding, then we tack the old data onto the end
2761 of the new data
2762 */
2763 const bool bExpand = IsExpandableSprm(nSpId);
2764 const sal_uInt8* pStartData
2765 = aEntry.mpData == nullptr ? nullptr : aEntry.mpData + 2;
2766 const sal_uInt8* pLastValidDataPos = maRawData + 512 - sizeof(sal_uInt32);
2767 if (pStartData != nullptr && pStartData > pLastValidDataPos)
2768 pStartData = nullptr;
2769 if ((IsReplaceAllSprm(nSpId) || bExpand) && pStartData)
2770 {
2771 sal_uInt32 nCurr = pDataSt->Tell();
2772 sal_uInt32 nPos = SVBT32ToUInt32(pStartData);
2773 sal_uInt16 nLen(0);
2774
2775 bool bOk = checkSeek(*pDataSt, nPos);
2776 if (bOk)
2777 {
2778 pDataSt->ReadUInt16( nLen );
2779 bOk = nLen <= pDataSt->remainingSize();
2780 }
2781
2782 if (bOk)
2783 {
2784 const sal_uInt16 nOrigLen = bExpand ? aEntry.mnLen : 0;
2785 sal_uInt8 *pOrigData = bExpand ? aEntry.mpData : nullptr;
2786
2787 aEntry.mnLen = nLen;
2788 aEntry.mpData =
2789 new sal_uInt8[aEntry.mnLen + nOrigLen];
2790 aEntry.mbMustDelete = true;
2791 aEntry.mnLen =
2792 pDataSt->ReadBytes(aEntry.mpData, aEntry.mnLen);
2793
2794 pDataSt->Seek( nCurr );
2795
2796 if (pOrigData)
2797 {
2798 memcpy(aEntry.mpData + aEntry.mnLen,
2799 pOrigData, nOrigLen);
2800 aEntry.mnLen = aEntry.mnLen + nOrigLen;
2801 }
2802 }
2803 }
2804 }
2805 break;
2806 default:
2807 OSL_FAIL("sweet god, what have you done!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2807" ": "), "%s", "sweet god, what have you done!"); }
} while (false)
;
2808 break;
2809 }
2810 }
2811
2812 maEntries.push_back(aEntry);
2813
2814#ifdef DEBUGSPRMREADER
2815 {
2816 sal_Int32 nLen;
2817 sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
2818 WW8SprmIter aIter(pSprms, nLen, maSprmParser);
2819 while (aIter.GetSprms())
2820 {
2821 fprintf(stderrstderr, "id is %x\n", aIter.GetCurrentId());
2822 aIter.advance();
2823 }
2824 }
2825#endif
2826 }
2827
2828 //one more FC than grrpl entries
2829 maEntries.emplace_back(Get_Long(pStart));
2830
2831 //we expect them sorted, but it appears possible for them to arrive unsorted
2832 std::stable_sort(maEntries.begin(), maEntries.end());
2833
2834 mnIdx = 0;
2835
2836 if (nStartFc >= 0)
2837 SeekPos(nStartFc);
2838
2839 pSt->Seek(nOldPos);
2840}
2841
2842WW8PLCFx_Fc_FKP::WW8Fkp::Entry::Entry(const Entry &rEntry)
2843 : mnFC(rEntry.mnFC), mnLen(rEntry.mnLen), mnIStd(rEntry.mnIStd),
2844 mbMustDelete(rEntry.mbMustDelete)
2845{
2846 if (mbMustDelete)
2847 {
2848 mpData = new sal_uInt8[mnLen];
2849 memcpy(mpData, rEntry.mpData, mnLen);
2850 }
2851 else
2852 mpData = rEntry.mpData;
2853}
2854
2855WW8PLCFx_Fc_FKP::WW8Fkp::Entry&
2856 WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator=(const Entry &rEntry)
2857{
2858 if (this == &rEntry)
2859 return *this;
2860
2861 if (mbMustDelete)
2862 delete[] mpData;
2863
2864 mnFC = rEntry.mnFC;
2865 mnLen = rEntry.mnLen;
2866 mnIStd = rEntry.mnIStd;
2867 mbMustDelete = rEntry.mbMustDelete;
2868
2869 if (rEntry.mbMustDelete)
2870 {
2871 mpData = new sal_uInt8[mnLen];
2872 memcpy(mpData, rEntry.mpData, mnLen);
2873 }
2874 else
2875 mpData = rEntry.mpData;
2876
2877 return *this;
2878}
2879
2880WW8PLCFx_Fc_FKP::WW8Fkp::Entry::~Entry()
2881{
2882 if (mbMustDelete)
2883 delete[] mpData;
2884}
2885
2886void WW8PLCFx_Fc_FKP::WW8Fkp::Reset(WW8_FC nFc)
2887{
2888 SetIdx(0);
2889 if (nFc >= 0)
2890 SeekPos(nFc);
2891}
2892
2893bool WW8PLCFx_Fc_FKP::WW8Fkp::SeekPos(WW8_FC nFc)
2894{
2895 if (nFc < maEntries[0].mnFC)
2896 {
2897 mnIdx = 0;
2898 return false; // not found: nPos less than smallest entry
2899 }
2900
2901 // Search from beginning?
2902 if ((mnIdx < 1) || (nFc < maEntries[mnIdx - 1].mnFC))
2903 mnIdx = 1;
2904
2905 sal_uInt8 nI = mnIdx;
2906 sal_uInt8 nEnd = mnIMax;
2907
2908 for(sal_uInt8 n = (1==mnIdx ? 1 : 2); n; --n )
2909 {
2910 for( ; nI <=nEnd; ++nI)
2911 { // search with an index that is incremented by 1
2912 if (nFc < maEntries[nI].mnFC)
2913 { // found position
2914 mnIdx = nI - 1; // nI - 1 is the correct index
2915 return true; // done
2916 }
2917 }
2918 nI = 1;
2919 nEnd = mnIdx-1;
2920 }
2921 mnIdx = mnIMax; // not found, greater than all entries
2922 return false;
2923}
2924
2925sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::Get(WW8_FC& rStart, WW8_FC& rEnd, sal_Int32& rLen)
2926 const
2927{
2928 rLen = 0;
2929
2930 if (mnIdx >= mnIMax)
2931 {
2932 rStart = WW8_FC_MAX;
2933 return nullptr;
2934 }
2935
2936 rStart = maEntries[mnIdx].mnFC;
2937 rEnd = maEntries[mnIdx + 1].mnFC;
2938
2939 sal_uInt8* pSprms = GetLenAndIStdAndSprms( rLen );
2940 return pSprms;
2941}
2942
2943void WW8PLCFx_Fc_FKP::WW8Fkp::SetIdx(sal_uInt8 nI)
2944{
2945 if (nI < mnIMax)
2946 {
2947 mnIdx = nI;
2948 }
2949}
2950
2951sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::GetLenAndIStdAndSprms(sal_Int32& rLen) const
2952{
2953 rLen = maEntries[mnIdx].mnLen;
2954 return maEntries[mnIdx].mpData;
2955}
2956
2957SprmResult WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm( sal_uInt16 nId, bool bFindFirst )
2958{
2959 if (mnIdx >= mnIMax)
2960 return SprmResult();
2961
2962 sal_Int32 nLen;
2963 sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
2964
2965 WW8SprmIter aIter(pSprms, nLen, maSprmParser);
2966 return aIter.FindSprm(nId, bFindFirst);
2967}
2968
2969void WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm(sal_uInt16 nId,
2970 std::vector<SprmResult> &rResult)
2971{
2972 if (mnIdx >= mnIMax)
2973 return;
2974
2975 sal_Int32 nLen;
2976 sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
2977
2978 WW8SprmIter aIter(pSprms, nLen, maSprmParser);
2979
2980 while(aIter.GetSprms())
2981 {
2982 if (aIter.GetCurrentId() == nId)
2983 {
2984 sal_Int32 nFixedLen = maSprmParser.DistanceToData(nId);
2985 sal_Int32 nL = maSprmParser.GetSprmSize(nId, aIter.GetSprms(), aIter.GetRemLen());
2986 rResult.emplace_back(aIter.GetCurrentParams(), nL - nFixedLen);
2987 }
2988 aIter.advance();
2989 };
2990}
2991
2992ww::WordVersion WW8PLCFx::GetFIBVersion() const
2993{
2994 return mrFib.GetFIBVersion();
2995}
2996
2997void WW8PLCFx::GetSprms( WW8PLCFxDesc* p )
2998{
2999 OSL_ENSURE( false, "Called wrong GetSprms" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "2999" ": "), "%s", "Called wrong GetSprms"); } } while (
false)
;
3000 p->nStartPos = p->nEndPos = WW8_CP_MAX;
3001 p->pMemPos = nullptr;
3002 p->nSprmsLen = 0;
3003 p->bRealLineEnd = false;
3004}
3005
3006long WW8PLCFx::GetNoSprms( WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen )
3007{
3008 OSL_ENSURE( false, "Called wrong GetNoSprms" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3008" ": "), "%s", "Called wrong GetNoSprms"); } } while
(false)
;
3009 rStart = rEnd = WW8_CP_MAX;
3010 rLen = 0;
3011 return 0;
3012}
3013
3014// ...Idx2: Default: ignore
3015sal_uInt32 WW8PLCFx::GetIdx2() const
3016{
3017 return 0;
3018}
3019
3020void WW8PLCFx::SetIdx2(sal_uInt32)
3021{
3022}
3023
3024namespace {
3025
3026class SamePos
3027{
3028private:
3029 long mnPo;
3030public:
3031 explicit SamePos(long nPo) : mnPo(nPo) {}
3032 bool operator()(const std::unique_ptr<WW8PLCFx_Fc_FKP::WW8Fkp>& pFkp)
3033 {return mnPo == pFkp->GetFilePos();}
3034};
3035
3036}
3037
3038bool WW8PLCFx_Fc_FKP::NewFkp()
3039{
3040 WW8_CP nPLCFStart, nPLCFEnd;
3041 void* pPage;
3042
3043 static const int WW8FkpSizeTabVer2[ PLCF_END ] =
3044 {
3045 1, 1, 0 /*, 0, 0, 0*/
3046 };
3047 static const int WW8FkpSizeTabVer6[ PLCF_END ] =
3048 {
3049 1, 7, 0 /*, 0, 0, 0*/
3050 };
3051 static const int WW8FkpSizeTabVer8[ PLCF_END ] =
3052 {
3053 1, 13, 0 /*, 0, 0, 0*/
3054 };
3055 const int* pFkpSizeTab;
3056
3057 switch (GetFIBVersion())
3058 {
3059 case ww::eWW1:
3060 case ww::eWW2:
3061 pFkpSizeTab = WW8FkpSizeTabVer2;
3062 break;
3063 case ww::eWW6:
3064 case ww::eWW7:
3065 pFkpSizeTab = WW8FkpSizeTabVer6;
3066 break;
3067 case ww::eWW8:
3068 pFkpSizeTab = WW8FkpSizeTabVer8;
3069 break;
3070 default:
3071 // program error!
3072 OSL_ENSURE( false, "nVersion not implemented!" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3072" ": "), "%s", "nVersion not implemented!"); } } while
(false)
;
3073 return false;
3074 }
3075
3076 if (!pPLCF->Get( nPLCFStart, nPLCFEnd, pPage ))
3077 {
3078 pFkp = nullptr;
3079 return false; // PLCF completely processed
3080 }
3081 pPLCF->advance();
3082 long nPo = SVBT16ToUInt16( static_cast<sal_uInt8 *>(pPage) );
3083 nPo <<= 9; // shift as LONG
3084
3085 long nCurrentFkpFilePos = pFkp ? pFkp->GetFilePos() : -1;
3086 if (nCurrentFkpFilePos == nPo)
3087 pFkp->Reset(GetStartFc());
3088 else
3089 {
3090 auto aIter =
3091 std::find_if(maFkpCache.begin(), maFkpCache.end(), SamePos(nPo));
3092 if (aIter != maFkpCache.end())
3093 {
3094 pFkp = aIter->get();
3095 pFkp->Reset(GetStartFc());
3096 }
3097 else
3098 {
3099 pFkp = new WW8Fkp(GetFIB(), pFKPStrm, pDataStrm, nPo,
3100 pFkpSizeTab[ ePLCF ], ePLCF, GetStartFc());
3101 maFkpCache.push_back(std::unique_ptr<WW8Fkp>(pFkp));
3102
3103 if (maFkpCache.size() > eMaxCache)
3104 {
3105 WW8Fkp* pCachedFkp = maFkpCache.front().get();
3106 if (!pCachedFkp->IsMustRemainCache())
3107 {
3108 maFkpCache.pop_front();
3109 }
3110 }
3111 }
3112 }
3113
3114 SetStartFc( -1 ); // only the first time
3115 return true;
3116}
3117
3118WW8PLCFx_Fc_FKP::WW8PLCFx_Fc_FKP(SvStream* pSt, SvStream* pTableSt,
3119 SvStream* pDataSt, const WW8Fib& rFib, ePLCFT ePl, WW8_FC nStartFcL)
3120 : WW8PLCFx(rFib, true), pFKPStrm(pSt), pDataStrm(pDataSt)
3121 , pFkp(nullptr), ePLCF(ePl)
3122{
3123 SetStartFc(nStartFcL);
3124 long nLenStruct = (8 > rFib.m_nVersion) ? 2 : 4;
3125 if (ePl == CHP)
3126 {
3127 pPLCF.reset(new WW8PLCF(*pTableSt, rFib.m_fcPlcfbteChpx, rFib.m_lcbPlcfbteChpx,
3128 nLenStruct, GetStartFc(), rFib.m_pnChpFirst, rFib.m_cpnBteChp));
3129 }
3130 else
3131 {
3132 pPLCF.reset(new WW8PLCF(*pTableSt, rFib.m_fcPlcfbtePapx, rFib.m_lcbPlcfbtePapx,
3133 nLenStruct, GetStartFc(), rFib.m_pnPapFirst, rFib.m_cpnBtePap));
3134 }
3135}
3136
3137WW8PLCFx_Fc_FKP::~WW8PLCFx_Fc_FKP()
3138{
3139 maFkpCache.clear();
3140 pPLCF.reset();
3141 pPCDAttrs.reset();
3142}
3143
3144sal_uInt32 WW8PLCFx_Fc_FKP::GetIdx() const
3145{
3146 sal_uInt32 u = pPLCF->GetIdx() << 8;
3147 if (pFkp)
3148 u |= pFkp->GetIdx();
3149 return u;
3150}
3151
3152void WW8PLCFx_Fc_FKP::SetIdx(sal_uInt32 nIdx)
3153{
3154 if( !( nIdx & 0xffffff00L ) )
3155 {
3156 pPLCF->SetIdx( nIdx >> 8 );
3157 pFkp = nullptr;
3158 }
3159 else
3160 { // there was a Fkp
3161 // Set PLCF one position back to retrieve the address of the Fkp
3162 pPLCF->SetIdx( ( nIdx >> 8 ) - 1 );
3163 if (NewFkp()) // read Fkp again
3164 {
3165 sal_uInt8 nFkpIdx = static_cast<sal_uInt8>(nIdx & 0xff);
3166 pFkp->SetIdx(nFkpIdx); // set Fkp-Pos again
3167 }
3168 }
3169}
3170
3171bool WW8PLCFx_Fc_FKP::SeekPos(WW8_FC nFcPos)
3172{
3173 // StartPos for next Where()
3174 SetStartFc( nFcPos );
3175
3176 // find StartPos for next pPLCF->Get()
3177 bool bRet = pPLCF->SeekPos(nFcPos);
3178
3179 // make FKP invalid?
3180 WW8_CP nPLCFStart, nPLCFEnd;
3181 void* pPage;
3182 if( pFkp && pPLCF->Get( nPLCFStart, nPLCFEnd, pPage ) )
3183 {
3184 long nPo = SVBT16ToUInt16( static_cast<sal_uInt8 *>(pPage) );
3185 nPo <<= 9; // shift as LONG
3186 if (nPo != pFkp->GetFilePos())
3187 pFkp = nullptr;
3188 else
3189 pFkp->SeekPos( nFcPos );
3190 }
3191 return bRet;
3192}
3193
3194WW8_FC WW8PLCFx_Fc_FKP::Where()
3195{
3196 if( !pFkp && !NewFkp() )
3197 return WW8_FC_MAX;
3198 WW8_FC nP = pFkp ? pFkp->Where() : WW8_FC_MAX;
3199 if( nP != WW8_FC_MAX )
3200 return nP;
3201
3202 pFkp = nullptr; // FKP finished -> get new
3203 return Where(); // easiest way: do it recursively
3204}
3205
3206sal_uInt8* WW8PLCFx_Fc_FKP::GetSprmsAndPos(WW8_FC& rStart, WW8_FC& rEnd, sal_Int32& rLen)
3207{
3208 rLen = 0; // Default
3209 rStart = rEnd = WW8_FC_MAX;
3210
3211 if( !pFkp ) // Fkp not there ?
3212 {
3213 if( !NewFkp() )
3214 return nullptr;
3215 }
3216
3217 sal_uInt8* pPos = pFkp ? pFkp->Get( rStart, rEnd, rLen ) : nullptr;
3218 if( rStart == WW8_FC_MAX ) //Not found
3219 return nullptr;
3220 return pPos;
3221}
3222
3223void WW8PLCFx_Fc_FKP::advance()
3224{
3225 if( !pFkp && !NewFkp() )
3226 return;
3227
3228 if (!pFkp)
3229 return;
3230
3231 pFkp->advance();
3232 if( pFkp->Where() == WW8_FC_MAX )
3233 (void)NewFkp();
3234}
3235
3236sal_uInt16 WW8PLCFx_Fc_FKP::GetIstd() const
3237{
3238 return pFkp ? pFkp->GetIstd() : 0xFFFF;
3239}
3240
3241void WW8PLCFx_Fc_FKP::GetPCDSprms( WW8PLCFxDesc& rDesc )
3242{
3243 rDesc.pMemPos = nullptr;
3244 rDesc.nSprmsLen = 0;
3245 if( pPCDAttrs )
3246 {
3247 if( !pFkp )
3248 {
3249 OSL_FAIL("+Problem: GetPCDSprms: NewFkp necessary (not possible!)" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3249" ": "), "%s", "+Problem: GetPCDSprms: NewFkp necessary (not possible!)"
); } } while (false)
;
3250 if( !NewFkp() )
3251 return;
3252 }
3253 pPCDAttrs->GetSprms(&rDesc);
3254 }
3255}
3256
3257SprmResult WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId, bool bFindFirst)
3258{
3259 // const would be nicer, but for that, NewFkp() would need to be replaced or eliminated
3260 if( !pFkp )
3261 {
3262 OSL_FAIL( "+Motz: HasSprm: NewFkp needed ( no const possible )" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3262" ": "), "%s", "+Motz: HasSprm: NewFkp needed ( no const possible )"
); } } while (false)
;
3263 // happens in BugDoc 31722
3264 if( !NewFkp() )
3265 return SprmResult();
3266 }
3267
3268 if (!pFkp)
3269 return SprmResult();
3270
3271 SprmResult aRes = pFkp->HasSprm(nId, bFindFirst);
3272
3273 if (!aRes.pSprm)
3274 {
3275 WW8PLCFxDesc aDesc;
3276 GetPCDSprms( aDesc );
3277
3278 if (aDesc.pMemPos)
3279 {
3280 WW8SprmIter aIter(aDesc.pMemPos, aDesc.nSprmsLen,
3281 pFkp->GetSprmParser());
3282 aRes = aIter.FindSprm(nId, bFindFirst);
3283 }
3284 }
3285
3286 return aRes;
3287}
3288
3289void WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId, std::vector<SprmResult> &rResult)
3290{
3291 // const would be nicer, but for that, NewFkp() would need to be replaced or eliminated
3292 if (!pFkp)
3293 {
3294 OSL_FAIL( "+Motz: HasSprm: NewFkp needed ( no const possible )" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3294" ": "), "%s", "+Motz: HasSprm: NewFkp needed ( no const possible )"
); } } while (false)
;
3295 // happens in BugDoc 31722
3296 if( !NewFkp() )
3297 return;
3298 }
3299
3300 if (!pFkp)
3301 return;
3302
3303 pFkp->HasSprm(nId, rResult);
3304
3305 WW8PLCFxDesc aDesc;
3306 GetPCDSprms( aDesc );
3307
3308 if (!aDesc.pMemPos)
3309 return;
3310
3311 const wwSprmParser &rSprmParser = pFkp->GetSprmParser();
3312 WW8SprmIter aIter(aDesc.pMemPos, aDesc.nSprmsLen, rSprmParser);
3313 while(aIter.GetSprms())
3314 {
3315 if (aIter.GetCurrentId() == nId)
3316 {
3317 sal_Int32 nFixedLen = rSprmParser.DistanceToData(nId);
3318 sal_Int32 nL = rSprmParser.GetSprmSize(nId, aIter.GetSprms(), aIter.GetRemLen());
3319 rResult.emplace_back(aIter.GetCurrentParams(), nL - nFixedLen);
3320 }
3321 aIter.advance();
3322 };
3323}
3324
3325WW8PLCFx_Cp_FKP::WW8PLCFx_Cp_FKP( SvStream* pSt, SvStream* pTableSt,
3326 SvStream* pDataSt, const WW8ScannerBase& rBase, ePLCFT ePl )
3327 : WW8PLCFx_Fc_FKP(pSt, pTableSt, pDataSt, *rBase.m_pWw8Fib, ePl,
3328 rBase.WW8Cp2Fc(0)), rSBase(rBase), nAttrStart(-1), nAttrEnd(-1),
3329 bLineEnd(false),
3330 bComplex( (7 < rBase.m_pWw8Fib->m_nVersion) || rBase.m_pWw8Fib->m_fComplex )
3331{
3332 ResetAttrStartEnd();
3333
3334 if (rSBase.m_pPiecePLCF)
3335 pPcd.reset( new WW8PLCFx_PCD(GetFIB(), rBase.m_pPiecePLCF.get(), 0, IsSevenMinus(GetFIBVersion())) );
3336
3337 /*
3338 Make a copy of the piece attributes for so that the calls to HasSprm on a
3339 Fc_FKP will be able to take into account the current piece attributes,
3340 despite the fact that such attributes can only be found through a cp based
3341 mechanism.
3342 */
3343 if (pPcd)
3344 {
3345 pPCDAttrs.reset( rSBase.m_pPLCFx_PCDAttrs ? new WW8PLCFx_PCDAttrs(
3346 *rSBase.m_pWw8Fib, pPcd.get(), &rSBase) : nullptr);
3347 }
3348
3349 pPieceIter = rSBase.m_pPieceIter.get();
3350}
3351
3352WW8PLCFx_Cp_FKP::~WW8PLCFx_Cp_FKP()
3353{
3354}
3355
3356void WW8PLCFx_Cp_FKP::ResetAttrStartEnd()
3357{
3358 nAttrStart = -1;
3359 nAttrEnd = -1;
3360 bLineEnd = false;
3361}
3362
3363sal_uInt32 WW8PLCFx_Cp_FKP::GetPCDIdx() const
3364{
3365 return pPcd ? pPcd->GetIdx() : 0;
3366}
3367
3368bool WW8PLCFx_Cp_FKP::SeekPos(WW8_CP nCpPos)
3369{
3370 if( pPcd ) // Complex
3371 {
3372 if( !pPcd->SeekPos( nCpPos ) ) // set piece
3373 return false;
3374 if (pPCDAttrs && !pPCDAttrs->GetIter()->SeekPos(nCpPos))
3375 return false;
3376 return WW8PLCFx_Fc_FKP::SeekPos(pPcd->CurrentPieceStartCp2Fc(nCpPos));
3377 }
3378 // NO piece table !!!
3379 return WW8PLCFx_Fc_FKP::SeekPos( rSBase.WW8Cp2Fc(nCpPos) );
3380}
3381
3382WW8_CP WW8PLCFx_Cp_FKP::Where()
3383{
3384 WW8_FC nFc = WW8PLCFx_Fc_FKP::Where();
3385 if( pPcd )
3386 return pPcd->CurrentPieceStartFc2Cp( nFc ); // identify piece
3387 return rSBase.WW8Fc2Cp( nFc ); // NO piece table !!!
3388}
3389
3390void WW8PLCFx_Cp_FKP::GetSprms(WW8PLCFxDesc* p)
3391{
3392 WW8_CP nOrigCp = p->nStartPos;
3393
3394 if (!GetDirty()) //Normal case
3395 {
3396 p->pMemPos = WW8PLCFx_Fc_FKP::GetSprmsAndPos(p->nStartPos, p->nEndPos,
3397 p->nSprmsLen);
3398 }
3399 else
3400 {
3401 /*
3402 For the odd case where we have a location in a fastsaved file which
3403 does not have an entry in the FKP, perhaps its para end is in the next
3404 piece, or perhaps the cp just doesn't exist at all in this document.
3405 AdvSprm doesn't know so it sets the PLCF as dirty and we figure out
3406 in this method what the situation is
3407
3408 It doesn't exist then the piece iterator will not be able to find it.
3409 Otherwise our cool fastsave algorithm can be brought to bear on the
3410 problem.
3411 */
3412 if( !pPieceIter )
3413 return;
3414 const sal_uInt32 nOldPos = pPieceIter->GetIdx();
3415 bool bOk = pPieceIter->SeekPos(nOrigCp);
3416 pPieceIter->SetIdx(nOldPos);
3417 if (!bOk)
3418 return;
3419 }
3420
3421 if( pPcd ) // piece table available
3422 {
3423 // Init ( no ++ called, yet )
3424 if( (nAttrStart > nAttrEnd) || (nAttrStart == -1) )
3425 {
3426 p->bRealLineEnd = (ePLCF == PAP);
3427
3428 if ( ((ePLCF == PAP ) || (ePLCF == CHP)) && (nOrigCp != WW8_CP_MAX) )
3429 {
3430 bool bIsUnicode=false;
3431 /*
3432 To find the end of a paragraph for a character in a
3433 complex format file.
3434
3435 It is necessary to know the piece that contains the
3436 character and the FC assigned to the character.
3437 */
3438
3439 //We set the piece iterator to the piece that contains the
3440 //character, now we have the correct piece for this character
3441 sal_uInt32 nOldPos = pPieceIter->GetIdx();
3442 p->nStartPos = nOrigCp;
3443 pPieceIter->SeekPos( p->nStartPos);
3444
3445 //This is the FC assigned to the character, but we already
3446 //have the result of the next stage, so we can skip this step
3447 //WW8_FC nStartFc = rSBase.WW8Cp2Fc(p->nStartPos, &bIsUnicode);
3448
3449 /*
3450 Using the FC of the character, first search the FKP that
3451 describes the character to find the smallest FC in the rgfc
3452 that is larger than the character FC.
3453 */
3454 //But the search has already been done, the next largest FC is
3455 //p->nEndPos.
3456 WW8_FC nOldEndPos = p->nEndPos;
3457
3458 /*
3459 If the FC found in the FKP is less than or equal to the limit
3460 FC of the piece, the end of the paragraph that contains the
3461 character is at the FKP FC minus 1.
3462 */
3463 WW8_CP nCpStart, nCpEnd;
3464 void* pData=nullptr;
3465 bool bOk = pPieceIter->Get(nCpStart, nCpEnd, pData);
3466
3467 if (!bOk)
3468 {
3469 pPieceIter->SetIdx(nOldPos);
3470 return;
3471 }
3472
3473 WW8_FC nLimitFC = SVBT32ToUInt32( static_cast<WW8_PCD*>(pData)->fc );
3474 WW8_FC nBeginLimitFC = nLimitFC;
3475 if (IsEightPlus(GetFIBVersion()))
3476 {
3477 nBeginLimitFC =
3478 WW8PLCFx_PCD::TransformPieceAddress(nLimitFC,
3479 bIsUnicode);
3480 }
3481
3482 WW8_CP nCpLen;
3483 bool bFail = o3tl::checked_sub(nCpEnd, nCpStart, nCpLen);
3484 if (bFail)
3485 {
3486 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3486" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3486" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3486" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3486" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3487 p->nStartPos = p->nEndPos = WW8_FC_MAX;
3488 pPieceIter->SetIdx(nOldPos);
3489 return;
3490 }
3491
3492 if (bIsUnicode)
3493 {
3494 bFail = o3tl::checked_multiply<WW8_CP>(nCpLen, 2, nCpLen);
3495 if (bFail)
3496 {
3497 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3497" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3497" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3497" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3497" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3498 p->nStartPos = p->nEndPos = WW8_FC_MAX;
3499 pPieceIter->SetIdx(nOldPos);
3500 return;
3501 }
3502 }
3503
3504 bFail = o3tl::checked_add(nBeginLimitFC, nCpLen, nLimitFC);
3505 if (bFail)
3506 {
3507 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3507" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3507" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3507" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3507" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3508 p->nStartPos = p->nEndPos = WW8_FC_MAX;
3509 pPieceIter->SetIdx(nOldPos);
3510 return;
3511 }
3512
3513 if (nOldEndPos <= nLimitFC)
3514 {
3515 bFail = o3tl::checked_sub(nLimitFC, nOldEndPos, nCpLen);
3516 if (bFail)
3517 {
3518 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3518" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3518" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3518" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3518" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3519 p->nStartPos = p->nEndPos = WW8_FC_MAX;
3520 pPieceIter->SetIdx(nOldPos);
3521 return;
3522 }
3523
3524 nCpLen /= (bIsUnicode ? 2 : 1);
3525
3526 bFail = o3tl::checked_sub(nCpEnd, nCpLen, p->nEndPos);
3527 if (bFail)
3528 {
3529 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3529" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3529" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3529" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3529" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3530 p->nStartPos = p->nEndPos = WW8_FC_MAX;
3531 pPieceIter->SetIdx(nOldPos);
3532 return;
3533 }
3534 }
3535 else
3536 {
3537 if (ePLCF == CHP)
3538 p->nEndPos = nCpEnd;
3539 else
3540 {
3541 /*
3542 If the FKP FC that was found was greater than the FC
3543 of the end of the piece, scan piece by piece toward
3544 the end of the document until a piece is found that
3545 contains a paragraph end mark.
3546 */
3547
3548 /*
3549 It's possible to check if a piece contains a paragraph
3550 mark by using the FC of the beginning of the piece to
3551 search in the FKPs for the smallest FC in the FKP rgfc
3552 that is greater than the FC of the beginning of the
3553 piece. If the FC found is less than or equal to the
3554 limit FC of the piece, then the character that ends
3555 the paragraph is the character immediately before the
3556 FKP fc
3557 */
3558
3559 pPieceIter->advance();
3560
3561 for (;pPieceIter->GetIdx() < pPieceIter->GetIMax();
3562 pPieceIter->advance())
3563 {
3564 if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) )
3565 {
3566 OSL_ENSURE( false, "piece iter broken!" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3566" ": "), "%s", "piece iter broken!"); } } while (false
)
;
3567 break;
3568 }
3569 bIsUnicode = false;
3570 sal_Int32 nFcStart=SVBT32ToUInt32(static_cast<WW8_PCD*>(pData)->fc);
3571
3572 if (IsEightPlus(GetFIBVersion()))
3573 {
3574 nFcStart =
3575 WW8PLCFx_PCD::TransformPieceAddress(
3576 nFcStart,bIsUnicode );
3577 }
3578
3579 bFail = o3tl::checked_sub(nCpEnd, nCpStart, nCpLen);
3580 if (bFail)
3581 {
3582 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3582" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3582" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3582" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3582" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3583 p->nStartPos = p->nEndPos = WW8_FC_MAX;
3584 continue;
3585 }
3586
3587 if (bIsUnicode)
3588 {
3589 bFail = o3tl::checked_multiply<WW8_CP>(nCpLen, 2, nCpLen);
3590 if (bFail)
3591 {
3592 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3592" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3592" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3592" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3592" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3593 p->nStartPos = p->nEndPos = WW8_FC_MAX;
3594 continue;
3595 }
3596 }
3597
3598 bFail = o3tl::checked_add(nFcStart, nCpLen, nLimitFC);
3599 if (bFail)
3600 {
3601 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3601" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3601" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3601" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3601" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3602 p->nStartPos = p->nEndPos = WW8_FC_MAX;
3603 continue;
3604 }
3605
3606 //if it doesn't exist, skip it
3607 if (!SeekPos(nCpStart))
3608 continue;
3609
3610 WW8_FC nOne,nSmallest;
3611 p->pMemPos = WW8PLCFx_Fc_FKP::GetSprmsAndPos(nOne,
3612 nSmallest, p->nSprmsLen);
3613
3614 if (nSmallest <= nLimitFC)
3615 {
3616 WW8_CP nCpDiff;
3617 bFail = o3tl::checked_sub(nLimitFC, nSmallest, nCpDiff);
3618 if (bFail)
3619 {
3620 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3620" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3620" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3620" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3620" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3621 p->nStartPos = p->nEndPos = WW8_FC_MAX;
3622 continue;
3623 }
3624 if (bIsUnicode)
3625 nCpDiff /= 2;
3626
3627 WW8_CP nEndPos;
3628 bFail = o3tl::checked_sub(nCpEnd, nCpDiff, nEndPos);
3629 if (bFail)
3630 {
3631 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3631" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3631" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3631" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3631" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3632 p->nStartPos = p->nEndPos = WW8_FC_MAX;
3633 continue;
3634 }
3635
3636 OSL_ENSURE(nEndPos >= p->nStartPos, "EndPos before StartPos")do { if (true && (!(nEndPos >= p->nStartPos))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3636" ": "), "%s", "EndPos before StartPos"); } } while
(false)
;
3637
3638 if (nEndPos >= p->nStartPos)
3639 p->nEndPos = nEndPos;
3640
3641 break;
3642 }
3643 }
3644 }
3645 }
3646 pPieceIter->SetIdx( nOldPos );
3647 }
3648 else
3649 WW8PLCFx_PCD::CurrentPieceFc2Cp( p->nStartPos, p->nEndPos,&rSBase );
3650 }
3651 else
3652 {
3653 p->nStartPos = nAttrStart;
3654 p->nEndPos = nAttrEnd;
3655 p->bRealLineEnd = bLineEnd;
3656 }
3657 }
3658 else // NO piece table !!!
3659 {
3660 p->nStartPos = rSBase.WW8Fc2Cp( p->nStartPos );
3661 p->nEndPos = rSBase.WW8Fc2Cp( p->nEndPos );
3662 p->bRealLineEnd = ePLCF == PAP;
3663 }
3664}
3665
3666void WW8PLCFx_Cp_FKP::advance()
3667{
3668 WW8PLCFx_Fc_FKP::advance();
3669 // !pPcd: emergency break
3670 if ( !bComplex || !pPcd )
3671 return;
3672
3673 if( GetPCDIdx() >= pPcd->GetIMax() ) // End of PLCF
3674 {
3675 nAttrStart = nAttrEnd = WW8_CP_MAX;
3676 return;
3677 }
3678
3679 sal_Int32 nFkpLen; // Fkp entry
3680 // get Fkp entry
3681 WW8PLCFx_Fc_FKP::GetSprmsAndPos(nAttrStart, nAttrEnd, nFkpLen);
3682
3683 WW8PLCFx_PCD::CurrentPieceFc2Cp( nAttrStart, nAttrEnd, &rSBase );
3684 bLineEnd = (ePLCF == PAP);
3685}
3686
3687WW8PLCFx_SEPX::WW8PLCFx_SEPX(SvStream* pSt, SvStream* pTableSt,
3688 const WW8Fib& rFib, WW8_CP nStartCp)
3689 : WW8PLCFx(rFib, true), maSprmParser(rFib),
3690 pStrm(pSt), nArrMax(256), nSprmSiz(0)
3691{
3692 if (rFib.m_lcbPlcfsed)
3693 pPLCF.reset( new WW8PLCF(*pTableSt, rFib.m_fcPlcfsed, rFib.m_lcbPlcfsed,
3694 GetFIBVersion() <= ww::eWW2 ? 6 : 12, nStartCp) );
3695
3696 pSprms.reset( new sal_uInt8[nArrMax] ); // maximum length
3697}
3698
3699WW8PLCFx_SEPX::~WW8PLCFx_SEPX()
3700{
3701}
3702
3703sal_uInt32 WW8PLCFx_SEPX::GetIdx() const
3704{
3705 return pPLCF ? pPLCF->GetIdx() : 0;
3706}
3707
3708void WW8PLCFx_SEPX::SetIdx(sal_uInt32 nIdx)
3709{
3710 if( pPLCF ) pPLCF->SetIdx( nIdx );
3711}
3712
3713bool WW8PLCFx_SEPX::SeekPos(WW8_CP nCpPos)
3714{
3715 return pPLCF && pPLCF->SeekPos( nCpPos );
3716}
3717
3718WW8_CP WW8PLCFx_SEPX::Where()
3719{
3720 return pPLCF ? pPLCF->Where() : 0;
3721}
3722
3723void WW8PLCFx_SEPX::GetSprms(WW8PLCFxDesc* p)
3724{
3725 if( !pPLCF ) return;
3726
3727 void* pData;
3728
3729 p->bRealLineEnd = false;
3730 if (!pPLCF->Get( p->nStartPos, p->nEndPos, pData ))
3731 {
3732 p->nStartPos = p->nEndPos = WW8_CP_MAX; // PLCF completely processed
3733 p->pMemPos = nullptr;
3734 p->nSprmsLen = 0;
3735 }
3736 else
3737 {
3738 sal_uInt32 nPo = SVBT32ToUInt32( static_cast<sal_uInt8*>(pData)+2 );
3739 if (nPo == 0xFFFFFFFF || !checkSeek(*pStrm, nPo))
3740 {
3741 p->nStartPos = p->nEndPos = WW8_CP_MAX; // Sepx empty
3742 p->pMemPos = nullptr;
3743 p->nSprmsLen = 0;
3744 }
3745 else
3746 {
3747 // read len
3748 if (GetFIBVersion() <= ww::eWW2) // eWW6 ?, docs say yes, but...
3749 {
3750 sal_uInt8 nSiz(0);
3751 pStrm->ReadUChar( nSiz );
3752 nSprmSiz = nSiz;
3753 }
3754 else
3755 {
3756 pStrm->ReadUInt16( nSprmSiz );
3757 }
3758
3759 std::size_t nRemaining = pStrm->remainingSize();
3760 if (nSprmSiz > nRemaining)
3761 nSprmSiz = nRemaining;
3762
3763 if( nSprmSiz > nArrMax )
3764 { // does not fit
3765 nArrMax = nSprmSiz; // Get more memory
3766 pSprms.reset( new sal_uInt8[nArrMax] );
3767 }
3768 nSprmSiz = pStrm->ReadBytes(pSprms.get(), nSprmSiz); // read Sprms
3769
3770 p->nSprmsLen = nSprmSiz;
3771 p->pMemPos = pSprms.get(); // return Position
3772 }
3773 }
3774}
3775
3776void WW8PLCFx_SEPX::advance()
3777{
3778 if (pPLCF)
3779 pPLCF->advance();
3780}
3781
3782SprmResult WW8PLCFx_SEPX::HasSprm(sal_uInt16 nId) const
3783{
3784 return HasSprm(nId, pSprms.get(), nSprmSiz);
3785}
3786
3787SprmResult WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId, const sal_uInt8* pOtherSprms,
3788 long nOtherSprmSiz ) const
3789{
3790 SprmResult aRet;
3791 if (pPLCF)
3792 {
3793 WW8SprmIter aIter(pOtherSprms, nOtherSprmSiz, maSprmParser);
3794 aRet = aIter.FindSprm(nId, /*bFindFirst=*/true);
3795 }
3796 return aRet;
3797}
3798
3799bool WW8PLCFx_SEPX::Find4Sprms(sal_uInt16 nId1,sal_uInt16 nId2,sal_uInt16 nId3,sal_uInt16 nId4,
3800 SprmResult& r1, SprmResult& r2, SprmResult& r3, SprmResult& r4) const
3801{
3802 if( !pPLCF )
3803 return false;
3804
3805 bool bFound = false;
3806
3807 sal_uInt8* pSp = pSprms.get();
3808 size_t i = 0;
3809 while (i + maSprmParser.MinSprmLen() <= nSprmSiz)
3810 {
3811 // Sprm found?
3812 const sal_uInt16 nCurrentId = maSprmParser.GetSprmId(pSp);
3813 sal_Int32 nRemLen = nSprmSiz - i;
3814 const sal_Int32 x = maSprmParser.GetSprmSize(nCurrentId, pSp, nRemLen);
3815 bool bValid = x <= nRemLen;
3816 if (!bValid)
3817 {
3818 SAL_WARN("sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "sprm longer than remaining bytes, doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3818" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "sprm longer than remaining bytes, doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm longer than remaining bytes, doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3818" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "sprm longer than remaining bytes, doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3818" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "sprm longer than remaining bytes, doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm longer than remaining bytes, doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3818" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3819 break;
3820 }
3821 bool bOk = true;
3822 if( nCurrentId == nId1 )
3823 {
3824 sal_Int32 nFixedLen = maSprmParser.DistanceToData(nId1);
3825 r1 = SprmResult(pSp + nFixedLen, x - nFixedLen);
3826 }
3827 else if( nCurrentId == nId2 )
3828 {
3829 sal_Int32 nFixedLen = maSprmParser.DistanceToData(nId2);
3830 r2 = SprmResult(pSp + nFixedLen, x - nFixedLen);
3831 }
3832 else if( nCurrentId == nId3 )
3833 {
3834 sal_Int32 nFixedLen = maSprmParser.DistanceToData(nId3);
3835 r3 = SprmResult(pSp + nFixedLen, x - nFixedLen);
3836 }
3837 else if( nCurrentId == nId4 )
3838 {
3839 sal_Int32 nFixedLen = maSprmParser.DistanceToData(nId4);
3840 r4 = SprmResult(pSp + nFixedLen, x - nFixedLen);
3841 }
3842 else
3843 bOk = false;
3844 bFound |= bOk;
3845 // increment pointer so that it points to next SPRM
3846 i += x;
3847 pSp += x;
3848 }
3849 return bFound;
3850}
3851
3852SprmResult WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId, sal_uInt8 n2nd ) const
3853{
3854 SprmResult aRet;
3855 if (pPLCF)
3856 {
3857 WW8SprmIter aIter(pSprms.get(), nSprmSiz, maSprmParser);
3858 aRet = aIter.FindSprm(nId, /*bFindFirst=*/true, &n2nd);
3859 }
3860 return aRet;
3861}
3862
3863WW8PLCFx_SubDoc::WW8PLCFx_SubDoc(SvStream* pSt, const WW8Fib& rFib,
3864 WW8_CP nStartCp, long nFcRef, long nLenRef, long nFcText, long nLenText,
3865 long nStruct)
3866 : WW8PLCFx(rFib, true)
3867{
3868 if( nLenRef && nLenText )
3869 {
3870 pRef.reset(new WW8PLCF(*pSt, nFcRef, nLenRef, nStruct, nStartCp));
3871 pText.reset(new WW8PLCF(*pSt, nFcText, nLenText, 0, nStartCp));
3872 }
3873}
3874
3875WW8PLCFx_SubDoc::~WW8PLCFx_SubDoc()
3876{
3877 pRef.reset();
3878 pText.reset();
3879}
3880
3881sal_uInt32 WW8PLCFx_SubDoc::GetIdx() const
3882{
3883 // Probably pText ... no need for it
3884 if( pRef )
3885 return ( pRef->GetIdx() << 16 | pText->GetIdx() );
3886 return 0;
3887}
3888
3889void WW8PLCFx_SubDoc::SetIdx(sal_uInt32 nIdx)
3890{
3891 if( pRef )
3892 {
3893 pRef->SetIdx( nIdx >> 16 );
3894 // Probably pText ... no need for it
3895 pText->SetIdx( nIdx & 0xFFFF );
3896 }
3897}
3898
3899bool WW8PLCFx_SubDoc::SeekPos( WW8_CP nCpPos )
3900{
3901 return pRef && pRef->SeekPos( nCpPos );
3902}
3903
3904WW8_CP WW8PLCFx_SubDoc::Where()
3905{
3906 return pRef ? pRef->Where() : WW8_CP_MAX;
3907}
3908
3909void WW8PLCFx_SubDoc::GetSprms(WW8PLCFxDesc* p)
3910{
3911 p->nStartPos = p->nEndPos = WW8_CP_MAX;
3912 p->pMemPos = nullptr;
3913 p->nSprmsLen = 0;
3914 p->bRealLineEnd = false;
3915
3916 if (!pRef)
3917 return;
3918
3919 sal_uInt32 nNr = pRef->GetIdx();
3920
3921 void *pData;
3922 WW8_CP nFoo;
3923 if (!pRef->Get(p->nStartPos, nFoo, pData))
3924 {
3925 p->nEndPos = p->nStartPos = WW8_CP_MAX;
3926 return;
3927 }
3928
3929 if (o3tl::checked_add<WW8_CP>(p->nStartPos, 1, p->nEndPos))
3930 {
3931 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3931" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3931" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3931" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3931" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3932 p->nEndPos = p->nStartPos = WW8_CP_MAX;
3933 return;
3934 }
3935
3936 if (!pText)
3937 return;
3938
3939 pText->SetIdx(nNr);
3940
3941 if (!pText->Get(p->nCp2OrIdx, p->nSprmsLen, pData))
3942 {
3943 p->nEndPos = p->nStartPos = WW8_CP_MAX;
3944 p->nSprmsLen = 0;
3945 return;
3946 }
3947
3948 if (p->nCp2OrIdx < 0 || p->nCp2OrIdx > p->nSprmsLen)
3949 {
3950 SAL_WARN("sw.ww8", "Document has invalid Cp or Idx, ignoring it")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Document has invalid Cp or Idx, ignoring it"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3950" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Document has invalid Cp or Idx, ignoring it"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Document has invalid Cp or Idx, ignoring it"; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3950" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Document has invalid Cp or Idx, ignoring it") ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3950" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Document has invalid Cp or Idx, ignoring it"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Document has invalid Cp or Idx, ignoring it"; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "3950" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
3951 p->nEndPos = p->nStartPos = WW8_CP_MAX;
3952 p->nSprmsLen = 0;
3953 return;
3954 }
3955
3956 p->nSprmsLen -= p->nCp2OrIdx;
3957}
3958
3959void WW8PLCFx_SubDoc::advance()
3960{
3961 if (pRef && pText)
3962 {
3963 pRef->advance();
3964 pText->advance();
3965 }
3966}
3967
3968// fields
3969WW8PLCFx_FLD::WW8PLCFx_FLD( SvStream* pSt, const WW8Fib& rMyFib, short nType)
3970 : WW8PLCFx(rMyFib, true), rFib(rMyFib)
3971{
3972 WW8_FC nFc;
3973 sal_Int32 nLen;
3974
3975 switch( nType )
3976 {
3977 case MAN_HDFT:
3978 nFc = rFib.m_fcPlcffldHdr;
3979 nLen = rFib.m_lcbPlcffldHdr;
3980 break;
3981 case MAN_FTN:
3982 nFc = rFib.m_fcPlcffldFootnote;
3983 nLen = rFib.m_lcbPlcffldFootnote;
3984 break;
3985 case MAN_EDN:
3986 nFc = rFib.m_fcPlcffldEdn;
3987 nLen = rFib.m_lcbPlcffldEdn;
3988 break;
3989 case MAN_AND:
3990 nFc = rFib.m_fcPlcffldAtn;
3991 nLen = rFib.m_lcbPlcffldAtn;
3992 break;
3993 case MAN_TXBX:
3994 nFc = rFib.m_fcPlcffldTxbx;
3995 nLen = rFib.m_lcbPlcffldTxbx;
3996 break;
3997 case MAN_TXBX_HDFT:
3998 nFc = rFib.m_fcPlcffldHdrTxbx;
3999 nLen = rFib.m_lcbPlcffldHdrTxbx;
4000 break;
4001 default:
4002 nFc = rFib.m_fcPlcffldMom;
4003 nLen = rFib.m_lcbPlcffldMom;
4004 break;
4005 }
4006
4007 if( nLen )
4008 pPLCF.reset( new WW8PLCFspecial( pSt, nFc, nLen, 2 ) );
4009}
4010
4011WW8PLCFx_FLD::~WW8PLCFx_FLD()
4012{
4013}
4014
4015sal_uInt32 WW8PLCFx_FLD::GetIdx() const
4016{
4017 return pPLCF ? pPLCF->GetIdx() : 0;
4018}
4019
4020void WW8PLCFx_FLD::SetIdx(sal_uInt32 nIdx)
4021{
4022 if( pPLCF )
4023 pPLCF->SetIdx( nIdx );
4024}
4025
4026bool WW8PLCFx_FLD::SeekPos(WW8_CP nCpPos)
4027{
4028 return pPLCF && pPLCF->SeekPosExact( nCpPos );
4029}
4030
4031WW8_CP WW8PLCFx_FLD::Where()
4032{
4033 return pPLCF ? pPLCF->Where() : WW8_CP_MAX;
4034}
4035
4036bool WW8PLCFx_FLD::StartPosIsFieldStart()
4037{
4038 void* pData;
4039 sal_Int32 nTest;
4040 return pPLCF && pPLCF->Get(nTest, pData) && ((static_cast<sal_uInt8*>(pData)[0] & 0x1f) == 0x13);
4041}
4042
4043bool WW8PLCFx_FLD::EndPosIsFieldEnd(WW8_CP& nCP)
4044{
4045 bool bRet = false;
4046
4047 if (pPLCF)
4048 {
4049 long n = pPLCF->GetIdx();
4050
4051 pPLCF->advance();
4052
4053 void* pData;
4054 sal_Int32 nTest;
4055 if ( pPLCF->Get(nTest, pData) && ((static_cast<sal_uInt8*>(pData)[0] & 0x1f) == 0x15) )
4056 {
4057 nCP = nTest;
4058 bRet = true;
4059 }
4060
4061 pPLCF->SetIdx(n);
4062 }
4063
4064 return bRet;
4065}
4066
4067void WW8PLCFx_FLD::GetSprms(WW8PLCFxDesc* p)
4068{
4069 p->nStartPos = p->nEndPos = WW8_CP_MAX;
4070 p->pMemPos = nullptr;
4071 p->nSprmsLen = 0;
4072 p->bRealLineEnd = false;
4073
4074 if (!pPLCF)
4075 {
4076 p->nStartPos = WW8_CP_MAX; // there are no fields
4077 return;
4078 }
4079
4080 long n = pPLCF->GetIdx();
4081
4082 sal_Int32 nP;
4083 void *pData;
4084 if (!pPLCF->Get(nP, pData)) // end of PLCFspecial?
4085 {
4086 p->nStartPos = WW8_CP_MAX; // PLCF completely processed
4087 return;
4088 }
4089
4090 p->nStartPos = nP;
4091
4092 pPLCF->advance();
4093 if (!pPLCF->Get(nP, pData)) // end of PLCFspecial?
4094 {
4095 p->nStartPos = WW8_CP_MAX; // PLCF completely processed
4096 return;
4097 }
4098
4099 p->nEndPos = nP;
4100
4101 pPLCF->SetIdx(n);
4102
4103 p->nCp2OrIdx = pPLCF->GetIdx();
4104}
4105
4106void WW8PLCFx_FLD::advance()
4107{
4108 SAL_WARN_IF(!pPLCF, "sw.ww8", "Call without PLCFspecial field")do { if (true && (!pPLCF)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "Call without PLCFspecial field"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4108" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Call without PLCFspecial field"), 0
); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Call without PLCFspecial field"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4108" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Call without PLCFspecial field") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4108" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Call without PLCFspecial field"), 0
); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Call without PLCFspecial field"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4108" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4109 if( !pPLCF )
4110 return;
4111 pPLCF->advance();
4112}
4113
4114bool WW8PLCFx_FLD::GetPara(long nIdx, WW8FieldDesc& rF)
4115{
4116 SAL_WARN_IF(!pPLCF, "sw.ww8", "Call without PLCFspecial field")do { if (true && (!pPLCF)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "Call without PLCFspecial field"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4116" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Call without PLCFspecial field"), 0
); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Call without PLCFspecial field"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4116" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Call without PLCFspecial field") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4116" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Call without PLCFspecial field"), 0
); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Call without PLCFspecial field"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4116" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4117 if( !pPLCF )
4118 return false;
4119
4120 long n = pPLCF->GetIdx();
4121 pPLCF->SetIdx(nIdx);
4122
4123 bool bOk = WW8GetFieldPara(*pPLCF, rF);
4124
4125 pPLCF->SetIdx(n);
4126 return bOk;
4127}
4128
4129// WW8PLCF_Book
4130void WW8ReadSTTBF(bool bVer8, SvStream& rStrm, sal_uInt32 nStart, sal_Int32 nLen,
4131 sal_uInt16 nExtraLen, rtl_TextEncoding eCS, std::vector<OUString> &rArray,
4132 std::vector<ww::bytes>* pExtraArray, std::vector<OUString>* pValueArray)
4133{
4134 if (nLen==0) // Handle Empty STTBF
4135 return;
4136
4137 sal_uInt64 const nOldPos = rStrm.Tell();
4138 if (checkSeek(rStrm, nStart))
4139 {
4140 sal_uInt16 nLen2(0);
4141 rStrm.ReadUInt16( nLen2 ); // bVer67: total length of structure
4142 // bVer8 : count of strings
4143
4144 if( bVer8 )
4145 {
4146 sal_uInt16 nStrings(0);
4147 bool bUnicode = (0xFFFF == nLen2);
4148 if (bUnicode)
4149 rStrm.ReadUInt16( nStrings );
4150 else
4151 nStrings = nLen2;
4152
4153 rStrm.ReadUInt16( nExtraLen );
4154
4155 const size_t nMinStringLen = bUnicode ? sizeof(sal_uInt16) : sizeof(sal_uInt8);
4156 const size_t nMinRecordSize = nExtraLen + nMinStringLen;
4157 const size_t nMaxPossibleStrings = rStrm.remainingSize() / nMinRecordSize;
4158 if (nStrings > nMaxPossibleStrings)
4159 {
4160 SAL_WARN("sw.ww8", "STTBF claims " << nStrings << " entries, but only " << nMaxPossibleStrings << " are possible")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "STTBF claims " <<
nStrings << " entries, but only " << nMaxPossibleStrings
<< " are possible") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4160" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "STTBF claims " << nStrings <<
" entries, but only " << nMaxPossibleStrings << " are possible"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "STTBF claims " << nStrings << " entries, but only "
<< nMaxPossibleStrings << " are possible"; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4160" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "STTBF claims " << nStrings << " entries, but only "
<< nMaxPossibleStrings << " are possible") == 1)
{ ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4160" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "STTBF claims " << nStrings <<
" entries, but only " << nMaxPossibleStrings << " are possible"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "STTBF claims " << nStrings << " entries, but only "
<< nMaxPossibleStrings << " are possible"; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4160" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4161 nStrings = nMaxPossibleStrings;
4162 }
4163
4164 if (nExtraLen && nStrings)
4165 {
4166 const size_t nMaxExtraLen = (rStrm.remainingSize() - (nStrings * nMinStringLen)) / nStrings;
4167 if (nExtraLen > nMaxExtraLen)
4168 {
4169 SAL_WARN("sw.ww8", "STTBF claims " << nMaxExtraLen << " extra len, but only " << nMaxExtraLen << " are possible")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "STTBF claims " <<
nMaxExtraLen << " extra len, but only " << nMaxExtraLen
<< " are possible") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4169" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "STTBF claims " << nMaxExtraLen
<< " extra len, but only " << nMaxExtraLen <<
" are possible"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "STTBF claims " << nMaxExtraLen
<< " extra len, but only " << nMaxExtraLen <<
" are possible"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4169" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "STTBF claims " << nMaxExtraLen << " extra len, but only "
<< nMaxExtraLen << " are possible") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4169" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "STTBF claims " << nMaxExtraLen
<< " extra len, but only " << nMaxExtraLen <<
" are possible"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "STTBF claims " << nMaxExtraLen
<< " extra len, but only " << nMaxExtraLen <<
" are possible"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4169" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4170 nExtraLen = nMaxExtraLen;
4171 }
4172 }
4173
4174 for (sal_uInt16 i=0; i < nStrings; ++i)
4175 {
4176 if (bUnicode)
4177 rArray.push_back(read_uInt16_PascalString(rStrm));
4178 else
4179 {
4180 OString aTmp = read_uInt8_lenPrefixed_uInt8s_ToOString(rStrm);
4181 rArray.push_back(OStringToOUString(aTmp, eCS));
4182 }
4183
4184 // Skip the extra data
4185 if (nExtraLen)
4186 {
4187 if (pExtraArray)
4188 {
4189 ww::bytes extraData(nExtraLen);
4190 rStrm.ReadBytes(extraData.data(), nExtraLen);
4191 pExtraArray->push_back(extraData);
4192 }
4193 else
4194 rStrm.SeekRel( nExtraLen );
4195 }
4196 }
4197 // read the value of the document variables, if requested.
4198 if (pValueArray)
4199 {
4200 for (sal_uInt16 i=0; i < nStrings; ++i)
4201 {
4202 if( bUnicode )
4203 pValueArray->push_back(read_uInt16_PascalString(rStrm));
4204 else
4205 {
4206 OString aTmp = read_uInt8_lenPrefixed_uInt8s_ToOString(rStrm);
4207 pValueArray->push_back(OStringToOUString(aTmp, eCS));
4208 }
4209 }
4210 }
4211 }
4212 else
4213 {
4214 if( nLen2 != nLen )
4215 {
4216 OSL_ENSURE(nLen2 == nLen,do { if (true && (!(nLen2 == nLen))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4217" ": "), "%s", "Fib length and read length are different"
); } } while (false)
4217 "Fib length and read length are different")do { if (true && (!(nLen2 == nLen))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4217" ": "), "%s", "Fib length and read length are different"
); } } while (false)
;
4218 if (nLen > SAL_MAX_UINT16((sal_uInt16) 0xFFFF))
4219 nLen = SAL_MAX_UINT16((sal_uInt16) 0xFFFF);
4220 else if (nLen < 2 )
4221 nLen = 2;
4222 nLen2 = static_cast<sal_uInt16>(nLen);
4223 }
4224 sal_uLong nRead = 0;
4225 for( nLen2 -= 2; nRead < nLen2; )
4226 {
4227 sal_uInt8 nBChar(0);
4228 rStrm.ReadUChar( nBChar );
4229 ++nRead;
4230 if (nBChar)
4231 {
4232 OString aTmp = read_uInt8s_ToOString(rStrm, nBChar);
4233 nRead += aTmp.getLength();
4234 rArray.push_back(OStringToOUString(aTmp, eCS));
4235 }
4236 else
4237 rArray.emplace_back();
4238
4239 // Skip the extra data (for bVer67 versions this must come from
4240 // external knowledge)
4241 if (nExtraLen)
4242 {
4243 if (pExtraArray)
4244 {
4245 ww::bytes extraData(nExtraLen);
4246 rStrm.ReadBytes(extraData.data(), nExtraLen);
4247 pExtraArray->push_back(extraData);
4248 }
4249 else
4250 rStrm.SeekRel( nExtraLen );
4251 nRead+=nExtraLen;
4252 }
4253 }
4254 }
4255 }
4256 rStrm.Seek(nOldPos);
4257}
4258
4259WW8PLCFx_Book::WW8PLCFx_Book(SvStream* pTableSt, const WW8Fib& rFib)
4260 : WW8PLCFx(rFib, false), nIsEnd(0), nBookmarkId(1)
4261{
4262 if( !rFib.m_fcPlcfbkf || !rFib.m_lcbPlcfbkf || !rFib.m_fcPlcfbkl ||
4263 !rFib.m_lcbPlcfbkl || !rFib.m_fcSttbfbkmk || !rFib.m_lcbSttbfbkmk )
4264 {
4265 nIMax = 0;
4266 }
4267 else
4268 {
4269 pBook[0].reset( new WW8PLCFspecial(pTableSt,rFib.m_fcPlcfbkf,rFib.m_lcbPlcfbkf,4) );
4270
4271 pBook[1].reset( new WW8PLCFspecial(pTableSt,rFib.m_fcPlcfbkl,rFib.m_lcbPlcfbkl,0) );
4272
4273 rtl_TextEncoding eStructChrSet = WW8Fib::GetFIBCharset(rFib.m_chseTables, rFib.m_lid);
4274
4275 WW8ReadSTTBF( (7 < rFib.m_nVersion), *pTableSt, rFib.m_fcSttbfbkmk,
4276 rFib.m_lcbSttbfbkmk, 0, eStructChrSet, aBookNames );
4277
4278 nIMax = aBookNames.size();
4279
4280 if( pBook[0]->GetIMax() < nIMax ) // Count of Bookmarks
4281 nIMax = pBook[0]->GetIMax();
4282 if( pBook[1]->GetIMax() < nIMax )
4283 nIMax = pBook[1]->GetIMax();
4284 aStatus.resize(nIMax);
4285 }
4286}
4287
4288WW8PLCFx_Book::~WW8PLCFx_Book()
4289{
4290}
4291
4292sal_uInt32 WW8PLCFx_Book::GetIdx() const
4293{
4294 return nIMax ? pBook[0]->GetIdx() : 0;
4295}
4296
4297void WW8PLCFx_Book::SetIdx(sal_uInt32 nI)
4298{
4299 if( nIMax )
4300 pBook[0]->SetIdx( nI );
4301}
4302
4303sal_uInt32 WW8PLCFx_Book::GetIdx2() const
4304{
4305 return nIMax ? ( pBook[1]->GetIdx() | ( nIsEnd ? 0x80000000 : 0 ) ) : 0;
4306}
4307
4308void WW8PLCFx_Book::SetIdx2(sal_uInt32 nI)
4309{
4310 if( nIMax )
4311 {
4312 pBook[1]->SetIdx( nI & 0x7fffffff );
4313 nIsEnd = static_cast<sal_uInt16>( ( nI >> 31 ) & 1 ); // 0 or 1
4314 }
4315}
4316
4317bool WW8PLCFx_Book::SeekPos(WW8_CP nCpPos)
4318{
4319 if( !pBook[0] )
4320 return false;
4321
4322 bool bOk = pBook[0]->SeekPosExact( nCpPos );
4323 bOk &= pBook[1]->SeekPosExact( nCpPos );
4324 nIsEnd = 0;
4325
4326 return bOk;
4327}
4328
4329WW8_CP WW8PLCFx_Book::Where()
4330{
4331 return pBook[nIsEnd]->Where();
4332}
4333
4334long WW8PLCFx_Book::GetNoSprms( WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen )
4335{
4336 void* pData;
4337 rEnd = WW8_CP_MAX;
4338 rLen = 0;
4339
4340 if (!pBook[0] || !pBook[1] || !nIMax || (pBook[nIsEnd]->GetIdx()) >= nIMax)
4341 {
4342 rStart = rEnd = WW8_CP_MAX;
4343 return -1;
4344 }
4345
4346 (void)pBook[nIsEnd]->Get( rStart, pData ); // query position
4347 return pBook[nIsEnd]->GetIdx();
4348}
4349
4350// The operator ++ has a pitfall: If 2 bookmarks adjoin each other,
4351// we should first go to the end of the first one
4352// and then to the beginning of the second one.
4353// But if 2 bookmarks with the length of 0 lie on top of each other,
4354// we *must* first find the start and end of each bookmark.
4355// The case of: ][
4356// [...]
4357// ][
4358// is not solved yet.
4359// Because I must jump back and forth in the start- and end-indices then.
4360// This would require one more index or bitfield to remember
4361// the already processed bookmarks.
4362
4363void WW8PLCFx_Book::advance()
4364{
4365 if( !(pBook[0] && pBook[1] && nIMax) )
4366 return;
4367
4368 (*pBook[nIsEnd]).advance();
4369
4370 sal_uLong l0 = pBook[0]->Where();
4371 sal_uLong l1 = pBook[1]->Where();
4372 if( l0 < l1 )
4373 nIsEnd = 0;
4374 else if( l1 < l0 )
4375 nIsEnd = 1;
4376 else
4377 {
4378 const void * p = pBook[0]->GetData(pBook[0]->GetIdx());
4379 long nPairFor = (p == nullptr) ? 0 : SVBT16ToUInt16(*static_cast<SVBT16 const *>(p));
4380 if (nPairFor == pBook[1]->GetIdx())
4381 nIsEnd = 0;
4382 else
4383 nIsEnd = nIsEnd ? 0 : 1;
4384 }
4385}
4386
4387long WW8PLCFx_Book::GetLen() const
4388{
4389 if( nIsEnd )
1
Assuming field 'nIsEnd' is 0
2
Taking false branch
4390 {
4391 OSL_ENSURE( false, "Incorrect call (1) of PLCF_Book::GetLen()" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4391" ": "), "%s", "Incorrect call (1) of PLCF_Book::GetLen()"
); } } while (false)
;
4392 return 0;
4393 }
4394 void * p;
4395 WW8_CP nStartPos;
4396 if( !pBook[0]->Get( nStartPos, p ) )
3
Calling 'WW8PLCFspecial::Get'
12
Returning from 'WW8PLCFspecial::Get'
13
Taking false branch
4397 {
4398 OSL_ENSURE( false, "Incorrect call (2) of PLCF_Book::GetLen()" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4398" ": "), "%s", "Incorrect call (2) of PLCF_Book::GetLen()"
); } } while (false)
;
4399 return 0;
4400 }
4401 const sal_uInt16 nEndIdx = SVBT16ToUInt16( *static_cast<SVBT16*>(p) );
14
Passing null pointer value via 1st parameter 'p'
15
Calling 'SVBT16ToUInt16'
4402 long nNum = pBook[1]->GetPos( nEndIdx );
4403 nNum -= nStartPos;
4404 return nNum;
4405}
4406
4407void WW8PLCFx_Book::SetStatus(sal_uInt16 nIndex, eBookStatus eStat)
4408{
4409 SAL_WARN_IF(nIndex >= nIMax, "sw.ww8",do { if (true && (nIndex >= nIMax)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "bookmark index "
<< nIndex << " invalid") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4410" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "bookmark index " << nIndex <<
" invalid"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "bookmark index " << nIndex
<< " invalid"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4410" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "bookmark index " << nIndex << " invalid"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4410" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "bookmark index " << nIndex <<
" invalid"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "bookmark index " << nIndex
<< " invalid"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4410" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
4410 "bookmark index " << nIndex << " invalid")do { if (true && (nIndex >= nIMax)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "bookmark index "
<< nIndex << " invalid") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4410" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "bookmark index " << nIndex <<
" invalid"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "bookmark index " << nIndex
<< " invalid"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4410" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "bookmark index " << nIndex << " invalid"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4410" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "bookmark index " << nIndex <<
" invalid"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "bookmark index " << nIndex
<< " invalid"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4410" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4411 eBookStatus eStatus = aStatus.at(nIndex);
4412 aStatus[nIndex] = static_cast<eBookStatus>(eStatus | eStat);
4413}
4414
4415eBookStatus WW8PLCFx_Book::GetStatus() const
4416{
4417 if (aStatus.empty())
4418 return BOOK_NORMAL;
4419 long nEndIdx = GetHandle();
4420 return ( nEndIdx < nIMax ) ? aStatus[nEndIdx] : BOOK_NORMAL;
4421}
4422
4423long WW8PLCFx_Book::GetHandle() const
4424{
4425 if( !pBook[0] || !pBook[1] )
4426 return LONG_MAX9223372036854775807L;
4427
4428 if( nIsEnd )
4429 return pBook[1]->GetIdx();
4430 else
4431 {
4432 if (const void* p = pBook[0]->GetData(pBook[0]->GetIdx()))
4433 return SVBT16ToUInt16( *static_cast<SVBT16 const *>(p) );
4434 else
4435 return LONG_MAX9223372036854775807L;
4436 }
4437}
4438
4439OUString WW8PLCFx_Book::GetBookmark(long nStart,long nEnd, sal_uInt16 &nIndex)
4440{
4441 bool bFound = false;
4442 sal_uInt16 i = 0;
4443 if (pBook[0] && pBook[1])
4444 {
4445 WW8_CP nStartCurrent, nEndCurrent;
4446 while (sal::static_int_cast<decltype(aBookNames)::size_type>(i) < aBookNames.size())
4447 {
4448 void* p;
4449 sal_uInt16 nEndIdx;
4450
4451 if( pBook[0]->GetData( i, nStartCurrent, p ) && p )
4452 nEndIdx = SVBT16ToUInt16( *static_cast<SVBT16*>(p) );
4453 else
4454 {
4455 OSL_ENSURE( false, "Bookmark-EndIdx not readable" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4455" ": "), "%s", "Bookmark-EndIdx not readable"); } }
while (false)
;
4456 nEndIdx = i;
4457 }
4458
4459 nEndCurrent = pBook[1]->GetPos( nEndIdx );
4460
4461 if ((nStartCurrent >= nStart) && (nEndCurrent <= nEnd))
4462 {
4463 nIndex = i;
4464 bFound=true;
4465 break;
4466 }
4467 ++i;
4468 }
4469 }
4470 return bFound ? aBookNames[i] : OUString();
4471}
4472
4473OUString WW8PLCFx_Book::GetUniqueBookmarkName(const OUString &rSuggestedName)
4474{
4475 OUString aRet(rSuggestedName.isEmpty() ? OUString("Unnamed") : rSuggestedName);
4476 size_t i = 0;
4477 while (i < aBookNames.size())
4478 {
4479 if (aRet == aBookNames[i])
4480 {
4481 sal_Int32 len = aRet.getLength();
4482 sal_Int32 p = len - 1;
4483 while (p > 0 && aRet[p] >= '0' && aRet[p] <= '9')
4484 --p;
4485 aRet = aRet.copy(0, p+1) + OUString::number(nBookmarkId++);
4486 i = 0; // start search from beginning
4487 }
4488 else
4489 ++i;
4490 }
4491 return aRet;
4492}
4493
4494void WW8PLCFx_Book::MapName(OUString& rName)
4495{
4496 if( !pBook[0] || !pBook[1] )
4497 return;
4498
4499 size_t i = 0;
4500 while (i < aBookNames.size())
4501 {
4502 if (rName.equalsIgnoreAsciiCase(aBookNames[i]))
4503 {
4504 rName = aBookNames[i];
4505 break;
4506 }
4507 ++i;
4508 }
4509}
4510
4511const OUString* WW8PLCFx_Book::GetName() const
4512{
4513 const OUString *pRet = nullptr;
4514 if (!nIsEnd && (pBook[0]->GetIdx() < nIMax))
4515 pRet = &(aBookNames[pBook[0]->GetIdx()]);
4516 return pRet;
4517}
4518
4519WW8PLCFx_AtnBook::WW8PLCFx_AtnBook(SvStream* pTableSt, const WW8Fib& rFib)
4520 : WW8PLCFx(rFib, /*bSprm=*/false),
4521 m_bIsEnd(false)
4522{
4523 if (!rFib.m_fcPlcfAtnbkf || !rFib.m_lcbPlcfAtnbkf || !rFib.m_fcPlcfAtnbkl || !rFib.m_lcbPlcfAtnbkl)
4524 {
4525 nIMax = 0;
4526 }
4527 else
4528 {
4529 m_pBook[0].reset( new WW8PLCFspecial(pTableSt, rFib.m_fcPlcfAtnbkf, rFib.m_lcbPlcfAtnbkf, 4) );
4530 m_pBook[1].reset( new WW8PLCFspecial(pTableSt, rFib.m_fcPlcfAtnbkl, rFib.m_lcbPlcfAtnbkl, 0) );
4531
4532 nIMax = m_pBook[0]->GetIMax();
4533 if (m_pBook[1]->GetIMax() < nIMax)
4534 nIMax = m_pBook[1]->GetIMax();
4535 }
4536}
4537
4538WW8PLCFx_AtnBook::~WW8PLCFx_AtnBook()
4539{
4540}
4541
4542sal_uInt32 WW8PLCFx_AtnBook::GetIdx() const
4543{
4544 return nIMax ? m_pBook[0]->GetIdx() : 0;
4545}
4546
4547void WW8PLCFx_AtnBook::SetIdx(sal_uInt32 nI)
4548{
4549 if( nIMax )
4550 m_pBook[0]->SetIdx( nI );
4551}
4552
4553sal_uInt32 WW8PLCFx_AtnBook::GetIdx2() const
4554{
4555 if (nIMax)
4556 return m_pBook[1]->GetIdx() | ( m_bIsEnd ? 0x80000000 : 0 );
4557 else
4558 return 0;
4559}
4560
4561void WW8PLCFx_AtnBook::SetIdx2(sal_uInt32 nI)
4562{
4563 if( nIMax )
4564 {
4565 m_pBook[1]->SetIdx( nI & 0x7fffffff );
4566 m_bIsEnd = static_cast<bool>(( nI >> 31 ) & 1);
4567 }
4568}
4569
4570bool WW8PLCFx_AtnBook::SeekPos(WW8_CP nCpPos)
4571{
4572 if (!m_pBook[0])
4573 return false;
4574
4575 bool bOk = m_pBook[0]->SeekPosExact(nCpPos);
4576 bOk &= m_pBook[1]->SeekPosExact(nCpPos);
4577 m_bIsEnd = false;
4578
4579 return bOk;
4580}
4581
4582WW8_CP WW8PLCFx_AtnBook::Where()
4583{
4584 return m_pBook[static_cast<int>(m_bIsEnd)]->Where();
4585}
4586
4587long WW8PLCFx_AtnBook::GetNoSprms( WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen )
4588{
4589 void* pData;
4590 rEnd = WW8_CP_MAX;
4591 rLen = 0;
4592
4593 if (!m_pBook[0] || !m_pBook[1] || !nIMax || (m_pBook[static_cast<int>(m_bIsEnd)]->GetIdx()) >= nIMax)
4594 {
4595 rStart = rEnd = WW8_CP_MAX;
4596 return -1;
4597 }
4598
4599 (void)m_pBook[static_cast<int>(m_bIsEnd)]->Get(rStart, pData);
4600 return m_pBook[static_cast<int>(m_bIsEnd)]->GetIdx();
4601}
4602
4603void WW8PLCFx_AtnBook::advance()
4604{
4605 if( !(m_pBook[0] && m_pBook[1] && nIMax) )
4606 return;
4607
4608 (*m_pBook[static_cast<int>(m_bIsEnd)]).advance();
4609
4610 sal_uLong l0 = m_pBook[0]->Where();
4611 sal_uLong l1 = m_pBook[1]->Where();
4612 if( l0 < l1 )
4613 m_bIsEnd = false;
4614 else if( l1 < l0 )
4615 m_bIsEnd = true;
4616 else
4617 {
4618 const void * p = m_pBook[0]->GetData(m_pBook[0]->GetIdx());
4619 long nPairFor = (p == nullptr) ? 0 : SVBT16ToUInt16(*static_cast<SVBT16 const *>(p));
4620 if (nPairFor == m_pBook[1]->GetIdx())
4621 m_bIsEnd = false;
4622 else
4623 m_bIsEnd = !m_bIsEnd;
4624 }
4625}
4626
4627long WW8PLCFx_AtnBook::getHandle() const
4628{
4629 if (!m_pBook[0] || !m_pBook[1])
4630 return LONG_MAX9223372036854775807L;
4631
4632 if (m_bIsEnd)
4633 return m_pBook[1]->GetIdx();
4634 else
4635 {
4636 if (const void* p = m_pBook[0]->GetData(m_pBook[0]->GetIdx()))
4637 return SVBT16ToUInt16(*static_cast<const SVBT16*>(p));
4638 else
4639 return LONG_MAX9223372036854775807L;
4640 }
4641}
4642
4643bool WW8PLCFx_AtnBook::getIsEnd() const
4644{
4645 return m_bIsEnd;
4646}
4647
4648WW8PLCFx_FactoidBook::WW8PLCFx_FactoidBook(SvStream* pTableSt, const WW8Fib& rFib)
4649 : WW8PLCFx(rFib, /*bSprm=*/false),
4650 m_bIsEnd(false)
4651{
4652 if (!rFib.m_fcPlcfBkfFactoid || !rFib.m_lcbPlcfBkfFactoid || !rFib.m_fcPlcfBklFactoid || !rFib.m_lcbPlcfBklFactoid)
4653 {
4654 m_nIMax = 0;
4655 }
4656 else
4657 {
4658 m_pBook[0].reset(new WW8PLCFspecial(pTableSt, rFib.m_fcPlcfBkfFactoid, rFib.m_lcbPlcfBkfFactoid, 6));
4659 m_pBook[1].reset(new WW8PLCFspecial(pTableSt, rFib.m_fcPlcfBklFactoid, rFib.m_lcbPlcfBklFactoid, 4));
4660
4661 m_nIMax = m_pBook[0]->GetIMax();
4662 if (m_pBook[1]->GetIMax() < m_nIMax)
4663 m_nIMax = m_pBook[1]->GetIMax();
4664 }
4665}
4666
4667WW8PLCFx_FactoidBook::~WW8PLCFx_FactoidBook()
4668{
4669}
4670
4671sal_uInt32 WW8PLCFx_FactoidBook::GetIdx() const
4672{
4673 return m_nIMax ? m_pBook[0]->GetIdx() : 0;
4674}
4675
4676void WW8PLCFx_FactoidBook::SetIdx(sal_uInt32 nI)
4677{
4678 if (m_nIMax)
4679 m_pBook[0]->SetIdx(nI);
4680}
4681
4682sal_uInt32 WW8PLCFx_FactoidBook::GetIdx2() const
4683{
4684 if (m_nIMax)
4685 return m_pBook[1]->GetIdx() | (m_bIsEnd ? 0x80000000 : 0);
4686 else
4687 return 0;
4688}
4689
4690void WW8PLCFx_FactoidBook::SetIdx2(sal_uInt32 nI)
4691{
4692 if (m_nIMax)
4693 {
4694 m_pBook[1]->SetIdx(nI & 0x7fffffff);
4695 m_bIsEnd = static_cast<bool>((nI >> 31) & 1);
4696 }
4697}
4698
4699bool WW8PLCFx_FactoidBook::SeekPos(WW8_CP nCpPos)
4700{
4701 if (!m_pBook[0])
4702 return false;
4703
4704 bool bOk = m_pBook[0]->SeekPosExact(nCpPos);
4705 bOk &= m_pBook[1]->SeekPosExact(nCpPos);
4706 m_bIsEnd = false;
4707
4708 return bOk;
4709}
4710
4711WW8_CP WW8PLCFx_FactoidBook::Where()
4712{
4713 return m_pBook[static_cast<int>(m_bIsEnd)]->Where();
4714}
4715
4716long WW8PLCFx_FactoidBook::GetNoSprms(WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen)
4717{
4718 void* pData;
4719 rEnd = WW8_CP_MAX;
4720 rLen = 0;
4721
4722 if (!m_pBook[0] || !m_pBook[1] || !m_nIMax || (m_pBook[static_cast<int>(m_bIsEnd)]->GetIdx()) >= m_nIMax)
4723 {
4724 rStart = rEnd = WW8_CP_MAX;
4725 return -1;
4726 }
4727
4728 (void)m_pBook[static_cast<int>(m_bIsEnd)]->Get(rStart, pData);
4729 return m_pBook[static_cast<int>(m_bIsEnd)]->GetIdx();
4730}
4731
4732void WW8PLCFx_FactoidBook::advance()
4733{
4734 if (!(m_pBook[0] && m_pBook[1] && m_nIMax))
4735 return;
4736
4737 (*m_pBook[static_cast<int>(m_bIsEnd)]).advance();
4738
4739 sal_uLong l0 = m_pBook[0]->Where();
4740 sal_uLong l1 = m_pBook[1]->Where();
4741 if (l0 < l1)
4742 m_bIsEnd = false;
4743 else if (l1 < l0)
4744 m_bIsEnd = true;
4745 else
4746 {
4747 const void * p = m_pBook[0]->GetData(m_pBook[0]->GetIdx());
4748 long nPairFor = (p == nullptr) ? 0 : SVBT16ToUInt16(*static_cast<SVBT16 const *>(p));
4749 if (nPairFor == m_pBook[1]->GetIdx())
4750 m_bIsEnd = false;
4751 else
4752 m_bIsEnd = !m_bIsEnd;
4753 }
4754}
4755
4756long WW8PLCFx_FactoidBook::getHandle() const
4757{
4758 if (!m_pBook[0] || !m_pBook[1])
4759 return LONG_MAX9223372036854775807L;
4760
4761 if (m_bIsEnd)
4762 return m_pBook[1]->GetIdx();
4763 else
4764 {
4765 if (const void* p = m_pBook[0]->GetData(m_pBook[0]->GetIdx()))
4766 return SVBT16ToUInt16(*static_cast<const SVBT16*>(p));
4767 else
4768 return LONG_MAX9223372036854775807L;
4769 }
4770}
4771
4772bool WW8PLCFx_FactoidBook::getIsEnd() const
4773{
4774 return m_bIsEnd;
4775}
4776
4777// In the end of a paragraph in WW6 the attribute extends after the <CR>.
4778// This will be reset by one character to be used with SW,
4779// if we don't expect trouble thereby.
4780void WW8PLCFMan::AdjustEnds( WW8PLCFxDesc& rDesc )
4781{
4782 // might be necessary to do this for pChp and/or pSep as well,
4783 // but its definitely the case for paragraphs that EndPos > StartPos
4784 // for a well formed paragraph as those always have a paragraph
4785 // <cr> in them
4786 if (&rDesc == m_pPap && rDesc.bRealLineEnd)
4787 {
4788 if (rDesc.nStartPos == rDesc.nEndPos && rDesc.nEndPos != WW8_CP_MAX)
4789 {
4790 SAL_WARN("sw.ww8", "WW8PLCFxDesc End same as Start, abandoning to avoid looping")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "WW8PLCFxDesc End same as Start, abandoning to avoid looping"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4790" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "WW8PLCFxDesc End same as Start, abandoning to avoid looping"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "WW8PLCFxDesc End same as Start, abandoning to avoid looping"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4790" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "WW8PLCFxDesc End same as Start, abandoning to avoid looping"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4790" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "WW8PLCFxDesc End same as Start, abandoning to avoid looping"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "WW8PLCFxDesc End same as Start, abandoning to avoid looping"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4790" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4791 rDesc.nEndPos = WW8_CP_MAX;
4792 }
4793 }
4794
4795 //Store old end position for supercool new property finder that uses
4796 //cp instead of fc's as nature intended
4797 rDesc.nOrigEndPos = rDesc.nEndPos;
4798 rDesc.nOrigStartPos = rDesc.nStartPos;
4799
4800 /*
4801 Normally given ^XXX{para end}^ we don't actually insert a para end
4802 character into the document, so we clip the para end property one to the
4803 left to make the para properties end when the paragraph text does. In a
4804 drawing textbox we actually do insert a para end character, so we don't
4805 clip it. Making the para end properties end after the para end char.
4806 */
4807 if (GetDoingDrawTextBox())
4808 return;
4809
4810 if ( (&rDesc == m_pPap) && rDesc.bRealLineEnd )
4811 {
4812 if ( m_pPap->nEndPos != WW8_CP_MAX ) // Para adjust
4813 {
4814 m_nLineEnd = m_pPap->nEndPos;// nLineEnd points *after* the <CR>
4815 m_pPap->nEndPos--; // shorten paragraph end by one character
4816
4817 // Is there already a sep end, which points to the current paragraph end?
4818 // Then we also must shorten by one character
4819 if( m_pSep->nEndPos == m_nLineEnd )
4820 m_pSep->nEndPos--;
4821 }
4822 }
4823 else if (&rDesc == m_pSep)
4824 {
4825 // Sep Adjust if end Char-Attr == paragraph end ...
4826 if( (rDesc.nEndPos == m_nLineEnd) && (rDesc.nEndPos > rDesc.nStartPos) )
4827 rDesc.nEndPos--; // ... then shorten by one character
4828 }
4829}
4830
4831void WW8PLCFxDesc::ReduceByOffset()
4832{
4833 SAL_WARN_IF(WW8_CP_MAX != nStartPos && nStartPos > nEndPos, "sw.ww8",do { if (true && (WW8_CP_MAX != nStartPos && nStartPos
> nEndPos)) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "End " << nEndPos
<< " before Start " << nStartPos) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4834" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << nEndPos << " before Start "
<< nStartPos), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "End " << nEndPos <<
" before Start " << nStartPos; ::sal::detail::log( (::
SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4834" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "End " << nEndPos << " before Start "
<< nStartPos) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4834" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << nEndPos << " before Start "
<< nStartPos), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "End " << nEndPos <<
" before Start " << nStartPos; ::sal::detail::log( (::
SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4834" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
4834 "End " << nEndPos << " before Start " << nStartPos)do { if (true && (WW8_CP_MAX != nStartPos && nStartPos
> nEndPos)) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "End " << nEndPos
<< " before Start " << nStartPos) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4834" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << nEndPos << " before Start "
<< nStartPos), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "End " << nEndPos <<
" before Start " << nStartPos; ::sal::detail::log( (::
SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4834" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "End " << nEndPos << " before Start "
<< nStartPos) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4834" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << nEndPos << " before Start "
<< nStartPos), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "End " << nEndPos <<
" before Start " << nStartPos; ::sal::detail::log( (::
SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4834" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4835
4836 if( nStartPos != WW8_CP_MAX )
4837 {
4838 /*
4839 ##516##,##517##
4840 Force the property change to happen at the beginning of this
4841 subdocument, same as in GetNewNoSprms, except that the target type is
4842 attributes attached to a piece that might span subdocument boundaries
4843 */
4844 if (nCpOfs > nStartPos)
4845 nStartPos = 0;
4846 else
4847 nStartPos -= nCpOfs;
4848 }
4849 if (nEndPos != WW8_CP_MAX)
4850 {
4851 if (nCpOfs > nEndPos)
4852 {
4853 SAL_WARN("sw.ww8", "broken subdocument piece entry")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken subdocument piece entry"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4853" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken subdocument piece entry"), 0
); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "broken subdocument piece entry"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4853" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken subdocument piece entry") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4853" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken subdocument piece entry"), 0
); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "broken subdocument piece entry"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4853" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4854 nEndPos = WW8_CP_MAX;
4855 }
4856 else
4857 nEndPos -= nCpOfs;
4858 }
4859}
4860
4861void WW8PLCFMan::GetNewSprms( WW8PLCFxDesc& rDesc )
4862{
4863 rDesc.pPLCFx->GetSprms(&rDesc);
4864 rDesc.ReduceByOffset();
4865
4866 rDesc.bFirstSprm = true;
4867 AdjustEnds( rDesc );
4868 rDesc.nOrigSprmsLen = rDesc.nSprmsLen;
4869}
4870
4871void WW8PLCFMan::GetNewNoSprms( WW8PLCFxDesc& rDesc )
4872{
4873 rDesc.nCp2OrIdx = rDesc.pPLCFx->GetNoSprms(rDesc.nStartPos, rDesc.nEndPos,
4874 rDesc.nSprmsLen);
4875
4876 SAL_WARN_IF(WW8_CP_MAX != rDesc.nStartPos && rDesc.nStartPos > rDesc.nEndPos, "sw.ww8",do { if (true && (WW8_CP_MAX != rDesc.nStartPos &&
rDesc.nStartPos > rDesc.nEndPos)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "End " <<
rDesc.nEndPos << " before Start " << rDesc.nStartPos
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4877" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << rDesc.nEndPos <<
" before Start " << rDesc.nStartPos), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"End " << rDesc.nEndPos << " before Start " <<
rDesc.nStartPos; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4877" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "End " << rDesc.nEndPos << " before Start "
<< rDesc.nStartPos) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4877" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << rDesc.nEndPos <<
" before Start " << rDesc.nStartPos), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"End " << rDesc.nEndPos << " before Start " <<
rDesc.nStartPos; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4877" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
4877 "End " << rDesc.nEndPos << " before Start " << rDesc.nStartPos)do { if (true && (WW8_CP_MAX != rDesc.nStartPos &&
rDesc.nStartPos > rDesc.nEndPos)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "End " <<
rDesc.nEndPos << " before Start " << rDesc.nStartPos
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4877" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << rDesc.nEndPos <<
" before Start " << rDesc.nStartPos), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"End " << rDesc.nEndPos << " before Start " <<
rDesc.nStartPos; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4877" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "End " << rDesc.nEndPos << " before Start "
<< rDesc.nStartPos) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4877" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << rDesc.nEndPos <<
" before Start " << rDesc.nStartPos), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"End " << rDesc.nEndPos << " before Start " <<
rDesc.nStartPos; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "4877" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
4878
4879 rDesc.ReduceByOffset();
4880
4881 rDesc.bFirstSprm = true;
4882 rDesc.nOrigSprmsLen = rDesc.nSprmsLen;
4883}
4884
4885sal_uInt16 WW8PLCFMan::GetId(const WW8PLCFxDesc* p) const
4886{
4887 sal_uInt16 nId = 0; // Id = 0 for empty attributes
4888
4889 if (p == m_pField)
4890 nId = eFLD;
4891 else if (p == m_pFootnote)
4892 nId = eFTN;
4893 else if (p == m_pEdn)
4894 nId = eEDN;
4895 else if (p == m_pAnd)
4896 nId = eAND;
4897 else if (p->nSprmsLen >= maSprmParser.MinSprmLen())
4898 nId = maSprmParser.GetSprmId(p->pMemPos);
4899
4900 return nId;
4901}
4902
4903WW8PLCFMan::WW8PLCFMan(const WW8ScannerBase* pBase, ManTypes nType, long nStartCp,
4904 bool bDoingDrawTextBox)
4905 : maSprmParser(*pBase->m_pWw8Fib),
4906 m_nLineEnd(WW8_CP_MAX),
4907 mbDoingDrawTextBox(bDoingDrawTextBox)
4908{
4909 m_pWwFib = pBase->m_pWw8Fib;
4910
4911 m_nManType = nType;
4912
4913 if( MAN_MAINTEXT == nType )
4914 {
4915 // search order of the attributes
4916 m_nPLCF = MAN_PLCF_COUNT;
4917 m_pField = &m_aD[0];
4918 m_pBkm = &m_aD[1];
4919 m_pEdn = &m_aD[2];
4920 m_pFootnote = &m_aD[3];
4921 m_pAnd = &m_aD[4];
4922
4923 m_pPcd = pBase->m_pPLCFx_PCD ? &m_aD[5] : nullptr;
4924 //pPcdA index == pPcd index + 1
4925 m_pPcdA = pBase->m_pPLCFx_PCDAttrs ? &m_aD[6] : nullptr;
4926
4927 m_pChp = &m_aD[7];
4928 m_pPap = &m_aD[8];
4929 m_pSep = &m_aD[9];
4930 m_pAtnBkm = &m_aD[10];
4931 m_pFactoidBkm = &m_aD[11];
4932
4933 m_pSep->pPLCFx = pBase->m_pSepPLCF.get();
4934 m_pFootnote->pPLCFx = pBase->m_pFootnotePLCF.get();
4935 m_pEdn->pPLCFx = pBase->m_pEdnPLCF.get();
4936 m_pBkm->pPLCFx = pBase->m_pBook.get();
4937 m_pAnd->pPLCFx = pBase->m_pAndPLCF.get();
4938 m_pAtnBkm->pPLCFx = pBase->m_pAtnBook.get();
4939 m_pFactoidBkm->pPLCFx = pBase->m_pFactoidBook.get();
4940
4941 }
4942 else
4943 {
4944 // search order of the attributes
4945 m_nPLCF = 7;
4946 m_pField = &m_aD[0];
4947 m_pBkm = pBase->m_pBook ? &m_aD[1] : nullptr;
4948
4949 m_pPcd = pBase->m_pPLCFx_PCD ? &m_aD[2] : nullptr;
4950 //pPcdA index == pPcd index + 1
4951 m_pPcdA= pBase->m_pPLCFx_PCDAttrs ? &m_aD[3] : nullptr;
4952
4953 m_pChp = &m_aD[4];
4954 m_pPap = &m_aD[5];
4955 m_pSep = &m_aD[6]; // Dummy
4956
4957 m_pAnd = m_pAtnBkm = m_pFactoidBkm = m_pFootnote = m_pEdn = nullptr; // not used at SpezText
4958 }
4959
4960 m_pChp->pPLCFx = pBase->m_pChpPLCF.get();
4961 m_pPap->pPLCFx = pBase->m_pPapPLCF.get();
4962 if( m_pPcd )
4963 m_pPcd->pPLCFx = pBase->m_pPLCFx_PCD.get();
4964 if( m_pPcdA )
4965 m_pPcdA->pPLCFx= pBase->m_pPLCFx_PCDAttrs.get();
4966 if( m_pBkm )
4967 m_pBkm->pPLCFx = pBase->m_pBook.get();
4968
4969 m_pMagicTables = pBase->m_pMagicTables.get();
4970 m_pSubdocs = pBase->m_pSubdocs.get();
4971 m_pExtendedAtrds = pBase->m_pExtendedAtrds.get();
4972
4973 switch( nType ) // field initialization
4974 {
4975 case MAN_HDFT:
4976 m_pField->pPLCFx = pBase->m_pFieldHdFtPLCF.get();
4977 m_pFdoa = pBase->m_pHdFtFdoa.get();
4978 m_pTxbx = pBase->m_pHdFtTxbx.get();
4979 m_pTxbxBkd = pBase->m_pHdFtTxbxBkd.get();
4980 break;
4981 case MAN_FTN:
4982 m_pField->pPLCFx = pBase->m_pFieldFootnotePLCF.get();
4983 m_pFdoa = m_pTxbx = m_pTxbxBkd = nullptr;
4984 break;
4985 case MAN_EDN:
4986 m_pField->pPLCFx = pBase->m_pFieldEdnPLCF.get();
4987 m_pFdoa = m_pTxbx = m_pTxbxBkd = nullptr;
4988 break;
4989 case MAN_AND:
4990 m_pField->pPLCFx = pBase->m_pFieldAndPLCF.get();
4991 m_pFdoa = m_pTxbx = m_pTxbxBkd = nullptr;
4992 break;
4993 case MAN_TXBX:
4994 m_pField->pPLCFx = pBase->m_pFieldTxbxPLCF.get();
4995 m_pTxbx = pBase->m_pMainTxbx.get();
4996 m_pTxbxBkd = pBase->m_pMainTxbxBkd.get();
4997 m_pFdoa = nullptr;
4998 break;
4999 case MAN_TXBX_HDFT:
5000 m_pField->pPLCFx = pBase->m_pFieldTxbxHdFtPLCF.get();
5001 m_pTxbx = pBase->m_pHdFtTxbx.get();
5002 m_pTxbxBkd = pBase->m_pHdFtTxbxBkd.get();
5003 m_pFdoa = nullptr;
5004 break;
5005 default:
5006 m_pField->pPLCFx = pBase->m_pFieldPLCF.get();
5007 m_pFdoa = pBase->m_pMainFdoa.get();
5008 m_pTxbx = pBase->m_pMainTxbx.get();
5009 m_pTxbxBkd = pBase->m_pMainTxbxBkd.get();
5010 break;
5011 }
5012
5013 WW8_CP cp = 0;
5014 m_pWwFib->GetBaseCp(nType, &cp); //TODO: check return value
5015 m_nCpO = cp;
5016
5017 if( nStartCp || m_nCpO )
5018 SeekPos( nStartCp ); // adjust PLCFe at text StartPos
5019
5020 // initialization to the member vars Low-Level
5021 GetChpPLCF()->ResetAttrStartEnd();
5022 GetPapPLCF()->ResetAttrStartEnd();
5023 for( sal_uInt16 i=0; i < m_nPLCF; ++i)
5024 {
5025 WW8PLCFxDesc* p = &m_aD[i];
5026
5027 /*
5028 ##516##,##517##
5029 For subdocuments we modify the cp of properties to be relative to
5030 the beginning of subdocuments, we should also do the same for
5031 piecetable changes, and piecetable properties, otherwise a piece
5032 change that happens in a subdocument is lost.
5033 */
5034 p->nCpOfs = ( p == m_pChp || p == m_pPap || p == m_pBkm || p == m_pPcd ||
5035 p == m_pPcdA ) ? m_nCpO : 0;
5036
5037 p->nCp2OrIdx = 0;
5038 p->bFirstSprm = false;
5039 p->pIdStack = nullptr;
5040
5041 if ((p == m_pChp) || (p == m_pPap))
5042 p->nStartPos = p->nEndPos = nStartCp;
5043 else
5044 p->nStartPos = p->nEndPos = WW8_CP_MAX;
5045 }
5046
5047 // initialization to the member vars High-Level
5048 for( sal_uInt16 i=0; i<m_nPLCF; ++i){
5049 WW8PLCFxDesc* p = &m_aD[i];
5050
5051 if( !p->pPLCFx )
5052 {
5053 p->nStartPos = p->nEndPos = WW8_CP_MAX;
5054 continue;
5055 }
5056
5057 if( p->pPLCFx->IsSprm() )
5058 {
5059 // Careful: nEndPos must be
5060 p->pIdStack = new std::stack<sal_uInt16>;
5061 if ((p == m_pChp) || (p == m_pPap))
5062 {
5063 WW8_CP nTemp = p->nEndPos+p->nCpOfs;
5064 p->pMemPos = nullptr;
5065 p->nSprmsLen = 0;
5066 p->nStartPos = nTemp;
5067 if (!(*p->pPLCFx).SeekPos(p->nStartPos))
5068 p->nEndPos = p->nStartPos = WW8_CP_MAX;
5069 else
5070 GetNewSprms( *p );
5071 }
5072 else
5073 GetNewSprms( *p ); // initialized at all PLCFs
5074 }
5075 else if( p->pPLCFx )
5076 GetNewNoSprms( *p );
5077 }
5078}
5079
5080WW8PLCFMan::~WW8PLCFMan()
5081{
5082 for( sal_uInt16 i=0; i<m_nPLCF; i++)
5083 delete m_aD[i].pIdStack;
5084}
5085
5086// 0. which attr class,
5087// 1. if it's an attr start,
5088// 2. CP, where is next attr change
5089sal_uInt16 WW8PLCFMan::WhereIdx(bool *const pbStart, WW8_CP *const pPos) const
5090{
5091 OSL_ENSURE(m_nPLCF,"What the hell")do { if (true && (!(m_nPLCF))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5091" ": "), "%s", "What the hell"); } } while (false)
;
5092 WW8_CP nNext = WW8_CP_MAX; // search order:
5093 sal_uInt16 nNextIdx = m_nPLCF;// first ending found ( CHP, PAP, ( SEP ) ),
5094 bool bStart = true; // now find beginnings ( ( SEP ), PAP, CHP )
5095 const WW8PLCFxDesc* pD;
5096 for (sal_uInt16 i=0; i < m_nPLCF; ++i)
5097 {
5098 pD = &m_aD[i];
5099 if (pD != m_pPcdA)
5100 {
5101 if( (pD->nEndPos < nNext) && (pD->nStartPos == WW8_CP_MAX) )
5102 {
5103 // otherwise start = end
5104 nNext = pD->nEndPos;
5105 nNextIdx = i;
5106 bStart = false;
5107 }
5108 }
5109 }
5110 for (sal_uInt16 i=m_nPLCF; i > 0; --i)
5111 {
5112 pD = &m_aD[i-1];
5113 if (pD != m_pPcdA && pD->nStartPos < nNext )
5114 {
5115 nNext = pD->nStartPos;
5116 nNextIdx = i-1;
5117 bStart = true;
5118 }
5119 }
5120 if( pPos )
5121 *pPos = nNext;
5122 if( pbStart )
5123 *pbStart = bStart;
5124 return nNextIdx;
5125}
5126
5127// gives the CP pos of the next attr change
5128WW8_CP WW8PLCFMan::Where() const
5129{
5130 WW8_CP l;
5131 WhereIdx(nullptr, &l);
5132 return l;
5133}
5134
5135void WW8PLCFMan::SeekPos( long nNewCp )
5136{
5137 m_pChp->pPLCFx->SeekPos( nNewCp + m_nCpO ); // create new attr
5138 m_pPap->pPLCFx->SeekPos( nNewCp + m_nCpO );
5139 m_pField->pPLCFx->SeekPos( nNewCp );
5140 if( m_pPcd )
5141 m_pPcd->pPLCFx->SeekPos( nNewCp + m_nCpO );
5142 if( m_pBkm )
5143 m_pBkm->pPLCFx->SeekPos( nNewCp + m_nCpO );
5144}
5145
5146void WW8PLCFMan::SaveAllPLCFx( WW8PLCFxSaveAll& rSave ) const
5147{
5148 sal_uInt16 n=0;
5149 if( m_pPcd )
5150 m_pPcd->Save( rSave.aS[n++] );
5151 if( m_pPcdA )
5152 m_pPcdA->Save( rSave.aS[n++] );
5153
5154 for(sal_uInt16 i=0; i<m_nPLCF; ++i)
5155 if( m_pPcd != &m_aD[i] && m_pPcdA != &m_aD[i] )
5156 m_aD[i].Save( rSave.aS[n++] );
5157}
5158
5159void WW8PLCFMan::RestoreAllPLCFx( const WW8PLCFxSaveAll& rSave )
5160{
5161 sal_uInt16 n=0;
5162 if( m_pPcd )
5163 m_pPcd->Restore( rSave.aS[n++] );
5164 if( m_pPcdA )
5165 m_pPcdA->Restore( rSave.aS[n++] );
5166
5167 for(sal_uInt16 i=0; i<m_nPLCF; ++i)
5168 if( m_pPcd != &m_aD[i] && m_pPcdA != &m_aD[i] )
5169 m_aD[i].Restore( rSave.aS[n++] );
5170}
5171
5172void WW8PLCFMan::GetSprmStart( short nIdx, WW8PLCFManResult* pRes ) const
5173{
5174 memset( pRes, 0, sizeof( WW8PLCFManResult ) );
5175
5176 // verifying !!!
5177
5178 pRes->nMemLen = 0;
5179
5180 const WW8PLCFxDesc* p = &m_aD[nIdx];
5181
5182 // first Sprm in a Group
5183 if( p->bFirstSprm )
5184 {
5185 if( p == m_pPap )
5186 pRes->nFlags |= MAN_MASK_NEW_PAP;
5187 else if( p == m_pSep )
5188 pRes->nFlags |= MAN_MASK_NEW_SEP;
5189 }
5190 pRes->pMemPos = p->pMemPos;
5191 pRes->nSprmId = GetId(p);
5192 pRes->nCp2OrIdx = p->nCp2OrIdx;
5193 if ((p == m_pFootnote) || (p == m_pEdn) || (p == m_pAnd))
5194 pRes->nMemLen = p->nSprmsLen;
5195 else if (p->nSprmsLen >= maSprmParser.MinSprmLen()) //normal
5196 {
5197 // Length of actual sprm
5198 pRes->nMemLen = maSprmParser.GetSprmSize(pRes->nSprmId, pRes->pMemPos, p->nSprmsLen);
5199 if (pRes->nMemLen > p->nSprmsLen)
5200 {
5201 SAL_WARN("sw.ww8", "Short sprm, len " << pRes->nMemLen << " claimed, max possible is " << p->nSprmsLen)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Short sprm, len " <<
pRes->nMemLen << " claimed, max possible is " <<
p->nSprmsLen) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5201" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Short sprm, len " << pRes->
nMemLen << " claimed, max possible is " << p->
nSprmsLen), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Short sprm, len " << pRes
->nMemLen << " claimed, max possible is " << p
->nSprmsLen; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5201" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Short sprm, len " << pRes->nMemLen <<
" claimed, max possible is " << p->nSprmsLen) == 1)
{ ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5201" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Short sprm, len " << pRes->
nMemLen << " claimed, max possible is " << p->
nSprmsLen), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Short sprm, len " << pRes
->nMemLen << " claimed, max possible is " << p
->nSprmsLen; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5201" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
5202 pRes->nSprmId = 0;
5203 }
5204 }
5205}
5206
5207void WW8PLCFMan::GetSprmEnd( short nIdx, WW8PLCFManResult* pRes ) const
5208{
5209 memset( pRes, 0, sizeof( WW8PLCFManResult ) );
5210
5211 const WW8PLCFxDesc* p = &m_aD[nIdx];
5212
5213 if (!(p->pIdStack->empty()))
5214 pRes->nSprmId = p->pIdStack->top(); // get end position
5215 else
5216 {
5217 OSL_ENSURE( false, "No Id on the Stack" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5217" ": "), "%s", "No Id on the Stack"); } } while (false
)
;
5218 pRes->nSprmId = 0;
5219 }
5220}
5221
5222void WW8PLCFMan::GetNoSprmStart( short nIdx, WW8PLCFManResult* pRes ) const
5223{
5224 const WW8PLCFxDesc* p = &m_aD[nIdx];
5225
5226 pRes->nCpPos = p->nStartPos;
5227 pRes->nMemLen = p->nSprmsLen;
5228 pRes->nCp2OrIdx = p->nCp2OrIdx;
5229
5230 if( p == m_pField )
5231 pRes->nSprmId = eFLD;
5232 else if( p == m_pFootnote )
5233 pRes->nSprmId = eFTN;
5234 else if( p == m_pEdn )
5235 pRes->nSprmId = eEDN;
5236 else if( p == m_pBkm )
5237 pRes->nSprmId = eBKN;
5238 else if (p == m_pAtnBkm)
5239 pRes->nSprmId = eATNBKN;
5240 else if (p == m_pFactoidBkm)
5241 pRes->nSprmId = eFACTOIDBKN;
5242 else if( p == m_pAnd )
5243 pRes->nSprmId = eAND;
5244 else if( p == m_pPcd )
5245 {
5246 //We slave the piece table attributes to the piece table, the piece
5247 //table attribute iterator contains the sprms for this piece.
5248 GetSprmStart( nIdx+1, pRes );
5249 }
5250 else
5251 pRes->nSprmId = 0; // default: not found
5252}
5253
5254void WW8PLCFMan::GetNoSprmEnd( short nIdx, WW8PLCFManResult* pRes ) const
5255{
5256 pRes->nMemLen = -1; // end tag
5257
5258 if( &m_aD[nIdx] == m_pBkm )
5259 pRes->nSprmId = eBKN;
5260 else if (&m_aD[nIdx] == m_pAtnBkm)
5261 pRes->nSprmId = eATNBKN;
5262 else if (&m_aD[nIdx] == m_pFactoidBkm)
5263 pRes->nSprmId = eFACTOIDBKN;
5264 else if( &m_aD[nIdx] == m_pPcd )
5265 {
5266 //We slave the piece table attributes to the piece table, the piece
5267 //table attribute iterator contains the sprms for this piece.
5268 GetSprmEnd( nIdx+1, pRes );
5269 }
5270 else
5271 pRes->nSprmId = 0;
5272}
5273
5274void WW8PLCFMan::TransferOpenSprms(std::stack<sal_uInt16> &rStack)
5275{
5276 for (sal_uInt16 i = 0; i < m_nPLCF; ++i)
5277 {
5278 WW8PLCFxDesc* p = &m_aD[i];
5279 if (!p || !p->pIdStack)
5280 continue;
5281 while (!p->pIdStack->empty())
5282 {
5283 rStack.push(p->pIdStack->top());
5284 p->pIdStack->pop();
5285 }
5286 }
5287}
5288
5289void WW8PLCFMan::AdvSprm(short nIdx, bool bStart)
5290{
5291 WW8PLCFxDesc* p = &m_aD[nIdx]; // determine sprm class(!)
5292
5293 p->bFirstSprm = false;
5294 if( bStart )
5295 {
5296 const sal_uInt16 nLastId = GetId(p);
5297 p->pIdStack->push(nLastId); // remember Id for attribute end
5298
5299 if( p->nSprmsLen )
5300 { /*
5301 Check, if we have to process more sprm(s).
5302 */
5303 if( p->pMemPos )
5304 {
5305 // Length of last sprm
5306 const sal_Int32 nSprmL = maSprmParser.GetSprmSize(nLastId, p->pMemPos, p->nSprmsLen);
5307
5308 // Reduce length of all sprms by length of last sprm
5309 p->nSprmsLen -= nSprmL;
5310
5311 // pos of next possible sprm
5312 if (p->nSprmsLen < maSprmParser.MinSprmLen())
5313 {
5314 // preventively set to 0, because the end follows!
5315 p->pMemPos = nullptr;
5316 p->nSprmsLen = 0;
5317 }
5318 else
5319 p->pMemPos += nSprmL;
5320 }
5321 else
5322 p->nSprmsLen = 0;
5323 }
5324 if (p->nSprmsLen < maSprmParser.MinSprmLen())
5325 p->nStartPos = WW8_CP_MAX; // the ending follows
5326 }
5327 else
5328 {
5329 if (!(p->pIdStack->empty()))
5330 p->pIdStack->pop();
5331 if (p->pIdStack->empty())
5332 {
5333 if ( (p == m_pChp) || (p == m_pPap) )
5334 {
5335 p->pMemPos = nullptr;
5336 p->nSprmsLen = 0;
5337 p->nStartPos = p->nOrigEndPos+p->nCpOfs;
5338
5339 /*
5340 On failed seek we have run out of sprms, probably. But if its
5341 a fastsaved file (has pPcd) then we may be just in a sprm free
5342 gap between pieces that have them, so set dirty flag in sprm
5343 finder to consider than.
5344 */
5345 if (!(*p->pPLCFx).SeekPos(p->nStartPos))
5346 {
5347 p->nEndPos = WW8_CP_MAX;
5348 p->pPLCFx->SetDirty(true);
5349 }
5350 if (!p->pPLCFx->GetDirty() || m_pPcd)
5351 GetNewSprms( *p );
5352 p->pPLCFx->SetDirty(false);
5353
5354 /*
5355 #i2325#
5356 To get the character and paragraph properties you first get
5357 the pap and chp and then apply the fastsaved pPcd properties
5358 to the range. If a pap or chp starts inside the pPcd range
5359 then we must bring the current pPcd range to a halt so as to
5360 end those sprms, then the pap/chp will be processed, and then
5361 we must force a restart of the pPcd on that pap/chp starting
5362 boundary. Doing that effectively means that the pPcd sprms will
5363 be applied to the new range. Not doing it means that the pPcd
5364 sprms will only be applied to the first pap/chp set of
5365 properties contained in the pap/chp range.
5366
5367 So we bring the pPcd to a halt on this location here, by
5368 settings its end to the current start, then store the starting
5369 position of the current range to clipstart. The pPcd sprms
5370 will end as normal (albeit earlier than originally expected),
5371 and the existence of a clipstart will force the pPcd iterator
5372 to reread the current set of sprms instead of advancing to its
5373 next set. Then the clipstart will be set as the starting
5374 position which will force them to be applied directly after
5375 the pap and chps.
5376 */
5377 if (m_pPcd && ((p->nStartPos > m_pPcd->nStartPos) ||
5378 (m_pPcd->nStartPos == WW8_CP_MAX)) &&
5379 (m_pPcd->nEndPos != p->nStartPos))
5380 {
5381 m_pPcd->nEndPos = p->nStartPos;
5382 static_cast<WW8PLCFx_PCD *>(m_pPcd->pPLCFx)->SetClipStart(
5383 p->nStartPos);
5384 }
5385
5386 }
5387 else
5388 {
5389 p->pPLCFx->advance(); // next Group of Sprms
5390 p->pMemPos = nullptr; // !!!
5391 p->nSprmsLen = 0;
5392 GetNewSprms( *p );
5393 }
5394 SAL_WARN_IF(p->nStartPos > p->nEndPos, "sw.ww8",do { if (true && (p->nStartPos > p->nEndPos)
) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "End " << p->
nEndPos << " before Start " << p->nStartPos) ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5395" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << p->nEndPos <<
" before Start " << p->nStartPos), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"End " << p->nEndPos << " before Start " <<
p->nStartPos; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5395" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "End " << p->nEndPos << " before Start "
<< p->nStartPos) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5395" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << p->nEndPos <<
" before Start " << p->nStartPos), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"End " << p->nEndPos << " before Start " <<
p->nStartPos; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5395" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
5395 "End " << p->nEndPos << " before Start " << p->nStartPos)do { if (true && (p->nStartPos > p->nEndPos)
) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "End " << p->
nEndPos << " before Start " << p->nStartPos) ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5395" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << p->nEndPos <<
" before Start " << p->nStartPos), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"End " << p->nEndPos << " before Start " <<
p->nStartPos; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5395" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "End " << p->nEndPos << " before Start "
<< p->nStartPos) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5395" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << p->nEndPos <<
" before Start " << p->nStartPos), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"End " << p->nEndPos << " before Start " <<
p->nStartPos; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5395" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
5396 }
5397 }
5398}
5399
5400void WW8PLCFMan::AdvNoSprm(short nIdx, bool bStart)
5401{
5402 /*
5403 For the case of a piece table we slave the piece table attribute iterator
5404 to the piece table and access it through that only. They are two separate
5405 structures, but act together as one logical one. The attributes only go
5406 to the next entry when the piece changes
5407 */
5408 WW8PLCFxDesc* p = &m_aD[nIdx];
5409
5410 if( p == m_pPcd )
5411 {
5412 AdvSprm(nIdx+1,bStart);
5413 if( bStart )
5414 p->nStartPos = m_aD[nIdx+1].nStartPos;
5415 else
5416 {
5417 if (m_aD[nIdx+1].pIdStack->empty())
5418 {
5419 WW8PLCFx_PCD *pTemp = static_cast<WW8PLCFx_PCD*>(m_pPcd->pPLCFx);
5420 /*
5421 #i2325#
5422 As per normal, go on to the next set of properties, i.e. we
5423 have traversed over to the next piece. With a clipstart set
5424 we are being told to reread the current piece sprms so as to
5425 reapply them to a new chp or pap range.
5426 */
5427 if (pTemp->GetClipStart() == -1)
5428 p->pPLCFx->advance();
5429 p->pMemPos = nullptr;
5430 p->nSprmsLen = 0;
5431 GetNewSprms( m_aD[nIdx+1] );
5432 GetNewNoSprms( *p );
5433 if (pTemp->GetClipStart() != -1)
5434 {
5435 /*
5436 #i2325#, now we will force our starting position to the
5437 clipping start so as to force the application of these
5438 sprms after the current pap/chp sprms so as to apply the
5439 fastsave sprms to the current range.
5440 */
5441 p->nStartPos = pTemp->GetClipStart();
5442 pTemp->SetClipStart(-1);
5443 }
5444 }
5445 }
5446 }
5447 else
5448 { // NoSprm without end
5449 p->pPLCFx->advance();
5450 p->pMemPos = nullptr; // MemPos invalid
5451 p->nSprmsLen = 0;
5452 GetNewNoSprms( *p );
5453 }
5454}
5455
5456void WW8PLCFMan::advance()
5457{
5458 bool bStart;
5459 const sal_uInt16 nIdx = WhereIdx(&bStart);
5460 if (nIdx < m_nPLCF)
5461 {
5462 WW8PLCFxDesc* p = &m_aD[nIdx];
5463
5464 p->bFirstSprm = true; // Default
5465
5466 if( p->pPLCFx->IsSprm() )
5467 AdvSprm( nIdx, bStart );
5468 else // NoSprm
5469 AdvNoSprm( nIdx, bStart );
5470 }
5471}
5472
5473// return true for the beginning of an attribute or error,
5474// false for the end of an attribute
5475// remaining return values are delivered to the caller from WW8PclxManResults.
5476bool WW8PLCFMan::Get(WW8PLCFManResult* pRes) const
5477{
5478 memset( pRes, 0, sizeof( WW8PLCFManResult ) );
5479 bool bStart;
5480 const sal_uInt16 nIdx = WhereIdx(&bStart);
5481
5482 if( nIdx >= m_nPLCF )
5483 {
5484 OSL_ENSURE( false, "Position not found" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5484" ": "), "%s", "Position not found"); } } while (false
)
;
5485 return true;
5486 }
5487
5488 if( m_aD[nIdx].pPLCFx->IsSprm() )
5489 {
5490 if( bStart )
5491 {
5492 GetSprmStart( nIdx, pRes );
5493 return true;
5494 }
5495 else
5496 {
5497 GetSprmEnd( nIdx, pRes );
5498 return false;
5499 }
5500 }
5501 else
5502 {
5503 if( bStart )
5504 {
5505 GetNoSprmStart( nIdx, pRes );
5506 return true;
5507 }
5508 else
5509 {
5510 GetNoSprmEnd( nIdx, pRes );
5511 return false;
5512 }
5513 }
5514}
5515
5516sal_uInt16 WW8PLCFMan::GetColl() const
5517{
5518 if( m_pPap->pPLCFx )
5519 return m_pPap->pPLCFx->GetIstd();
5520 else
5521 {
5522 OSL_ENSURE( false, "GetColl without PLCF_Pap" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5522" ": "), "%s", "GetColl without PLCF_Pap"); } } while
(false)
;
5523 return 0;
5524 }
5525}
5526
5527WW8PLCFx_FLD* WW8PLCFMan::GetField() const
5528{
5529 return static_cast<WW8PLCFx_FLD*>(m_pField->pPLCFx);
5530}
5531
5532SprmResult WW8PLCFMan::HasParaSprm( sal_uInt16 nId ) const
5533{
5534 return static_cast<WW8PLCFx_Cp_FKP*>(m_pPap->pPLCFx)->HasSprm( nId );
5535}
5536
5537SprmResult WW8PLCFMan::HasCharSprm( sal_uInt16 nId ) const
5538{
5539 return static_cast<WW8PLCFx_Cp_FKP*>(m_pChp->pPLCFx)->HasSprm( nId );
5540}
5541
5542void WW8PLCFMan::HasCharSprm(sal_uInt16 nId,
5543 std::vector<SprmResult> &rResult) const
5544{
5545 static_cast<WW8PLCFx_Cp_FKP*>(m_pChp->pPLCFx)->HasSprm(nId, rResult);
5546}
5547
5548void WW8PLCFx::Save( WW8PLCFxSave1& rSave ) const
5549{
5550 rSave.nPLCFxPos = GetIdx();
5551 rSave.nPLCFxPos2 = GetIdx2();
5552 rSave.nPLCFxMemOfs = 0;
5553 rSave.nStartFC = GetStartFc();
5554}
5555
5556void WW8PLCFx::Restore( const WW8PLCFxSave1& rSave )
5557{
5558 SetIdx( rSave.nPLCFxPos );
5559 SetIdx2( rSave.nPLCFxPos2 );
5560 SetStartFc( rSave.nStartFC );
5561}
5562
5563sal_uInt32 WW8PLCFx_Cp_FKP::GetIdx2() const
5564{
5565 return GetPCDIdx();
5566}
5567
5568void WW8PLCFx_Cp_FKP::SetIdx2(sal_uInt32 nIdx)
5569{
5570 if( pPcd )
5571 pPcd->SetIdx( nIdx );
5572}
5573
5574void WW8PLCFx_Cp_FKP::Save( WW8PLCFxSave1& rSave ) const
5575{
5576 if (pFkp)
5577 pFkp->IncMustRemainCache();
5578 WW8PLCFx::Save( rSave );
5579
5580 rSave.nAttrStart = nAttrStart;
5581 rSave.nAttrEnd = nAttrEnd;
5582 rSave.bLineEnd = bLineEnd;
5583}
5584
5585void WW8PLCFx_Cp_FKP::Restore( const WW8PLCFxSave1& rSave )
5586{
5587 WW8PLCFx::Restore( rSave );
5588
5589 nAttrStart = rSave.nAttrStart;
5590 nAttrEnd = rSave.nAttrEnd;
5591 bLineEnd = rSave.bLineEnd;
5592
5593 if (pFkp)
5594 pFkp->DecMustRemainCache();
5595}
5596
5597void WW8PLCFxDesc::Save( WW8PLCFxSave1& rSave ) const
5598{
5599 if( !pPLCFx )
5600 return;
5601
5602 pPLCFx->Save( rSave );
5603 if( !pPLCFx->IsSprm() )
5604 return;
5605
5606 WW8PLCFxDesc aD;
5607 aD.nStartPos = nOrigStartPos+nCpOfs;
5608 aD.nCpOfs = rSave.nCpOfs = nCpOfs;
5609 if (!(pPLCFx->SeekPos(aD.nStartPos)))
5610 {
5611 aD.nEndPos = WW8_CP_MAX;
5612 pPLCFx->SetDirty(true);
5613 }
5614 pPLCFx->GetSprms(&aD);
5615 pPLCFx->SetDirty(false);
5616 aD.ReduceByOffset();
5617 rSave.nStartCp = aD.nStartPos;
5618 rSave.nPLCFxMemOfs = nOrigSprmsLen - nSprmsLen;
5619}
5620
5621void WW8PLCFxDesc::Restore( const WW8PLCFxSave1& rSave )
5622{
5623 if( !pPLCFx )
5624 return;
5625
5626 pPLCFx->Restore( rSave );
5627 if( !pPLCFx->IsSprm() )
5628 return;
5629
5630 WW8PLCFxDesc aD;
5631 aD.nStartPos = rSave.nStartCp+rSave.nCpOfs;
5632 nCpOfs = aD.nCpOfs = rSave.nCpOfs;
5633 if (!(pPLCFx->SeekPos(aD.nStartPos)))
5634 {
5635 aD.nEndPos = WW8_CP_MAX;
5636 pPLCFx->SetDirty(true);
5637 }
5638 pPLCFx->GetSprms(&aD);
5639 pPLCFx->SetDirty(false);
5640 aD.ReduceByOffset();
5641
5642 if (nOrigSprmsLen > aD.nSprmsLen)
5643 {
5644 //two entries exist for the same offset, cut and run
5645 SAL_WARN("sw.ww8", "restored properties don't match saved properties, bailing out")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "restored properties don't match saved properties, bailing out"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5645" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "restored properties don't match saved properties, bailing out"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "restored properties don't match saved properties, bailing out"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5645" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "restored properties don't match saved properties, bailing out"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5645" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "restored properties don't match saved properties, bailing out"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "restored properties don't match saved properties, bailing out"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5645" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
5646 nSprmsLen = 0;
5647 pMemPos = nullptr;
5648 }
5649 else
5650 {
5651 nSprmsLen = nOrigSprmsLen - rSave.nPLCFxMemOfs;
5652 pMemPos = aD.pMemPos == nullptr ? nullptr : aD.pMemPos + rSave.nPLCFxMemOfs;
5653 }
5654}
5655
5656namespace
5657{
5658 sal_uInt32 Readcb(SvStream& rSt, ww::WordVersion eVer)
5659 {
5660 if (eVer <= ww::eWW2)
5661 {
5662 sal_uInt16 nShort(0);
5663 rSt.ReadUInt16(nShort);
5664 return nShort;
5665 }
5666 else
5667 {
5668 sal_uInt32 nLong(0);
5669 rSt.ReadUInt32(nLong);
5670 return nLong;
5671 }
5672 }
5673}
5674
5675bool WW8Fib::GetBaseCp(ManTypes nType, WW8_CP * cp) const
5676{
5677 assert(cp != nullptr)(static_cast <bool> (cp != nullptr) ? void (0) : __assert_fail
("cp != nullptr", "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
, 5677, __extension__ __PRETTY_FUNCTION__))
;
5678 WW8_CP nOffset = 0;
5679
5680 switch (nType)
5681 {
5682 case MAN_TXBX_HDFT:
5683 if (m_ccpTxbx < 0) {
5684 return false;
5685 }
5686 nOffset = m_ccpTxbx;
5687 [[fallthrough]];
5688 case MAN_TXBX:
5689 if (m_ccpEdn < 0 || m_ccpEdn > std::numeric_limits<WW8_CP>::max() - nOffset) {
5690 return false;
5691 }
5692 nOffset += m_ccpEdn;
5693 [[fallthrough]];
5694 case MAN_EDN:
5695 if (m_ccpAtn < 0 || m_ccpAtn > std::numeric_limits<WW8_CP>::max() - nOffset) {
5696 return false;
5697 }
5698 nOffset += m_ccpAtn;
5699 [[fallthrough]];
5700 case MAN_AND:
5701 if (m_ccpMcr < 0 || m_ccpMcr > std::numeric_limits<WW8_CP>::max() - nOffset) {
5702 return false;
5703 }
5704 nOffset += m_ccpMcr;
5705 /*
5706 // fall through
5707
5708 A subdocument of this kind (MAN_MACRO) probably exists in some defunct
5709 version of MSWord, but now ccpMcr is always 0. If some example that
5710 uses this comes to light, this is the likely calculation required
5711
5712 case MAN_MACRO:
5713 */
5714 if (m_ccpHdr < 0 || m_ccpHdr > std::numeric_limits<WW8_CP>::max() - nOffset) {
5715 return false;
5716 }
5717 nOffset += m_ccpHdr;
5718 [[fallthrough]];
5719 case MAN_HDFT:
5720 if (m_ccpFootnote < 0 || m_ccpFootnote > std::numeric_limits<WW8_CP>::max() - nOffset) {
5721 return false;
5722 }
5723 nOffset += m_ccpFootnote;
5724 [[fallthrough]];
5725 case MAN_FTN:
5726 if (m_ccpText < 0 || m_ccpText > std::numeric_limits<WW8_CP>::max() - nOffset) {
5727 return false;
5728 }
5729 nOffset += m_ccpText;
5730 [[fallthrough]];
5731 case MAN_MAINTEXT:
5732 break;
5733 }
5734 *cp = nOffset;
5735 return true;
5736}
5737
5738ww::WordVersion WW8Fib::GetFIBVersion() const
5739{
5740 ww::WordVersion eVer = ww::eWW8;
5741 /*
5742 * Word for Windows 2 I think (1.X might work too if anyone has an example.
5743 *
5744 * 0xA59B for Word 1 for Windows
5745 * 0xA59C for Word 1 for OS/2 "PM Word"
5746 *
5747 * Various pages claim that the fileformats of Word 1 and 2 for Windows are
5748 * equivalent to Word for Macintosh 4 and 5. On the other hand
5749 *
5750 * wIdents for Word for Mac versions...
5751 * 0xFE32 for Word 1
5752 * 0xFE34 for Word 3
5753 * 0xFE37 for Word 4 et 5.
5754 *
5755 * and this document
5756 * http://cmsdoc.cern.ch/documents/docformat/CMS_CERN_LetterHead.word is
5757 * claimed to be "Word 5 for Mac" by Office etc and has that wIdent, but
5758 * its format isn't the same as that of Word 2 for windows. Nor is it
5759 * the same as that of Word for DOS/PCWord 5
5760 */
5761 if (m_wIdent == 0xa59b || m_wIdent == 0xa59c)
5762 eVer = ww::eWW1;
5763 else if (m_wIdent == 0xa5db)
5764 eVer = ww::eWW2;
5765 else
5766 {
5767 switch (m_nVersion)
5768 {
5769 case 6:
5770 eVer = ww::eWW6;
5771 break;
5772 case 7:
5773 eVer = ww::eWW7;
5774 break;
5775 case 8:
5776 eVer = ww::eWW8;
5777 break;
5778 }
5779 }
5780 return eVer;
5781}
5782
5783WW8Fib::WW8Fib(SvStream& rSt, sal_uInt8 nWantedVersion, sal_uInt32 nOffset):
5784 m_fDot(false), m_fGlsy(false), m_fComplex(false), m_fHasPic(false), m_cQuickSaves(0),
5785 m_fEncrypted(false), m_fWhichTableStm(false), m_fReadOnlyRecommended(false),
5786 m_fWriteReservation(false), m_fExtChar(false), m_fFarEast(false), m_fObfuscated(false),
5787 m_fMac(false), m_fEmptySpecial(false), m_fLoadOverridePage(false), m_fFuturesavedUndo(false),
5788 m_fWord97Saved(false), m_fWord2000Saved(false)
5789 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
5790 // above bit-field member initializations can be moved to the class definition
5791{
5792 // See [MS-DOC] 2.5.15 "How to read the FIB".
5793 sal_uInt8 aBits1;
5794 sal_uInt8 aBits2;
5795 sal_uInt8 aVer8Bits1; // only used starting with WinWord 8
5796 rSt.Seek( nOffset );
5797 /*
5798 note desired number, identify file version number
5799 and check against desired number!
5800 */
5801 m_nVersion = nWantedVersion;
5802 rSt.ReadUInt16( m_wIdent );
5803 rSt.ReadUInt16( m_nFib );
5804 rSt.ReadUInt16( m_nProduct );
5805 if( ERRCODE_NONEErrCode(0) != rSt.GetError() )
5806 {
5807 sal_Int16 nFibMin;
5808 sal_Int16 nFibMax;
5809 // note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
5810 switch( m_nVersion )
5811 {
5812 case 6:
5813 nFibMin = 0x0065; // from 101 WinWord 6.0
5814 // 102 "
5815 // and 103 WinWord 6.0 for Macintosh
5816 // 104 "
5817 nFibMax = 0x0069; // to 105 WinWord 95
5818 break;
5819 case 7:
5820 nFibMin = 0x0069; // from 105 WinWord 95
5821 nFibMax = 0x0069; // to 105 WinWord 95
5822 break;
5823 case 8:
5824 nFibMin = 0x006A; // from 106 WinWord 97
5825 nFibMax = 0x00c1; // to 193 WinWord 97 (?)
5826 break;
5827 default:
5828 nFibMin = 0; // program error!
5829 nFibMax = 0;
5830 m_nFib = 1;
5831 OSL_ENSURE( false, "nVersion not implemented!" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "5831" ": "), "%s", "nVersion not implemented!"); } } while
(false)
;
5832 break;
5833 }
5834 if ( (m_nFib < nFibMin) || (m_nFib > nFibMax) )
5835 {
5836 m_nFibError = ERR_SWG_READ_ERRORErrCode(ErrCodeArea::Sw, ErrCodeClass::Read, 2 ); // report error
5837 return;
5838 }
5839 }
5840
5841 ww::WordVersion eVer = GetFIBVersion();
5842
5843 // helper vars for Ver67:
5844 sal_Int16 pnChpFirst_Ver67=0;
5845 sal_Int16 pnPapFirst_Ver67=0;
5846 sal_Int16 cpnBteChp_Ver67=0;
5847 sal_Int16 cpnBtePap_Ver67=0;
5848
5849 // read FIB
5850 sal_uInt16 nTmpLid = 0;
5851 rSt.ReadUInt16(nTmpLid);
5852 m_lid = LanguageType(nTmpLid);
5853 rSt.ReadInt16( m_pnNext );
5854 rSt.ReadUChar( aBits1 );
5855 rSt.ReadUChar( aBits2 );
5856 rSt.ReadUInt16( m_nFibBack );
5857 rSt.ReadUInt16( m_nHash );
5858 rSt.ReadUInt16( m_nKey );
5859 rSt.ReadUChar( m_envr );
5860 rSt.ReadUChar( aVer8Bits1 ); // only have an empty reserve field under Ver67
5861 // content from aVer8Bits1
5862
5863 // sal_uInt8 fMac :1;
5864 // sal_uInt8 fEmptySpecial :1;
5865 // sal_uInt8 fLoadOverridePage :1;
5866 // sal_uInt8 fFuturesavedUndo :1;
5867 // sal_uInt8 fWord97Saved :1;
5868 // sal_uInt8 :3;
5869 rSt.ReadUInt16( m_chse );
5870 rSt.ReadUInt16( m_chseTables );
5871 rSt.ReadInt32( m_fcMin );
5872 rSt.ReadInt32( m_fcMac );
5873
5874// insertion for WW8
5875 if (IsEightPlus(eVer))
5876 {
5877 rSt.ReadUInt16( m_csw );
5878
5879 // Marke: "rgsw" Beginning of the array of shorts
5880 rSt.ReadUInt16( m_wMagicCreated );
5881 rSt.ReadUInt16( m_wMagicRevised );
5882 rSt.ReadUInt16( m_wMagicCreatedPrivate );
5883 rSt.ReadUInt16( m_wMagicRevisedPrivate );
5884 rSt.SeekRel( 9 * sizeof( sal_Int16 ) );
5885
5886 /*
5887 // these are the 9 unused fields:
5888 && (bVer67 || WW8ReadINT16( rSt, pnFbpChpFirst_W6 )) // 1
5889 && (bVer67 || WW8ReadINT16( rSt, pnChpFirst_W6 )) // 2
5890 && (bVer67 || WW8ReadINT16( rSt, cpnBteChp_W6 )) // 3
5891 && (bVer67 || WW8ReadINT16( rSt, pnFbpPapFirst_W6 )) // 4
5892 && (bVer67 || WW8ReadINT16( rSt, pnPapFirst_W6 )) // 5
5893 && (bVer67 || WW8ReadINT16( rSt, cpnBtePap_W6 )) // 6
5894 && (bVer67 || WW8ReadINT16( rSt, pnFbpLvcFirst_W6 )) // 7
5895 && (bVer67 || WW8ReadINT16( rSt, pnLvcFirst_W6 )) // 8
5896 && (bVer67 || WW8ReadINT16( rSt, cpnBteLvc_W6 )) // 9
5897 */
5898 sal_uInt16 nTmpFE = 0;
5899 rSt.ReadUInt16(nTmpFE);
5900 m_lidFE = LanguageType(nTmpFE);
5901 rSt.ReadUInt16( m_clw );
5902 }
5903
5904// end of the insertion for WW8
5905
5906 // Marke: "rglw" Beginning of the array of longs
5907 rSt.ReadInt32( m_cbMac );
5908
5909 // ignore 2 longs, because they are unimportant
5910 rSt.SeekRel( 2 * sizeof( sal_Int32) );
5911
5912 // skipping 2 more longs only at Ver67
5913 if (IsSevenMinus(eVer))
5914 rSt.SeekRel( 2 * sizeof( sal_Int32) );
5915
5916 rSt.ReadInt32( m_ccpText );
5917 rSt.ReadInt32( m_ccpFootnote );
5918 rSt.ReadInt32( m_ccpHdr );
5919 rSt.ReadInt32( m_ccpMcr );
5920 rSt.ReadInt32( m_ccpAtn );
5921 rSt.ReadInt32( m_ccpEdn );
5922 rSt.ReadInt32( m_ccpTxbx );
5923 rSt.ReadInt32( m_ccpHdrTxbx );
5924
5925 // only skip one more long at Ver67
5926 if (IsSevenMinus(eVer))
5927 rSt.SeekRel( 1 * sizeof( sal_Int32) );
5928 else
5929 {
5930// insertion for WW8
5931 rSt.ReadInt32( m_pnFbpChpFirst );
5932 rSt.ReadInt32( m_pnChpFirst );
5933 rSt.ReadInt32( m_cpnBteChp );
5934 rSt.ReadInt32( m_pnFbpPapFirst );
5935 rSt.ReadInt32( m_pnPapFirst );
5936 rSt.ReadInt32( m_cpnBtePap );
5937 rSt.ReadInt32( m_pnFbpLvcFirst );
5938 rSt.ReadInt32( m_pnLvcFirst );
5939 rSt.ReadInt32( m_cpnBteLvc );
5940 rSt.ReadInt32( m_fcIslandFirst );
5941 rSt.ReadInt32( m_fcIslandLim );
5942 rSt.ReadUInt16( m_cfclcb );
5943
5944 // Read cswNew to find out if nFib should be ignored.
5945 sal_uInt32 nPos = rSt.Tell();
5946 rSt.SeekRel(m_cfclcb * 8);
5947 if (rSt.good())
5948 {
5949 rSt.ReadUInt16(m_cswNew);
5950 }
5951 rSt.Seek(nPos);
5952 }
5953
5954// end of the insertion for WW8
5955
5956 // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
5957 rSt.ReadInt32( m_fcStshfOrig );
5958 m_lcbStshfOrig = Readcb(rSt, eVer);
5959 rSt.ReadInt32( m_fcStshf );
5960 m_lcbStshf = Readcb(rSt, eVer);
5961 rSt.ReadInt32( m_fcPlcffndRef );
5962 m_lcbPlcffndRef = Readcb(rSt, eVer);
5963 rSt.ReadInt32( m_fcPlcffndText );
5964 m_lcbPlcffndText = Readcb(rSt, eVer);
5965 rSt.ReadInt32( m_fcPlcfandRef );
5966 m_lcbPlcfandRef = Readcb(rSt, eVer);
5967 rSt.ReadInt32( m_fcPlcfandText );
5968 m_lcbPlcfandText = Readcb(rSt, eVer);
5969 rSt.ReadInt32( m_fcPlcfsed );
5970 m_lcbPlcfsed = Readcb(rSt, eVer);
5971 rSt.ReadInt32( m_fcPlcfpad );
5972 m_lcbPlcfpad = Readcb(rSt, eVer);
5973 rSt.ReadInt32( m_fcPlcfphe );
5974 m_lcbPlcfphe = Readcb(rSt, eVer);
5975 rSt.ReadInt32( m_fcSttbfglsy );
5976 m_lcbSttbfglsy = Readcb(rSt, eVer);
5977 rSt.ReadInt32( m_fcPlcfglsy );
5978 m_lcbPlcfglsy = Readcb(rSt, eVer);
5979 rSt.ReadInt32( m_fcPlcfhdd );
5980 m_lcbPlcfhdd = Readcb(rSt, eVer);
5981 rSt.ReadInt32( m_fcPlcfbteChpx );
5982 m_lcbPlcfbteChpx = Readcb(rSt, eVer);
5983 rSt.ReadInt32( m_fcPlcfbtePapx );
5984 m_lcbPlcfbtePapx = Readcb(rSt, eVer);
5985 rSt.ReadInt32( m_fcPlcfsea );
5986 m_lcbPlcfsea = Readcb(rSt, eVer);
5987 rSt.ReadInt32( m_fcSttbfffn );
5988 m_lcbSttbfffn = Readcb(rSt, eVer);
5989 rSt.ReadInt32( m_fcPlcffldMom );
5990 m_lcbPlcffldMom = Readcb(rSt, eVer);
5991 rSt.ReadInt32( m_fcPlcffldHdr );
5992 m_lcbPlcffldHdr = Readcb(rSt, eVer);
5993 rSt.ReadInt32( m_fcPlcffldFootnote );
5994 m_lcbPlcffldFootnote = Readcb(rSt, eVer);
5995 rSt.ReadInt32( m_fcPlcffldAtn );
5996 m_lcbPlcffldAtn = Readcb(rSt, eVer);
5997 rSt.ReadInt32( m_fcPlcffldMcr );
5998 m_lcbPlcffldMcr = Readcb(rSt, eVer);
5999 rSt.ReadInt32( m_fcSttbfbkmk );
6000 m_lcbSttbfbkmk = Readcb(rSt, eVer);
6001 rSt.ReadInt32( m_fcPlcfbkf );
6002 m_lcbPlcfbkf = Readcb(rSt, eVer);
6003 rSt.ReadInt32( m_fcPlcfbkl );
6004 m_lcbPlcfbkl = Readcb(rSt, eVer);
6005 rSt.ReadInt32( m_fcCmds );
6006 m_lcbCmds = Readcb(rSt, eVer);
6007 rSt.ReadInt32( m_fcPlcfmcr );
6008 m_lcbPlcfmcr = Readcb(rSt, eVer);
6009 rSt.ReadInt32( m_fcSttbfmcr );
6010 m_lcbSttbfmcr = Readcb(rSt, eVer);
6011 if (eVer >= ww::eWW2)
6012 {
6013 rSt.ReadInt32( m_fcPrDrvr );
6014 m_lcbPrDrvr = Readcb(rSt, eVer);
6015 rSt.ReadInt32( m_fcPrEnvPort );
6016 m_lcbPrEnvPort = Readcb(rSt, eVer);
6017 rSt.ReadInt32( m_fcPrEnvLand );
6018 m_lcbPrEnvLand = Readcb(rSt, eVer);
6019 }
6020 else
6021 {
6022 rSt.ReadInt32( m_fcPrEnvPort );
6023 m_lcbPrEnvPort = Readcb(rSt, eVer);
6024 }
6025 rSt.ReadInt32( m_fcWss );
6026 m_lcbWss = Readcb(rSt, eVer);
6027 rSt.ReadInt32( m_fcDop );
6028 m_lcbDop = Readcb(rSt, eVer);
6029 rSt.ReadInt32( m_fcSttbfAssoc );
6030 m_lcbSttbfAssoc = Readcb(rSt, eVer);
6031 rSt.ReadInt32( m_fcClx );
6032 m_lcbClx = Readcb(rSt, eVer);
6033 rSt.ReadInt32( m_fcPlcfpgdFootnote );
6034 m_lcbPlcfpgdFootnote = Readcb(rSt, eVer);
6035 rSt.ReadInt32( m_fcAutosaveSource );
6036 m_lcbAutosaveSource = Readcb(rSt, eVer);
6037 rSt.ReadInt32( m_fcGrpStAtnOwners );
6038 m_lcbGrpStAtnOwners = Readcb(rSt, eVer);
6039 rSt.ReadInt32( m_fcSttbfAtnbkmk );
6040 m_lcbSttbfAtnbkmk = Readcb(rSt, eVer);
6041
6042 // only skip more shot at Ver67
6043 if (IsSevenMinus(eVer))
6044 {
6045 if (eVer == ww::eWW1)
6046 rSt.SeekRel(1*sizeof(sal_Int32));
6047 rSt.SeekRel(1*sizeof(sal_Int16));
6048
6049 if (eVer >= ww::eWW2)
6050 {
6051 rSt.ReadInt16(pnChpFirst_Ver67);
6052 rSt.ReadInt16(pnPapFirst_Ver67);
6053 }
6054 rSt.ReadInt16(cpnBteChp_Ver67);
6055 rSt.ReadInt16(cpnBtePap_Ver67);
6056 }
6057
6058 if (eVer > ww::eWW2)
6059 {
6060 rSt.ReadInt32( m_fcPlcfdoaMom );
6061 rSt.ReadInt32( m_lcbPlcfdoaMom );
6062 rSt.ReadInt32( m_fcPlcfdoaHdr );
6063 rSt.ReadInt32( m_lcbPlcfdoaHdr );
6064 rSt.ReadInt32( m_fcPlcfspaMom );
6065 rSt.ReadInt32( m_lcbPlcfspaMom );
6066 rSt.ReadInt32( m_fcPlcfspaHdr );
6067 rSt.ReadInt32( m_lcbPlcfspaHdr );
6068
6069 rSt.ReadInt32( m_fcPlcfAtnbkf );
6070 rSt.ReadInt32( m_lcbPlcfAtnbkf );
6071 rSt.ReadInt32( m_fcPlcfAtnbkl );
6072 rSt.ReadInt32( m_lcbPlcfAtnbkl );
6073 rSt.ReadInt32( m_fcPms );
6074 rSt.ReadInt32( m_lcbPMS );
6075 rSt.ReadInt32( m_fcFormFieldSttbf );
6076 rSt.ReadInt32( m_lcbFormFieldSttbf );
6077 rSt.ReadInt32( m_fcPlcfendRef );
6078 rSt.ReadInt32( m_lcbPlcfendRef );
6079 rSt.ReadInt32( m_fcPlcfendText );
6080 rSt.ReadInt32( m_lcbPlcfendText );
6081 rSt.ReadInt32( m_fcPlcffldEdn );
6082 rSt.ReadInt32( m_lcbPlcffldEdn );
6083 rSt.ReadInt32( m_fcPlcfpgdEdn );
6084 rSt.ReadInt32( m_lcbPlcfpgdEdn );
6085 rSt.ReadInt32( m_fcDggInfo );
6086 rSt.ReadInt32( m_lcbDggInfo );
6087 rSt.ReadInt32( m_fcSttbfRMark );
6088 rSt.ReadInt32( m_lcbSttbfRMark );
6089 rSt.ReadInt32( m_fcSttbfCaption );
6090 rSt.ReadInt32( m_lcbSttbfCaption );
6091 rSt.ReadInt32( m_fcSttbAutoCaption );
6092 rSt.ReadInt32( m_lcbSttbAutoCaption );
6093 rSt.ReadInt32( m_fcPlcfwkb );
6094 rSt.ReadInt32( m_lcbPlcfwkb );
6095 rSt.ReadInt32( m_fcPlcfspl );
6096 rSt.ReadInt32( m_lcbPlcfspl );
6097 rSt.ReadInt32( m_fcPlcftxbxText );
6098 rSt.ReadInt32( m_lcbPlcftxbxText );
6099 rSt.ReadInt32( m_fcPlcffldTxbx );
6100 rSt.ReadInt32( m_lcbPlcffldTxbx );
6101 rSt.ReadInt32( m_fcPlcfHdrtxbxText );
6102 rSt.ReadInt32( m_lcbPlcfHdrtxbxText );
6103 rSt.ReadInt32( m_fcPlcffldHdrTxbx );
6104 rSt.ReadInt32( m_lcbPlcffldHdrTxbx );
6105 rSt.ReadInt32( m_fcStwUser );
6106 rSt.ReadUInt32( m_lcbStwUser );
6107 rSt.ReadInt32( m_fcSttbttmbd );
6108 rSt.ReadUInt32( m_lcbSttbttmbd );
6109 }
6110
6111 if( ERRCODE_NONEErrCode(0) == rSt.GetError() )
6112 {
6113 // set bit flag
6114 m_fDot = aBits1 & 0x01 ;
6115 m_fGlsy = ( aBits1 & 0x02 ) >> 1;
6116 m_fComplex = ( aBits1 & 0x04 ) >> 2;
6117 m_fHasPic = ( aBits1 & 0x08 ) >> 3;
6118 m_cQuickSaves = ( aBits1 & 0xf0 ) >> 4;
6119 m_fEncrypted = aBits2 & 0x01 ;
6120 m_fWhichTableStm= ( aBits2 & 0x02 ) >> 1;
6121 m_fReadOnlyRecommended = (aBits2 & 0x4) >> 2;
6122 m_fWriteReservation = (aBits2 & 0x8) >> 3;
6123 m_fExtChar = ( aBits2 & 0x10 ) >> 4;
6124 // dummy = ( aBits2 & 0x20 ) >> 5;
6125 m_fFarEast = ( aBits2 & 0x40 ) >> 6; // #i90932#
6126 // dummy = ( aBits2 & 0x80 ) >> 7;
6127
6128 /*
6129 p.r.n. fill targeted variable with xxx_Ver67
6130 or set flags
6131 */
6132 if (IsSevenMinus(eVer))
6133 {
6134 m_pnChpFirst = pnChpFirst_Ver67;
6135 m_pnPapFirst = pnPapFirst_Ver67;
6136 m_cpnBteChp = cpnBteChp_Ver67;
6137 m_cpnBtePap = cpnBtePap_Ver67;
6138 }
6139 else if (IsEightPlus(eVer))
6140 {
6141 m_fMac = aVer8Bits1 & 0x01 ;
6142 m_fEmptySpecial = ( aVer8Bits1 & 0x02 ) >> 1;
6143 m_fLoadOverridePage = ( aVer8Bits1 & 0x04 ) >> 2;
6144 m_fFuturesavedUndo = ( aVer8Bits1 & 0x08 ) >> 3;
6145 m_fWord97Saved = ( aVer8Bits1 & 0x10 ) >> 4;
6146 m_fWord2000Saved = ( aVer8Bits1 & 0x20 ) >> 5;
6147
6148 /*
6149 especially for WW8:
6150 identify the values for PLCF and PLF LFO
6151 and PLCF for the textbox break descriptors
6152 */
6153 long nOldPos = rSt.Tell();
6154
6155 rSt.Seek( 0x02da );
6156 rSt.ReadInt32( m_fcSttbFnm );
6157 rSt.ReadInt32( m_lcbSttbFnm );
6158 rSt.ReadInt32( m_fcPlcfLst );
6159 rSt.ReadInt32( m_lcbPlcfLst );
6160 rSt.ReadInt32( m_fcPlfLfo );
6161 rSt.ReadInt32( m_lcbPlfLfo );
6162 rSt.ReadInt32( m_fcPlcftxbxBkd );
6163 rSt.ReadInt32( m_lcbPlcftxbxBkd );
6164 rSt.ReadInt32( m_fcPlcfHdrtxbxBkd );
6165 rSt.ReadInt32( m_lcbPlcfHdrtxbxBkd );
6166 if( ERRCODE_NONEErrCode(0) != rSt.GetError() )
6167 {
6168 m_nFibError = ERR_SWG_READ_ERRORErrCode(ErrCodeArea::Sw, ErrCodeClass::Read, 2 );
6169 }
6170
6171 rSt.Seek( 0x372 ); // fcSttbListNames
6172 rSt.ReadInt32( m_fcSttbListNames );
6173 rSt.ReadInt32( m_lcbSttbListNames );
6174
6175 if (m_cfclcb > 93)
6176 {
6177 rSt.Seek( 0x382 ); // MagicTables
6178 rSt.ReadInt32( m_fcPlcfTch );
6179 rSt.ReadInt32( m_lcbPlcfTch );
6180 }
6181
6182 if (m_cfclcb > 113)
6183 {
6184 rSt.Seek( 0x41A ); // new ATRD
6185 rSt.ReadInt32( m_fcAtrdExtra );
6186 rSt.ReadUInt32( m_lcbAtrdExtra );
6187 }
6188
6189 // Factoid bookmarks
6190 if (m_cfclcb > 134)
6191 {
6192 rSt.Seek(0x432);
6193 rSt.ReadInt32(m_fcPlcfBkfFactoid);
6194 rSt.ReadUInt32(m_lcbPlcfBkfFactoid);
6195
6196 rSt.Seek(0x442);
6197 rSt.ReadInt32(m_fcPlcfBklFactoid);
6198 rSt.ReadUInt32(m_lcbPlcfBklFactoid);
6199
6200 rSt.Seek(0x44a);
6201 rSt.ReadInt32(m_fcFactoidData);
6202 rSt.ReadUInt32(m_lcbFactoidData);
6203 }
6204
6205 if( ERRCODE_NONEErrCode(0) != rSt.GetError() )
6206 m_nFibError = ERR_SWG_READ_ERRORErrCode(ErrCodeArea::Sw, ErrCodeClass::Read, 2 );
6207
6208 rSt.Seek( 0x5bc ); // Actual nFib introduced in Word 2003
6209 rSt.ReadUInt16( m_nFib_actual );
6210
6211 rSt.Seek( nOldPos );
6212 }
6213 }
6214 else
6215 {
6216 m_nFibError = ERR_SWG_READ_ERRORErrCode(ErrCodeArea::Sw, ErrCodeClass::Read, 2 ); // report error
6217 }
6218}
6219
6220WW8Fib::WW8Fib(sal_uInt8 nVer, bool bDot):
6221 m_nVersion(nVer), m_fDot(false), m_fGlsy(false), m_fComplex(false), m_fHasPic(false), m_cQuickSaves(0),
6222 m_fEncrypted(false), m_fWhichTableStm(false), m_fReadOnlyRecommended(false),
6223 m_fWriteReservation(false), m_fExtChar(false), m_fFarEast(false), m_fObfuscated(false),
6224 m_fMac(false), m_fEmptySpecial(false), m_fLoadOverridePage(false), m_fFuturesavedUndo(false),
6225 m_fWord97Saved(false), m_fWord2000Saved(false)
6226 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
6227 // above bit-field member initializations can be moved to the class definition
6228{
6229 if (8 == nVer)
6230 {
6231 m_fcMin = 0x800;
6232 m_wIdent = 0xa5ec;
6233 m_nFib = 0x0101;
6234 m_nFibBack = 0xbf;
6235 m_nProduct = 0x204D;
6236 m_fDot = bDot;
6237
6238 m_csw = 0x0e; // Is this really necessary???
6239 m_cfclcb = 0x88; // -""-
6240 m_clw = 0x16; // -""-
6241 m_pnFbpChpFirst = m_pnFbpPapFirst = m_pnFbpLvcFirst = 0x000fffff;
6242 m_fExtChar = true;
6243 m_fWord97Saved = m_fWord2000Saved = true;
6244
6245 // Just a fancy way to write 'Caolan80'.
6246 m_wMagicCreated = 0x6143;
6247 m_wMagicRevised = 0x6C6F;
6248 m_wMagicCreatedPrivate = 0x6E61;
6249 m_wMagicRevisedPrivate = 0x3038;
6250 }
6251 else
6252 {
6253 m_fcMin = 0x300;
6254 m_wIdent = 0xa5dc;
6255 m_nFib = m_nFibBack = 0x65;
6256 m_nProduct = 0xc02d;
6257 }
6258
6259 //If nFib is 0x00D9 or greater, then cQuickSaves MUST be 0xF
6260 m_cQuickSaves = m_nFib >= 0x00D9 ? 0xF : 0;
6261
6262 // --> #i90932#
6263 m_lid = LanguageType(0x409); // LANGUAGE_ENGLISH_US
6264
6265 LanguageType nLang = Application::GetSettings().GetLanguageTag().getLanguageType();
6266 m_fFarEast = MsLangId::isCJK(nLang);
6267 if (m_fFarEast)
6268 m_lidFE = nLang;
6269 else
6270 m_lidFE = m_lid;
6271
6272 LanguageTag aLanguageTag( m_lid );
6273 LocaleDataWrapper aLocaleWrapper( aLanguageTag );
6274 m_nNumDecimalSep = aLocaleWrapper.getNumDecimalSep()[0];
6275}
6276
6277
6278void WW8Fib::WriteHeader(SvStream& rStrm)
6279{
6280 bool bVer8 = 8 == m_nVersion;
6281
6282 size_t nUnencryptedHdr = bVer8 ? 0x44 : 0x24;
6283 std::unique_ptr<sal_uInt8[]> pDataPtr( new sal_uInt8[ nUnencryptedHdr ] );
6284 sal_uInt8 *pData = pDataPtr.get();
6285 memset( pData, 0, nUnencryptedHdr );
6286
6287 m_cbMac = rStrm.TellEnd();
6288
6289 Set_UInt16( pData, m_wIdent );
6290 Set_UInt16( pData, m_nFib );
6291 Set_UInt16( pData, m_nProduct );
6292 Set_UInt16( pData, static_cast<sal_uInt16>(m_lid) );
6293 Set_UInt16( pData, m_pnNext );
6294
6295 sal_uInt16 nBits16 = 0;
6296 if( m_fDot ) nBits16 |= 0x0001;
6297 if( m_fGlsy) nBits16 |= 0x0002;
6298 if( m_fComplex ) nBits16 |= 0x0004;
6299 if( m_fHasPic ) nBits16 |= 0x0008;
6300 nBits16 |= (0xf0 & ( m_cQuickSaves << 4 ));
6301 if( m_fEncrypted ) nBits16 |= 0x0100;
6302 if( m_fWhichTableStm ) nBits16 |= 0x0200;
6303
6304 if (m_fReadOnlyRecommended)
6305 nBits16 |= 0x0400;
6306 if (m_fWriteReservation)
6307 nBits16 |= 0x0800;
6308
6309 if( m_fExtChar ) nBits16 |= 0x1000;
6310 if( m_fFarEast ) nBits16 |= 0x4000; // #i90932#
6311 if( m_fObfuscated ) nBits16 |= 0x8000;
6312 Set_UInt16( pData, nBits16 );
6313
6314 Set_UInt16( pData, m_nFibBack );
6315 Set_UInt16( pData, m_nHash );
6316 Set_UInt16( pData, m_nKey );
6317 Set_UInt8( pData, m_envr );
6318
6319 sal_uInt8 nBits8 = 0;
6320 if( bVer8 )
6321 {
6322 if( m_fMac ) nBits8 |= 0x0001;
6323 if( m_fEmptySpecial ) nBits8 |= 0x0002;
6324 if( m_fLoadOverridePage ) nBits8 |= 0x0004;
6325 if( m_fFuturesavedUndo ) nBits8 |= 0x0008;
6326 if( m_fWord97Saved ) nBits8 |= 0x0010;
6327 if( m_fWord2000Saved ) nBits8 |= 0x0020;
6328 }
6329 // under Ver67 these are only reserved
6330 Set_UInt8( pData, nBits8 );
6331
6332 Set_UInt16( pData, m_chse );
6333 Set_UInt16( pData, m_chseTables );
6334 Set_UInt32( pData, m_fcMin );
6335 Set_UInt32( pData, m_fcMac );
6336
6337// insertion for WW8
6338
6339 // Marke: "rgsw" Beginning of the array of shorts
6340 if( bVer8 )
6341 {
6342 Set_UInt16( pData, m_csw );
6343 Set_UInt16( pData, m_wMagicCreated );
6344 Set_UInt16( pData, m_wMagicRevised );
6345 Set_UInt16( pData, m_wMagicCreatedPrivate );
6346 Set_UInt16( pData, m_wMagicRevisedPrivate );
6347 pData += 9 * sizeof( sal_Int16 );
6348 Set_UInt16( pData, static_cast<sal_uInt16>(m_lidFE) );
6349 Set_UInt16( pData, m_clw );
6350 }
6351
6352// end of the insertion for WW8
6353
6354 // Marke: "rglw" Beginning of the array of longs
6355 Set_UInt32( pData, m_cbMac );
6356
6357 rStrm.WriteBytes(pDataPtr.get(), nUnencryptedHdr);
6358}
6359
6360void WW8Fib::Write(SvStream& rStrm)
6361{
6362 bool bVer8 = 8 == m_nVersion;
6363
6364 WriteHeader( rStrm );
6365
6366 size_t nUnencryptedHdr = bVer8 ? 0x44 : 0x24;
6367
6368 std::unique_ptr<sal_uInt8[]> pDataPtr( new sal_uInt8[ m_fcMin - nUnencryptedHdr ] );
6369 sal_uInt8 *pData = pDataPtr.get();
6370 memset( pData, 0, m_fcMin - nUnencryptedHdr );
6371
6372 m_cbMac = rStrm.TellEnd();
6373
6374 // ignore 2 longs, because they are unimportant
6375 pData += 2 * sizeof( sal_Int32);
6376
6377 // skipping 2 more longs only at Ver67
6378 if( !bVer8 )
6379 pData += 2 * sizeof( sal_Int32);
6380
6381 Set_UInt32( pData, m_ccpText );
6382 Set_UInt32( pData, m_ccpFootnote );
6383 Set_UInt32( pData, m_ccpHdr );
6384 Set_UInt32( pData, m_ccpMcr );
6385 Set_UInt32( pData, m_ccpAtn );
6386 Set_UInt32( pData, m_ccpEdn );
6387 Set_UInt32( pData, m_ccpTxbx );
6388 Set_UInt32( pData, m_ccpHdrTxbx );
6389
6390 // only skip one more long at Ver67
6391 if( !bVer8 )
6392 pData += 1 * sizeof( sal_Int32);
6393
6394// insertion for WW8
6395 if( bVer8 )
6396 {
6397 Set_UInt32( pData, m_pnFbpChpFirst );
6398 Set_UInt32( pData, m_pnChpFirst );
6399 Set_UInt32( pData, m_cpnBteChp );
6400 Set_UInt32( pData, m_pnFbpPapFirst );
6401 Set_UInt32( pData, m_pnPapFirst );
6402 Set_UInt32( pData, m_cpnBtePap );
6403 Set_UInt32( pData, m_pnFbpLvcFirst );
6404 Set_UInt32( pData, m_pnLvcFirst );
6405 Set_UInt32( pData, m_cpnBteLvc );
6406 Set_UInt32( pData, m_fcIslandFirst );
6407 Set_UInt32( pData, m_fcIslandLim );
6408 Set_UInt16( pData, m_cfclcb );
6409 }
6410// end of the insertion for WW8
6411
6412 // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
6413 Set_UInt32( pData, m_fcStshfOrig );
6414 Set_UInt32( pData, m_lcbStshfOrig );
6415 Set_UInt32( pData, m_fcStshf );
6416 Set_UInt32( pData, m_lcbStshf );
6417 Set_UInt32( pData, m_fcPlcffndRef );
6418 Set_UInt32( pData, m_lcbPlcffndRef );
6419 Set_UInt32( pData, m_fcPlcffndText );
6420 Set_UInt32( pData, m_lcbPlcffndText );
6421 Set_UInt32( pData, m_fcPlcfandRef );
6422 Set_UInt32( pData, m_lcbPlcfandRef );
6423 Set_UInt32( pData, m_fcPlcfandText );
6424 Set_UInt32( pData, m_lcbPlcfandText );
6425 Set_UInt32( pData, m_fcPlcfsed );
6426 Set_UInt32( pData, m_lcbPlcfsed );
6427 Set_UInt32( pData, m_fcPlcfpad );
6428 Set_UInt32( pData, m_lcbPlcfpad );
6429 Set_UInt32( pData, m_fcPlcfphe );
6430 Set_UInt32( pData, m_lcbPlcfphe );
6431 Set_UInt32( pData, m_fcSttbfglsy );
6432 Set_UInt32( pData, m_lcbSttbfglsy );
6433 Set_UInt32( pData, m_fcPlcfglsy );
6434 Set_UInt32( pData, m_lcbPlcfglsy );
6435 Set_UInt32( pData, m_fcPlcfhdd );
6436 Set_UInt32( pData, m_lcbPlcfhdd );
6437 Set_UInt32( pData, m_fcPlcfbteChpx );
6438 Set_UInt32( pData, m_lcbPlcfbteChpx );
6439 Set_UInt32( pData, m_fcPlcfbtePapx );
6440 Set_UInt32( pData, m_lcbPlcfbtePapx );
6441 Set_UInt32( pData, m_fcPlcfsea );
6442 Set_UInt32( pData, m_lcbPlcfsea );
6443 Set_UInt32( pData, m_fcSttbfffn );
6444 Set_UInt32( pData, m_lcbSttbfffn );
6445 Set_UInt32( pData, m_fcPlcffldMom );
6446 Set_UInt32( pData, m_lcbPlcffldMom );
6447 Set_UInt32( pData, m_fcPlcffldHdr );
6448 Set_UInt32( pData, m_lcbPlcffldHdr );
6449 Set_UInt32( pData, m_fcPlcffldFootnote );
6450 Set_UInt32( pData, m_lcbPlcffldFootnote );
6451 Set_UInt32( pData, m_fcPlcffldAtn );
6452 Set_UInt32( pData, m_lcbPlcffldAtn );
6453 Set_UInt32( pData, m_fcPlcffldMcr );
6454 Set_UInt32( pData, m_lcbPlcffldMcr );
6455 Set_UInt32( pData, m_fcSttbfbkmk );
6456 Set_UInt32( pData, m_lcbSttbfbkmk );
6457 Set_UInt32( pData, m_fcPlcfbkf );
6458 Set_UInt32( pData, m_lcbPlcfbkf );
6459 Set_UInt32( pData, m_fcPlcfbkl );
6460 Set_UInt32( pData, m_lcbPlcfbkl );
6461 Set_UInt32( pData, m_fcCmds );
6462 Set_UInt32( pData, m_lcbCmds );
6463 Set_UInt32( pData, m_fcPlcfmcr );
6464 Set_UInt32( pData, m_lcbPlcfmcr );
6465 Set_UInt32( pData, m_fcSttbfmcr );
6466 Set_UInt32( pData, m_lcbSttbfmcr );
6467 Set_UInt32( pData, m_fcPrDrvr );
6468 Set_UInt32( pData, m_lcbPrDrvr );
6469 Set_UInt32( pData, m_fcPrEnvPort );
6470 Set_UInt32( pData, m_lcbPrEnvPort );
6471 Set_UInt32( pData, m_fcPrEnvLand );
6472 Set_UInt32( pData, m_lcbPrEnvLand );
6473 Set_UInt32( pData, m_fcWss );
6474 Set_UInt32( pData, m_lcbWss );
6475 Set_UInt32( pData, m_fcDop );
6476 Set_UInt32( pData, m_lcbDop );
6477 Set_UInt32( pData, m_fcSttbfAssoc );
6478 Set_UInt32( pData, m_lcbSttbfAssoc );
6479 Set_UInt32( pData, m_fcClx );
6480 Set_UInt32( pData, m_lcbClx );
6481 Set_UInt32( pData, m_fcPlcfpgdFootnote );
6482 Set_UInt32( pData, m_lcbPlcfpgdFootnote );
6483 Set_UInt32( pData, m_fcAutosaveSource );
6484 Set_UInt32( pData, m_lcbAutosaveSource );
6485 Set_UInt32( pData, m_fcGrpStAtnOwners );
6486 Set_UInt32( pData, m_lcbGrpStAtnOwners );
6487 Set_UInt32( pData, m_fcSttbfAtnbkmk );
6488 Set_UInt32( pData, m_lcbSttbfAtnbkmk );
6489
6490 // only skip one more short at Ver67
6491 if( !bVer8 )
6492 {
6493 pData += 1*sizeof( sal_Int16);
6494 Set_UInt16( pData, static_cast<sal_uInt16>(m_pnChpFirst) );
6495 Set_UInt16( pData, static_cast<sal_uInt16>(m_pnPapFirst) );
6496 Set_UInt16( pData, static_cast<sal_uInt16>(m_cpnBteChp) );
6497 Set_UInt16( pData, static_cast<sal_uInt16>(m_cpnBtePap) );
6498 }
6499
6500 Set_UInt32( pData, m_fcPlcfdoaMom ); // only at Ver67, in Ver8 unused
6501 Set_UInt32( pData, m_lcbPlcfdoaMom ); // only at Ver67, in Ver8 unused
6502 Set_UInt32( pData, m_fcPlcfdoaHdr ); // only at Ver67, in Ver8 unused
6503 Set_UInt32( pData, m_lcbPlcfdoaHdr ); // only at Ver67, in Ver8 unused
6504
6505 Set_UInt32( pData, m_fcPlcfspaMom ); // in Ver67 empty reserve
6506 Set_UInt32( pData, m_lcbPlcfspaMom ); // in Ver67 empty reserve
6507 Set_UInt32( pData, m_fcPlcfspaHdr ); // in Ver67 empty reserve
6508 Set_UInt32( pData, m_lcbPlcfspaHdr ); // in Ver67 empty reserve
6509
6510 Set_UInt32( pData, m_fcPlcfAtnbkf );
6511 Set_UInt32( pData, m_lcbPlcfAtnbkf );
6512 Set_UInt32( pData, m_fcPlcfAtnbkl );
6513 Set_UInt32( pData, m_lcbPlcfAtnbkl );
6514 Set_UInt32( pData, m_fcPms );
6515 Set_UInt32( pData, m_lcbPMS );
6516 Set_UInt32( pData, m_fcFormFieldSttbf );
6517 Set_UInt32( pData, m_lcbFormFieldSttbf );
6518 Set_UInt32( pData, m_fcPlcfendRef );
6519 Set_UInt32( pData, m_lcbPlcfendRef );
6520 Set_UInt32( pData, m_fcPlcfendText );
6521 Set_UInt32( pData, m_lcbPlcfendText );
6522 Set_UInt32( pData, m_fcPlcffldEdn );
6523 Set_UInt32( pData, m_lcbPlcffldEdn );
6524 Set_UInt32( pData, m_fcPlcfpgdEdn );
6525 Set_UInt32( pData, m_lcbPlcfpgdEdn );
6526 Set_UInt32( pData, m_fcDggInfo ); // in Ver67 empty reserve
6527 Set_UInt32( pData, m_lcbDggInfo ); // in Ver67 empty reserve
6528 Set_UInt32( pData, m_fcSttbfRMark );
6529 Set_UInt32( pData, m_lcbSttbfRMark );
6530 Set_UInt32( pData, m_fcSttbfCaption );
6531 Set_UInt32( pData, m_lcbSttbfCaption );
6532 Set_UInt32( pData, m_fcSttbAutoCaption );
6533 Set_UInt32( pData, m_lcbSttbAutoCaption );
6534 Set_UInt32( pData, m_fcPlcfwkb );
6535 Set_UInt32( pData, m_lcbPlcfwkb );
6536 Set_UInt32( pData, m_fcPlcfspl ); // in Ver67 empty reserve
6537 Set_UInt32( pData, m_lcbPlcfspl ); // in Ver67 empty reserve
6538 Set_UInt32( pData, m_fcPlcftxbxText );
6539 Set_UInt32( pData, m_lcbPlcftxbxText );
6540 Set_UInt32( pData, m_fcPlcffldTxbx );
6541 Set_UInt32( pData, m_lcbPlcffldTxbx );
6542 Set_UInt32( pData, m_fcPlcfHdrtxbxText );
6543 Set_UInt32( pData, m_lcbPlcfHdrtxbxText );
6544 Set_UInt32( pData, m_fcPlcffldHdrTxbx );
6545 Set_UInt32( pData, m_lcbPlcffldHdrTxbx );
6546
6547 if( bVer8 )
6548 {
6549 pData += 0x2da - 0x27a; // Pos + Offset (fcPlcfLst - fcStwUser)
6550 Set_UInt32( pData, m_fcSttbFnm);
6551 Set_UInt32( pData, m_lcbSttbFnm);
6552 Set_UInt32( pData, m_fcPlcfLst );
6553 Set_UInt32( pData, m_lcbPlcfLst );
6554 Set_UInt32( pData, m_fcPlfLfo );
6555 Set_UInt32( pData, m_lcbPlfLfo );
6556 Set_UInt32( pData, m_fcPlcftxbxBkd );
6557 Set_UInt32( pData, m_lcbPlcftxbxBkd );
6558 Set_UInt32( pData, m_fcPlcfHdrtxbxBkd );
6559 Set_UInt32( pData, m_lcbPlcfHdrtxbxBkd );
6560
6561 pData += 0x372 - 0x302; // Pos + Offset (fcSttbListNames - fcDocUndo)
6562 Set_UInt32( pData, m_fcSttbListNames );
6563 Set_UInt32( pData, m_lcbSttbListNames );
6564
6565 pData += 0x382 - 0x37A;
6566 Set_UInt32( pData, m_fcPlcfTch );
6567 Set_UInt32( pData, m_lcbPlcfTch );
6568
6569 pData += 0x3FA - 0x38A;
6570 Set_UInt16( pData, sal_uInt16(0x0002));
6571 Set_UInt16( pData, sal_uInt16(0x00D9));
6572
6573 pData += 0x41A - 0x3FE;
6574 Set_UInt32( pData, m_fcAtrdExtra );
6575 Set_UInt32( pData, m_lcbAtrdExtra );
6576
6577 pData += 0x42a - 0x422;
6578 Set_UInt32(pData, m_fcSttbfBkmkFactoid);
6579 Set_UInt32(pData, m_lcbSttbfBkmkFactoid);
6580 Set_UInt32(pData, m_fcPlcfBkfFactoid);
6581 Set_UInt32(pData, m_lcbPlcfBkfFactoid);
6582
6583 pData += 0x442 - 0x43A;
6584 Set_UInt32(pData, m_fcPlcfBklFactoid);
6585 Set_UInt32(pData, m_lcbPlcfBklFactoid);
6586 Set_UInt32(pData, m_fcFactoidData);
6587 Set_UInt32(pData, m_lcbFactoidData);
6588
6589 pData += 0x4BA - 0x452;
6590 Set_UInt32(pData, m_fcPlcffactoid);
6591 Set_UInt32(pData, m_lcbPlcffactoid);
6592
6593 pData += 0x4DA - 0x4c2;
6594 Set_UInt32( pData, m_fcHplxsdr );
6595 Set_UInt32( pData, 0);
6596 }
6597
6598 rStrm.WriteBytes(pDataPtr.get(), m_fcMin - nUnencryptedHdr);
6599}
6600
6601rtl_TextEncoding WW8Fib::GetFIBCharset(sal_uInt16 chs, LanguageType nLidLocale)
6602{
6603 OSL_ENSURE(chs <= 0x100, "overflowed winword charset set")do { if (true && (!(chs <= 0x100))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6603" ": "), "%s", "overflowed winword charset set"); }
} while (false)
;
6604 if (chs == 0x0100)
6605 return RTL_TEXTENCODING_APPLE_ROMAN(((rtl_TextEncoding) 2));
6606 if (chs == 0 && static_cast<sal_uInt16>(nLidLocale) >= 999)
6607 {
6608 /*
6609 nLidLocale:
6610 language stamp -- localized version In pre-WinWord 2.0 files this
6611 value was the nLocale. If value is < 999, then it is the nLocale,
6612 otherwise it is the lid.
6613 */
6614 css::lang::Locale aLocale(LanguageTag::convertToLocale(nLidLocale));
6615 return msfilter::util::getBestTextEncodingFromLocale(aLocale);
6616 }
6617 return rtl_getTextEncodingFromWindowsCharset(static_cast<sal_uInt8>(chs));
6618}
6619
6620MSOFactoidType::MSOFactoidType()
6621 : m_nId(0)
6622{
6623}
6624
6625namespace MSOPBString
6626{
6627static OUString Read(SvStream& rStream)
6628{
6629 OUString aRet;
6630
6631 sal_uInt16 nBuf(0);
6632 rStream.ReadUInt16(nBuf);
6633 sal_uInt16 nCch = nBuf & 0x7fff; // Bits 1..15.
6634 bool bAnsiString = (nBuf & (1 << 15)) >> 15; // 16th bit.
6635 if (bAnsiString)
6636 aRet = OStringToOUString(read_uInt8s_ToOString(rStream, nCch), RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11)));
6637 else
6638 aRet = read_uInt16s_ToOUString(rStream, nCch);
6639
6640 return aRet;
6641}
6642
6643static void Write(const OUString& rString, SvStream& rStream)
6644{
6645 sal_uInt16 nBuf = 0;
6646 nBuf |= rString.getLength(); // cch, 0..14th bits.
6647 nBuf |= 0x8000; // fAnsiString, 15th bit.
6648 rStream.WriteUInt16(nBuf);
6649 SwWW8Writer::WriteString8(rStream, rString, false, RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11)));
6650}
6651};
6652
6653void MSOFactoidType::Read(SvStream& rStream)
6654{
6655 sal_uInt32 cbFactoid(0);
6656 rStream.ReadUInt32(cbFactoid);
6657 rStream.ReadUInt32(m_nId);
6658 m_aUri = MSOPBString::Read(rStream);
6659 m_aTag = MSOPBString::Read(rStream);
6660 MSOPBString::Read(rStream); // rgbDownloadURL
6661}
6662
6663void MSOFactoidType::Write(WW8Export& rExport)
6664{
6665 SvStream& rStream = *rExport.pTableStrm;
6666
6667 SvMemoryStream aStream;
6668 aStream.WriteUInt32(m_nId); // id
6669 MSOPBString::Write(m_aUri, aStream);
6670 MSOPBString::Write(m_aTag, aStream);
6671 MSOPBString::Write("", aStream); // rgbDownloadURL
6672 rStream.WriteUInt32(aStream.Tell());
6673 aStream.Seek(0);
6674 rStream.WriteStream(aStream);
6675}
6676
6677void MSOPropertyBagStore::Read(SvStream& rStream)
6678{
6679 sal_uInt32 cFactoidType(0);
6680 rStream.ReadUInt32(cFactoidType);
6681 for (sal_uInt32 i = 0; i < cFactoidType && rStream.good(); ++i)
6682 {
6683 MSOFactoidType aFactoidType;
6684 aFactoidType.Read(rStream);
6685 m_aFactoidTypes.push_back(aFactoidType);
6686 }
6687 sal_uInt16 cbHdr(0);
6688 rStream.ReadUInt16(cbHdr);
6689 SAL_WARN_IF(cbHdr != 0xc, "sw.ww8", "MSOPropertyBagStore::Read: unexpected cbHdr")do { if (true && (cbHdr != 0xc)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "MSOPropertyBagStore::Read: unexpected cbHdr"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6689" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "MSOPropertyBagStore::Read: unexpected cbHdr"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "MSOPropertyBagStore::Read: unexpected cbHdr"; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6689" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "MSOPropertyBagStore::Read: unexpected cbHdr") ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6689" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "MSOPropertyBagStore::Read: unexpected cbHdr"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "MSOPropertyBagStore::Read: unexpected cbHdr"; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6689" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
6690 sal_uInt16 nVer(0);
6691 rStream.ReadUInt16(nVer);
6692 SAL_WARN_IF(nVer != 0x0100, "sw.ww8", "MSOPropertyBagStore::Read: unexpected nVer")do { if (true && (nVer != 0x0100)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "MSOPropertyBagStore::Read: unexpected nVer"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6692" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "MSOPropertyBagStore::Read: unexpected nVer"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "MSOPropertyBagStore::Read: unexpected nVer"; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6692" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "MSOPropertyBagStore::Read: unexpected nVer") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6692" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "MSOPropertyBagStore::Read: unexpected nVer"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "MSOPropertyBagStore::Read: unexpected nVer"; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6692" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
6693 rStream.SeekRel(4); // cfactoid
6694 sal_uInt32 nCste(0);
6695 rStream.ReadUInt32(nCste);
6696
6697 //each string has a 2 byte len record at the start
6698 const size_t nMaxPossibleRecords = rStream.remainingSize() / sizeof(sal_uInt16);
6699 if (nCste > nMaxPossibleRecords)
6700 {
6701 SAL_WARN("sw.ww8", nCste << " records claimed, but max possible is " << nMaxPossibleRecords)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << nCste << " records claimed, but max possible is "
<< nMaxPossibleRecords) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6701" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << nCste << " records claimed, but max possible is "
<< nMaxPossibleRecords), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << nCste <<
" records claimed, but max possible is " << nMaxPossibleRecords
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6701" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << nCste << " records claimed, but max possible is "
<< nMaxPossibleRecords) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6701" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << nCste << " records claimed, but max possible is "
<< nMaxPossibleRecords), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << nCste <<
" records claimed, but max possible is " << nMaxPossibleRecords
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6701" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
6702 nCste = nMaxPossibleRecords;
6703 }
6704
6705 for (sal_uInt32 i = 0; i < nCste; ++i)
6706 {
6707 OUString aString = MSOPBString::Read(rStream);
6708 m_aStringTable.push_back(aString);
6709 }
6710}
6711
6712void MSOPropertyBagStore::Write(WW8Export& rExport)
6713{
6714 SvStream& rStream = *rExport.pTableStrm;
6715 rStream.WriteUInt32(m_aFactoidTypes.size()); // cFactoidType
6716 for (MSOFactoidType& rType : m_aFactoidTypes)
6717 rType.Write(rExport);
6718 rStream.WriteUInt16(0xc); // cbHdr
6719 rStream.WriteUInt16(0x0100); // sVer
6720 rStream.WriteUInt32(0); // cfactoid
6721 rStream.WriteUInt32(m_aStringTable.size()); // cste
6722 for (const OUString& rString : m_aStringTable)
6723 MSOPBString::Write(rString, rStream);
6724}
6725
6726MSOProperty::MSOProperty()
6727 : m_nKey(0)
6728 , m_nValue(0)
6729{
6730}
6731
6732void MSOProperty::Read(SvStream& rStream)
6733{
6734 rStream.ReadUInt32(m_nKey);
6735 rStream.ReadUInt32(m_nValue);
6736}
6737
6738void MSOProperty::Write(SvStream& rStream)
6739{
6740 rStream.WriteUInt32(m_nKey);
6741 rStream.WriteUInt32(m_nValue);
6742}
6743
6744MSOPropertyBag::MSOPropertyBag()
6745 : m_nId(0)
6746{
6747}
6748
6749bool MSOPropertyBag::Read(SvStream& rStream)
6750{
6751 rStream.ReadUInt16(m_nId);
6752 sal_uInt16 cProp(0);
6753 rStream.ReadUInt16(cProp);
6754 if (!rStream.good())
6755 return false;
6756 rStream.SeekRel(2); // cbUnknown
6757 //each MSOProperty is 8 bytes in size
6758 const size_t nMaxPossibleRecords = rStream.remainingSize() / 8;
6759 if (cProp > nMaxPossibleRecords)
6760 {
6761 SAL_WARN("sw.ww8", cProp << " records claimed, but max possible is " << nMaxPossibleRecords)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << cProp << " records claimed, but max possible is "
<< nMaxPossibleRecords) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6761" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << cProp << " records claimed, but max possible is "
<< nMaxPossibleRecords), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << cProp <<
" records claimed, but max possible is " << nMaxPossibleRecords
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6761" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << cProp << " records claimed, but max possible is "
<< nMaxPossibleRecords) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6761" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << cProp << " records claimed, but max possible is "
<< nMaxPossibleRecords), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << cProp <<
" records claimed, but max possible is " << nMaxPossibleRecords
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6761" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
6762 cProp = nMaxPossibleRecords;
6763 }
6764 for (sal_uInt16 i = 0; i < cProp && rStream.good(); ++i)
6765 {
6766 MSOProperty aProperty;
6767 aProperty.Read(rStream);
6768 m_aProperties.push_back(aProperty);
6769 }
6770 return rStream.good();
6771}
6772
6773void MSOPropertyBag::Write(WW8Export& rExport)
6774{
6775 SvStream& rStream = *rExport.pTableStrm;
6776 rStream.WriteUInt16(m_nId);
6777 rStream.WriteUInt16(m_aProperties.size());
6778 rStream.WriteUInt16(0); // cbUnknown
6779 for (MSOProperty& rProperty : m_aProperties)
6780 rProperty.Write(rStream);
6781}
6782
6783void WW8SmartTagData::Read(SvStream& rStream, WW8_FC fcFactoidData, sal_uInt32 lcbFactoidData)
6784{
6785 sal_uInt64 nOldPosition = rStream.Tell();
6786 if (!checkSeek(rStream, fcFactoidData))
6787 return;
6788
6789 m_aPropBagStore.Read(rStream);
6790 while (rStream.good() && rStream.Tell() < fcFactoidData + lcbFactoidData)
6791 {
6792 MSOPropertyBag aPropertyBag;
6793 if (!aPropertyBag.Read(rStream))
6794 break;
6795 m_aPropBags.push_back(aPropertyBag);
6796 }
6797
6798 rStream.Seek(nOldPosition);
6799}
6800
6801void WW8SmartTagData::Write(WW8Export& rExport)
6802{
6803 m_aPropBagStore.Write(rExport);
6804 for (MSOPropertyBag& rPropertyBag : m_aPropBags)
6805 rPropertyBag.Write(rExport);
6806}
6807
6808WW8Style::WW8Style(SvStream& rStream, WW8Fib& rFibPara)
6809 : m_rFib(rFibPara), m_rStream(rStream), m_cstd(0), m_cbSTDBaseInFile(0), m_fStdStylenamesWritten(0)
6810 , m_stiMaxWhenSaved(0), m_istdMaxFixedWhenSaved(0), m_nVerBuiltInNamesWhenSaved(0)
6811 , m_ftcAsci(0), m_ftcFE(0), m_ftcOther(0), m_ftcBi(0)
6812{
6813 if (!checkSeek(m_rStream, m_rFib.m_fcStshf))
6814 return;
6815
6816 sal_uInt16 cbStshi = 0; // 2 bytes size of the following STSHI structure
6817 sal_uInt32 nRemaining = m_rFib.m_lcbStshf;
6818 const sal_uInt32 nMinValidStshi = 4;
6819
6820 if (m_rFib.GetFIBVersion() <= ww::eWW2)
6821 {
6822 cbStshi = 0;
6823 m_cstd = 256;
6824 }
6825 else
6826 {
6827 if (m_rFib.m_nFib < 67) // old Version ? (need to find this again to fix)
6828 cbStshi = nMinValidStshi;
6829 else // new version
6830 {
6831 if (nRemaining < sizeof(cbStshi))
6832 return;
6833 // reads the length of the structure in the file
6834 m_rStream.ReadUInt16( cbStshi );
6835 nRemaining-=2;
6836 }
6837 }
6838
6839 cbStshi = std::min(static_cast<sal_uInt32>(cbStshi), nRemaining);
6840 if (cbStshi < nMinValidStshi)
6841 return;
6842
6843 const sal_uInt16 nRead = cbStshi;
6844 do
6845 {
6846 m_rStream.ReadUInt16( m_cstd );
6847
6848 m_rStream.ReadUInt16( m_cbSTDBaseInFile );
6849
6850 if( 6 > nRead ) break;
6851
6852 sal_uInt16 a16Bit;
6853 m_rStream.ReadUInt16( a16Bit );
6854 m_fStdStylenamesWritten = a16Bit & 0x0001;
6855
6856 if( 8 > nRead ) break;
6857 m_rStream.ReadUInt16( m_stiMaxWhenSaved );
6858
6859 if( 10 > nRead ) break;
6860 m_rStream.ReadUInt16( m_istdMaxFixedWhenSaved );
6861
6862 if( 12 > nRead ) break;
6863 m_rStream.ReadUInt16( m_nVerBuiltInNamesWhenSaved );
6864
6865 if( 14 > nRead ) break;
6866 m_rStream.ReadUInt16( m_ftcAsci );
6867
6868 if( 16 > nRead ) break;
6869 m_rStream.ReadUInt16( m_ftcFE );
6870
6871 if ( 18 > nRead ) break;
6872 m_rStream.ReadUInt16( m_ftcOther );
6873
6874 m_ftcBi = m_ftcOther;
6875
6876 if ( 20 > nRead ) break;
6877 m_rStream.ReadUInt16( m_ftcBi );
6878
6879 // p.r.n. ignore the rest
6880 if( 20 < nRead )
6881 m_rStream.SeekRel( nRead-20 );
6882 }
6883 while( false ); // trick: the block above will be passed through exactly one time
6884 // and that's why we can early exit with "break".
6885
6886 nRemaining -= cbStshi;
6887
6888 //There will be stshi.cstd (cbSTD, STD) pairs in the file following the
6889 //STSHI. Note that styles can be empty, i.e. cbSTD == 0
6890 const sal_uInt32 nMinRecordSize = sizeof(sal_uInt16);
6891 const sal_uInt16 nMaxPossibleRecords = nRemaining/nMinRecordSize;
6892
6893 OSL_ENSURE(m_cstd <= nMaxPossibleRecords,do { if (true && (!(m_cstd <= nMaxPossibleRecords)
)) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6894" ": "), "%s", "allegedly more styles that available data"
); } } while (false)
6894 "allegedly more styles that available data")do { if (true && (!(m_cstd <= nMaxPossibleRecords)
)) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "6894" ": "), "%s", "allegedly more styles that available data"
); } } while (false)
;
6895 m_cstd = std::min(m_cstd, nMaxPossibleRecords);
6896}
6897
6898// Read1STDFixed() reads a style. If the style is completely existent,
6899// so it has no empty slot, we should allocate memory and a pointer should
6900// reference to STD (perhaps filled with 0). If the slot is empty,
6901// it will return a null pointer.
6902std::unique_ptr<WW8_STD> WW8Style::Read1STDFixed(sal_uInt16& rSkip)
6903{
6904 std::unique_ptr<WW8_STD> pStd;
6905
6906 sal_uInt16 cbStd(0);
6907 m_rStream.ReadUInt16(cbStd); // read length
6908
6909 const sal_uInt16 nRead = m_cbSTDBaseInFile;
6910 if( cbStd >= m_cbSTDBaseInFile )
6911 {
6912 // Fixed part completely available
6913
6914 // read fixed part of STD
6915 pStd.reset(new WW8_STD);
6916 memset( pStd.get(), 0, sizeof( *pStd ) );
6917
6918 do
6919 {
6920 if( 2 > nRead ) break;
6921
6922 sal_uInt16 a16Bit = 0;
6923 m_rStream.ReadUInt16( a16Bit );
6924 pStd->sti = a16Bit & 0x0fff ;
6925 pStd->fScratch = sal_uInt16(0 != ( a16Bit & 0x1000 ));
6926 pStd->fInvalHeight = sal_uInt16(0 != ( a16Bit & 0x2000 ));
6927 pStd->fHasUpe = sal_uInt16(0 != ( a16Bit & 0x4000 ));
6928 pStd->fMassCopy = sal_uInt16(0 != ( a16Bit & 0x8000 ));
6929
6930 if( 4 > nRead ) break;
6931 a16Bit = 0;
6932 m_rStream.ReadUInt16( a16Bit );
6933 pStd->sgc = a16Bit & 0x000f ;
6934 pStd->istdBase = ( a16Bit & 0xfff0 ) >> 4;
6935
6936 if( 6 > nRead ) break;
6937 a16Bit = 0;
6938 m_rStream.ReadUInt16( a16Bit );
6939 pStd->cupx = a16Bit & 0x000f ;
6940 pStd->istdNext = ( a16Bit & 0xfff0 ) >> 4;
6941
6942 if( 8 > nRead ) break;
6943 m_rStream.ReadUInt16( pStd->bchUpe );
6944
6945 // from Ver8 this two fields should be added:
6946 if(10 > nRead ) break;
6947 a16Bit = 0;
6948 m_rStream.ReadUInt16( a16Bit );
6949 pStd->fAutoRedef = a16Bit & 0x0001 ;
6950 pStd->fHidden = ( a16Bit & 0x0002 ) >> 1;
6951 // You never know: cautionary skipped
6952 if (nRead > 10)
6953 {
6954 auto nSkip = std::min<sal_uInt64>(nRead - 10, m_rStream.remainingSize());
6955 m_rStream.Seek(m_rStream.Tell() + nSkip);
6956 }
6957 }
6958 while( false ); // trick: the block above will passed through exactly one time
6959 // and can be left early with a "break"
6960
6961 if (!m_rStream.good() || !nRead)
6962 {
6963 pStd.reset(); // report error with NULL
6964 }
6965
6966 rSkip = cbStd - m_cbSTDBaseInFile;
6967 }
6968 else
6969 { // Fixed part too short
6970 if( cbStd )
6971 m_rStream.SeekRel( cbStd ); // skip leftovers
6972 rSkip = 0;
6973 }
6974 return pStd;
6975}
6976
6977std::unique_ptr<WW8_STD> WW8Style::Read1Style(sal_uInt16& rSkip, OUString* pString)
6978{
6979 // Attention: MacWord-Documents have their Stylenames
6980 // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
6981
6982 std::unique_ptr<WW8_STD> pStd = Read1STDFixed(rSkip); // read STD
6983
6984 // string desired?
6985 if( pString )
6986 { // real style?
6987 if ( pStd )
6988 {
6989 sal_Int32 nLenStringBytes = 0;
6990 switch( m_rFib.m_nVersion )
6991 {
6992 case 6:
6993 case 7:
6994 // read pascal string
6995 *pString = read_uInt8_BeltAndBracesString(m_rStream, RTL_TEXTENCODING_MS_1252(((rtl_TextEncoding) 1)));
6996 // leading len and trailing zero --> 2
6997 nLenStringBytes = pString->getLength() + 2;
6998 break;
6999 case 8:
7000 // handle Unicode-String with leading length short and
7001 // trailing zero
7002 if (TestBeltAndBraces(m_rStream))
7003 {
7004 *pString = read_uInt16_BeltAndBracesString(m_rStream);
7005 nLenStringBytes = (pString->getLength() + 2) * 2;
7006 }
7007 else
7008 {
7009 /*
7010 #i8114#
7011 This is supposed to be impossible, it's just supposed
7012 to be 16 bit count followed by the string and ending
7013 in a 0 short. But "Lotus SmartSuite Product: Word Pro"
7014 is creating invalid style names in ww7- format. So we
7015 use the belt and braces of the ms strings to see if
7016 they are not corrupt. If they are then we try them as
7017 8bit ones
7018 */
7019 *pString = read_uInt8_BeltAndBracesString(m_rStream,RTL_TEXTENCODING_MS_1252(((rtl_TextEncoding) 1)));
7020 // leading len and trailing zero --> 2
7021 nLenStringBytes = pString->getLength() + 2;
7022 }
7023 break;
7024 default:
7025 OSL_ENSURE(false, "It was forgotten to code nVersion!")do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7025" ": "), "%s", "It was forgotten to code nVersion!"
); } } while (false)
;
7026 break;
7027 }
7028 if (nLenStringBytes > rSkip)
7029 {
7030 SAL_WARN("sw.ww8", "WW8Style structure corrupt")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "WW8Style structure corrupt"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7030" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "WW8Style structure corrupt"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "WW8Style structure corrupt"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7030" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "WW8Style structure corrupt") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7030" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "WW8Style structure corrupt"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "WW8Style structure corrupt"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7030" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
7031 nLenStringBytes = rSkip;
7032 }
7033 rSkip -= nLenStringBytes;
7034 }
7035 else
7036 pString->clear(); // can not return a name
7037 }
7038 return pStd;
7039}
7040
7041namespace {
7042const sal_uInt16 maxStrSize = 65;
7043
7044struct WW8_FFN_Ver6
7045{
7046 WW8_FFN_BASE base;
7047 // from Ver6
7048 char szFfn[maxStrSize]; // 0x6 or 0x40 from Ver8 on zero terminated string that
7049 // records name of font.
7050 // Maximal size of szFfn is 65 characters.
7051 // Attention: This array can also be smaller!!!
7052 // Possibly followed by a second sz which records the
7053 // name of an alternate font to use if the first named
7054 // font does not exist on this system.
7055};
7056
7057}
7058
7059// #i43762# check font name for illegal characters
7060static void lcl_checkFontname( OUString& sString )
7061{
7062 // for efficiency, we'd like to use String methods as far as possible.
7063 // Hence, we will:
7064 // 1) convert all invalid chars to \u0001
7065 // 2) then erase all \u0001 chars (if anywhere found), and
7066 // 3) erase leading/trailing ';', in case a font name was
7067 // completely removed
7068
7069 // convert all invalid chars to \u0001
7070 OUStringBuffer aBuf(sString);
7071 const sal_Int32 nLen = aBuf.getLength();
7072 bool bFound = false;
7073 for ( sal_Int32 n = 0; n < nLen; ++n )
7074 {
7075 if ( aBuf[n] < 0x20 )
7076 {
7077 aBuf[n] = 1;
7078 bFound = true;
7079 }
7080 }
7081 sString = aBuf.makeStringAndClear();
7082
7083 // if anything was found, remove \u0001 + leading/trailing ';'
7084 if( bFound )
7085 {
7086 sString = comphelper::string::strip(sString.replaceAll("\001", ""), ';');
7087 }
7088}
7089
7090namespace
7091{
7092 sal_uInt16 calcMaxFonts(sal_uInt8 *p, sal_Int32 nFFn)
7093 {
7094 // Figure out the max number of fonts defined here
7095 sal_uInt16 nMax = 0;
7096 sal_Int32 nRemaining = nFFn;
7097 while (nRemaining)
7098 {
7099 //p[0] is cbFfnM1, the alleged total length of FFN - 1.
7100 //i.e. length after cbFfnM1
7101 const sal_uInt16 cbFfnM1 = *p++;
7102 --nRemaining;
7103
7104 if (cbFfnM1 > nRemaining)
7105 break;
7106
7107 nMax++;
7108 nRemaining -= cbFfnM1;
7109 p += cbFfnM1;
7110 }
7111 return nMax;
7112 }
7113
7114 template<typename T> bool readU8(
7115 sal_uInt8 const * p, std::size_t offset, sal_uInt8 const * pEnd,
7116 T * value)
7117 {
7118 assert(p <= pEnd)(static_cast <bool> (p <= pEnd) ? void (0) : __assert_fail
("p <= pEnd", "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
, 7118, __extension__ __PRETTY_FUNCTION__))
;
7119 assert(value != nullptr)(static_cast <bool> (value != nullptr) ? void (0) : __assert_fail
("value != nullptr", "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
, 7119, __extension__ __PRETTY_FUNCTION__))
;
7120 if (offset >= o3tl::make_unsigned(pEnd - p)) {
7121 return false;
7122 }
7123 *value = p[offset];
7124 return true;
7125 }
7126
7127 bool readS16(
7128 sal_uInt8 const * p, std::size_t offset, sal_uInt8 const * pEnd,
7129 short * value)
7130 {
7131 assert(p <= pEnd)(static_cast <bool> (p <= pEnd) ? void (0) : __assert_fail
("p <= pEnd", "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
, 7131, __extension__ __PRETTY_FUNCTION__))
;
7132 assert(value != nullptr)(static_cast <bool> (value != nullptr) ? void (0) : __assert_fail
("value != nullptr", "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
, 7132, __extension__ __PRETTY_FUNCTION__))
;
7133 if (offset > o3tl::make_unsigned(pEnd - p)
7134 || static_cast<std::size_t>(pEnd - p) - offset < 2)
7135 {
7136 return false;
7137 }
7138 *value = unsigned(p[offset]) + (unsigned(p[offset + 1]) << 8);
7139 return true;
7140 }
7141
7142 sal_Int32 getStringLength(
7143 sal_uInt8 const * p, std::size_t offset, sal_uInt8 const * pEnd)
7144 {
7145 assert(p <= pEnd)(static_cast <bool> (p <= pEnd) ? void (0) : __assert_fail
("p <= pEnd", "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
, 7145, __extension__ __PRETTY_FUNCTION__))
;
7146 assert(pEnd - p <= SAL_MAX_INT32)(static_cast <bool> (pEnd - p <= ((sal_Int32) 0x7FFFFFFF
)) ? void (0) : __assert_fail ("pEnd - p <= SAL_MAX_INT32"
, "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
, 7146, __extension__ __PRETTY_FUNCTION__))
;
7147 if (offset >= o3tl::make_unsigned(pEnd - p)) {
7148 return -1;
7149 }
7150 void const * p2 = std::memchr(
7151 p + offset, 0, static_cast<std::size_t>(pEnd - p) - offset);
7152 if (p2 == nullptr) {
7153 return -1;
7154 }
7155 return static_cast<sal_uInt8 const *>(p2) - (p + offset);
7156 }
7157}
7158
7159WW8Fonts::WW8Fonts( SvStream& rSt, WW8Fib const & rFib )
7160{
7161 // Attention: MacWord-Documents have their Fontnames
7162 // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
7163 if( rFib.m_lcbSttbfffn <= 2 )
7164 {
7165 OSL_ENSURE( false, "font table is broken! (rFib.lcbSttbfffn < 2)" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7165" ": "), "%s", "font table is broken! (rFib.lcbSttbfffn < 2)"
); } } while (false)
;
7166 return;
7167 }
7168
7169 if (!checkSeek(rSt, rFib.m_fcSttbfffn))
7170 return;
7171
7172 sal_Int32 nFFn = rFib.m_lcbSttbfffn - 2;
7173
7174 const sal_uInt64 nMaxPossible = rSt.remainingSize();
7175 if (o3tl::make_unsigned(nFFn) > nMaxPossible)
7176 {
7177 SAL_WARN("sw.ww8", "FFN structure longer than available data")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "FFN structure longer than available data"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7177" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FFN structure longer than available data"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FFN structure longer than available data"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7177" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FFN structure longer than available data") == 1)
{ ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7177" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "FFN structure longer than available data"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FFN structure longer than available data"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7177" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
7178 nFFn = nMaxPossible;
7179 }
7180
7181 // allocate Font Array
7182 std::vector<sal_uInt8> aA(nFFn);
7183 memset(aA.data(), 0, nFFn);
7184
7185 ww::WordVersion eVersion = rFib.GetFIBVersion();
7186
7187 sal_uInt16 nMax(0);
7188 if( eVersion >= ww::eWW8 )
7189 {
7190 // bVer8: read the count of strings in nMax
7191 rSt.ReadUInt16(nMax);
7192 }
7193
7194 // Ver8: skip undefined uint16
7195 // Ver67: skip the herein stored total byte of structure
7196 // - we already got that information in rFib.lcbSttbfffn
7197 rSt.SeekRel( 2 );
7198
7199 // read all font information
7200 nFFn = rSt.ReadBytes(aA.data(), nFFn);
7201 sal_uInt8 * const pEnd = aA.data() + nFFn;
7202 const sal_uInt16 nCalcMax = calcMaxFonts(aA.data(), nFFn);
7203
7204 if (eVersion < ww::eWW8)
7205 nMax = nCalcMax;
7206 else
7207 {
7208 //newer versions include supportive count of fonts, so take min of that
7209 //and calced max
7210 nMax = std::min(nMax, nCalcMax);
7211 }
7212
7213 if (nMax)
7214 {
7215 // allocate Index Array
7216 m_aFontA.resize(nMax);
7217 WW8_FFN* p = m_aFontA.data();
7218
7219 if( eVersion <= ww::eWW2 )
7220 {
7221 sal_uInt8 const * pVer2 = aA.data();
7222 sal_uInt16 i = 0;
7223 for(; i<nMax; ++i, ++p)
7224 {
7225 if (!readU8(
7226 pVer2, offsetof(WW8_FFN_BASE, cbFfnM1)__builtin_offsetof(WW8_FFN_BASE, cbFfnM1), pEnd,
7227 &p->aFFNBase.cbFfnM1))
7228 {
7229 break;
7230 }
7231
7232 p->aFFNBase.prg = 0;
7233 p->aFFNBase.fTrueType = 0;
7234 p->aFFNBase.ff = 0;
7235
7236 if (!(readU8(pVer2, 1, pEnd, &p->aFFNBase.wWeight)
7237 && readU8(pVer2, 2, pEnd, &p->aFFNBase.chs)))
7238 {
7239 break;
7240 }
7241 /*
7242 #i8726# 7- seems to encode the name in the same encoding as
7243 the font, e.g load the doc in 97 and save to see the unicode
7244 ver of the asian fontnames in that example to confirm.
7245 */
7246 rtl_TextEncoding eEnc = WW8Fib::GetFIBCharset(p->aFFNBase.chs, rFib.m_lid);
7247 if ((eEnc == RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10))) || (eEnc == RTL_TEXTENCODING_DONTKNOW(((rtl_TextEncoding) 0))))
7248 eEnc = RTL_TEXTENCODING_MS_1252(((rtl_TextEncoding) 1));
7249
7250 sal_Int32 n = getStringLength(pVer2, 1 + 2, pEnd);
7251 if (n == -1) {
7252 break;
7253 }
7254 p->sFontname = OUString(
7255 reinterpret_cast<char const *>(pVer2 + 1 + 2), n, eEnc);
7256 pVer2 = pVer2 + p->aFFNBase.cbFfnM1 + 1;
7257 }
7258 nMax = i;
7259 }
7260 else if( eVersion < ww::eWW8 )
7261 {
7262 sal_uInt8 const * pVer6 = aA.data();
7263 sal_uInt16 i = 0;
7264 for(; i<nMax; ++i, ++p)
7265 {
7266 if (!readU8(
7267 pVer6, offsetof(WW8_FFN_BASE, cbFfnM1)__builtin_offsetof(WW8_FFN_BASE, cbFfnM1), pEnd,
7268 &p->aFFNBase.cbFfnM1))
7269 {
7270 break;
7271 }
7272 sal_uInt8 c2;
7273 if (!readU8(pVer6, 1, pEnd, &c2)) {
7274 break;
7275 }
7276
7277 p->aFFNBase.prg = c2 & 0x02;
7278 p->aFFNBase.fTrueType = (c2 & 0x04) >> 2;
7279 // skip a reserve bit
7280 p->aFFNBase.ff = (c2 & 0x70) >> 4;
7281
7282 if (!(readS16(
7283 pVer6, offsetof(WW8_FFN_BASE, wWeight)__builtin_offsetof(WW8_FFN_BASE, wWeight), pEnd,
7284 &p->aFFNBase.wWeight)
7285 && readU8(
7286 pVer6, offsetof(WW8_FFN_BASE, chs)__builtin_offsetof(WW8_FFN_BASE, chs), pEnd, &p->aFFNBase.chs)
7287 && readU8(
7288 pVer6, offsetof(WW8_FFN_BASE, ibszAlt)__builtin_offsetof(WW8_FFN_BASE, ibszAlt), pEnd,
7289 &p->aFFNBase.ibszAlt)))
7290 {
7291 break;
7292 }
7293 /*
7294 #i8726# 7- seems to encode the name in the same encoding as
7295 the font, e.g load the doc in 97 and save to see the unicode
7296 ver of the asian fontnames in that example to confirm.
7297 */
7298 rtl_TextEncoding eEnc = WW8Fib::GetFIBCharset(p->aFFNBase.chs, rFib.m_lid);
7299 if ((eEnc == RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10))) || (eEnc == RTL_TEXTENCODING_DONTKNOW(((rtl_TextEncoding) 0))))
7300 eEnc = RTL_TEXTENCODING_MS_1252(((rtl_TextEncoding) 1));
7301 sal_Int32 n = getStringLength(
7302 pVer6, offsetof(WW8_FFN_Ver6, szFfn)__builtin_offsetof(WW8_FFN_Ver6, szFfn), pEnd);
7303 if (n == -1) {
7304 break;
7305 }
7306 p->sFontname = OUString(
7307 reinterpret_cast<char const *>(
7308 pVer6 + offsetof(WW8_FFN_Ver6, szFfn)__builtin_offsetof(WW8_FFN_Ver6, szFfn)),
7309 n, eEnc);
7310 if (p->aFFNBase.ibszAlt && p->aFFNBase.ibszAlt < maxStrSize) //don't start after end of string
7311 {
7312 n = getStringLength(
7313 pVer6, offsetof(WW8_FFN_Ver6, szFfn)__builtin_offsetof(WW8_FFN_Ver6, szFfn) + p->aFFNBase.ibszAlt,
7314 pEnd);
7315 if (n == -1) {
7316 break;
7317 }
7318 p->sFontname += ";" + OUString(
7319 reinterpret_cast<char const *>(
7320 pVer6 + offsetof(WW8_FFN_Ver6, szFfn)__builtin_offsetof(WW8_FFN_Ver6, szFfn) + p->aFFNBase.ibszAlt),
7321 n, eEnc);
7322 }
7323 else
7324 {
7325 //#i18369# if it's a symbol font set Symbol as fallback
7326 if (
7327 RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10)) == WW8Fib::GetFIBCharset(p->aFFNBase.chs, rFib.m_lid)
7328 && p->sFontname!="Symbol"
7329 )
7330 {
7331 p->sFontname += ";Symbol";
7332 }
7333 }
7334 pVer6 = pVer6 + p->aFFNBase.cbFfnM1 + 1;
7335 }
7336 nMax = i;
7337 }
7338 else
7339 {
7340 //count of bytes in minimum FontFamilyInformation payload
7341 const sal_uInt8 cbMinFFNPayload = 41;
7342 sal_uInt16 nValidFonts = 0;
7343 sal_Int32 nRemainingFFn = nFFn;
7344 sal_uInt8* pRaw = aA.data();
7345 for (sal_uInt16 i=0; i < nMax && nRemainingFFn; ++i, ++p)
7346 {
7347 //pRaw[0] is cbFfnM1, the alleged total length of FFN - 1
7348 //i.e. length after cbFfnM1
7349 sal_uInt8 cbFfnM1 = *pRaw++;
7350 --nRemainingFFn;
7351
7352 if (cbFfnM1 > nRemainingFFn)
7353 break;
7354
7355 if (cbFfnM1 < cbMinFFNPayload)
7356 break;
7357
7358 p->aFFNBase.cbFfnM1 = cbFfnM1;
7359
7360 sal_uInt8 *pVer8 = pRaw;
7361
7362 sal_uInt8 c2 = *pVer8++;
7363 --cbFfnM1;
7364
7365 p->aFFNBase.prg = c2 & 0x02;
7366 p->aFFNBase.fTrueType = (c2 & 0x04) >> 2;
7367 // skip a reserve bit
7368 p->aFFNBase.ff = (c2 & 0x70) >> 4;
7369
7370 p->aFFNBase.wWeight = SVBT16ToUInt16(*reinterpret_cast<SVBT16*>(pVer8));
7371 pVer8+=2;
7372 cbFfnM1-=2;
7373
7374 p->aFFNBase.chs = *pVer8++;
7375 --cbFfnM1;
7376
7377 p->aFFNBase.ibszAlt = *pVer8++;
7378 --cbFfnM1;
7379
7380 pVer8 += 10; //PANOSE
7381 cbFfnM1-=10;
7382 pVer8 += 24; //FONTSIGNATURE
7383 cbFfnM1-=24;
7384
7385 assert(cbFfnM1 >= 2)(static_cast <bool> (cbFfnM1 >= 2) ? void (0) : __assert_fail
("cbFfnM1 >= 2", "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
, 7385, __extension__ __PRETTY_FUNCTION__))
;
7386
7387 sal_uInt8 nMaxNullTerminatedPossible = cbFfnM1/2 - 1;
7388 sal_Unicode *pPrimary = reinterpret_cast<sal_Unicode*>(pVer8);
7389 pPrimary[nMaxNullTerminatedPossible] = 0;
7390#ifdef OSL_BIGENDIAN
7391 swapEndian(pPrimary);
7392#endif
7393 p->sFontname = pPrimary;
7394 if (p->aFFNBase.ibszAlt && p->aFFNBase.ibszAlt < nMaxNullTerminatedPossible)
7395 {
7396 sal_Unicode *pSecondary = pPrimary + p->aFFNBase.ibszAlt;
7397#ifdef OSL_BIGENDIAN
7398 swapEndian(pSecondary);
7399#endif
7400 p->sFontname += OUStringLiteral(u";") + pSecondary;
7401 }
7402
7403 // #i43762# check font name for illegal characters
7404 lcl_checkFontname( p->sFontname );
7405
7406 // set pointer one font back to original array
7407 pRaw += p->aFFNBase.cbFfnM1;
7408 nRemainingFFn -= p->aFFNBase.cbFfnM1;
7409 ++nValidFonts;
7410 }
7411 OSL_ENSURE(nMax == nValidFonts, "Font count differs with availability")do { if (true && (!(nMax == nValidFonts))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7411" ": "), "%s", "Font count differs with availability"
); } } while (false)
;
7412 nMax = std::min(nMax, nValidFonts);
7413 }
7414 }
7415 m_aFontA.resize(nMax);
7416 m_aFontA.shrink_to_fit();
7417}
7418
7419const WW8_FFN* WW8Fonts::GetFont( sal_uInt16 nNum ) const
7420{
7421 if (nNum >= m_aFontA.size())
7422 return nullptr;
7423
7424 return &m_aFontA[nNum];
7425}
7426
7427// Search after a header/footer for an index in the ww list from header/footer
7428
7429// specials for WinWord6 and -7:
7430//
7431// 1) At the start of reading we must build WWPLCF_HdFt with Fib and Dop
7432// 2) The main text must be read sequentially over all sections
7433// 3) For every header/footer in the main text, we must call UpdateIndex()
7434// exactly once with the parameter from the attribute.
7435// (per section can be maximally one). This call must take place *after*
7436// the last call from GetTextPos().
7437// 4) GetTextPos() can be called with exactly one flag
7438// out of WW8_{FOOTER,HEADER}_{ODD,EVEN,FIRST} (Do not change!)
7439// -> maybe we can get a right result then
7440
7441WW8PLCF_HdFt::WW8PLCF_HdFt( SvStream* pSt, WW8Fib const & rFib, WW8Dop const & rDop )
7442 : aPLCF(*pSt, rFib.m_fcPlcfhdd , rFib.m_lcbPlcfhdd , 0)
7443{
7444 nIdxOffset = 0;
7445
7446 /*
7447 This dop.grpfIhdt has a bit set for each special
7448 footnote *and endnote!!* separator,continuation separator, and
7449 continuation notice entry, the documentation does not mention the
7450 endnote separators, the documentation also gets the index numbers
7451 backwards when specifying which bits to test. The bottom six bits
7452 of this value must be tested and skipped over. Each section's
7453 grpfIhdt is then tested for the existence of the appropriate headers
7454 and footers, at the end of each section the nIdxOffset must be updated
7455 to point to the beginning of the next section's group of headers and
7456 footers in this PLCF, UpdateIndex does that task.
7457 */
7458 for( sal_uInt8 nI = 0x1; nI <= 0x20; nI <<= 1 )
7459 if( nI & rDop.grpfIhdt ) // bit set?
7460 nIdxOffset++;
7461}
7462
7463bool WW8PLCF_HdFt::GetTextPos(sal_uInt8 grpfIhdt, sal_uInt8 nWhich, WW8_CP& rStart,
7464 WW8_CP& rLen)
7465{
7466 sal_uInt8 nI = 0x01;
7467 short nIdx = nIdxOffset;
7468 while (true)
7469 {
7470 if( nI & nWhich )
7471 break; // found
7472 if( grpfIhdt & nI )
7473 nIdx++; // uninteresting Header / Footer
7474 nI <<= 1; // text next bit
7475 if( nI > 0x20 )
7476 return false; // not found
7477 }
7478 // nIdx is HdFt-Index
7479 WW8_CP nEnd;
7480 void* pData;
7481
7482 aPLCF.SetIdx( nIdx ); // Lookup suitable CP
7483 aPLCF.Get( rStart, nEnd, pData );
7484 if (nEnd < rStart)
7485 {
7486 SAL_WARN("sw.ww8", "End " << nEnd << " before Start " << rStart)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "End " << nEnd <<
" before Start " << rStart) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7486" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << nEnd << " before Start "
<< rStart), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "End " << nEnd << " before Start "
<< rStart; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7486" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "End " << nEnd << " before Start " <<
rStart) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7486" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << nEnd << " before Start "
<< rStart), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "End " << nEnd << " before Start "
<< rStart; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7486" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
7487 return false;
7488 }
7489
7490 bool bFail = o3tl::checked_sub(nEnd, rStart, rLen);
7491 if (bFail)
7492 {
7493 SAL_WARN("sw.ww8", "broken offset, ignoring")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "broken offset, ignoring"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7493" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7493" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "broken offset, ignoring") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7493" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "broken offset, ignoring"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"broken offset, ignoring"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7493" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
7494 return false;
7495 }
7496
7497 aPLCF.advance();
7498
7499 return true;
7500}
7501
7502void WW8PLCF_HdFt::GetTextPosExact(short nIdx, WW8_CP& rStart, WW8_CP& rLen)
7503{
7504 WW8_CP nEnd;
7505 void* pData;
7506
7507 aPLCF.SetIdx( nIdx ); // Lookup suitable CP
7508 aPLCF.Get( rStart, nEnd, pData );
7509 if (nEnd < rStart)
7510 {
7511 SAL_WARN("sw.ww8", "End " << nEnd << " before Start " << rStart)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "End " << nEnd <<
" before Start " << rStart) == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7511" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << nEnd << " before Start "
<< rStart), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "End " << nEnd << " before Start "
<< rStart; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7511" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "End " << nEnd << " before Start " <<
rStart) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7511" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "End " << nEnd << " before Start "
<< rStart), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "End " << nEnd << " before Start "
<< rStart; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7511" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
7512 rLen = 0;
7513 return;
7514 }
7515 if (o3tl::checked_sub(nEnd, rStart, rLen))
7516 {
7517 SAL_WARN("sw.ww8", "GetTextPosExact overflow")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "GetTextPosExact overflow"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7517" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "GetTextPosExact overflow"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"GetTextPosExact overflow"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7517" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "GetTextPosExact overflow") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7517" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "GetTextPosExact overflow"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"GetTextPosExact overflow"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "7517" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
7518 rLen = 0;
7519 }
7520}
7521
7522void WW8PLCF_HdFt::UpdateIndex( sal_uInt8 grpfIhdt )
7523{
7524 // Caution: Description is not correct
7525 for( sal_uInt8 nI = 0x01; nI <= 0x20; nI <<= 1 )
7526 if( nI & grpfIhdt )
7527 nIdxOffset++;
7528}
7529
7530WW8Dop::WW8Dop(SvStream& rSt, sal_Int16 nFib, sal_Int32 nPos, sal_uInt32 nSize):
7531 fFacingPages(false), fWidowControl(false), fPMHMainDoc(false), grfSuppression(0), fpc(0),
7532 grpfIhdt(0), rncFootnote(0), nFootnote(0), fOutlineDirtySave(false), fOnlyMacPics(false),
7533 fOnlyWinPics(false), fLabelDoc(false), fHyphCapitals(false), fAutoHyphen(false),
7534 fFormNoFields(false), fLinkStyles(false), fRevMarking(false), fBackup(false),
7535 fExactCWords(false), fPagHidden(false), fPagResults(false), fLockAtn(false),
7536 fMirrorMargins(false), fReadOnlyRecommended(false), fDfltTrueType(false),
7537 fPagSuppressTopSpacing(false), fProtEnabled(false), fDispFormFieldSel(false), fRMView(false),
7538 fRMPrint(false), fWriteReservation(false), fLockRev(false), fEmbedFonts(false),
7539 copts_fNoTabForInd(false), copts_fNoSpaceRaiseLower(false), copts_fSupressSpbfAfterPgBrk(false),
7540 copts_fWrapTrailSpaces(false), copts_fMapPrintTextColor(false), copts_fNoColumnBalance(false),
7541 copts_fConvMailMergeEsc(false), copts_fSupressTopSpacing(false),
7542 copts_fOrigWordTableRules(false), copts_fTransparentMetafiles(false),
7543 copts_fShowBreaksInFrames(false), copts_fSwapBordersFacingPgs(false), copts_fExpShRtn(false),
7544 rncEdn(0), nEdn(0), epc(0), fPrintFormData(false), fSaveFormData(false), fShadeFormData(false),
7545 fWCFootnoteEdn(false), wvkSaved(0), wScaleSaved(0), zkSaved(0), fRotateFontW6(false),
7546 iGutterPos(false), fNoTabForInd(false), fNoSpaceRaiseLower(false),
7547 fSupressSpbfAfterPageBreak(false), fWrapTrailSpaces(false), fMapPrintTextColor(false),
7548 fNoColumnBalance(false), fConvMailMergeEsc(false), fSupressTopSpacing(false),
7549 fOrigWordTableRules(false), fTransparentMetafiles(false), fShowBreaksInFrames(false),
7550 fSwapBordersFacingPgs(false), fCompatibilityOptions_Unknown1_13(false), fExpShRtn(false),
7551 fCompatibilityOptions_Unknown1_15(false), fCompatibilityOptions_Unknown1_16(false),
7552 fSuppressTopSpacingMac5(false), fTruncDxaExpand(false), fPrintBodyBeforeHdr(false),
7553 fNoLeading(false), fCompatibilityOptions_Unknown1_21(false), fMWSmallCaps(false),
7554 fCompatibilityOptions_Unknown1_23(false), fCompatibilityOptions_Unknown1_24(false),
7555 fCompatibilityOptions_Unknown1_25(false), fCompatibilityOptions_Unknown1_26(false),
7556 fCompatibilityOptions_Unknown1_27(false), fCompatibilityOptions_Unknown1_28(false),
7557 fCompatibilityOptions_Unknown1_29(false), fCompatibilityOptions_Unknown1_30(false),
7558 fCompatibilityOptions_Unknown1_31(false), fUsePrinterMetrics(false), lvl(0), fHtmlDoc(false),
7559 fSnapBorder(false), fIncludeHeader(false), fIncludeFooter(false), fForcePageSizePag(false),
7560 fMinFontSizePag(false), fHaveVersions(false), fAutoVersion(false),
7561 fCompatibilityOptions_Unknown2_1(false), fCompatibilityOptions_Unknown2_2(false),
7562 fDontUseHTMLAutoSpacing(false), fCompatibilityOptions_Unknown2_4(false),
7563 fCompatibilityOptions_Unknown2_5(false), fCompatibilityOptions_Unknown2_6(false),
7564 fCompatibilityOptions_Unknown2_7(false), fCompatibilityOptions_Unknown2_8(false),
7565 fCompatibilityOptions_Unknown2_9(false), fCompatibilityOptions_Unknown2_10(false),
7566 fCompatibilityOptions_Unknown2_11(false), fCompatibilityOptions_Unknown2_12(false),
7567 fCompatibilityOptions_Unknown2_13(false), fCompatibilityOptions_Unknown2_14(false),
7568 fCompatibilityOptions_Unknown2_15(false), fCompatibilityOptions_Unknown2_16(false),
7569 fCompatibilityOptions_Unknown2_17(false), fCompatibilityOptions_Unknown2_18(false),
7570 fCompatibilityOptions_Unknown2_19(false), fCompatibilityOptions_Unknown2_20(false),
7571 fCompatibilityOptions_Unknown2_21(false), fCompatibilityOptions_Unknown2_22(false),
7572 fCompatibilityOptions_Unknown2_23(false), fCompatibilityOptions_Unknown2_24(false),
7573 fCompatibilityOptions_Unknown2_25(false), fCompatibilityOptions_Unknown2_26(false),
7574 fCompatibilityOptions_Unknown2_27(false), fCompatibilityOptions_Unknown2_28(false),
7575 fCompatibilityOptions_Unknown2_29(false), fCompatibilityOptions_Unknown2_30(false),
7576 fCompatibilityOptions_Unknown2_31(false), fCompatibilityOptions_Unknown2_32(false),
7577 fUnknown3(0), fUseBackGroundInAllmodes(false), fDoNotEmbedSystemFont(false), fWordCompat(false),
7578 fLiveRecover(false), fEmbedFactoids(false), fFactoidXML(false), fFactoidAllDone(false),
7579 fFolioPrint(false), fReverseFolio(false), iTextLineEnding(0), fHideFcc(false),
7580 fAcetateShowMarkup(false), fAcetateShowAtn(false), fAcetateShowInsDel(false),
7581 fAcetateShowProps(false)
7582 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
7583 // above bit-field member initializations can be moved to the class definition
7584{
7585 fDontUseHTMLAutoSpacing = true; //default
7586 fAcetateShowAtn = true; //default
7587 const sal_uInt32 nMaxDopSize = 0x268;
7588 std::unique_ptr<sal_uInt8[]> pDataPtr( new sal_uInt8[ nMaxDopSize ] );
7589 sal_uInt8* pData = pDataPtr.get();
7590
7591 sal_uInt32 nRead = std::min(nMaxDopSize, nSize);
7592 if (nSize < 2 || !checkSeek(rSt, nPos) || nRead != rSt.ReadBytes(pData, nRead))
7593 nDopError = ERR_SWG_READ_ERRORErrCode(ErrCodeArea::Sw, ErrCodeClass::Read, 2 ); // report error
7594 else
7595 {
7596 if (nMaxDopSize > nRead)
7597 memset( pData + nRead, 0, nMaxDopSize - nRead );
7598
7599 // interpret the data
7600 sal_uInt32 a32Bit;
7601 sal_uInt16 a16Bit;
7602 sal_uInt8 a8Bit;
7603
7604 a16Bit = Get_UShort( pData ); // 0 0x00
7605 fFacingPages = 0 != ( a16Bit & 0x0001 ) ;
7606 fWidowControl = 0 != ( a16Bit & 0x0002 ) ;
7607 fPMHMainDoc = 0 != ( a16Bit & 0x0004 ) ;
7608 grfSuppression = ( a16Bit & 0x0018 ) >> 3;
7609 fpc = ( a16Bit & 0x0060 ) >> 5;
7610 grpfIhdt = ( a16Bit & 0xff00 ) >> 8;
7611
7612 a16Bit = Get_UShort( pData ); // 2 0x02
7613 rncFootnote = a16Bit & 0x0003 ;
7614 nFootnote = ( a16Bit & ~0x0003 ) >> 2 ;
7615
7616 a8Bit = Get_Byte( pData ); // 4 0x04
7617 fOutlineDirtySave = 0 != ( a8Bit & 0x01 );
7618
7619 a8Bit = Get_Byte( pData ); // 5 0x05
7620 fOnlyMacPics = 0 != ( a8Bit & 0x01 );
7621 fOnlyWinPics = 0 != ( a8Bit & 0x02 );
7622 fLabelDoc = 0 != ( a8Bit & 0x04 );
7623 fHyphCapitals = 0 != ( a8Bit & 0x08 );
7624 fAutoHyphen = 0 != ( a8Bit & 0x10 );
7625 fFormNoFields = 0 != ( a8Bit & 0x20 );
7626 fLinkStyles = 0 != ( a8Bit & 0x40 );
7627 fRevMarking = 0 != ( a8Bit & 0x80 );
7628
7629 a8Bit = Get_Byte( pData ); // 6 0x06
7630 fBackup = 0 != ( a8Bit & 0x01 );
7631 fExactCWords = 0 != ( a8Bit & 0x02 );
7632 fPagHidden = 0 != ( a8Bit & 0x04 );
7633 fPagResults = 0 != ( a8Bit & 0x08 );
7634 fLockAtn = 0 != ( a8Bit & 0x10 );
7635 fMirrorMargins = 0 != ( a8Bit & 0x20 );
7636 fReadOnlyRecommended = 0 != ( a8Bit & 0x40 );
7637 fDfltTrueType = 0 != ( a8Bit & 0x80 );
7638
7639 a8Bit = Get_Byte( pData ); // 7 0x07
7640 fPagSuppressTopSpacing = 0 != ( a8Bit & 0x01 );
7641 fProtEnabled = 0 != ( a8Bit & 0x02 );
7642 fDispFormFieldSel = 0 != ( a8Bit & 0x04 );
7643 fRMView = 0 != ( a8Bit & 0x08 );
7644 fRMPrint = 0 != ( a8Bit & 0x10 );
7645 fWriteReservation = 0 != ( a8Bit & 0x20 );
7646 fLockRev = 0 != ( a8Bit & 0x40 );
7647 fEmbedFonts = 0 != ( a8Bit & 0x80 );
7648
7649 a8Bit = Get_Byte( pData ); // 8 0x08
7650 copts_fNoTabForInd = 0 != ( a8Bit & 0x01 );
7651 copts_fNoSpaceRaiseLower = 0 != ( a8Bit & 0x02 );
7652 copts_fSupressSpbfAfterPgBrk = 0 != ( a8Bit & 0x04 );
7653 copts_fWrapTrailSpaces = 0 != ( a8Bit & 0x08 );
7654 copts_fMapPrintTextColor = 0 != ( a8Bit & 0x10 );
7655 copts_fNoColumnBalance = 0 != ( a8Bit & 0x20 );
7656 copts_fConvMailMergeEsc = 0 != ( a8Bit & 0x40 );
7657 copts_fSupressTopSpacing = 0 != ( a8Bit & 0x80 );
7658
7659 a8Bit = Get_Byte( pData ); // 9 0x09
7660 copts_fOrigWordTableRules = 0 != ( a8Bit & 0x01 );
7661 copts_fTransparentMetafiles = 0 != ( a8Bit & 0x02 );
7662 copts_fShowBreaksInFrames = 0 != ( a8Bit & 0x04 );
7663 copts_fSwapBordersFacingPgs = 0 != ( a8Bit & 0x08 );
7664 copts_fExpShRtn = 0 != ( a8Bit & 0x20 ); // #i56856#
7665
7666 dxaTab = Get_Short( pData ); // 10 0x0a
7667 wSpare = Get_UShort( pData ); // 12 0x0c
7668 dxaHotZ = Get_UShort( pData ); // 14 0x0e
7669 cConsecHypLim = Get_UShort( pData ); // 16 0x10
7670 wSpare2 = Get_UShort( pData ); // 18 0x12
7671 dttmCreated = Get_Long( pData ); // 20 0x14
7672 dttmRevised = Get_Long( pData ); // 24 0x18
7673 dttmLastPrint = Get_Long( pData ); // 28 0x1c
7674 nRevision = Get_Short( pData ); // 32 0x20
7675 tmEdited = Get_Long( pData ); // 34 0x22
7676 cWords = Get_Long( pData ); // 38 0x26
7677 cCh = Get_Long( pData ); // 42 0x2a
7678 cPg = Get_Short( pData ); // 46 0x2e
7679 cParas = Get_Long( pData ); // 48 0x30
7680
7681 a16Bit = Get_UShort( pData ); // 52 0x34
7682 rncEdn = a16Bit & 0x0003 ;
7683 nEdn = ( a16Bit & ~0x0003 ) >> 2;
7684
7685 a16Bit = Get_UShort( pData ); // 54 0x36
7686 epc = a16Bit & 0x0003 ;
7687 nfcFootnoteRef = ( a16Bit & 0x003c ) >> 2;
7688 nfcEdnRef = ( a16Bit & 0x03c0 ) >> 6;
7689 fPrintFormData = 0 != ( a16Bit & 0x0400 );
7690 fSaveFormData = 0 != ( a16Bit & 0x0800 );
7691 fShadeFormData = 0 != ( a16Bit & 0x1000 );
7692 fWCFootnoteEdn = 0 != ( a16Bit & 0x8000 );
7693
7694 cLines = Get_Long( pData ); // 56 0x38
7695 cWordsFootnoteEnd = Get_Long( pData ); // 60 0x3c
7696 cChFootnoteEdn = Get_Long( pData ); // 64 0x40
7697 cPgFootnoteEdn = Get_Short( pData ); // 68 0x44
7698 cParasFootnoteEdn = Get_Long( pData ); // 70 0x46
7699 cLinesFootnoteEdn = Get_Long( pData ); // 74 0x4a
7700 lKeyProtDoc = Get_Long( pData ); // 78 0x4e
7701
7702 a16Bit = Get_UShort( pData ); // 82 0x52
7703 wvkSaved = a16Bit & 0x0007 ;
7704 wScaleSaved = ( a16Bit & 0x0ff8 ) >> 3 ;
7705 zkSaved = ( a16Bit & 0x3000 ) >> 12;
7706 fRotateFontW6 = ( a16Bit & 0x4000 ) >> 14;
7707 iGutterPos = ( a16Bit & 0x8000 ) >> 15;
7708
7709 if (nFib >= 103) // Word 6/32bit, 95, 97, 2000, 2002, 2003, 2007
7710 {
7711 a32Bit = Get_ULong( pData ); // 84 0x54
7712 SetCompatibilityOptions(a32Bit);
7713 }
7714
7715 //#i22436#, for all WW7- documents
7716 if (nFib <= 104) // Word 95
7717 fUsePrinterMetrics = true;
7718
7719 if (nFib > 105) // Word 97, 2000, 2002, 2003, 2007
7720 {
7721 adt = Get_Short( pData ); // 88 0x58
7722
7723 doptypography.ReadFromMem(pData); // 90 0x5a
7724
7725 memcpy( &dogrid, pData, sizeof( WW8_DOGRID )); // 400 0x190
7726 pData += sizeof( WW8_DOGRID );
7727
7728 a16Bit = Get_UShort( pData ); // 410 0x19a
7729 // the following 9 bit are uninteresting
7730 fHtmlDoc = ( a16Bit & 0x0200 ) >> 9 ;
7731 fSnapBorder = ( a16Bit & 0x0800 ) >> 11 ;
7732 fIncludeHeader = ( a16Bit & 0x1000 ) >> 12 ;
7733 fIncludeFooter = ( a16Bit & 0x2000 ) >> 13 ;
7734 fForcePageSizePag = ( a16Bit & 0x4000 ) >> 14 ;
7735 fMinFontSizePag = ( a16Bit & 0x8000 ) >> 15 ;
7736
7737 a16Bit = Get_UShort( pData ); // 412 0x19c
7738 fHaveVersions = 0 != ( a16Bit & 0x0001 );
7739 fAutoVersion = 0 != ( a16Bit & 0x0002 );
7740
7741 pData += 12; // 414 0x19e
7742
7743 cChWS = Get_Long( pData ); // 426 0x1aa
7744 cChWSFootnoteEdn = Get_Long( pData ); // 430 0x1ae
7745 grfDocEvents = Get_Long( pData ); // 434 0x1b2
7746
7747 pData += 4+30+8; // 438 0x1b6; 442 0x1ba; 472 0x1d8; 476 0x1dc
7748
7749 cDBC = Get_Long( pData ); // 480 0x1e0
7750 cDBCFootnoteEdn = Get_Long( pData ); // 484 0x1e4
7751
7752 pData += 1 * sizeof( sal_Int32); // 488 0x1e8
7753
7754 nfcFootnoteRef = Get_Short( pData ); // 492 0x1ec
7755 nfcEdnRef = Get_Short( pData ); // 494 0x1ee
7756 hpsZoomFontPag = Get_Short( pData ); // 496 0x1f0
7757 dywDispPag = Get_Short( pData ); // 498 0x1f2
7758
7759 if (nRead >= 516)
7760 {
7761 //500 -> 508, Appear to be repeated here in 2000+
7762 pData += 8; // 500 0x1f4
7763 a32Bit = Get_Long( pData ); // 508 0x1fc
7764 SetCompatibilityOptions(a32Bit);
7765 a32Bit = Get_Long( pData ); // 512 0x200
7766
7767 // i#78591#
7768 SetCompatibilityOptions2(a32Bit);
7769 }
7770 if (nRead >= 550)
7771 {
7772 pData += 32;
7773 a16Bit = Get_UShort( pData );
7774 fDoNotEmbedSystemFont = ( a16Bit & 0x0001 );
7775 fWordCompat = ( a16Bit & 0x0002 ) >> 1;
7776 fLiveRecover = ( a16Bit & 0x0004 ) >> 2;
7777 fEmbedFactoids = ( a16Bit & 0x0008 ) >> 3;
7778 fFactoidXML = ( a16Bit & 0x00010 ) >> 4;
7779 fFactoidAllDone = ( a16Bit & 0x0020 ) >> 5;
7780 fFolioPrint = ( a16Bit & 0x0040 ) >> 6;
7781 fReverseFolio = ( a16Bit & 0x0080 ) >> 7;
7782 iTextLineEnding = ( a16Bit & 0x0700 ) >> 8;
7783 fHideFcc = ( a16Bit & 0x0800 ) >> 11;
7784 fAcetateShowMarkup = ( a16Bit & 0x1000 ) >> 12;
7785 fAcetateShowAtn = ( a16Bit & 0x2000 ) >> 13;
7786 fAcetateShowInsDel = ( a16Bit & 0x4000 ) >> 14;
7787 fAcetateShowProps = ( a16Bit & 0x8000 ) >> 15;
7788 }
7789 if (nRead >= 600)
7790 {
7791 pData += 48;
7792 a16Bit = Get_Short(pData);
7793 fUseBackGroundInAllmodes = (a16Bit & 0x0080) >> 7;
7794 }
7795 }
7796 }
7797}
7798
7799WW8Dop::WW8Dop():
7800 fFacingPages(false), fWidowControl(true), fPMHMainDoc(false), grfSuppression(0), fpc(1),
7801 grpfIhdt(0), rncFootnote(0), nFootnote(1), fOutlineDirtySave(true), fOnlyMacPics(false),
7802 fOnlyWinPics(false), fLabelDoc(false), fHyphCapitals(true), fAutoHyphen(false),
7803 fFormNoFields(false), fLinkStyles(false), fRevMarking(false), fBackup(true),
7804 fExactCWords(false), fPagHidden(true), fPagResults(true), fLockAtn(false),
7805 fMirrorMargins(false), fReadOnlyRecommended(false), fDfltTrueType(true),
7806 fPagSuppressTopSpacing(false), fProtEnabled(false), fDispFormFieldSel(false), fRMView(true),
7807 fRMPrint(true), fWriteReservation(false), fLockRev(false), fEmbedFonts(false),
7808 copts_fNoTabForInd(false), copts_fNoSpaceRaiseLower(false), copts_fSupressSpbfAfterPgBrk(false),
7809 copts_fWrapTrailSpaces(false), copts_fMapPrintTextColor(false), copts_fNoColumnBalance(false),
7810 copts_fConvMailMergeEsc(false), copts_fSupressTopSpacing(false),
7811 copts_fOrigWordTableRules(false), copts_fTransparentMetafiles(false),
7812 copts_fShowBreaksInFrames(false), copts_fSwapBordersFacingPgs(false), copts_fExpShRtn(false),
7813 dxaTab(0x2d0), dxaHotZ(0x168), nRevision(1),
7814 rncEdn(0), nEdn(1), epc(3), fPrintFormData(false), fSaveFormData(false), fShadeFormData(true),
7815 fWCFootnoteEdn(false), wvkSaved(2), wScaleSaved(100), zkSaved(0), fRotateFontW6(false),
7816 iGutterPos(false), fNoTabForInd(false), fNoSpaceRaiseLower(false),
7817 fSupressSpbfAfterPageBreak(false), fWrapTrailSpaces(false), fMapPrintTextColor(false),
7818 fNoColumnBalance(false), fConvMailMergeEsc(false), fSupressTopSpacing(false),
7819 fOrigWordTableRules(false), fTransparentMetafiles(false), fShowBreaksInFrames(false),
7820 fSwapBordersFacingPgs(false), fCompatibilityOptions_Unknown1_13(false), fExpShRtn(false),
7821 fCompatibilityOptions_Unknown1_15(false), fCompatibilityOptions_Unknown1_16(false),
7822 fSuppressTopSpacingMac5(false), fTruncDxaExpand(false), fPrintBodyBeforeHdr(false),
7823 fNoLeading(true), fCompatibilityOptions_Unknown1_21(false), fMWSmallCaps(false),
7824 fCompatibilityOptions_Unknown1_23(false), fCompatibilityOptions_Unknown1_24(false),
7825 fCompatibilityOptions_Unknown1_25(false), fCompatibilityOptions_Unknown1_26(false),
7826 fCompatibilityOptions_Unknown1_27(false), fCompatibilityOptions_Unknown1_28(false),
7827 fCompatibilityOptions_Unknown1_29(false), fCompatibilityOptions_Unknown1_30(false),
7828 fCompatibilityOptions_Unknown1_31(false), fUsePrinterMetrics(true), lvl(9), fHtmlDoc(false),
7829 fSnapBorder(false), fIncludeHeader(true), fIncludeFooter(true), fForcePageSizePag(false),
7830 fMinFontSizePag(false), fHaveVersions(false), fAutoVersion(false),
7831 cChWS(0), cChWSFootnoteEdn(0), cDBC(0), cDBCFootnoteEdn(0), nfcEdnRef(2),
7832 fCompatibilityOptions_Unknown2_1(false), fCompatibilityOptions_Unknown2_2(false),
7833 fDontUseHTMLAutoSpacing(false), fCompatibilityOptions_Unknown2_4(false),
7834 fCompatibilityOptions_Unknown2_5(false), fCompatibilityOptions_Unknown2_6(false),
7835 fCompatibilityOptions_Unknown2_7(false), fCompatibilityOptions_Unknown2_8(false),
7836 fCompatibilityOptions_Unknown2_9(false), fCompatibilityOptions_Unknown2_10(false),
7837 fCompatibilityOptions_Unknown2_11(false), fCompatibilityOptions_Unknown2_12(false),
7838 fCompatibilityOptions_Unknown2_13(false), fCompatibilityOptions_Unknown2_14(false),
7839 fCompatibilityOptions_Unknown2_15(false), fCompatibilityOptions_Unknown2_16(false),
7840 fCompatibilityOptions_Unknown2_17(false), fCompatibilityOptions_Unknown2_18(false),
7841 fCompatibilityOptions_Unknown2_19(false), fCompatibilityOptions_Unknown2_20(false),
7842 fCompatibilityOptions_Unknown2_21(false), fCompatibilityOptions_Unknown2_22(false),
7843 fCompatibilityOptions_Unknown2_23(false), fCompatibilityOptions_Unknown2_24(false),
7844 fCompatibilityOptions_Unknown2_25(false), fCompatibilityOptions_Unknown2_26(false),
7845 fCompatibilityOptions_Unknown2_27(false), fCompatibilityOptions_Unknown2_28(false),
7846 fCompatibilityOptions_Unknown2_29(false), fCompatibilityOptions_Unknown2_30(false),
7847 fCompatibilityOptions_Unknown2_31(false), fCompatibilityOptions_Unknown2_32(false),
7848 fUnknown3(0), fUseBackGroundInAllmodes(false), fDoNotEmbedSystemFont(false), fWordCompat(false),
7849 fLiveRecover(false), fEmbedFactoids(false), fFactoidXML(false), fFactoidAllDone(false),
7850 fFolioPrint(false), fReverseFolio(false), iTextLineEnding(0), fHideFcc(false),
7851 fAcetateShowMarkup(false), fAcetateShowAtn(true), fAcetateShowInsDel(false),
7852 fAcetateShowProps(false)
7853 // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
7854 // above bit-field member initializations can be moved to the class definition
7855{
7856 /*
7857 Writer acts like this all the time at the moment, ideally we need an
7858 option for these two as well to import word docs that are not like
7859 this by default
7860 */
7861 // put in initialization list
7862 // fNoLeading = true;
7863 //fUsePrinterMetrics = true;
7864}
7865
7866void WW8Dop::SetCompatibilityOptions(sal_uInt32 a32Bit)
7867{
7868 fNoTabForInd = ( a32Bit & 0x00000001 ) ;
7869 fNoSpaceRaiseLower = ( a32Bit & 0x00000002 ) >> 1 ;
7870 fSupressSpbfAfterPageBreak = ( a32Bit & 0x00000004 ) >> 2 ;
7871 fWrapTrailSpaces = ( a32Bit & 0x00000008 ) >> 3 ;
7872 fMapPrintTextColor = ( a32Bit & 0x00000010 ) >> 4 ;
7873 fNoColumnBalance = ( a32Bit & 0x00000020 ) >> 5 ;
7874 fConvMailMergeEsc = ( a32Bit & 0x00000040 ) >> 6 ;
7875 fSupressTopSpacing = ( a32Bit & 0x00000080 ) >> 7 ;
7876 fOrigWordTableRules = ( a32Bit & 0x00000100 ) >> 8 ;
7877 fTransparentMetafiles = ( a32Bit & 0x00000200 ) >> 9 ;
7878 fShowBreaksInFrames = ( a32Bit & 0x00000400 ) >> 10 ;
7879 fSwapBordersFacingPgs = ( a32Bit & 0x00000800 ) >> 11 ;
7880 fCompatibilityOptions_Unknown1_13 = ( a32Bit & 0x00001000 ) >> 12 ;
7881 fExpShRtn = ( a32Bit & 0x00002000 ) >> 13 ; // #i56856#
7882 fCompatibilityOptions_Unknown1_15 = ( a32Bit & 0x00004000 ) >> 14 ;
7883 fCompatibilityOptions_Unknown1_16 = ( a32Bit & 0x00008000 ) >> 15 ;
7884 fSuppressTopSpacingMac5 = ( a32Bit & 0x00010000 ) >> 16 ;
7885 fTruncDxaExpand = ( a32Bit & 0x00020000 ) >> 17 ;
7886 fPrintBodyBeforeHdr = ( a32Bit & 0x00040000 ) >> 18 ;
7887 fNoLeading = ( a32Bit & 0x00080000 ) >> 19 ;
7888 fCompatibilityOptions_Unknown1_21 = ( a32Bit & 0x00100000 ) >> 20 ;
7889 fMWSmallCaps = ( a32Bit & 0x00200000 ) >> 21 ;
7890 fCompatibilityOptions_Unknown1_23 = ( a32Bit & 0x00400000 ) >> 22 ;
7891 fCompatibilityOptions_Unknown1_24 = ( a32Bit & 0x00800800 ) >> 23 ;
7892 fCompatibilityOptions_Unknown1_25 = ( a32Bit & 0x01000000 ) >> 24 ;
7893 fCompatibilityOptions_Unknown1_26 = ( a32Bit & 0x02000000 ) >> 25 ;
7894 fCompatibilityOptions_Unknown1_27 = ( a32Bit & 0x04000000 ) >> 26 ;
7895 fCompatibilityOptions_Unknown1_28 = ( a32Bit & 0x08000000 ) >> 27 ;
7896 fCompatibilityOptions_Unknown1_29 = ( a32Bit & 0x10000000 ) >> 28 ;
7897 fCompatibilityOptions_Unknown1_30 = ( a32Bit & 0x20000000 ) >> 29 ;
7898 fCompatibilityOptions_Unknown1_31 = ( a32Bit & 0x40000000 ) >> 30 ;
7899
7900 fUsePrinterMetrics = ( a32Bit & 0x80000000 ) >> 31 ;
7901}
7902
7903sal_uInt32 WW8Dop::GetCompatibilityOptions() const
7904{
7905 sal_uInt32 a32Bit = 0;
7906 if (fNoTabForInd) a32Bit |= 0x00000001;
7907 if (fNoSpaceRaiseLower) a32Bit |= 0x00000002;
7908 if (fSupressSpbfAfterPageBreak) a32Bit |= 0x00000004;
7909 if (fWrapTrailSpaces) a32Bit |= 0x00000008;
7910 if (fMapPrintTextColor) a32Bit |= 0x00000010;
7911 if (fNoColumnBalance) a32Bit |= 0x00000020;
7912 if (fConvMailMergeEsc) a32Bit |= 0x00000040;
7913 if (fSupressTopSpacing) a32Bit |= 0x00000080;
7914 if (fOrigWordTableRules) a32Bit |= 0x00000100;
7915 if (fTransparentMetafiles) a32Bit |= 0x00000200;
7916 if (fShowBreaksInFrames) a32Bit |= 0x00000400;
7917 if (fSwapBordersFacingPgs) a32Bit |= 0x00000800;
7918 if (fCompatibilityOptions_Unknown1_13) a32Bit |= 0x00001000;
7919 if (fExpShRtn) a32Bit |= 0x00002000; // #i56856#
7920 if (fCompatibilityOptions_Unknown1_15) a32Bit |= 0x00004000;
7921 if (fCompatibilityOptions_Unknown1_16) a32Bit |= 0x00008000;
7922 if (fSuppressTopSpacingMac5) a32Bit |= 0x00010000;
7923 if (fTruncDxaExpand) a32Bit |= 0x00020000;
7924 if (fPrintBodyBeforeHdr) a32Bit |= 0x00040000;
7925 if (fNoLeading) a32Bit |= 0x00080000;
7926 if (fCompatibilityOptions_Unknown1_21) a32Bit |= 0x00100000;
7927 if (fMWSmallCaps) a32Bit |= 0x00200000;
7928 if (fCompatibilityOptions_Unknown1_23) a32Bit |= 0x00400000;
7929 if (fCompatibilityOptions_Unknown1_24) a32Bit |= 0x00800000;
7930 if (fCompatibilityOptions_Unknown1_25) a32Bit |= 0x01000000;
7931 if (fCompatibilityOptions_Unknown1_26) a32Bit |= 0x02000000;
7932 if (fCompatibilityOptions_Unknown1_27) a32Bit |= 0x04000000;
7933 if (fCompatibilityOptions_Unknown1_28) a32Bit |= 0x08000000;
7934 if (fCompatibilityOptions_Unknown1_29) a32Bit |= 0x10000000;
7935 if (fCompatibilityOptions_Unknown1_30) a32Bit |= 0x20000000;
7936 if (fCompatibilityOptions_Unknown1_31) a32Bit |= 0x40000000;
7937 if (fUsePrinterMetrics) a32Bit |= 0x80000000;
7938 return a32Bit;
7939}
7940
7941// i#78591#
7942void WW8Dop::SetCompatibilityOptions2(sal_uInt32 a32Bit)
7943{
7944 fCompatibilityOptions_Unknown2_1 = ( a32Bit & 0x00000001 );
7945 fCompatibilityOptions_Unknown2_2 = ( a32Bit & 0x00000002 ) >> 1 ;
7946 fDontUseHTMLAutoSpacing = ( a32Bit & 0x00000004 ) >> 2 ;
7947 fCompatibilityOptions_Unknown2_4 = ( a32Bit & 0x00000008 ) >> 3 ;
7948 fCompatibilityOptions_Unknown2_5 = ( a32Bit & 0x00000010 ) >> 4 ;
7949 fCompatibilityOptions_Unknown2_6 = ( a32Bit & 0x00000020 ) >> 5 ;
7950 fCompatibilityOptions_Unknown2_7 = ( a32Bit & 0x00000040 ) >> 6 ;
7951 fCompatibilityOptions_Unknown2_8 = ( a32Bit & 0x00000080 ) >> 7 ;
7952 fCompatibilityOptions_Unknown2_9 = ( a32Bit & 0x00000100 ) >> 8 ;
7953 fCompatibilityOptions_Unknown2_10 = ( a32Bit & 0x00000200 ) >> 9 ;
7954 fCompatibilityOptions_Unknown2_11 = ( a32Bit & 0x00000400 ) >> 10 ;
7955 fCompatibilityOptions_Unknown2_12 = ( a32Bit & 0x00000800 ) >> 11 ;
7956 fCompatibilityOptions_Unknown2_13 = ( a32Bit & 0x00001000 ) >> 12 ;
7957 fCompatibilityOptions_Unknown2_14 = ( a32Bit & 0x00002000 ) >> 13 ;
7958 fCompatibilityOptions_Unknown2_15 = ( a32Bit & 0x00004000 ) >> 14 ;
7959 fCompatibilityOptions_Unknown2_16 = ( a32Bit & 0x00008000 ) >> 15 ;
7960 fCompatibilityOptions_Unknown2_17 = ( a32Bit & 0x00010000 ) >> 16 ;
7961 fCompatibilityOptions_Unknown2_18 = ( a32Bit & 0x00020000 ) >> 17 ;
7962 fCompatibilityOptions_Unknown2_19 = ( a32Bit & 0x00040000 ) >> 18 ;
7963 fCompatibilityOptions_Unknown2_20 = ( a32Bit & 0x00080000 ) >> 19 ;
7964 fCompatibilityOptions_Unknown2_21 = ( a32Bit & 0x00100000 ) >> 20 ;
7965 fCompatibilityOptions_Unknown2_22 = ( a32Bit & 0x00200000 ) >> 21 ;
7966 fCompatibilityOptions_Unknown2_23 = ( a32Bit & 0x00400000 ) >> 22 ;
7967 fCompatibilityOptions_Unknown2_24 = ( a32Bit & 0x00800800 ) >> 23 ;
7968 fCompatibilityOptions_Unknown2_25 = ( a32Bit & 0x01000800 ) >> 24 ;
7969 fCompatibilityOptions_Unknown2_26 = ( a32Bit & 0x02000800 ) >> 25 ;
7970 fCompatibilityOptions_Unknown2_27 = ( a32Bit & 0x04000800 ) >> 26 ;
7971 fCompatibilityOptions_Unknown2_28 = ( a32Bit & 0x08000800 ) >> 27 ;
7972 fCompatibilityOptions_Unknown2_29 = ( a32Bit & 0x10000800 ) >> 28 ;
7973 fCompatibilityOptions_Unknown2_30 = ( a32Bit & 0x20000800 ) >> 29 ;
7974 fCompatibilityOptions_Unknown2_31 = ( a32Bit & 0x40000800 ) >> 30 ;
7975 fCompatibilityOptions_Unknown2_32 = ( a32Bit & 0x80000000 ) >> 31 ;
7976}
7977
7978sal_uInt32 WW8Dop::GetCompatibilityOptions2() const
7979{
7980 sal_uInt32 a32Bit = 0;
7981 if (fCompatibilityOptions_Unknown2_1) a32Bit |= 0x00000001;
7982 if (fCompatibilityOptions_Unknown2_2) a32Bit |= 0x00000002;
7983 if (fDontUseHTMLAutoSpacing) a32Bit |= 0x00000004;
7984 if (fCompatibilityOptions_Unknown2_4) a32Bit |= 0x00000008;
7985 if (fCompatibilityOptions_Unknown2_5) a32Bit |= 0x00000010;
7986 if (fCompatibilityOptions_Unknown2_6) a32Bit |= 0x00000020;
7987 if (fCompatibilityOptions_Unknown2_7) a32Bit |= 0x00000040;
7988 if (fCompatibilityOptions_Unknown2_8) a32Bit |= 0x00000080;
7989 if (fCompatibilityOptions_Unknown2_9) a32Bit |= 0x00000100;
7990 if (fCompatibilityOptions_Unknown2_10) a32Bit |= 0x00000200;
7991 if (fCompatibilityOptions_Unknown2_11) a32Bit |= 0x00000400;
7992 if (fCompatibilityOptions_Unknown2_12) a32Bit |= 0x00000800;
7993 if (fCompatibilityOptions_Unknown2_13) a32Bit |= 0x00001000;
7994 //#i42909# set thai "line breaking rules" compatibility option
7995 // pflin, wonder whether bUseThaiLineBreakingRules is correct
7996 // when importing word document.
7997 if (bUseThaiLineBreakingRules) a32Bit |= 0x00002000;
7998 else if (fCompatibilityOptions_Unknown2_14) a32Bit |= 0x00002000;
7999 if (fCompatibilityOptions_Unknown2_15) a32Bit |= 0x00004000;
8000 if (fCompatibilityOptions_Unknown2_16) a32Bit |= 0x00008000;
8001 if (fCompatibilityOptions_Unknown2_17) a32Bit |= 0x00010000;
8002 if (fCompatibilityOptions_Unknown2_18) a32Bit |= 0x00020000;
8003 if (fCompatibilityOptions_Unknown2_19) a32Bit |= 0x00040000;
8004 if (fCompatibilityOptions_Unknown2_20) a32Bit |= 0x00080000;
8005 if (fCompatibilityOptions_Unknown2_21) a32Bit |= 0x00100000;
8006 if (fCompatibilityOptions_Unknown2_22) a32Bit |= 0x00200000;
8007 if (fCompatibilityOptions_Unknown2_23) a32Bit |= 0x00400000;
8008 if (fCompatibilityOptions_Unknown2_24) a32Bit |= 0x00800000;
8009 if (fCompatibilityOptions_Unknown2_25) a32Bit |= 0x01000000;
8010 if (fCompatibilityOptions_Unknown2_26) a32Bit |= 0x02000000;
8011 if (fCompatibilityOptions_Unknown2_27) a32Bit |= 0x04000000;
8012 if (fCompatibilityOptions_Unknown2_28) a32Bit |= 0x08000000;
8013 if (fCompatibilityOptions_Unknown2_29) a32Bit |= 0x10000000;
8014 if (fCompatibilityOptions_Unknown2_30) a32Bit |= 0x20000000;
8015 if (fCompatibilityOptions_Unknown2_31) a32Bit |= 0x40000000;
8016 if (fCompatibilityOptions_Unknown2_32) a32Bit |= 0x80000000;
8017 return a32Bit;
8018}
8019
8020void WW8Dop::Write(SvStream& rStrm, WW8Fib& rFib) const
8021{
8022 const int nMaxDopLen = 610;
8023 sal_uInt32 nLen = 8 == rFib.m_nVersion ? nMaxDopLen : 84;
8024 rFib.m_fcDop = rStrm.Tell();
8025 rFib.m_lcbDop = nLen;
8026
8027 sal_uInt8 aData[ nMaxDopLen ] = {};
8028 sal_uInt8* pData = aData;
8029
8030 // analyse the data
8031 sal_uInt16 a16Bit;
8032 sal_uInt8 a8Bit;
8033
8034 a16Bit = 0; // 0 0x00
8035 if (fFacingPages)
8036 a16Bit |= 0x0001;
8037 if (fWidowControl)
8038 a16Bit |= 0x0002;
8039 if (fPMHMainDoc)
8040 a16Bit |= 0x0004;
8041 a16Bit |= ( 0x0018 & (grfSuppression << 3));
8042 a16Bit |= ( 0x0060 & (fpc << 5));
8043 a16Bit |= ( 0xff00 & (grpfIhdt << 8));
8044 Set_UInt16( pData, a16Bit );
8045
8046 a16Bit = 0; // 2 0x02
8047 a16Bit |= ( 0x0003 & rncFootnote );
8048 a16Bit |= ( ~0x0003 & (nFootnote << 2));
8049 Set_UInt16( pData, a16Bit );
8050
8051 a8Bit = 0; // 4 0x04
8052 if( fOutlineDirtySave ) a8Bit |= 0x01;
8053 Set_UInt8( pData, a8Bit );
8054
8055 a8Bit = 0; // 5 0x05
8056 if( fOnlyMacPics ) a8Bit |= 0x01;
8057 if( fOnlyWinPics ) a8Bit |= 0x02;
8058 if( fLabelDoc ) a8Bit |= 0x04;
8059 if( fHyphCapitals ) a8Bit |= 0x08;
8060 if( fAutoHyphen ) a8Bit |= 0x10;
8061 if( fFormNoFields ) a8Bit |= 0x20;
8062 if( fLinkStyles ) a8Bit |= 0x40;
8063 if( fRevMarking ) a8Bit |= 0x80;
8064 Set_UInt8( pData, a8Bit );
8065
8066 a8Bit = 0; // 6 0x06
8067 if( fBackup ) a8Bit |= 0x01;
8068 if( fExactCWords ) a8Bit |= 0x02;
8069 if( fPagHidden ) a8Bit |= 0x04;
8070 if( fPagResults ) a8Bit |= 0x08;
8071 if( fLockAtn ) a8Bit |= 0x10;
8072 if( fMirrorMargins ) a8Bit |= 0x20;
8073 if( fReadOnlyRecommended ) a8Bit |= 0x40;
8074 if( fDfltTrueType ) a8Bit |= 0x80;
8075 Set_UInt8( pData, a8Bit );
8076
8077 a8Bit = 0; // 7 0x07
8078 if( fPagSuppressTopSpacing ) a8Bit |= 0x01;
8079 if( fProtEnabled ) a8Bit |= 0x02;
8080 if( fDispFormFieldSel ) a8Bit |= 0x04;
8081 if( fRMView ) a8Bit |= 0x08;
8082 if( fRMPrint ) a8Bit |= 0x10;
8083 if( fWriteReservation ) a8Bit |= 0x20;
8084 if( fLockRev ) a8Bit |= 0x40;
8085 if( fEmbedFonts ) a8Bit |= 0x80;
8086 Set_UInt8( pData, a8Bit );
8087
8088 a8Bit = 0; // 8 0x08
8089 if( copts_fNoTabForInd ) a8Bit |= 0x01;
8090 if( copts_fNoSpaceRaiseLower ) a8Bit |= 0x02;
8091 if( copts_fSupressSpbfAfterPgBrk ) a8Bit |= 0x04;
8092 if( copts_fWrapTrailSpaces ) a8Bit |= 0x08;
8093 if( copts_fMapPrintTextColor ) a8Bit |= 0x10;
8094 if( copts_fNoColumnBalance ) a8Bit |= 0x20;
8095 if( copts_fConvMailMergeEsc ) a8Bit |= 0x40;
8096 if( copts_fSupressTopSpacing ) a8Bit |= 0x80;
8097 Set_UInt8( pData, a8Bit );
8098
8099 a8Bit = 0; // 9 0x09
8100 if( copts_fOrigWordTableRules ) a8Bit |= 0x01;
8101 if( copts_fTransparentMetafiles ) a8Bit |= 0x02;
8102 if( copts_fShowBreaksInFrames ) a8Bit |= 0x04;
8103 if( copts_fSwapBordersFacingPgs ) a8Bit |= 0x08;
8104 if( copts_fExpShRtn ) a8Bit |= 0x20; // #i56856#
8105 Set_UInt8( pData, a8Bit );
8106
8107 Set_UInt16( pData, dxaTab ); // 10 0x0a
8108 Set_UInt16( pData, wSpare ); // 12 0x0c
8109 Set_UInt16( pData, dxaHotZ ); // 14 0x0e
8110 Set_UInt16( pData, cConsecHypLim ); // 16 0x10
8111 Set_UInt16( pData, wSpare2 ); // 18 0x12
8112 Set_UInt32( pData, dttmCreated ); // 20 0x14
8113 Set_UInt32( pData, dttmRevised ); // 24 0x18
8114 Set_UInt32( pData, dttmLastPrint ); // 28 0x1c
8115 Set_UInt16( pData, nRevision ); // 32 0x20
8116 Set_UInt32( pData, tmEdited ); // 34 0x22
8117 Set_UInt32( pData, cWords ); // 38 0x26
8118 Set_UInt32( pData, cCh ); // 42 0x2a
8119 Set_UInt16( pData, cPg ); // 46 0x2e
8120 Set_UInt32( pData, cParas ); // 48 0x30
8121
8122 a16Bit = 0; // 52 0x34
8123 a16Bit |= ( 0x0003 & rncEdn );
8124 a16Bit |= (~0x0003 & ( nEdn << 2));
8125 Set_UInt16( pData, a16Bit );
8126
8127 a16Bit = 0; // 54 0x36
8128 a16Bit |= (0x0003 & epc );
8129 a16Bit |= (0x003c & (nfcFootnoteRef << 2));
8130 a16Bit |= (0x03c0 & (nfcEdnRef << 6));
8131 if( fPrintFormData ) a16Bit |= 0x0400;
8132 if( fSaveFormData ) a16Bit |= 0x0800;
8133 if( fShadeFormData ) a16Bit |= 0x1000;
8134 if( fWCFootnoteEdn ) a16Bit |= 0x8000;
8135 Set_UInt16( pData, a16Bit );
8136
8137 Set_UInt32( pData, cLines ); // 56 0x38
8138 Set_UInt32( pData, cWordsFootnoteEnd ); // 60 0x3c
8139 Set_UInt32( pData, cChFootnoteEdn ); // 64 0x40
8140 Set_UInt16( pData, cPgFootnoteEdn ); // 68 0x44
8141 Set_UInt32( pData, cParasFootnoteEdn ); // 70 0x46
8142 Set_UInt32( pData, cLinesFootnoteEdn ); // 74 0x4a
8143 Set_UInt32( pData, lKeyProtDoc ); // 78 0x4e
8144
8145 a16Bit = 0; // 82 0x52
8146 if (wvkSaved)
8147 a16Bit |= 0x0007;
8148 a16Bit |= (0x0ff8 & (wScaleSaved << 3));
8149 a16Bit |= (0x3000 & (zkSaved << 12));
8150 Set_UInt16( pData, a16Bit );
8151
8152 if( 8 == rFib.m_nVersion )
8153 {
8154 Set_UInt32(pData, GetCompatibilityOptions()); // 84 0x54
8155
8156 Set_UInt16( pData, adt ); // 88 0x58
8157
8158 doptypography.WriteToMem(pData); // 400 0x190
8159
8160 memcpy( pData, &dogrid, sizeof( WW8_DOGRID ));
8161 pData += sizeof( WW8_DOGRID );
8162
8163 a16Bit = 0x12; // set lvl to 9 // 410 0x19a
8164 if( fHtmlDoc ) a16Bit |= 0x0200;
8165 if( fSnapBorder ) a16Bit |= 0x0800;
8166 if( fIncludeHeader ) a16Bit |= 0x1000;
8167 if( fIncludeFooter ) a16Bit |= 0x2000;
8168 if( fForcePageSizePag ) a16Bit |= 0x4000;
8169 if( fMinFontSizePag ) a16Bit |= 0x8000;
8170 Set_UInt16( pData, a16Bit );
8171
8172 a16Bit = 0; // 412 0x19c
8173 if( fHaveVersions ) a16Bit |= 0x0001;
8174 if( fAutoVersion ) a16Bit |= 0x0002;
8175 Set_UInt16( pData, a16Bit );
8176
8177 pData += 12; // 414 0x19e
8178
8179 Set_UInt32( pData, cChWS ); // 426 0x1aa
8180 Set_UInt32( pData, cChWSFootnoteEdn ); // 430 0x1ae
8181 Set_UInt32( pData, grfDocEvents ); // 434 0x1b2
8182
8183 pData += 4+30+8; // 438 0x1b6; 442 0x1ba; 472 0x1d8; 476 0x1dc
8184
8185 Set_UInt32( pData, cDBC ); // 480 0x1e0
8186 Set_UInt32( pData, cDBCFootnoteEdn ); // 484 0x1e4
8187
8188 pData += 1 * sizeof( sal_Int32); // 488 0x1e8
8189
8190 Set_UInt16( pData, nfcFootnoteRef ); // 492 0x1ec
8191 Set_UInt16( pData, nfcEdnRef ); // 494 0x1ee
8192 Set_UInt16( pData, hpsZoomFontPag ); // 496 0x1f0
8193 Set_UInt16( pData, dywDispPag ); // 498 0x1f2
8194
8195 //500 -> 508, Appear to be repeated here in 2000+
8196 pData += 8;
8197 Set_UInt32(pData, GetCompatibilityOptions());
8198 Set_UInt32(pData, GetCompatibilityOptions2());
8199 pData += 32;
8200
8201 a16Bit = 0;
8202 if (fEmbedFactoids)
8203 a16Bit |= 0x8;
8204 if (fAcetateShowMarkup)
8205 a16Bit |= 0x1000;
8206 //Word XP at least requires fAcetateShowMarkup to honour fAcetateShowAtn
8207 if (fAcetateShowAtn)
8208 {
8209 a16Bit |= 0x1000;
8210 a16Bit |= 0x2000;
8211 }
8212 Set_UInt16(pData, a16Bit);
8213
8214 pData += 48;
8215 a16Bit = 0x0080;
8216 Set_UInt16(pData, a16Bit);
8217 }
8218 rStrm.WriteBytes(aData, nLen);
8219}
8220
8221void WW8DopTypography::ReadFromMem(sal_uInt8 *&pData)
8222{
8223 sal_uInt16 a16Bit = Get_UShort(pData);
8224 m_fKerningPunct = (a16Bit & 0x0001);
8225 m_iJustification = (a16Bit & 0x0006) >> 1;
8226 m_iLevelOfKinsoku = (a16Bit & 0x0018) >> 3;
8227 m_f2on1 = (a16Bit & 0x0020) >> 5;
8228 m_reserved1 = (a16Bit & 0x03C0) >> 6;
8229 m_reserved2 = (a16Bit & 0xFC00) >> 10;
8230
8231 m_cchFollowingPunct = Get_Short(pData);
8232 m_cchLeadingPunct = Get_Short(pData);
8233
8234 sal_Int16 i;
8235 for (i=0; i < nMaxFollowing; ++i)
8236 m_rgxchFPunct[i] = Get_Short(pData);
8237 for (i=0; i < nMaxLeading; ++i)
8238 m_rgxchLPunct[i] = Get_Short(pData);
8239
8240 if (m_cchFollowingPunct >= 0 && m_cchFollowingPunct < nMaxFollowing)
8241 m_rgxchFPunct[m_cchFollowingPunct]=0;
8242 else
8243 m_rgxchFPunct[nMaxFollowing - 1]=0;
8244
8245 if (m_cchLeadingPunct >= 0 && m_cchLeadingPunct < nMaxLeading)
8246 m_rgxchLPunct[m_cchLeadingPunct]=0;
8247 else
8248 m_rgxchLPunct[nMaxLeading - 1]=0;
8249
8250}
8251
8252void WW8DopTypography::WriteToMem(sal_uInt8 *&pData) const
8253{
8254 sal_uInt16 a16Bit = sal_uInt16(m_fKerningPunct);
8255 a16Bit |= (m_iJustification << 1) & 0x0006;
8256 a16Bit |= (m_iLevelOfKinsoku << 3) & 0x0018;
8257 a16Bit |= (int(m_f2on1) << 5) & 0x0020;
8258 a16Bit |= (m_reserved1 << 6) & 0x03C0;
8259 a16Bit |= (m_reserved2 << 10) & 0xFC00;
8260 Set_UInt16(pData,a16Bit);
8261
8262 Set_UInt16(pData,m_cchFollowingPunct);
8263 Set_UInt16(pData,m_cchLeadingPunct);
8264
8265 sal_Int16 i;
8266 for (i=0; i < nMaxFollowing; ++i)
8267 Set_UInt16(pData,m_rgxchFPunct[i]);
8268 for (i=0; i < nMaxLeading; ++i)
8269 Set_UInt16(pData,m_rgxchLPunct[i]);
8270}
8271
8272LanguageType WW8DopTypography::GetConvertedLang() const
8273{
8274 LanguageType nLang;
8275 //I have assumed people's republic/taiwan == simplified/traditional
8276
8277 //This isn't a documented issue, so we might have it all wrong,
8278 //i.e. i.e. what's with the powers of two ?
8279
8280 /*
8281 One example of 3 for reserved1 which was really Japanese, perhaps last bit
8282 is for some other use ?, or redundant. If more examples trigger the assert
8283 we might be able to figure it out.
8284 */
8285 switch(m_reserved1 & 0xE)
8286 {
8287 case 2: //Japan
8288 nLang = LANGUAGE_JAPANESELanguageType(0x0411);
8289 break;
8290 case 4: //Chinese (People's Republic)
8291 nLang = LANGUAGE_CHINESE_SIMPLIFIEDLanguageType(0x0804);
8292 break;
8293 case 6: //Korean
8294 nLang = LANGUAGE_KOREANLanguageType(0x0412);
8295 break;
8296 case 8: //Chinese (Taiwan)
8297 nLang = LANGUAGE_CHINESE_TRADITIONALLanguageType(0x0404);
8298 break;
8299 default:
8300 OSL_ENSURE(false, "Unknown MS Asian Typography language, report")do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8300" ": "), "%s", "Unknown MS Asian Typography language, report"
); } } while (false)
;
8301 nLang = LANGUAGE_CHINESE_SIMPLIFIED_LEGACYLanguageType(0x0004);
8302 break;
8303 case 0:
8304 //And here we have the possibility that it says 2, but it's really
8305 //a bug and only japanese level 2 has been selected after a custom
8306 //version was chosen on last save!
8307 nLang = LANGUAGE_JAPANESELanguageType(0x0411);
8308 break;
8309 }
8310 return nLang;
8311}
8312
8313// Sprms
8314
8315sal_uInt16 wwSprmParser::GetSprmTailLen(sal_uInt16 nId, const sal_uInt8* pSprm, sal_Int32 nRemLen)
8316 const
8317{
8318 SprmInfo aSprm = GetSprmInfo(nId);
8319 sal_uInt16 nL = 0; // number of Bytes to read
8320
8321 //sprmPChgTabs
8322 switch( nId )
8323 {
8324 case 23:
8325 case 0xC615:
8326 if( pSprm[1 + mnDelta] != 255 )
8327 nL = static_cast< sal_uInt16 >(pSprm[1 + mnDelta] + aSprm.nLen);
8328 else
8329 {
8330 sal_uInt8 nDelIdx = 2 + mnDelta;
8331 sal_uInt8 nDel = nDelIdx < nRemLen ? pSprm[nDelIdx] : 0;
8332 sal_uInt8 nInsIdx = 3 + mnDelta + 4 * nDel;
8333 sal_uInt8 nIns = nInsIdx < nRemLen ? pSprm[nInsIdx] : 0;
8334
8335 nL = 2 + 4 * nDel + 3 * nIns;
8336 }
8337 break;
8338 case 0xD608:
8339 {
8340 sal_uInt8 nIndex = 1 + mnDelta;
8341 if (nIndex + 1 >= nRemLen)
8342 {
8343 SAL_WARN("sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "sprm longer than remaining bytes, doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8343" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "sprm longer than remaining bytes, doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm longer than remaining bytes, doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8343" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "sprm longer than remaining bytes, doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8343" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "sprm longer than remaining bytes, doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm longer than remaining bytes, doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8343" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
8344 nL = 0;
8345 }
8346 else
8347 nL = SVBT16ToUInt16(&pSprm[nIndex]);
8348 break;
8349 }
8350 default:
8351 switch (aSprm.nVari)
8352 {
8353 case L_FIX:
8354 nL = aSprm.nLen; // Excl. Token
8355 break;
8356 case L_VAR:
8357 // Variable 1-Byte Length?
8358 // Excl. Token + Var-Lengthbyte
8359 nL = static_cast< sal_uInt16 >(pSprm[1 + mnDelta] + aSprm.nLen);
8360 break;
8361 case L_VAR2:
8362 {
8363 // Variable 2-Byte Length?
8364 // Excl. Token + Var-Lengthbyte
8365 sal_uInt8 nIndex = 1 + mnDelta;
8366 sal_uInt16 nCount;
8367 if (nIndex + 1 >= nRemLen)
8368 {
8369 SAL_WARN("sw.ww8", "sprm longer than remaining bytes, doc or parser is wrong")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "sprm longer than remaining bytes, doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8369" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "sprm longer than remaining bytes, doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm longer than remaining bytes, doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8369" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "sprm longer than remaining bytes, doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8369" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "sprm longer than remaining bytes, doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm longer than remaining bytes, doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8369" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
8370 nCount = 0;
8371 }
8372 else
8373 nCount = SVBT16ToUInt16(&pSprm[nIndex]);
8374 nL = static_cast< sal_uInt16 >(nCount + aSprm.nLen - 1);
8375 break;
8376 }
8377 default:
8378 OSL_ENSURE(false, "Unknown sprm variant")do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8378" ": "), "%s", "Unknown sprm variant"); } } while (
false)
;
8379 break;
8380 }
8381 break;
8382 }
8383 return nL;
8384}
8385
8386// one or two bytes at the beginning at the sprm id
8387sal_uInt16 wwSprmParser::GetSprmId(const sal_uInt8* pSp) const
8388{
8389 OSL_ENSURE(pSp, "Why GetSprmId with pSp of 0")do { if (true && (!(pSp))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8389" ": "), "%s", "Why GetSprmId with pSp of 0"); } } while
(false)
;
8390 if (!pSp)
8391 return 0;
8392
8393 sal_uInt16 nId = 0;
8394
8395 if (ww::IsSevenMinus(meVersion))
8396 {
8397 nId = *pSp; // [0..0xff]
8398 }
8399 else
8400 {
8401 nId = SVBT16ToUInt16(pSp);
8402 if (0x0800 > nId)
8403 nId = 0;
8404 }
8405
8406 return nId;
8407}
8408
8409// with tokens and length byte
8410sal_Int32 wwSprmParser::GetSprmSize(sal_uInt16 nId, const sal_uInt8* pSprm, sal_Int32 nRemLen) const
8411{
8412 return GetSprmTailLen(nId, pSprm, nRemLen) + 1 + mnDelta + SprmDataOfs(nId);
8413}
8414
8415sal_uInt8 wwSprmParser::SprmDataOfs(sal_uInt16 nId) const
8416{
8417 return GetSprmInfo(nId).nVari;
8418}
8419
8420sal_Int32 wwSprmParser::DistanceToData(sal_uInt16 nId) const
8421{
8422 return 1 + mnDelta + SprmDataOfs(nId);
8423}
8424
8425SprmResult wwSprmParser::findSprmData(sal_uInt16 nId, sal_uInt8* pSprms,
8426 sal_Int32 nLen) const
8427{
8428 while (nLen >= MinSprmLen())
8429 {
8430 const sal_uInt16 nCurrentId = GetSprmId(pSprms);
8431 // set pointer to data
8432 sal_Int32 nSize = GetSprmSize(nCurrentId, pSprms, nLen);
8433
8434 bool bValid = nSize <= nLen;
8435
8436 SAL_WARN_IF(!bValid, "sw.ww8",do { if (true && (!bValid)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "sprm 0x" <<
std::hex << nCurrentId << std::dec << " longer than remaining bytes, "
<< nSize << " vs " << nLen << "doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8438" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "sprm 0x" << std::hex <<
nCurrentId << std::dec << " longer than remaining bytes, "
<< nSize << " vs " << nLen << "doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm 0x" << std::hex << nCurrentId <<
std::dec << " longer than remaining bytes, " << nSize
<< " vs " << nLen << "doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8438" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "sprm 0x" << std::hex << nCurrentId <<
std::dec << " longer than remaining bytes, " << nSize
<< " vs " << nLen << "doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8438" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "sprm 0x" << std::hex <<
nCurrentId << std::dec << " longer than remaining bytes, "
<< nSize << " vs " << nLen << "doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm 0x" << std::hex << nCurrentId <<
std::dec << " longer than remaining bytes, " << nSize
<< " vs " << nLen << "doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8438" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
8437 "sprm 0x" << std::hex << nCurrentId << std::dec << " longer than remaining bytes, " <<do { if (true && (!bValid)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "sprm 0x" <<
std::hex << nCurrentId << std::dec << " longer than remaining bytes, "
<< nSize << " vs " << nLen << "doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8438" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "sprm 0x" << std::hex <<
nCurrentId << std::dec << " longer than remaining bytes, "
<< nSize << " vs " << nLen << "doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm 0x" << std::hex << nCurrentId <<
std::dec << " longer than remaining bytes, " << nSize
<< " vs " << nLen << "doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8438" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "sprm 0x" << std::hex << nCurrentId <<
std::dec << " longer than remaining bytes, " << nSize
<< " vs " << nLen << "doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8438" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "sprm 0x" << std::hex <<
nCurrentId << std::dec << " longer than remaining bytes, "
<< nSize << " vs " << nLen << "doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm 0x" << std::hex << nCurrentId <<
std::dec << " longer than remaining bytes, " << nSize
<< " vs " << nLen << "doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8438" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
8438 nSize << " vs " << nLen << "doc or parser is wrong")do { if (true && (!bValid)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "sprm 0x" <<
std::hex << nCurrentId << std::dec << " longer than remaining bytes, "
<< nSize << " vs " << nLen << "doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8438" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "sprm 0x" << std::hex <<
nCurrentId << std::dec << " longer than remaining bytes, "
<< nSize << " vs " << nLen << "doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm 0x" << std::hex << nCurrentId <<
std::dec << " longer than remaining bytes, " << nSize
<< " vs " << nLen << "doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8438" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "sprm 0x" << std::hex << nCurrentId <<
std::dec << " longer than remaining bytes, " << nSize
<< " vs " << nLen << "doc or parser is wrong"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8438" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "sprm 0x" << std::hex <<
nCurrentId << std::dec << " longer than remaining bytes, "
<< nSize << " vs " << nLen << "doc or parser is wrong"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "sprm 0x" << std::hex << nCurrentId <<
std::dec << " longer than remaining bytes, " << nSize
<< " vs " << nLen << "doc or parser is wrong"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8scan.cxx"
":" "8438" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
8439
8440 if (nCurrentId == nId && bValid) // Sprm found
8441 {
8442 sal_Int32 nFixedLen = DistanceToData(nId);
8443 return SprmResult(pSprms + nFixedLen, nSize - nFixedLen);
8444 }
8445
8446 //Clip to available size if wrong
8447 nSize = std::min(nSize, nLen);
8448 pSprms += nSize;
8449 nLen -= nSize;
8450 }
8451 // Sprm not found
8452 return SprmResult();
8453}
8454
8455SEPr::SEPr() :
8456 bkc(2), fTitlePage(0), fAutoPgn(0), nfcPgn(0), fUnlocked(0), cnsPgn(0),
8457 fPgnRestart(0), fEndNote(1), lnc(0), grpfIhdt(0), nLnnMod(0), dxaLnn(0),
8458 dxaPgn(720), dyaPgn(720), fLBetween(0), vjc(0), dmBinFirst(0),
8459 dmBinOther(0), dmPaperReq(0), fPropRMark(0), ibstPropRMark(0),
8460 dttmPropRMark(0), dxtCharSpace(0), dyaLinePitch(0), clm(0), reserved1(0),
8461 dmOrientPage(0), iHeadingPgn(0), pgnStart(1), lnnMin(0), wTextFlow(0),
8462 reserved2(0), pgbApplyTo(0), pgbPageDepth(0), pgbOffsetFrom(0),
8463 xaPage(lLetterWidth), yaPage(lLetterHeight), xaPageNUp(lLetterWidth), yaPageNUp(lLetterHeight),
8464 dxaLeft(1800), dxaRight(1800), dyaTop(1440), dyaBottom(1440), dzaGutter(0),
8465 dyaHdrTop(720), dyaHdrBottom(720), ccolM1(0), fEvenlySpaced(1),
8466 reserved3(0), fBiDi(0), fFacingCol(0), fRTLGutter(0), fRTLAlignment(0),
8467 dxaColumns(720), dxaColumnWidth(0), dmOrientFirst(0), fLayout(0),
8468 reserved4(0)
8469{
8470}
8471
8472bool checkRead(SvStream &rSt, void *pDest, sal_uInt32 nLength)
8473{
8474 return (rSt.ReadBytes(pDest, nLength) == static_cast<std::size_t>(nLength));
8475}
8476
8477#ifdef OSL_BIGENDIAN
8478void swapEndian(sal_Unicode *pString)
8479{
8480 for (sal_Unicode *pWork = pString; *pWork; ++pWork)
8481 *pWork = OSL_SWAPWORD(*pWork)((sal_uInt16)((sal_uInt16)((((sal_uInt8)(((sal_uInt16)(*pWork
) >> 8) & 0xFF))) & 0xFF) | (((sal_uInt16)(((sal_uInt8
)((sal_uInt16)(*pWork) & 0xFF))) & 0xFF) << 8))
)
;
8482}
8483#endif
8484
8485/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/tools/solar.h

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#ifndef INCLUDED_TOOLS_SOLAR_H
21#define INCLUDED_TOOLS_SOLAR_H
22
23#include <sal/types.h>
24#include <osl/endian.h>
25
26/** Intermediate type to solve type clash with Windows headers.
27 Should be removed as soon as all code parts have been reviewed
28 and the correct type is known. Most of the times ULONG is meant
29 to be a 32-Bit unsigned integer type as sal_uInt32 is often
30 used for data exchange or for similar method args. */
31typedef sal_uIntPtr sal_uLong; /* Replaces type ULONG */
32
33// misc. macros to leverage platform and compiler differences
34
35// solar binary types
36
37/* Solar (portable) Binary (exchange) Type; OSI 6 subset
38 always little endian;
39 not necessarily aligned */
40
41typedef sal_uInt8 SVBT16[2];
42typedef sal_uInt8 SVBT32[4];
43typedef sal_uInt8 SVBT64[8];
44
45#ifdef __cplusplus201703L
46
47inline sal_uInt16 SVBT16ToUInt16( const SVBT16 p ) { return static_cast<sal_uInt16>
48 (static_cast<sal_uInt16>(p[0])
16
Array access (from variable 'p') results in a null pointer dereference
49 + (static_cast<sal_uInt16>(p[1]) << 8)); }
50inline sal_Int16 SVBT16ToInt16( const SVBT16 p ) { return sal_Int16(SVBT16ToUInt16(p)); }
51inline sal_uInt32 SVBT32ToUInt32 ( const SVBT32 p ) { return static_cast<sal_uInt32>
52 (static_cast<sal_uInt32>(p[0])
53 + (static_cast<sal_uInt32>(p[1]) << 8)
54 + (static_cast<sal_uInt32>(p[2]) << 16)
55 + (static_cast<sal_uInt32>(p[3]) << 24)); }
56#if defined OSL_LITENDIAN
57inline double SVBT64ToDouble( const SVBT64 p )
58{
59 double n;
60 reinterpret_cast<sal_uInt8*>(&n)[0] = p[0];
61 reinterpret_cast<sal_uInt8*>(&n)[1] = p[1];
62 reinterpret_cast<sal_uInt8*>(&n)[2] = p[2];
63 reinterpret_cast<sal_uInt8*>(&n)[3] = p[3];
64 reinterpret_cast<sal_uInt8*>(&n)[4] = p[4];
65 reinterpret_cast<sal_uInt8*>(&n)[5] = p[5];
66 reinterpret_cast<sal_uInt8*>(&n)[6] = p[6];
67 reinterpret_cast<sal_uInt8*>(&n)[7] = p[7];
68 return n;
69}
70#else
71inline double SVBT64ToDouble( const SVBT64 p ) { double n;
72 reinterpret_cast<sal_uInt8*>(&n)[0] = p[7];
73 reinterpret_cast<sal_uInt8*>(&n)[1] = p[6];
74 reinterpret_cast<sal_uInt8*>(&n)[2] = p[5];
75 reinterpret_cast<sal_uInt8*>(&n)[3] = p[4];
76 reinterpret_cast<sal_uInt8*>(&n)[4] = p[3];
77 reinterpret_cast<sal_uInt8*>(&n)[5] = p[2];
78 reinterpret_cast<sal_uInt8*>(&n)[6] = p[1];
79 reinterpret_cast<sal_uInt8*>(&n)[7] = p[0];
80 return n; }
81#endif
82
83inline void ShortToSVBT16( sal_uInt16 n, SVBT16 p )
84{
85 p[0] = static_cast<sal_uInt8>(n);
86 p[1] = static_cast<sal_uInt8>(n >> 8);
87}
88inline void UInt32ToSVBT32 ( sal_uInt32 n, SVBT32 p )
89{
90 p[0] = static_cast<sal_uInt8>(n);
91 p[1] = static_cast<sal_uInt8>(n >> 8);
92 p[2] = static_cast<sal_uInt8>(n >> 16);
93 p[3] = static_cast<sal_uInt8>(n >> 24);
94}
95inline void Int32ToSVBT32 ( sal_Int32 n, SVBT32 p ) { UInt32ToSVBT32(sal_uInt32(n), p); }
96#if defined OSL_LITENDIAN
97inline void DoubleToSVBT64( double n, SVBT64 p ) { p[0] = reinterpret_cast<sal_uInt8*>(&n)[0];
98 p[1] = reinterpret_cast<sal_uInt8*>(&n)[1];
99 p[2] = reinterpret_cast<sal_uInt8*>(&n)[2];
100 p[3] = reinterpret_cast<sal_uInt8*>(&n)[3];
101 p[4] = reinterpret_cast<sal_uInt8*>(&n)[4];
102 p[5] = reinterpret_cast<sal_uInt8*>(&n)[5];
103 p[6] = reinterpret_cast<sal_uInt8*>(&n)[6];
104 p[7] = reinterpret_cast<sal_uInt8*>(&n)[7]; }
105#else
106inline void DoubleToSVBT64( double n, SVBT64 p ) { p[0] = reinterpret_cast<sal_uInt8*>(&n)[7];
107 p[1] = reinterpret_cast<sal_uInt8*>(&n)[6];
108 p[2] = reinterpret_cast<sal_uInt8*>(&n)[5];
109 p[3] = reinterpret_cast<sal_uInt8*>(&n)[4];
110 p[4] = reinterpret_cast<sal_uInt8*>(&n)[3];
111 p[5] = reinterpret_cast<sal_uInt8*>(&n)[2];
112 p[6] = reinterpret_cast<sal_uInt8*>(&n)[1];
113 p[7] = reinterpret_cast<sal_uInt8*>(&n)[0]; }
114#endif
115#endif
116
117#endif
118
119/* vim:set shiftwidth=4 softtabstop=4 expandtab: */