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