Bug Summary

File:home/maarten/src/libreoffice/core/include/tools/ref.hxx
Warning:line 87, column 19
Potential memory leak

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 rtfdispatchvalue.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/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/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/oox/generated -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/writerfilter/source -I /home/maarten/src/libreoffice/core/writerfilter/inc -I /home/maarten/src/libreoffice/core/writerfilter/source -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/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/writerfilter/source/rtftok/rtfdispatchvalue.cxx

/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdispatchvalue.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
10#include "rtfdocumentimpl.hxx"
11
12#include <com/sun/star/beans/XPropertySet.hpp>
13#include <com/sun/star/text/WrapTextMode.hpp>
14#include <com/sun/star/document/XDocumentProperties.hpp>
15#include <comphelper/sequence.hxx>
16#include <i18nlangtag/languagetag.hxx>
17#include <osl/thread.h>
18#include <sal/log.hxx>
19#include <rtl/tencinfo.h>
20#include <tools/UnitConversion.hxx>
21
22#include <ooxml/resourceids.hxx>
23
24#include "rtfcharsets.hxx"
25#include "rtffly.hxx"
26#include "rtfreferenceproperties.hxx"
27#include "rtfskipdestination.hxx"
28
29#include <unotools/defaultencoding.hxx>
30#include <unotools/wincodepage.hxx>
31
32using namespace com::sun::star;
33
34namespace writerfilter
35{
36static int getNumberFormat(int nParam)
37{
38 static const int aMap[]
39 = { NS_ooxml::LN_Value_ST_NumberFormat_decimal,
40 NS_ooxml::LN_Value_ST_NumberFormat_upperRoman,
41 NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman,
42 NS_ooxml::LN_Value_ST_NumberFormat_upperLetter,
43 NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter,
44 NS_ooxml::LN_Value_ST_NumberFormat_ordinal,
45 NS_ooxml::LN_Value_ST_NumberFormat_cardinalText,
46 NS_ooxml::LN_Value_ST_NumberFormat_ordinalText,
47 NS_ooxml::LN_Value_ST_NumberFormat_none, // Undefined in RTF 1.8 spec.
48 NS_ooxml::LN_Value_ST_NumberFormat_none, // Undefined in RTF 1.8 spec.
49 NS_ooxml::LN_Value_ST_NumberFormat_ideographDigital,
50 NS_ooxml::LN_Value_ST_NumberFormat_japaneseCounting,
51 NS_ooxml::LN_Value_ST_NumberFormat_aiueo,
52 NS_ooxml::LN_Value_ST_NumberFormat_iroha,
53 NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth,
54 NS_ooxml::LN_Value_ST_NumberFormat_decimalHalfWidth,
55 NS_ooxml::LN_Value_ST_NumberFormat_japaneseLegal,
56 NS_ooxml::LN_Value_ST_NumberFormat_japaneseDigitalTenThousand,
57 NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircleChinese,
58 NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth2,
59 NS_ooxml::LN_Value_ST_NumberFormat_aiueoFullWidth,
60 NS_ooxml::LN_Value_ST_NumberFormat_irohaFullWidth,
61 NS_ooxml::LN_Value_ST_NumberFormat_decimalZero,
62 NS_ooxml::LN_Value_ST_NumberFormat_bullet,
63 NS_ooxml::LN_Value_ST_NumberFormat_ganada,
64 NS_ooxml::LN_Value_ST_NumberFormat_chosung,
65 NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedFullstop,
66 NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedParen,
67 NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircleChinese,
68 NS_ooxml::LN_Value_ST_NumberFormat_ideographEnclosedCircle,
69 NS_ooxml::LN_Value_ST_NumberFormat_ideographTraditional,
70 NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiac,
71 NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiacTraditional,
72 NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCounting,
73 NS_ooxml::LN_Value_ST_NumberFormat_ideographLegalTraditional,
74 NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCountingThousand,
75 NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseDigital,
76 NS_ooxml::LN_Value_ST_NumberFormat_chineseCounting,
77 NS_ooxml::LN_Value_ST_NumberFormat_chineseLegalSimplified,
78 NS_ooxml::LN_Value_ST_NumberFormat_chineseCountingThousand,
79 NS_ooxml::LN_Value_ST_NumberFormat_decimal,
80 NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital,
81 NS_ooxml::LN_Value_ST_NumberFormat_koreanCounting,
82 NS_ooxml::LN_Value_ST_NumberFormat_koreanLegal,
83 NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital2,
84 NS_ooxml::LN_Value_ST_NumberFormat_hebrew1,
85 NS_ooxml::LN_Value_ST_NumberFormat_arabicAlpha,
86 NS_ooxml::LN_Value_ST_NumberFormat_hebrew2,
87 NS_ooxml::LN_Value_ST_NumberFormat_arabicAbjad };
88 const int nLen = SAL_N_ELEMENTS(aMap)(sizeof(sal_n_array_size(aMap)));
89 int nValue = 0;
90 if (nParam >= 0 && nParam < nLen)
91 nValue = aMap[nParam];
92 else // 255 and the other cases.
93 nValue = NS_ooxml::LN_Value_ST_NumberFormat_none;
94 return nValue;
95}
96
97namespace rtftok
98{
99bool RTFDocumentImpl::dispatchTableSprmValue(RTFKeyword nKeyword, int nParam)
100{
101 int nSprm = 0;
102 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
3
Memory is allocated
103 switch (nKeyword)
4
Control jumps to 'case RTF_SBASEDON:' at line 130
104 {
105 case RTF_LEVELJC:
106 {
107 nSprm = NS_ooxml::LN_CT_Lvl_lvlJc;
108 int nValue = 0;
109 switch (nParam)
110 {
111 case 0:
112 nValue = NS_ooxml::LN_Value_ST_Jc_left;
113 break;
114 case 1:
115 nValue = NS_ooxml::LN_Value_ST_Jc_center;
116 break;
117 case 2:
118 nValue = NS_ooxml::LN_Value_ST_Jc_right;
119 break;
120 }
121 pIntValue = new RTFValue(nValue);
122 break;
123 }
124 case RTF_LEVELSTARTAT:
125 nSprm = NS_ooxml::LN_CT_Lvl_start;
126 break;
127 case RTF_LEVELPICTURE:
128 nSprm = NS_ooxml::LN_CT_Lvl_lvlPicBulletId;
129 break;
130 case RTF_SBASEDON:
131 nSprm = NS_ooxml::LN_CT_Style_basedOn;
132 pIntValue = new RTFValue(getStyleName(nParam));
5
Calling move assignment operator for 'SvRef<writerfilter::rtftok::RTFValue>'
133 break;
134 default:
135 break;
136 }
137 if (nSprm > 0)
138 {
139 m_aStates.top().getTableSprms().set(nSprm, pIntValue);
140 return true;
141 }
142 if (nKeyword == RTF_LEVELNFC)
143 {
144 pIntValue = new RTFValue(getNumberFormat(nParam));
145 putNestedAttribute(m_aStates.top().getTableSprms(), NS_ooxml::LN_CT_Lvl_numFmt,
146 NS_ooxml::LN_CT_NumFmt_val, pIntValue);
147 return true;
148 }
149
150 return false;
151}
152
153bool RTFDocumentImpl::dispatchCharacterSprmValue(RTFKeyword nKeyword, int nParam)
154{
155 int nSprm = 0;
156 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
157
158 switch (nKeyword)
159 {
160 case RTF_FS:
161 case RTF_AFS:
162 switch (m_aStates.top().getRunType())
163 {
164 case RTFParserState::RunType::HICH:
165 case RTFParserState::RunType::RTLCH_LTRCH_1:
166 case RTFParserState::RunType::LTRCH_RTLCH_2:
167 case RTFParserState::RunType::DBCH:
168 nSprm = NS_ooxml::LN_EG_RPrBase_szCs;
169 break;
170 case RTFParserState::RunType::NONE:
171 case RTFParserState::RunType::LOCH:
172 case RTFParserState::RunType::LTRCH_RTLCH_1:
173 case RTFParserState::RunType::RTLCH_LTRCH_2:
174 default:
175 nSprm = NS_ooxml::LN_EG_RPrBase_sz;
176 break;
177 }
178 break;
179 case RTF_EXPNDTW:
180 nSprm = NS_ooxml::LN_EG_RPrBase_spacing;
181 break;
182 case RTF_KERNING:
183 nSprm = NS_ooxml::LN_EG_RPrBase_kern;
184 break;
185 case RTF_CHARSCALEX:
186 nSprm = NS_ooxml::LN_EG_RPrBase_w;
187 break;
188 default:
189 break;
190 }
191 if (nSprm > 0)
192 {
193 m_aStates.top().getCharacterSprms().set(nSprm, pIntValue);
194 return true;
195 }
196
197 return false;
198}
199
200bool RTFDocumentImpl::dispatchCharacterAttributeValue(RTFKeyword nKeyword, int nParam)
201{
202 int nSprm = 0;
203
204 switch (nKeyword)
205 {
206 case RTF_LANG:
207 case RTF_ALANG:
208 switch (m_aStates.top().getRunType())
209 {
210 case RTFParserState::RunType::HICH:
211 case RTFParserState::RunType::RTLCH_LTRCH_1:
212 case RTFParserState::RunType::LTRCH_RTLCH_2:
213 nSprm = NS_ooxml::LN_CT_Language_bidi;
214 break;
215 case RTFParserState::RunType::DBCH:
216 nSprm = NS_ooxml::LN_CT_Language_eastAsia;
217 break;
218 case RTFParserState::RunType::NONE:
219 case RTFParserState::RunType::LOCH:
220 case RTFParserState::RunType::LTRCH_RTLCH_1:
221 case RTFParserState::RunType::RTLCH_LTRCH_2:
222 default:
223 nSprm = NS_ooxml::LN_CT_Language_val;
224 break;
225 }
226 break;
227 case RTF_LANGFE: // this one is always CJK apparently
228 nSprm = NS_ooxml::LN_CT_Language_eastAsia;
229 break;
230 default:
231 break;
232 }
233 if (nSprm > 0)
234 {
235 LanguageTag aTag((LanguageType(static_cast<sal_uInt16>(nParam))));
236 auto pValue = new RTFValue(aTag.getBcp47());
237 putNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_EG_RPrBase_lang, nSprm,
238 pValue);
239 // Language is a character property, but we should store it at a paragraph level as well for fields.
240 if (nKeyword == RTF_LANG && m_bNeedPap)
241 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_EG_RPrBase_lang,
242 nSprm, pValue);
243 return true;
244 }
245
246 return false;
247}
248
249bool RTFDocumentImpl::dispatchParagraphSprmValue(RTFKeyword nKeyword, int nParam)
250{
251 int nSprm = 0;
252 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
253
254 switch (nKeyword)
255 {
256 case RTF_ITAP:
257 nSprm = NS_ooxml::LN_tblDepth;
258 // tdf#117268: If \itap0 is encountered inside tables (between \cellxN and \cell), then
259 // use the default value (1), as Word apparently does
260 if (nParam == 0 && (m_nTopLevelCells != 0 || m_nNestedCells != 0))
261 {
262 nParam = 1;
263 pIntValue = new RTFValue(nParam);
264 }
265 break;
266 default:
267 break;
268 }
269 if (nSprm > 0)
270 {
271 m_aStates.top().getParagraphSprms().set(nSprm, pIntValue);
272 if (nKeyword == RTF_ITAP && nParam > 0)
273 {
274 while (m_aTableBufferStack.size() < sal::static_int_cast<std::size_t>(nParam))
275 {
276 m_aTableBufferStack.emplace_back(RTFBuffer_t());
277 }
278 // Invalid tables may omit INTBL after ITAP
279 dispatchFlag(RTF_INTBL); // sets newly pushed buffer as current
280 assert(m_aStates.top().getCurrentBuffer() == &m_aTableBufferStack.back())(static_cast <bool> (m_aStates.top().getCurrentBuffer()
== &m_aTableBufferStack.back()) ? void (0) : __assert_fail
("m_aStates.top().getCurrentBuffer() == &m_aTableBufferStack.back()"
, "/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdispatchvalue.cxx"
, 280, __extension__ __PRETTY_FUNCTION__))
;
281 }
282 return true;
283 }
284
285 return false;
286}
287
288bool RTFDocumentImpl::dispatchInfoValue(RTFKeyword nKeyword, int nParam)
289{
290 int nSprm = 0;
291
292 switch (nKeyword)
293 {
294 case RTF_YR:
295 {
296 m_aStates.top().setYear(nParam);
297 nSprm = 1;
298 }
299 break;
300 case RTF_MO:
301 {
302 m_aStates.top().setMonth(nParam);
303 nSprm = 1;
304 }
305 break;
306 case RTF_DY:
307 {
308 m_aStates.top().setDay(nParam);
309 nSprm = 1;
310 }
311 break;
312 case RTF_HR:
313 {
314 m_aStates.top().setHour(nParam);
315 nSprm = 1;
316 }
317 break;
318 case RTF_MIN:
319 {
320 m_aStates.top().setMinute(nParam);
321 nSprm = 1;
322 }
323 break;
324 default:
325 break;
326 }
327
328 return nSprm > 0;
329}
330
331bool RTFDocumentImpl::dispatchFrameValue(RTFKeyword nKeyword, int nParam)
332{
333 Id nId = 0;
334 switch (nKeyword)
335 {
336 case RTF_ABSW:
337 nId = NS_ooxml::LN_CT_FramePr_w;
338 break;
339 case RTF_ABSH:
340 nId = NS_ooxml::LN_CT_FramePr_h;
341 break;
342 case RTF_POSX:
343 {
344 nId = NS_ooxml::LN_CT_FramePr_x;
345 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_xAlign, 0);
346 }
347 break;
348 case RTF_POSY:
349 {
350 nId = NS_ooxml::LN_CT_FramePr_y;
351 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_yAlign, 0);
352 }
353 break;
354 default:
355 break;
356 }
357
358 if (nId > 0)
359 {
360 m_bNeedPap = true;
361 // Don't try to support text frames inside tables for now.
362 if (m_aStates.top().getCurrentBuffer() != &m_aTableBufferStack.back())
363 m_aStates.top().getFrame().setSprm(nId, nParam);
364
365 return true;
366 }
367
368 return false;
369}
370
371bool RTFDocumentImpl::dispatchTableValue(RTFKeyword nKeyword, int nParam)
372{
373 int nSprm = 0;
374 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
375
376 switch (nKeyword)
377 {
378 case RTF_CELLX:
379 {
380 int& rCurrentCellX(
381 (Destination::NESTEDTABLEPROPERTIES == m_aStates.top().getDestination())
382 ? m_nNestedCurrentCellX
383 : m_nTopLevelCurrentCellX);
384 int nCellX = nParam - rCurrentCellX;
385 const int COL_DFLT_WIDTH
386 = 41; // sw/source/filter/inc/wrtswtbl.hxx, minimal possible width of cells.
387 if (!nCellX)
388 nCellX = COL_DFLT_WIDTH;
389
390 // If there is a negative left margin, then the first cellx is relative to that.
391 RTFValue::Pointer_t pTblInd
392 = m_aStates.top().getTableRowSprms().find(NS_ooxml::LN_CT_TblPrBase_tblInd);
393 if (rCurrentCellX == 0 && pTblInd)
394 {
395 RTFValue::Pointer_t pWidth
396 = pTblInd->getAttributes().find(NS_ooxml::LN_CT_TblWidth_w);
397 if (pWidth && pWidth->getInt() < 0)
398 nCellX = -1 * (pWidth->getInt() - nParam);
399 }
400
401 rCurrentCellX = nParam;
402 auto pXValue = new RTFValue(nCellX);
403 m_aStates.top().getTableRowSprms().set(NS_ooxml::LN_CT_TblGridBase_gridCol, pXValue,
404 RTFOverwrite::NO_APPEND);
405 if (Destination::NESTEDTABLEPROPERTIES == m_aStates.top().getDestination())
406 {
407 m_nNestedCells++;
408 // Push cell properties.
409 m_aNestedTableCellsSprms.push_back(m_aStates.top().getTableCellSprms());
410 m_aNestedTableCellsAttributes.push_back(m_aStates.top().getTableCellAttributes());
411 }
412 else
413 {
414 m_nTopLevelCells++;
415 // Push cell properties.
416 m_aTopLevelTableCellsSprms.push_back(m_aStates.top().getTableCellSprms());
417 m_aTopLevelTableCellsAttributes.push_back(m_aStates.top().getTableCellAttributes());
418 }
419
420 m_aStates.top().getTableCellSprms() = m_aDefaultState.getTableCellSprms();
421 m_aStates.top().getTableCellAttributes() = m_aDefaultState.getTableCellAttributes();
422 // We assume text after a row definition always belongs to the table, to handle text before the real INTBL token
423 dispatchFlag(RTF_INTBL);
424 if (!m_nCellxMax)
425 {
426 // Wasn't in table, but now is -> tblStart.
427 RTFSprms aAttributes;
428 RTFSprms aSprms;
429 aSprms.set(NS_ooxml::LN_tblStart, new RTFValue(1));
430 writerfilter::Reference<Properties>::Pointer_t pProperties
431 = new RTFReferenceProperties(aAttributes, aSprms);
432 Mapper().props(pProperties);
433 }
434 m_nCellxMax = std::max(m_nCellxMax, nParam);
435 return true;
436 }
437 break;
438 case RTF_TRRH:
439 {
440 OUString hRule("auto");
441 if (nParam < 0)
442 {
443 tools::SvRef<RTFValue> pAbsValue(new RTFValue(-nParam));
444 std::swap(pIntValue, pAbsValue);
445
446 hRule = "exact";
447 }
448 else if (nParam > 0)
449 hRule = "atLeast";
450
451 putNestedAttribute(m_aStates.top().getTableRowSprms(),
452 NS_ooxml::LN_CT_TrPrBase_trHeight, NS_ooxml::LN_CT_Height_val,
453 pIntValue);
454
455 auto pHRule = new RTFValue(hRule);
456 putNestedAttribute(m_aStates.top().getTableRowSprms(),
457 NS_ooxml::LN_CT_TrPrBase_trHeight, NS_ooxml::LN_CT_Height_hRule,
458 pHRule);
459 return true;
460 }
461 break;
462 case RTF_TRLEFT:
463 {
464 // the value is in twips
465 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblInd,
466 NS_ooxml::LN_CT_TblWidth_type,
467 new RTFValue(NS_ooxml::LN_Value_ST_TblWidth_dxa));
468 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblInd,
469 NS_ooxml::LN_CT_TblWidth_w, new RTFValue(nParam));
470 auto const aDestination = m_aStates.top().getDestination();
471 int& rCurrentTRLeft((Destination::NESTEDTABLEPROPERTIES == aDestination)
472 ? m_nNestedTRLeft
473 : m_nTopLevelTRLeft);
474 int& rCurrentCellX((Destination::NESTEDTABLEPROPERTIES == aDestination)
475 ? m_nNestedCurrentCellX
476 : m_nTopLevelCurrentCellX);
477 rCurrentTRLeft = rCurrentCellX = nParam;
478 return true;
479 }
480 break;
481 case RTF_CLSHDNG:
482 {
483 int nValue = -1;
484 switch (nParam)
485 {
486 case 500:
487 nValue = NS_ooxml::LN_Value_ST_Shd_pct5;
488 break;
489 case 1000:
490 nValue = NS_ooxml::LN_Value_ST_Shd_pct10;
491 break;
492 case 1200:
493 nValue = NS_ooxml::LN_Value_ST_Shd_pct12;
494 break;
495 case 1500:
496 nValue = NS_ooxml::LN_Value_ST_Shd_pct15;
497 break;
498 case 2000:
499 nValue = NS_ooxml::LN_Value_ST_Shd_pct20;
500 break;
501 case 2500:
502 nValue = NS_ooxml::LN_Value_ST_Shd_pct25;
503 break;
504 case 3000:
505 nValue = NS_ooxml::LN_Value_ST_Shd_pct30;
506 break;
507 case 3500:
508 nValue = NS_ooxml::LN_Value_ST_Shd_pct35;
509 break;
510 case 3700:
511 nValue = NS_ooxml::LN_Value_ST_Shd_pct37;
512 break;
513 case 4000:
514 nValue = NS_ooxml::LN_Value_ST_Shd_pct40;
515 break;
516 case 4500:
517 nValue = NS_ooxml::LN_Value_ST_Shd_pct45;
518 break;
519 case 5000:
520 nValue = NS_ooxml::LN_Value_ST_Shd_pct50;
521 break;
522 case 5500:
523 nValue = NS_ooxml::LN_Value_ST_Shd_pct55;
524 break;
525 case 6000:
526 nValue = NS_ooxml::LN_Value_ST_Shd_pct60;
527 break;
528 case 6200:
529 nValue = NS_ooxml::LN_Value_ST_Shd_pct62;
530 break;
531 case 6500:
532 nValue = NS_ooxml::LN_Value_ST_Shd_pct65;
533 break;
534 case 7000:
535 nValue = NS_ooxml::LN_Value_ST_Shd_pct70;
536 break;
537 case 7500:
538 nValue = NS_ooxml::LN_Value_ST_Shd_pct75;
539 break;
540 case 8000:
541 nValue = NS_ooxml::LN_Value_ST_Shd_pct80;
542 break;
543 case 8500:
544 nValue = NS_ooxml::LN_Value_ST_Shd_pct85;
545 break;
546 case 8700:
547 nValue = NS_ooxml::LN_Value_ST_Shd_pct87;
548 break;
549 case 9000:
550 nValue = NS_ooxml::LN_Value_ST_Shd_pct90;
551 break;
552 case 9500:
553 nValue = NS_ooxml::LN_Value_ST_Shd_pct95;
554 break;
555 default:
556 break;
557 }
558 if (nValue != -1)
559 putNestedAttribute(m_aStates.top().getTableCellSprms(),
560 NS_ooxml::LN_CT_TcPrBase_shd, NS_ooxml::LN_CT_Shd_val,
561 new RTFValue(nValue));
562 return true;
563 }
564 break;
565 case RTF_CLPADB:
566 case RTF_CLPADL:
567 case RTF_CLPADR:
568 case RTF_CLPADT:
569 {
570 RTFSprms aAttributes;
571 aAttributes.set(NS_ooxml::LN_CT_TblWidth_type,
572 new RTFValue(NS_ooxml::LN_Value_ST_TblWidth_dxa));
573 aAttributes.set(NS_ooxml::LN_CT_TblWidth_w, new RTFValue(nParam));
574 // Top and left is swapped, that's what Word does.
575 switch (nKeyword)
576 {
577 case RTF_CLPADB:
578 nSprm = NS_ooxml::LN_CT_TcMar_bottom;
579 break;
580 case RTF_CLPADL:
581 nSprm = NS_ooxml::LN_CT_TcMar_top;
582 break;
583 case RTF_CLPADR:
584 nSprm = NS_ooxml::LN_CT_TcMar_right;
585 break;
586 case RTF_CLPADT:
587 nSprm = NS_ooxml::LN_CT_TcMar_left;
588 break;
589 default:
590 break;
591 }
592 putNestedSprm(m_aStates.top().getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_tcMar,
593 nSprm, new RTFValue(aAttributes));
594 return true;
595 }
596 break;
597 case RTF_TRPADDFB:
598 case RTF_TRPADDFL:
599 case RTF_TRPADDFR:
600 case RTF_TRPADDFT:
601 {
602 RTFSprms aAttributes;
603 switch (nParam)
604 {
605 case 3:
606 aAttributes.set(NS_ooxml::LN_CT_TblWidth_type,
607 new RTFValue(NS_ooxml::LN_Value_ST_TblWidth_dxa));
608 break;
609 }
610 switch (nKeyword)
611 {
612 case RTF_TRPADDFB:
613 nSprm = NS_ooxml::LN_CT_TcMar_bottom;
614 break;
615 case RTF_TRPADDFL:
616 nSprm = NS_ooxml::LN_CT_TcMar_left;
617 break;
618 case RTF_TRPADDFR:
619 nSprm = NS_ooxml::LN_CT_TcMar_right;
620 break;
621 case RTF_TRPADDFT:
622 nSprm = NS_ooxml::LN_CT_TcMar_top;
623 break;
624 default:
625 break;
626 }
627 putNestedAttribute(m_aStates.top().getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_tcMar,
628 nSprm, new RTFValue(aAttributes));
629 putNestedAttribute(m_aDefaultState.getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_tcMar,
630 nSprm, new RTFValue(aAttributes));
631 return true;
632 }
633 break;
634 case RTF_TRPADDB:
635 case RTF_TRPADDL:
636 case RTF_TRPADDR:
637 case RTF_TRPADDT:
638 {
639 RTFSprms aAttributes;
640 aAttributes.set(NS_ooxml::LN_CT_TblWidth_w, new RTFValue(nParam));
641 switch (nKeyword)
642 {
643 case RTF_TRPADDB:
644 nSprm = NS_ooxml::LN_CT_TcMar_bottom;
645 break;
646 case RTF_TRPADDL:
647 nSprm = NS_ooxml::LN_CT_TcMar_left;
648 break;
649 case RTF_TRPADDR:
650 nSprm = NS_ooxml::LN_CT_TcMar_right;
651 break;
652 case RTF_TRPADDT:
653 nSprm = NS_ooxml::LN_CT_TcMar_top;
654 break;
655 default:
656 break;
657 }
658 putNestedSprm(m_aStates.top().getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_tcMar,
659 nSprm, new RTFValue(aAttributes));
660 putNestedSprm(m_aDefaultState.getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_tcMar,
661 nSprm, new RTFValue(aAttributes));
662 return true;
663 }
664 break;
665 case RTF_TRGAPH:
666 // Half of the space between the cells of a table row: default left/right table cell margin.
667 if (nParam > 0)
668 {
669 RTFSprms aAttributes;
670 aAttributes.set(NS_ooxml::LN_CT_TblWidth_type,
671 new RTFValue(NS_ooxml::LN_Value_ST_TblWidth_dxa));
672 aAttributes.set(NS_ooxml::LN_CT_TblWidth_w, pIntValue);
673 putNestedSprm(m_aStates.top().getTableRowSprms(),
674 NS_ooxml::LN_CT_TblPrBase_tblCellMar, NS_ooxml::LN_CT_TblCellMar_left,
675 new RTFValue(aAttributes));
676 putNestedSprm(m_aStates.top().getTableRowSprms(),
677 NS_ooxml::LN_CT_TblPrBase_tblCellMar,
678 NS_ooxml::LN_CT_TblCellMar_right, new RTFValue(aAttributes));
679 }
680 return true;
681 break;
682 case RTF_TRFTSWIDTH:
683 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblW,
684 NS_ooxml::LN_CT_TblWidth_type, pIntValue);
685 return true;
686 break;
687 case RTF_TRWWIDTH:
688 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblW,
689 NS_ooxml::LN_CT_TblWidth_w, pIntValue);
690 return true;
691 break;
692 default:
693 break;
694 }
695
696 return false;
697}
698
699RTFError RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
700{
701 setNeedSect(true);
702 checkUnicode(/*bUnicode =*/nKeyword != RTF_U, /*bHex =*/true);
1
Assuming 'nKeyword' is not equal to RTF_U
703 RTFSkipDestination aSkip(*this);
704 int nSprm = 0;
705 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
706 // Trivial table sprms.
707 if (dispatchTableSprmValue(nKeyword, nParam))
2
Calling 'RTFDocumentImpl::dispatchTableSprmValue'
708 {
709 return RTFError::OK;
710 }
711
712 // Trivial character sprms.
713 if (dispatchCharacterSprmValue(nKeyword, nParam))
714 {
715 return RTFError::OK;
716 }
717
718 // Trivial character attributes.
719 if (dispatchCharacterAttributeValue(nKeyword, nParam))
720 {
721 return RTFError::OK;
722 }
723
724 // Trivial paragraph sprms.
725 if (dispatchParagraphSprmValue(nKeyword, nParam))
726 {
727 return RTFError::OK;
728 }
729
730 // Info group.
731 if (dispatchInfoValue(nKeyword, nParam))
732 {
733 return RTFError::OK;
734 }
735
736 // Frame size / position.
737 if (dispatchFrameValue(nKeyword, nParam))
738 {
739 return RTFError::OK;
740 }
741
742 // Table-related values.
743 if (dispatchTableValue(nKeyword, nParam))
744 {
745 return RTFError::OK;
746 }
747
748 // Then check for the more complex ones.
749 switch (nKeyword)
750 {
751 case RTF_F:
752 case RTF_AF:
753 switch (m_aStates.top().getRunType())
754 {
755 case RTFParserState::RunType::HICH:
756 case RTFParserState::RunType::RTLCH_LTRCH_1:
757 case RTFParserState::RunType::LTRCH_RTLCH_2:
758 nSprm = NS_ooxml::LN_CT_Fonts_cs;
759 break;
760 case RTFParserState::RunType::DBCH:
761 nSprm = NS_ooxml::LN_CT_Fonts_eastAsia;
762 break;
763 case RTFParserState::RunType::NONE:
764 case RTFParserState::RunType::LOCH:
765 case RTFParserState::RunType::LTRCH_RTLCH_1:
766 case RTFParserState::RunType::RTLCH_LTRCH_2:
767 default:
768 nSprm = NS_ooxml::LN_CT_Fonts_ascii;
769 break;
770 }
771
772 if (m_aStates.top().getDestination() == Destination::FONTTABLE
773 || m_aStates.top().getDestination() == Destination::FONTENTRY)
774 {
775 m_aFontIndexes.push_back(nParam);
776 m_nCurrentFontIndex = getFontIndex(nParam);
777 }
778 else if (m_aStates.top().getDestination() == Destination::LISTLEVEL)
779 {
780 RTFSprms aFontAttributes;
781 aFontAttributes.set(nSprm, new RTFValue(m_aFontNames[getFontIndex(nParam)]));
782 RTFSprms aRunPropsSprms;
783 aRunPropsSprms.set(NS_ooxml::LN_EG_RPrBase_rFonts, new RTFValue(aFontAttributes));
784 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Lvl_rPr,
785 new RTFValue(RTFSprms(), aRunPropsSprms),
786 RTFOverwrite::NO_APPEND);
787 }
788 else
789 {
790 m_nCurrentFontIndex = getFontIndex(nParam);
791 auto pValue = new RTFValue(getFontName(m_nCurrentFontIndex));
792 putNestedAttribute(m_aStates.top().getCharacterSprms(),
793 NS_ooxml::LN_EG_RPrBase_rFonts, nSprm, pValue);
794 if (nKeyword == RTF_F)
795 m_aStates.top().setCurrentEncoding(getEncoding(m_nCurrentFontIndex));
796 }
797 break;
798 case RTF_RED:
799 m_aStates.top().getCurrentColor().SetRed(nParam);
800 break;
801 case RTF_GREEN:
802 m_aStates.top().getCurrentColor().SetGreen(nParam);
803 break;
804 case RTF_BLUE:
805 m_aStates.top().getCurrentColor().SetBlue(nParam);
806 break;
807 case RTF_FCHARSET:
808 {
809 // we always send text to the domain mapper in OUString, so no
810 // need to send encoding info
811 int i;
812 for (i = 0; i < nRTFEncodings; i++)
813 {
814 if (aRTFEncodings[i].charset == nParam)
815 break;
816 }
817 if (i == nRTFEncodings)
818 // not found
819 return RTFError::OK;
820
821 m_nCurrentEncoding
822 = aRTFEncodings[i].codepage == 0 // Default (CP_ACP)
823 ? osl_getThreadTextEncoding()
824 : rtl_getTextEncodingFromWindowsCodePage(aRTFEncodings[i].codepage);
825 m_aStates.top().setCurrentEncoding(m_nCurrentEncoding);
826 }
827 break;
828 case RTF_ANSICPG:
829 case RTF_CPG:
830 {
831 rtl_TextEncoding nEncoding
832 = (nParam == 0)
833 ? utl_getWinTextEncodingFromLangStr(utl_getLocaleForGlobalDefaultEncoding())
834 : rtl_getTextEncodingFromWindowsCodePage(nParam);
835 if (nKeyword == RTF_ANSICPG)
836 m_aDefaultState.setCurrentEncoding(nEncoding);
837 else
838 m_nCurrentEncoding = nEncoding;
839 m_aStates.top().setCurrentEncoding(nEncoding);
840 }
841 break;
842 case RTF_CF:
843 {
844 RTFSprms aAttributes;
845 auto pValue = new RTFValue(sal_uInt32(getColorTable(nParam)));
846 aAttributes.set(NS_ooxml::LN_CT_Color_val, pValue);
847 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_color,
848 new RTFValue(aAttributes));
849 }
850 break;
851 case RTF_S:
852 {
853 m_aStates.top().setCurrentStyleIndex(nParam);
854
855 if (m_aStates.top().getDestination() == Destination::STYLESHEET
856 || m_aStates.top().getDestination() == Destination::STYLEENTRY)
857 {
858 m_nCurrentStyleIndex = nParam;
859 auto pValue = new RTFValue(NS_ooxml::LN_Value_ST_StyleType_paragraph);
860 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_Style_type,
861 pValue); // paragraph style
862 }
863 else
864 {
865 OUString aName = getStyleName(nParam);
866 if (!aName.isEmpty())
867 {
868 if (m_aStates.top().getDestination() == Destination::LISTLEVEL)
869 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Lvl_pStyle,
870 new RTFValue(aName));
871 else
872 m_aStates.top().getParagraphSprms().set(NS_ooxml::LN_CT_PPrBase_pStyle,
873 new RTFValue(aName));
874 }
875 }
876 }
877 break;
878 case RTF_CS:
879 m_aStates.top().setCurrentCharacterStyleIndex(nParam);
880 if (m_aStates.top().getDestination() == Destination::STYLESHEET
881 || m_aStates.top().getDestination() == Destination::STYLEENTRY)
882 {
883 m_nCurrentStyleIndex = nParam;
884 auto pValue = new RTFValue(NS_ooxml::LN_Value_ST_StyleType_character);
885 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_Style_type,
886 pValue); // character style
887 }
888 else
889 {
890 OUString aName = getStyleName(nParam);
891 if (!aName.isEmpty())
892 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_rStyle,
893 new RTFValue(aName));
894 }
895 break;
896 case RTF_DS:
897 if (m_aStates.top().getDestination() == Destination::STYLESHEET
898 || m_aStates.top().getDestination() == Destination::STYLEENTRY)
899 {
900 m_nCurrentStyleIndex = nParam;
901 auto pValue = new RTFValue(0); // TODO no value in enum StyleType?
902 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_Style_type,
903 pValue); // section style
904 }
905 break;
906 case RTF_TS:
907 if (m_aStates.top().getDestination() == Destination::STYLESHEET
908 || m_aStates.top().getDestination() == Destination::STYLEENTRY)
909 {
910 m_nCurrentStyleIndex = nParam;
911 // FIXME the correct value would be NS_ooxml::LN_Value_ST_StyleType_table but maybe table styles mess things up in dmapper, be cautious and disable them for now
912 auto pValue = new RTFValue(0);
913 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_Style_type,
914 pValue); // table style
915 }
916 break;
917 case RTF_DEFF:
918 m_nDefaultFontIndex = nParam;
919 break;
920 case RTF_STSHFDBCH:
921 // tdf#123703 switch off longer space sequence except in the case of the fixed compatibility setting font id 31505
922 if (nParam != 31505)
923 m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_longerSpaceSequence,
924 new RTFValue(0));
925 break;
926 case RTF_DEFLANG:
927 case RTF_ADEFLANG:
928 {
929 LanguageTag aTag((LanguageType(static_cast<sal_uInt16>(nParam))));
930 auto pValue = new RTFValue(aTag.getBcp47());
931 putNestedAttribute(m_aStates.top().getCharacterSprms(),
932 (nKeyword == RTF_DEFLANG ? NS_ooxml::LN_EG_RPrBase_lang
933 : NS_ooxml::LN_CT_Language_bidi),
934 nSprm, pValue);
935 }
936 break;
937 case RTF_CHCBPAT:
938 {
939 auto pValue = new RTFValue(sal_uInt32(nParam ? getColorTable(nParam) : COL_AUTO));
940 putNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_EG_RPrBase_shd,
941 NS_ooxml::LN_CT_Shd_fill, pValue);
942 }
943 break;
944 case RTF_CLCBPAT:
945 case RTF_CLCBPATRAW:
946 {
947 auto pValue = new RTFValue(sal_uInt32(getColorTable(nParam)));
948 putNestedAttribute(m_aStates.top().getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_shd,
949 NS_ooxml::LN_CT_Shd_fill, pValue);
950 }
951 break;
952 case RTF_CBPAT:
953 if (nParam)
954 {
955 auto pValue = new RTFValue(sal_uInt32(getColorTable(nParam)));
956 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PrBase_shd,
957 NS_ooxml::LN_CT_Shd_fill, pValue);
958 }
959 break;
960 case RTF_ULC:
961 {
962 auto pValue = new RTFValue(sal_uInt32(getColorTable(nParam)));
963 m_aStates.top().getCharacterSprms().set(0x6877, pValue);
964 }
965 break;
966 case RTF_HIGHLIGHT:
967 {
968 auto pValue = new RTFValue(sal_uInt32(nParam ? getColorTable(nParam) : COL_AUTO));
969 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_highlight, pValue);
970 }
971 break;
972 case RTF_UP:
973 case RTF_DN:
974 {
975 auto pValue = new RTFValue(nParam * (nKeyword == RTF_UP ? 1 : -1));
976 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_position, pValue);
977 }
978 break;
979 case RTF_HORZVERT:
980 {
981 auto pValue = new RTFValue(int(true));
982 m_aStates.top().getCharacterAttributes().set(NS_ooxml::LN_CT_EastAsianLayout_vert,
983 pValue);
984 if (nParam)
985 // rotate fits to a single line
986 m_aStates.top().getCharacterAttributes().set(
987 NS_ooxml::LN_CT_EastAsianLayout_vertCompress, pValue);
988 }
989 break;
990 case RTF_EXPND:
991 {
992 // Convert quarter-points to twentieths of a point
993 auto pValue = new RTFValue(nParam * 5);
994 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_spacing, pValue);
995 }
996 break;
997 case RTF_TWOINONE:
998 {
999 auto pValue = new RTFValue(int(true));
1000 m_aStates.top().getCharacterAttributes().set(NS_ooxml::LN_CT_EastAsianLayout_combine,
1001 pValue);
1002 Id nId = 0;
1003 switch (nParam)
1004 {
1005 case 0:
1006 nId = NS_ooxml::LN_Value_ST_CombineBrackets_none;
1007 break;
1008 case 1:
1009 nId = NS_ooxml::LN_Value_ST_CombineBrackets_round;
1010 break;
1011 case 2:
1012 nId = NS_ooxml::LN_Value_ST_CombineBrackets_square;
1013 break;
1014 case 3:
1015 nId = NS_ooxml::LN_Value_ST_CombineBrackets_angle;
1016 break;
1017 case 4:
1018 nId = NS_ooxml::LN_Value_ST_CombineBrackets_curly;
1019 break;
1020 }
1021 if (nId > 0)
1022 m_aStates.top().getCharacterAttributes().set(
1023 NS_ooxml::LN_CT_EastAsianLayout_combineBrackets, new RTFValue(nId));
1024 }
1025 break;
1026 case RTF_SL:
1027 {
1028 // This is similar to RTF_ABSH, negative value means 'exact', positive means 'at least'.
1029 tools::SvRef<RTFValue> pValue(
1030 new RTFValue(NS_ooxml::LN_Value_doc_ST_LineSpacingRule_atLeast));
1031 if (nParam < 0)
1032 {
1033 pValue = new RTFValue(NS_ooxml::LN_Value_doc_ST_LineSpacingRule_exact);
1034 pIntValue = new RTFValue(-nParam);
1035 }
1036 m_aStates.top().getParagraphAttributes().set(NS_ooxml::LN_CT_Spacing_lineRule, pValue);
1037 m_aStates.top().getParagraphAttributes().set(NS_ooxml::LN_CT_Spacing_line, pIntValue);
1038 }
1039 break;
1040 case RTF_SLMULT:
1041 if (nParam > 0)
1042 {
1043 auto pValue = new RTFValue(NS_ooxml::LN_Value_doc_ST_LineSpacingRule_auto);
1044 m_aStates.top().getParagraphAttributes().set(NS_ooxml::LN_CT_Spacing_lineRule,
1045 pValue);
1046 }
1047 break;
1048 case RTF_BRDRW:
1049 {
1050 // dmapper expects it in 1/8 pt, we have it in twip - but avoid rounding 1 to 0
1051 if (nParam > 1)
1052 nParam = nParam * 2 / 5;
1053 auto pValue = new RTFValue(nParam);
1054 putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_sz, pValue);
1055 }
1056 break;
1057 case RTF_BRDRCF:
1058 {
1059 auto pValue = new RTFValue(sal_uInt32(getColorTable(nParam)));
1060 putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_color, pValue);
1061 }
1062 break;
1063 case RTF_BRSP:
1064 {
1065 // dmapper expects it in points, we have it in twip
1066 auto pValue = new RTFValue(nParam / 20);
1067 putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_space, pValue);
1068 }
1069 break;
1070 case RTF_TX:
1071 {
1072 m_aStates.top().getTabAttributes().set(NS_ooxml::LN_CT_TabStop_pos, pIntValue);
1073 auto pValue = new RTFValue(m_aStates.top().getTabAttributes());
1074 if (m_aStates.top().getDestination() == Destination::LISTLEVEL)
1075 putNestedSprm(m_aStates.top().getTableSprms(), NS_ooxml::LN_CT_PPrBase_tabs,
1076 NS_ooxml::LN_CT_Tabs_tab, pValue);
1077 else
1078 putNestedSprm(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_tabs,
1079 NS_ooxml::LN_CT_Tabs_tab, pValue);
1080 m_aStates.top().getTabAttributes().clear();
1081 }
1082 break;
1083 case RTF_ILVL:
1084 putNestedSprm(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_numPr,
1085 NS_ooxml::LN_CT_NumPr_ilvl, pIntValue);
1086 break;
1087 case RTF_LISTTEMPLATEID:
1088 // This one is not referenced anywhere, so it's pointless to store it at the moment.
1089 break;
1090 case RTF_LISTID:
1091 {
1092 if (m_aStates.top().getDestination() == Destination::LISTENTRY)
1093 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_AbstractNum_abstractNumId,
1094 pIntValue);
1095 else if (m_aStates.top().getDestination() == Destination::LISTOVERRIDEENTRY)
1096 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Num_abstractNumId, pIntValue);
1097 m_aStates.top().setCurrentListIndex(nParam);
1098 }
1099 break;
1100 case RTF_LS:
1101 {
1102 if (m_aStates.top().getDestination() == Destination::LISTOVERRIDEENTRY)
1103 {
1104 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_AbstractNum_nsid,
1105 pIntValue);
1106 m_aStates.top().setCurrentListOverrideIndex(nParam);
1107 }
1108 else
1109 {
1110 // Insert at the start, so properties inherited from the list
1111 // can be overridden by direct formatting. But still allow the
1112 // case when old-style paragraph numbering is already
1113 // tokenized.
1114 putNestedSprm(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_numPr,
1115 NS_ooxml::LN_CT_NumPr_numId, pIntValue, RTFOverwrite::YES_PREPEND);
1116 }
1117 }
1118 break;
1119 case RTF_UC:
1120 if ((SAL_MIN_INT16((sal_Int16) (-0x7FFF - 1)) <= nParam) && (nParam <= SAL_MAX_INT16((sal_Int16) 0x7FFF)))
1121 m_aStates.top().setUc(nParam);
1122 break;
1123 case RTF_U:
1124 // sal_Unicode is unsigned 16-bit, RTF may represent that as a
1125 // signed SAL_MIN_INT16..SAL_MAX_INT16 or 0..SAL_MAX_UINT16. The
1126 // static_cast() will do the right thing.
1127 if ((SAL_MIN_INT16((sal_Int16) (-0x7FFF - 1)) <= nParam) && (nParam <= SAL_MAX_UINT16((sal_uInt16) 0xFFFF)))
1128 {
1129 if (m_aStates.top().getDestination() == Destination::LEVELNUMBERS)
1130 {
1131 if (nParam != ';')
1132 m_aStates.top().getLevelNumbers().push_back(sal_Int32(nParam));
1133 else
1134 // ';' in \u form is not considered valid.
1135 m_aStates.top().setLevelNumbersValid(false);
1136 }
1137 else
1138 m_aUnicodeBuffer.append(static_cast<sal_Unicode>(nParam));
1139 m_aStates.top().getCharsToSkip() = m_aStates.top().getUc();
1140 }
1141 break;
1142 case RTF_LEVELFOLLOW:
1143 {
1144 OUString sValue;
1145 switch (nParam)
1146 {
1147 case 0:
1148 sValue = "tab";
1149 break;
1150 case 1:
1151 sValue = "space";
1152 break;
1153 case 2:
1154 sValue = "nothing";
1155 break;
1156 }
1157 if (!sValue.isEmpty())
1158 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Lvl_suff, new RTFValue(sValue));
1159 }
1160 break;
1161 case RTF_FPRQ:
1162 {
1163 sal_Int32 nValue = 0;
1164 switch (nParam)
1165 {
1166 case 0:
1167 nValue = NS_ooxml::LN_Value_ST_Pitch_default;
1168 break;
1169 case 1:
1170 nValue = NS_ooxml::LN_Value_ST_Pitch_fixed;
1171 break;
1172 case 2:
1173 nValue = NS_ooxml::LN_Value_ST_Pitch_variable;
1174 break;
1175 }
1176 if (nValue)
1177 {
1178 RTFSprms aAttributes;
1179 aAttributes.set(NS_ooxml::LN_CT_Pitch_val, new RTFValue(nValue));
1180 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Font_pitch,
1181 new RTFValue(aAttributes));
1182 }
1183 }
1184 break;
1185 case RTF_LISTOVERRIDECOUNT:
1186 // Ignore this for now, the exporter always emits it with a zero parameter.
1187 break;
1188 case RTF_PICSCALEX:
1189 m_aStates.top().getPicture().nScaleX = nParam;
1190 break;
1191 case RTF_PICSCALEY:
1192 m_aStates.top().getPicture().nScaleY = nParam;
1193 break;
1194 case RTF_PICW:
1195 m_aStates.top().getPicture().nWidth = nParam;
1196 break;
1197 case RTF_PICH:
1198 m_aStates.top().getPicture().nHeight = nParam;
1199 break;
1200 case RTF_PICWGOAL:
1201 m_aStates.top().getPicture().nGoalWidth = convertTwipToMm100(nParam);
1202 break;
1203 case RTF_PICHGOAL:
1204 m_aStates.top().getPicture().nGoalHeight = convertTwipToMm100(nParam);
1205 break;
1206 case RTF_PICCROPL:
1207 m_aStates.top().getPicture().nCropL = convertTwipToMm100(nParam);
1208 break;
1209 case RTF_PICCROPR:
1210 m_aStates.top().getPicture().nCropR = convertTwipToMm100(nParam);
1211 break;
1212 case RTF_PICCROPT:
1213 m_aStates.top().getPicture().nCropT = convertTwipToMm100(nParam);
1214 break;
1215 case RTF_PICCROPB:
1216 m_aStates.top().getPicture().nCropB = convertTwipToMm100(nParam);
1217 break;
1218 case RTF_SHPWRK:
1219 {
1220 int nValue = 0;
1221 switch (nParam)
1222 {
1223 case 0:
1224 nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_bothSides;
1225 break;
1226 case 1:
1227 nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_left;
1228 break;
1229 case 2:
1230 nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_right;
1231 break;
1232 case 3:
1233 nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_largest;
1234 break;
1235 default:
1236 break;
1237 }
1238 auto pValue = new RTFValue(nValue);
1239 RTFValue::Pointer_t pTight
1240 = m_aStates.top().getCharacterSprms().find(NS_ooxml::LN_EG_WrapType_wrapTight);
1241 if (pTight)
1242 pTight->getAttributes().set(NS_ooxml::LN_CT_WrapTight_wrapText, pValue);
1243 else
1244 m_aStates.top().getCharacterAttributes().set(NS_ooxml::LN_CT_WrapSquare_wrapText,
1245 pValue);
1246 }
1247 break;
1248 case RTF_SHPWR:
1249 {
1250 switch (nParam)
1251 {
1252 case 1:
1253 m_aStates.top().getShape().setWrap(text::WrapTextMode_NONE);
1254 break;
1255 case 2:
1256 m_aStates.top().getShape().setWrap(text::WrapTextMode_PARALLEL);
1257 break;
1258 case 3:
1259 m_aStates.top().getShape().setWrap(text::WrapTextMode_THROUGH);
1260 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_WrapType_wrapNone,
1261 new RTFValue());
1262 break;
1263 case 4:
1264 m_aStates.top().getShape().setWrap(text::WrapTextMode_PARALLEL);
1265 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_WrapType_wrapTight,
1266 new RTFValue());
1267 break;
1268 case 5:
1269 m_aStates.top().getShape().setWrap(text::WrapTextMode_THROUGH);
1270 break;
1271 }
1272 }
1273 break;
1274 case RTF_COLS:
1275 putNestedAttribute(m_aStates.top().getSectionSprms(),
1276 NS_ooxml::LN_EG_SectPrContents_cols, NS_ooxml::LN_CT_Columns_num,
1277 pIntValue);
1278 break;
1279 case RTF_COLSX:
1280 putNestedAttribute(m_aStates.top().getSectionSprms(),
1281 NS_ooxml::LN_EG_SectPrContents_cols, NS_ooxml::LN_CT_Columns_space,
1282 pIntValue);
1283 break;
1284 case RTF_COLNO:
1285 putNestedSprm(m_aStates.top().getSectionSprms(), NS_ooxml::LN_EG_SectPrContents_cols,
1286 NS_ooxml::LN_CT_Columns_col, pIntValue);
1287 break;
1288 case RTF_COLW:
1289 case RTF_COLSR:
1290 {
1291 RTFSprms& rAttributes = getLastAttributes(m_aStates.top().getSectionSprms(),
1292 NS_ooxml::LN_EG_SectPrContents_cols);
1293 rAttributes.set(
1294 (nKeyword == RTF_COLW ? NS_ooxml::LN_CT_Column_w : NS_ooxml::LN_CT_Column_space),
1295 pIntValue);
1296 }
1297 break;
1298 case RTF_PAPERH:
1299 putNestedAttribute(m_aDefaultState.getSectionSprms(),
1300 NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_h,
1301 pIntValue);
1302 [[fallthrough]]; // set the default + current value
1303 case RTF_PGHSXN:
1304 putNestedAttribute(m_aStates.top().getSectionSprms(),
1305 NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_h,
1306 pIntValue);
1307 break;
1308 case RTF_PAPERW:
1309 putNestedAttribute(m_aDefaultState.getSectionSprms(),
1310 NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_w,
1311 pIntValue);
1312 [[fallthrough]]; // set the default + current value
1313 case RTF_PGWSXN:
1314 putNestedAttribute(m_aStates.top().getSectionSprms(),
1315 NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_w,
1316 pIntValue);
1317 break;
1318 case RTF_MARGL:
1319 putNestedAttribute(m_aDefaultState.getSectionSprms(),
1320 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_left,
1321 pIntValue);
1322 [[fallthrough]]; // set the default + current value
1323 case RTF_MARGLSXN:
1324 putNestedAttribute(m_aStates.top().getSectionSprms(),
1325 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_left,
1326 pIntValue);
1327 break;
1328 case RTF_MARGR:
1329 putNestedAttribute(m_aDefaultState.getSectionSprms(),
1330 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_right,
1331 pIntValue);
1332 [[fallthrough]]; // set the default + current value
1333 case RTF_MARGRSXN:
1334 putNestedAttribute(m_aStates.top().getSectionSprms(),
1335 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_right,
1336 pIntValue);
1337 break;
1338 case RTF_MARGT:
1339 putNestedAttribute(m_aDefaultState.getSectionSprms(),
1340 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_top,
1341 pIntValue);
1342 [[fallthrough]]; // set the default + current value
1343 case RTF_MARGTSXN:
1344 putNestedAttribute(m_aStates.top().getSectionSprms(),
1345 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_top,
1346 pIntValue);
1347 break;
1348 case RTF_MARGB:
1349 putNestedAttribute(m_aDefaultState.getSectionSprms(),
1350 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_bottom,
1351 pIntValue);
1352 [[fallthrough]]; // set the default + current value
1353 case RTF_MARGBSXN:
1354 putNestedAttribute(m_aStates.top().getSectionSprms(),
1355 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_bottom,
1356 pIntValue);
1357 break;
1358 case RTF_HEADERY:
1359 putNestedAttribute(m_aStates.top().getSectionSprms(),
1360 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_header,
1361 pIntValue);
1362 break;
1363 case RTF_FOOTERY:
1364 putNestedAttribute(m_aStates.top().getSectionSprms(),
1365 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_footer,
1366 pIntValue);
1367 break;
1368 case RTF_DEFTAB:
1369 m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_defaultTabStop, pIntValue);
1370 break;
1371 case RTF_LINEMOD:
1372 putNestedAttribute(m_aStates.top().getSectionSprms(),
1373 NS_ooxml::LN_EG_SectPrContents_lnNumType,
1374 NS_ooxml::LN_CT_LineNumber_countBy, pIntValue);
1375 break;
1376 case RTF_LINEX:
1377 if (nParam)
1378 putNestedAttribute(m_aStates.top().getSectionSprms(),
1379 NS_ooxml::LN_EG_SectPrContents_lnNumType,
1380 NS_ooxml::LN_CT_LineNumber_distance, pIntValue);
1381 break;
1382 case RTF_LINESTARTS:
1383 {
1384 // OOXML <w:lnNumType w:start="..."/> is 0-based, RTF is 1-based.
1385 auto pStart = tools::make_ref<RTFValue>(nParam - 1);
1386 putNestedAttribute(m_aStates.top().getSectionSprms(),
1387 NS_ooxml::LN_EG_SectPrContents_lnNumType,
1388 NS_ooxml::LN_CT_LineNumber_start, pStart);
1389 }
1390 break;
1391 case RTF_REVAUTH:
1392 case RTF_REVAUTHDEL:
1393 {
1394 auto pValue = new RTFValue(m_aAuthors[nParam]);
1395 putNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_trackchange,
1396 NS_ooxml::LN_CT_TrackChange_author, pValue);
1397 }
1398 break;
1399 case RTF_REVDTTM:
1400 case RTF_REVDTTMDEL:
1401 {
1402 OUString aStr(
1403 OStringToOUString(DTTM22OString(nParam), m_aStates.top().getCurrentEncoding()));
1404 auto pValue = new RTFValue(aStr);
1405 putNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_trackchange,
1406 NS_ooxml::LN_CT_TrackChange_date, pValue);
1407 }
1408 break;
1409 case RTF_SHPLEFT:
1410 m_aStates.top().getShape().setLeft(convertTwipToMm100(nParam));
1411 break;
1412 case RTF_SHPTOP:
1413 m_aStates.top().getShape().setTop(convertTwipToMm100(nParam));
1414 break;
1415 case RTF_SHPRIGHT:
1416 m_aStates.top().getShape().setRight(convertTwipToMm100(nParam));
1417 break;
1418 case RTF_SHPBOTTOM:
1419 m_aStates.top().getShape().setBottom(convertTwipToMm100(nParam));
1420 break;
1421 case RTF_SHPZ:
1422 m_aStates.top().getShape().setZ(nParam);
1423 break;
1424 case RTF_FFTYPE:
1425 switch (nParam)
1426 {
1427 case 0:
1428 m_nFormFieldType = RTFFormFieldType::TEXT;
1429 break;
1430 case 1:
1431 m_nFormFieldType = RTFFormFieldType::CHECKBOX;
1432 break;
1433 case 2:
1434 m_nFormFieldType = RTFFormFieldType::LIST;
1435 break;
1436 default:
1437 m_nFormFieldType = RTFFormFieldType::NONE;
1438 break;
1439 }
1440 break;
1441 case RTF_FFDEFRES:
1442 if (m_nFormFieldType == RTFFormFieldType::CHECKBOX)
1443 m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFCheckBox_default, pIntValue);
1444 else if (m_nFormFieldType == RTFFormFieldType::LIST)
1445 m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_default, pIntValue);
1446 break;
1447 case RTF_FFRES:
1448 // 25 means undefined, see [MS-DOC] 2.9.79, FFDataBits.
1449 if (m_nFormFieldType == RTFFormFieldType::CHECKBOX && nParam != 25)
1450 m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFCheckBox_checked, pIntValue);
1451 else if (m_nFormFieldType == RTFFormFieldType::LIST)
1452 m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_result, pIntValue);
1453 break;
1454 case RTF_EDMINS:
1455 if (m_xDocumentProperties.is())
1456 {
1457 // tdf#116851 some RTF may be malformed
1458 if (nParam < 0)
1459 nParam = -nParam;
1460 m_xDocumentProperties->setEditingDuration(nParam);
1461 }
1462 break;
1463 case RTF_NOFPAGES:
1464 case RTF_NOFWORDS:
1465 case RTF_NOFCHARS:
1466 case RTF_NOFCHARSWS:
1467 if (m_xDocumentProperties.is())
1468 {
1469 comphelper::SequenceAsHashMap aSeq = m_xDocumentProperties->getDocumentStatistics();
1470 OUString aName;
1471 switch (nKeyword)
1472 {
1473 case RTF_NOFPAGES:
1474 aName = "PageCount";
1475 nParam = 99;
1476 break;
1477 case RTF_NOFWORDS:
1478 aName = "WordCount";
1479 break;
1480 case RTF_NOFCHARS:
1481 aName = "CharacterCount";
1482 break;
1483 case RTF_NOFCHARSWS:
1484 aName = "NonWhitespaceCharacterCount";
1485 break;
1486 default:
1487 break;
1488 }
1489 if (!aName.isEmpty())
1490 {
1491 aSeq[aName] <<= sal_Int32(nParam);
1492 m_xDocumentProperties->setDocumentStatistics(aSeq.getAsConstNamedValueList());
1493 }
1494 }
1495 break;
1496 case RTF_VERSION:
1497 if (m_xDocumentProperties.is())
1498 m_xDocumentProperties->setEditingCycles(nParam);
1499 break;
1500 case RTF_VERN:
1501 // Ignore this for now, later the RTF writer version could be used to add hacks for older buggy writers.
1502 break;
1503 case RTF_FTNSTART:
1504 putNestedSprm(m_aDefaultState.getParagraphSprms(),
1505 NS_ooxml::LN_EG_SectPrContents_footnotePr,
1506 NS_ooxml::LN_EG_FtnEdnNumProps_numStart, pIntValue);
1507 break;
1508 case RTF_AFTNSTART:
1509 putNestedSprm(m_aDefaultState.getParagraphSprms(),
1510 NS_ooxml::LN_EG_SectPrContents_endnotePr,
1511 NS_ooxml::LN_EG_FtnEdnNumProps_numStart, pIntValue);
1512 break;
1513 case RTF_DFRMTXTX:
1514 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_hSpace, nParam);
1515 break;
1516 case RTF_DFRMTXTY:
1517 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_vSpace, nParam);
1518 break;
1519 case RTF_DXFRTEXT:
1520 {
1521 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_hSpace, nParam);
1522 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_vSpace, nParam);
1523 }
1524 break;
1525 case RTF_FLYVERT:
1526 {
1527 RTFVertOrient aVertOrient(nParam);
1528 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_yAlign,
1529 aVertOrient.GetAlign());
1530 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_vAnchor,
1531 aVertOrient.GetAnchor());
1532 }
1533 break;
1534 case RTF_FLYHORZ:
1535 {
1536 RTFHoriOrient aHoriOrient(nParam);
1537 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_xAlign,
1538 aHoriOrient.GetAlign());
1539 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_hAnchor,
1540 aHoriOrient.GetAnchor());
1541 }
1542 break;
1543 case RTF_FLYANCHOR:
1544 break;
1545 case RTF_WMETAFILE:
1546 m_aStates.top().getPicture().eWMetafile = nParam;
1547 break;
1548 case RTF_SB:
1549 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_spacing,
1550 NS_ooxml::LN_CT_Spacing_before, pIntValue);
1551 break;
1552 case RTF_SA:
1553 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_spacing,
1554 NS_ooxml::LN_CT_Spacing_after, pIntValue);
1555 break;
1556 case RTF_DPX:
1557 m_aStates.top().getDrawingObject().setLeft(convertTwipToMm100(nParam));
1558 break;
1559 case RTF_DPY:
1560 m_aStates.top().getDrawingObject().setTop(convertTwipToMm100(nParam));
1561 break;
1562 case RTF_DPXSIZE:
1563 m_aStates.top().getDrawingObject().setRight(convertTwipToMm100(nParam));
1564 break;
1565 case RTF_DPYSIZE:
1566 m_aStates.top().getDrawingObject().setBottom(convertTwipToMm100(nParam));
1567 break;
1568 case RTF_PNSTART:
1569 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Lvl_start, pIntValue);
1570 break;
1571 case RTF_PNF:
1572 {
1573 auto pValue = new RTFValue(m_aFontNames[getFontIndex(nParam)]);
1574 RTFSprms aAttributes;
1575 aAttributes.set(NS_ooxml::LN_CT_Fonts_ascii, pValue);
1576 putNestedSprm(m_aStates.top().getTableSprms(), NS_ooxml::LN_CT_Lvl_rPr,
1577 NS_ooxml::LN_EG_RPrBase_rFonts, new RTFValue(aAttributes));
1578 }
1579 break;
1580 case RTF_VIEWSCALE:
1581 m_aSettingsTableAttributes.set(NS_ooxml::LN_CT_Zoom_percent, pIntValue);
1582 break;
1583 case RTF_BIN:
1584 {
1585 m_aStates.top().setInternalState(RTFInternalState::BIN);
1586 m_aStates.top().setBinaryToRead(nParam);
1587 }
1588 break;
1589 case RTF_DPLINECOR:
1590 m_aStates.top().getDrawingObject().setLineColorR(nParam);
1591 m_aStates.top().getDrawingObject().setHasLineColor(true);
1592 break;
1593 case RTF_DPLINECOG:
1594 m_aStates.top().getDrawingObject().setLineColorG(nParam);
1595 m_aStates.top().getDrawingObject().setHasLineColor(true);
1596 break;
1597 case RTF_DPLINECOB:
1598 m_aStates.top().getDrawingObject().setLineColorB(nParam);
1599 m_aStates.top().getDrawingObject().setHasLineColor(true);
1600 break;
1601 case RTF_DPFILLBGCR:
1602 m_aStates.top().getDrawingObject().setFillColorR(nParam);
1603 m_aStates.top().getDrawingObject().setHasFillColor(true);
1604 break;
1605 case RTF_DPFILLBGCG:
1606 m_aStates.top().getDrawingObject().setFillColorG(nParam);
1607 m_aStates.top().getDrawingObject().setHasFillColor(true);
1608 break;
1609 case RTF_DPFILLBGCB:
1610 m_aStates.top().getDrawingObject().setFillColorB(nParam);
1611 m_aStates.top().getDrawingObject().setHasFillColor(true);
1612 break;
1613 case RTF_DODHGT:
1614 m_aStates.top().getDrawingObject().setDhgt(nParam);
1615 break;
1616 case RTF_DPPOLYCOUNT:
1617 if (nParam >= 0)
1618 {
1619 m_aStates.top().getDrawingObject().setPolyLineCount(nParam);
1620 }
1621 break;
1622 case RTF_DPPTX:
1623 {
1624 RTFDrawingObject& rDrawingObject = m_aStates.top().getDrawingObject();
1625
1626 if (rDrawingObject.getPolyLinePoints().empty())
1627 dispatchValue(RTF_DPPOLYCOUNT, 2);
1628
1629 rDrawingObject.getPolyLinePoints().emplace_back(
1630 awt::Point(convertTwipToMm100(nParam), 0));
1631 }
1632 break;
1633 case RTF_DPPTY:
1634 {
1635 RTFDrawingObject& rDrawingObject = m_aStates.top().getDrawingObject();
1636 if (!rDrawingObject.getPolyLinePoints().empty())
1637 {
1638 rDrawingObject.getPolyLinePoints().back().Y = convertTwipToMm100(nParam);
1639 rDrawingObject.setPolyLineCount(rDrawingObject.getPolyLineCount() - 1);
1640 if (rDrawingObject.getPolyLineCount() == 0 && rDrawingObject.getPropertySet().is())
1641 {
1642 uno::Sequence<uno::Sequence<awt::Point>> aPointSequenceSequence
1643 = { comphelper::containerToSequence(rDrawingObject.getPolyLinePoints()) };
1644 rDrawingObject.getPropertySet()->setPropertyValue(
1645 "PolyPolygon", uno::Any(aPointSequenceSequence));
1646 }
1647 }
1648 }
1649 break;
1650 case RTF_SHPFBLWTXT:
1651 // Shape is below text -> send it to the background.
1652 m_aStates.top().getShape().setInBackground(nParam != 0);
1653 break;
1654 case RTF_FI:
1655 {
1656 if (m_aStates.top().getDestination() == Destination::LISTLEVEL)
1657 {
1658 if (m_aStates.top().getLevelNumbersValid())
1659 putNestedAttribute(m_aStates.top().getTableSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1660 NS_ooxml::LN_CT_Ind_firstLine, pIntValue);
1661 else
1662 m_aInvalidListLevelFirstIndents[m_nListLevel] = nParam;
1663 }
1664 else
1665 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1666 NS_ooxml::LN_CT_Ind_firstLine, pIntValue);
1667 break;
1668 }
1669 case RTF_LI:
1670 {
1671 if (m_aStates.top().getDestination() == Destination::LISTLEVEL)
1672 {
1673 if (m_aStates.top().getLevelNumbersValid())
1674 putNestedAttribute(m_aStates.top().getTableSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1675 NS_ooxml::LN_CT_Ind_left, pIntValue);
1676 }
1677 else
1678 {
1679 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1680 NS_ooxml::LN_CT_Ind_left, pIntValue);
1681 }
1682 // It turns out \li should reset the \fi inherited from the stylesheet.
1683 // So set the direct formatting to zero, if we don't have such direct formatting yet.
1684 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1685 NS_ooxml::LN_CT_Ind_firstLine, new RTFValue(0),
1686 RTFOverwrite::NO_IGNORE);
1687 }
1688 break;
1689 case RTF_RI:
1690 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1691 NS_ooxml::LN_CT_Ind_right, pIntValue);
1692 break;
1693 case RTF_LIN:
1694 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1695 NS_ooxml::LN_CT_Ind_start, pIntValue);
1696 break;
1697 case RTF_RIN:
1698 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1699 NS_ooxml::LN_CT_Ind_end, pIntValue);
1700 break;
1701 case RTF_OUTLINELEVEL:
1702 m_aStates.top().getParagraphSprms().set(NS_ooxml::LN_CT_PPrBase_outlineLvl, pIntValue);
1703 break;
1704 case RTF_PROPTYPE:
1705 {
1706 switch (nParam)
1707 {
1708 case 3:
1709 m_aStates.top().setPropType(cppu::UnoType<sal_Int32>::get());
1710 break;
1711 case 5:
1712 m_aStates.top().setPropType(cppu::UnoType<double>::get());
1713 break;
1714 case 11:
1715 m_aStates.top().setPropType(cppu::UnoType<bool>::get());
1716 break;
1717 case 30:
1718 m_aStates.top().setPropType(cppu::UnoType<OUString>::get());
1719 break;
1720 case 64:
1721 m_aStates.top().setPropType(cppu::UnoType<util::DateTime>::get());
1722 break;
1723 }
1724 }
1725 break;
1726 case RTF_DIBITMAP:
1727 m_aStates.top().getPicture().eStyle = RTFBmpStyle::DIBITMAP;
1728 break;
1729 case RTF_TRWWIDTHA:
1730 m_aStates.top().setTableRowWidthAfter(nParam);
1731 break;
1732 case RTF_ANIMTEXT:
1733 {
1734 Id nId = 0;
1735 switch (nParam)
1736 {
1737 case 0:
1738 nId = NS_ooxml::LN_Value_ST_TextEffect_none;
1739 break;
1740 case 2:
1741 nId = NS_ooxml::LN_Value_ST_TextEffect_blinkBackground;
1742 break;
1743 }
1744
1745 if (nId > 0)
1746 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_effect,
1747 new RTFValue(nId));
1748 break;
1749 }
1750 case RTF_VIEWBKSP:
1751 {
1752 m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_displayBackgroundShape, pIntValue);
1753 // Send this token immediately, if it only appears before the first
1754 // run, it will be too late, we ignored the background shape already by then.
1755 outputSettingsTable();
1756 break;
1757 }
1758 case RTF_STEXTFLOW:
1759 {
1760 Id nId = 0;
1761 switch (nParam)
1762 {
1763 case 0:
1764 nId = NS_ooxml::LN_Value_ST_TextDirection_lrTb;
1765 break;
1766 case 1:
1767 nId = NS_ooxml::LN_Value_ST_TextDirection_tbRl;
1768 break;
1769 }
1770
1771 if (nId > 0)
1772 {
1773 m_aStates.top().getSectionSprms().set(NS_ooxml::LN_EG_SectPrContents_textDirection,
1774 new RTFValue(nId));
1775 }
1776 }
1777 break;
1778 default:
1779 {
1780 SAL_INFO("writerfilter", "TODO handle value '" << keywordToString(nKeyword) << "'")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "writerfilter")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "TODO handle value '"
<< keywordToString(nKeyword) << "'") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("writerfilter"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdispatchvalue.cxx"
":" "1780" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "TODO handle value '" << keywordToString
(nKeyword) << "'"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "TODO handle value '" << keywordToString
(nKeyword) << "'"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("writerfilter"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdispatchvalue.cxx"
":" "1780" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "TODO handle value '" << keywordToString(nKeyword
) << "'") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("writerfilter"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdispatchvalue.cxx"
":" "1780" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "TODO handle value '" << keywordToString
(nKeyword) << "'"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "TODO handle value '" << keywordToString
(nKeyword) << "'"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("writerfilter"), ("/home/maarten/src/libreoffice/core/writerfilter/source/rtftok/rtfdispatchvalue.cxx"
":" "1780" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1781 aSkip.setParsed(false);
1782 }
1783 break;
1784 }
1785 return RTFError::OK;
1786}
1787
1788} // namespace rtftok
1789} // namespace writerfilter
1790
1791/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/tools/ref.hxx

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#ifndef INCLUDED_TOOLS_REF_HXX
20#define INCLUDED_TOOLS_REF_HXX
21
22#include <sal/config.h>
23#include <cassert>
24#include <tools/toolsdllapi.h>
25#include <utility>
26
27/**
28 This implements similar functionality to boost::intrusive_ptr
29*/
30
31namespace tools {
32
33/** T must be a class that extends SvRefBase */
34template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final {
35public:
36 SvRef(): pObj(nullptr) {}
37
38 SvRef(SvRef&& rObj) noexcept
39 {
40 pObj = rObj.pObj;
41 rObj.pObj = nullptr;
42 }
43
44 SvRef(SvRef const & rObj): pObj(rObj.pObj)
45 {
46 if (pObj != nullptr) pObj->AddNextRef();
47 }
48
49 SvRef(T * pObjP): pObj(pObjP)
50 {
51 if (pObj != nullptr) pObj->AddFirstRef();
52 }
53
54 ~SvRef()
55 {
56 if (pObj != nullptr) pObj->ReleaseRef();
57 }
58
59 void clear()
60 {
61 if (pObj != nullptr) {
62 T * pRefObj = pObj;
63 pObj = nullptr;
64 pRefObj->ReleaseRef();
65 }
66 }
67
68 SvRef & operator =(SvRef const & rObj)
69 {
70 if (rObj.pObj != nullptr) {
71 rObj.pObj->AddNextRef();
72 }
73 T * pRefObj = pObj;
74 pObj = rObj.pObj;
75 if (pRefObj != nullptr) {
76 pRefObj->ReleaseRef();
77 }
78 return *this;
79 }
80
81 SvRef & operator =(SvRef && rObj)
82 {
83 if (pObj != nullptr) {
6
Taking true branch
84 pObj->ReleaseRef();
85 }
86 pObj = rObj.pObj;
87 rObj.pObj = nullptr;
7
Potential memory leak
88 return *this;
89 }
90
91 bool is() const { return pObj != nullptr; }
92
93 explicit operator bool() const { return is(); }
94
95 T * get() const { return pObj; }
96
97 T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail
("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx"
, 97, __extension__ __PRETTY_FUNCTION__))
; return pObj; }
98
99 T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail
("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx"
, 99, __extension__ __PRETTY_FUNCTION__))
; return *pObj; }
100
101 bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; }
102 bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); }
103
104private:
105 T * pObj;
106};
107
108/**
109 * This implements similar functionality to std::make_shared.
110 */
111template<typename T, typename... Args>
112SvRef<T> make_ref(Args&& ... args)
113{
114 return SvRef<T>(new T(std::forward<Args>(args)...));
115}
116
117}
118
119/** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */
120class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase
121{
122 // work around a clang 3.5 optimization bug: if the bNoDelete is *first*
123 // it mis-compiles "if (--nRefCount == 0)" and never deletes any object
124 unsigned int nRefCount : 31;
125 // the only reason this is not bool is because MSVC cannot handle mixed type bitfields
126 unsigned int bNoDelete : 1;
127
128protected:
129 virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE;
130
131public:
132 SvRefBase() : nRefCount(0), bNoDelete(1) {}
133 SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {}
134
135 SvRefBase & operator=(const SvRefBase &) { return *this; }
136
137 void RestoreNoDelete()
138 { bNoDelete = 1; }
139
140 void AddNextRef()
141 {
142 assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) &&
"Do not add refs to dead objects") ? void (0) : __assert_fail
("nRefCount < (1 << 30) && \"Do not add refs to dead objects\""
, "/home/maarten/src/libreoffice/core/include/tools/ref.hxx",
142, __extension__ __PRETTY_FUNCTION__))
;
143 ++nRefCount;
144 }
145
146 void AddFirstRef()
147 {
148 assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) &&
"Do not add refs to dead objects") ? void (0) : __assert_fail
("nRefCount < (1 << 30) && \"Do not add refs to dead objects\""
, "/home/maarten/src/libreoffice/core/include/tools/ref.hxx",
148, __extension__ __PRETTY_FUNCTION__))
;
149 if( bNoDelete )
150 bNoDelete = 0;
151 ++nRefCount;
152 }
153
154 void ReleaseRef()
155 {
156 assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail
("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx"
, 156, __extension__ __PRETTY_FUNCTION__))
;
157 if( --nRefCount == 0 && !bNoDelete)
158 {
159 // I'm not sure about the original purpose of this line, but right now
160 // it serves the purpose that anything that attempts to do an AddRef()
161 // after an object is deleted will trip an assert.
162 nRefCount = 1 << 30;
163 delete this;
164 }
165 }
166
167 unsigned int GetRefCount() const
168 { return nRefCount; }
169};
170
171template<typename T>
172class SvCompatWeakBase;
173
174/** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T.
175*/
176template<typename T>
177class SvCompatWeakHdl final : public SvRefBase
178{
179 friend class SvCompatWeakBase<T>;
180 T* _pObj;
181
182 SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {}
183
184public:
185 void ResetWeakBase( ) { _pObj = nullptr; }
186 T* GetObj() { return _pObj; }
187};
188
189/** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame.
190 Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted.
191*/
192template<typename T>
193class SvCompatWeakBase
194{
195 tools::SvRef< SvCompatWeakHdl<T> > _xHdl;
196
197public:
198 /** Does not use initializer due to compiler warnings,
199 because the lifetime of the _xHdl object can exceed the lifetime of this class.
200 */
201 SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); }
202
203 ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); }
204
205 SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); }
206};
207
208/** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak.
209*/
210template<typename T>
211class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef
212{
213 tools::SvRef< SvCompatWeakHdl<T> > _xHdl;
214public:
215 SvCompatWeakRef( ) {}
216 SvCompatWeakRef( T* pObj )
217 { if( pObj ) _xHdl = pObj->GetHdl(); }
218#if defined(__COVERITY__)
219 ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {}
220#endif
221 SvCompatWeakRef& operator = ( T * pObj )
222 { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; }
223 bool is() const
224 { return _xHdl.is() && _xHdl->GetObj(); }
225 explicit operator bool() const { return is(); }
226 T* operator -> () const
227 { return _xHdl.is() ? _xHdl->GetObj() : nullptr; }
228 operator T* () const
229 { return _xHdl.is() ? _xHdl->GetObj() : nullptr; }
230};
231
232#endif
233
234/* vim:set shiftwidth=4 softtabstop=4 expandtab: */