android: Update app-specific/MIME type icons
[LibreOffice.git] / writerfilter / source / rtftok / rtfdispatchvalue.cxx
blob69157a97829f03641edf6cce6edb5a49fed2cdb8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include "rtfdocumentimpl.hxx"
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>
22 #include <ooxml/resourceids.hxx>
24 #include "rtfcharsets.hxx"
25 #include "rtffly.hxx"
26 #include "rtfreferenceproperties.hxx"
27 #include "rtfskipdestination.hxx"
29 #include <unotools/defaultencoding.hxx>
30 #include <unotools/wincodepage.hxx>
32 using namespace com::sun::star;
34 namespace writerfilter
36 static int getNumberFormat(int nParam)
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);
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;
97 namespace rtftok
99 bool RTFDocumentImpl::dispatchTableSprmValue(RTFKeyword nKeyword, int nParam)
101 int nSprm = 0;
102 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
103 switch (nKeyword)
105 case RTFKeyword::LEVELJC:
107 nSprm = NS_ooxml::LN_CT_Lvl_lvlJc;
108 int nValue = 0;
109 switch (nParam)
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;
121 pIntValue = new RTFValue(nValue);
122 break;
124 case RTFKeyword::LEVELSTARTAT:
125 nSprm = NS_ooxml::LN_CT_Lvl_start;
126 break;
127 case RTFKeyword::LEVELPICTURE:
128 nSprm = NS_ooxml::LN_CT_Lvl_lvlPicBulletId;
129 break;
130 case RTFKeyword::SBASEDON:
131 nSprm = NS_ooxml::LN_CT_Style_basedOn;
132 pIntValue = new RTFValue(getStyleName(nParam));
133 break;
134 case RTFKeyword::SNEXT:
135 nSprm = NS_ooxml::LN_CT_Style_next;
136 pIntValue = new RTFValue(getStyleName(nParam));
137 break;
138 default:
139 break;
141 if (nSprm > 0)
143 m_aStates.top().getTableSprms().set(nSprm, pIntValue);
144 return true;
146 if (nKeyword == RTFKeyword::LEVELNFC)
148 pIntValue = new RTFValue(getNumberFormat(nParam));
149 putNestedAttribute(m_aStates.top().getTableSprms(), NS_ooxml::LN_CT_Lvl_numFmt,
150 NS_ooxml::LN_CT_NumFmt_val, pIntValue);
151 return true;
154 return false;
157 bool RTFDocumentImpl::dispatchCharacterSprmValue(RTFKeyword nKeyword, int nParam)
159 int nSprm = 0;
160 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
162 switch (nKeyword)
164 case RTFKeyword::FS:
165 case RTFKeyword::AFS:
166 switch (m_aStates.top().getRunType())
168 case RTFParserState::RunType::HICH:
169 case RTFParserState::RunType::RTLCH_LTRCH_1:
170 case RTFParserState::RunType::LTRCH_RTLCH_2:
171 nSprm = NS_ooxml::LN_EG_RPrBase_szCs;
172 break;
173 case RTFParserState::RunType::NONE:
174 case RTFParserState::RunType::LOCH:
175 case RTFParserState::RunType::LTRCH_RTLCH_1:
176 case RTFParserState::RunType::RTLCH_LTRCH_2:
177 case RTFParserState::RunType::DBCH:
178 default:
179 nSprm = NS_ooxml::LN_EG_RPrBase_sz;
180 break;
182 break;
183 case RTFKeyword::EXPNDTW:
184 nSprm = NS_ooxml::LN_EG_RPrBase_spacing;
185 break;
186 case RTFKeyword::KERNING:
187 nSprm = NS_ooxml::LN_EG_RPrBase_kern;
188 break;
189 case RTFKeyword::CHARSCALEX:
190 nSprm = NS_ooxml::LN_EG_RPrBase_w;
191 break;
192 default:
193 break;
195 if (nSprm > 0)
197 if (m_aStates.top().getDestination() == Destination::LISTLEVEL)
199 m_aStates.top().getTableSprms().set(nSprm, pIntValue);
201 else
203 m_aStates.top().getCharacterSprms().set(nSprm, pIntValue);
205 return true;
208 return false;
211 bool RTFDocumentImpl::dispatchCharacterAttributeValue(RTFKeyword nKeyword, int nParam)
213 int nSprm = 0;
215 switch (nKeyword)
217 case RTFKeyword::LANG:
218 case RTFKeyword::ALANG:
219 switch (m_aStates.top().getRunType())
221 case RTFParserState::RunType::HICH:
222 case RTFParserState::RunType::RTLCH_LTRCH_1:
223 case RTFParserState::RunType::LTRCH_RTLCH_2:
224 nSprm = NS_ooxml::LN_CT_Language_bidi;
225 break;
226 case RTFParserState::RunType::DBCH:
227 nSprm = NS_ooxml::LN_CT_Language_eastAsia;
228 break;
229 case RTFParserState::RunType::NONE:
230 case RTFParserState::RunType::LOCH:
231 case RTFParserState::RunType::LTRCH_RTLCH_1:
232 case RTFParserState::RunType::RTLCH_LTRCH_2:
233 default:
234 nSprm = NS_ooxml::LN_CT_Language_val;
235 break;
237 break;
238 case RTFKeyword::LANGFE: // this one is always CJK apparently
239 nSprm = NS_ooxml::LN_CT_Language_eastAsia;
240 break;
241 default:
242 break;
244 if (nSprm > 0)
246 LanguageTag aTag((LanguageType(static_cast<sal_uInt16>(nParam))));
247 auto pValue = new RTFValue(aTag.getBcp47());
248 putNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_EG_RPrBase_lang, nSprm,
249 pValue);
250 // Language is a character property, but we should store it at a paragraph level as well for fields.
251 if (nKeyword == RTFKeyword::LANG && m_bNeedPap)
252 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_EG_RPrBase_lang,
253 nSprm, pValue);
254 return true;
257 return false;
260 bool RTFDocumentImpl::dispatchParagraphSprmValue(RTFKeyword nKeyword, int nParam)
262 int nSprm = 0;
263 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
265 switch (nKeyword)
267 case RTFKeyword::ITAP:
268 nSprm = NS_ooxml::LN_tblDepth;
269 // tdf#117268: If \itap0 is encountered inside tables (between \cellxN and \cell), then
270 // use the default value (1), as Word apparently does
271 if (nParam == 0 && (m_nTopLevelCells != 0 || m_nNestedCells != 0))
273 nParam = 1;
274 pIntValue = new RTFValue(nParam);
276 break;
277 default:
278 break;
280 if (nSprm > 0)
282 m_aStates.top().getParagraphSprms().set(nSprm, pIntValue);
283 if (nKeyword == RTFKeyword::ITAP && nParam > 0)
285 while (m_aTableBufferStack.size() < sal::static_int_cast<std::size_t>(nParam))
287 m_aTableBufferStack.emplace_back();
289 // Invalid tables may omit INTBL after ITAP
290 dispatchFlag(RTFKeyword::INTBL); // sets newly pushed buffer as current
291 assert(m_aStates.top().getCurrentBuffer() == &m_aTableBufferStack.back());
293 return true;
296 return false;
299 bool RTFDocumentImpl::dispatchInfoValue(RTFKeyword nKeyword, int nParam)
301 int nSprm = 0;
303 switch (nKeyword)
305 case RTFKeyword::YR:
307 m_aStates.top().setYear(nParam);
308 nSprm = 1;
310 break;
311 case RTFKeyword::MO:
313 m_aStates.top().setMonth(nParam);
314 nSprm = 1;
316 break;
317 case RTFKeyword::DY:
319 m_aStates.top().setDay(nParam);
320 nSprm = 1;
322 break;
323 case RTFKeyword::HR:
325 m_aStates.top().setHour(nParam);
326 nSprm = 1;
328 break;
329 case RTFKeyword::MIN:
331 m_aStates.top().setMinute(nParam);
332 nSprm = 1;
334 break;
335 default:
336 break;
339 return nSprm > 0;
342 bool RTFDocumentImpl::dispatchFrameValue(RTFKeyword nKeyword, int nParam)
344 Id nId = 0;
345 switch (nKeyword)
347 case RTFKeyword::ABSW:
348 nId = NS_ooxml::LN_CT_FramePr_w;
349 break;
350 case RTFKeyword::ABSH:
351 nId = NS_ooxml::LN_CT_FramePr_h;
352 break;
353 case RTFKeyword::POSX:
355 nId = NS_ooxml::LN_CT_FramePr_x;
356 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_xAlign, 0);
358 break;
359 case RTFKeyword::POSY:
361 nId = NS_ooxml::LN_CT_FramePr_y;
362 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_yAlign, 0);
364 break;
365 default:
366 break;
369 if (nId > 0)
371 m_bNeedPap = true;
372 // Don't try to support text frames inside tables for now.
373 if (m_aStates.top().getCurrentBuffer() != &m_aTableBufferStack.back())
374 m_aStates.top().getFrame().setSprm(nId, nParam);
376 return true;
379 return false;
382 bool RTFDocumentImpl::dispatchTableValue(RTFKeyword nKeyword, int nParam)
384 int nSprm = 0;
385 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
387 switch (nKeyword)
389 case RTFKeyword::CELLX:
391 int& rCurrentCellX(
392 (Destination::NESTEDTABLEPROPERTIES == m_aStates.top().getDestination())
393 ? m_nNestedCurrentCellX
394 : m_nTopLevelCurrentCellX);
395 int nCellX = nParam - rCurrentCellX;
397 if (!nCellX && nParam > 0)
399 // If width of cell is 0, BUT there is a value for \cellxN use minimal
400 // possible width. But if \cellxN has no value leave 0 so autofit will
401 // try to resolve this.
403 // sw/source/filter/inc/wrtswtbl.hxx, minimal possible width of cells.
404 const int COL_DFLT_WIDTH = 41;
405 nCellX = COL_DFLT_WIDTH;
408 // If there is a negative left margin, then the first cellx is relative to that.
409 RTFValue::Pointer_t pTblInd
410 = m_aStates.top().getTableRowSprms().find(NS_ooxml::LN_CT_TblPrBase_tblInd);
411 if (rCurrentCellX == 0 && pTblInd)
413 RTFValue::Pointer_t pWidth
414 = pTblInd->getAttributes().find(NS_ooxml::LN_CT_TblWidth_w);
415 if (pWidth && pWidth->getInt() < 0)
416 nCellX = -1 * (pWidth->getInt() - nParam);
419 rCurrentCellX = nParam;
420 auto pXValue = new RTFValue(nCellX);
421 m_aStates.top().getTableRowSprms().set(NS_ooxml::LN_CT_TblGridBase_gridCol, pXValue,
422 RTFOverwrite::NO_APPEND);
423 if (Destination::NESTEDTABLEPROPERTIES == m_aStates.top().getDestination())
425 m_nNestedCells++;
426 // Push cell properties.
427 m_aNestedTableCellsSprms.push_back(m_aStates.top().getTableCellSprms());
428 m_aNestedTableCellsAttributes.push_back(m_aStates.top().getTableCellAttributes());
430 else
432 m_nTopLevelCells++;
433 // Push cell properties.
434 m_aTopLevelTableCellsSprms.push_back(m_aStates.top().getTableCellSprms());
435 m_aTopLevelTableCellsAttributes.push_back(m_aStates.top().getTableCellAttributes());
438 m_aStates.top().getTableCellSprms() = m_aDefaultState.getTableCellSprms();
439 m_aStates.top().getTableCellAttributes() = m_aDefaultState.getTableCellAttributes();
440 // We assume text after a row definition always belongs to the table, to handle text before the real INTBL token
441 dispatchFlag(RTFKeyword::INTBL);
442 if (!m_nCellxMax)
444 // Wasn't in table, but now is -> tblStart.
445 RTFSprms aAttributes;
446 RTFSprms aSprms;
447 aSprms.set(NS_ooxml::LN_tblStart, new RTFValue(1));
448 writerfilter::Reference<Properties>::Pointer_t pProperties
449 = new RTFReferenceProperties(std::move(aAttributes), std::move(aSprms));
450 Mapper().props(pProperties);
452 m_nCellxMax = std::max(m_nCellxMax, nParam);
453 return true;
455 break;
456 case RTFKeyword::TRRH:
458 OUString hRule("auto");
459 if (nParam < 0)
461 tools::SvRef<RTFValue> pAbsValue(new RTFValue(-nParam));
462 std::swap(pIntValue, pAbsValue);
464 hRule = "exact";
466 else if (nParam > 0)
467 hRule = "atLeast";
469 putNestedAttribute(m_aStates.top().getTableRowSprms(),
470 NS_ooxml::LN_CT_TrPrBase_trHeight, NS_ooxml::LN_CT_Height_val,
471 pIntValue);
473 auto pHRule = new RTFValue(hRule);
474 putNestedAttribute(m_aStates.top().getTableRowSprms(),
475 NS_ooxml::LN_CT_TrPrBase_trHeight, NS_ooxml::LN_CT_Height_hRule,
476 pHRule);
477 return true;
479 break;
480 case RTFKeyword::TRLEFT:
481 case RTFKeyword::TBLIND:
483 // the value is in twips
484 auto const aDestination = m_aStates.top().getDestination();
485 int& rCurrentTRLeft((Destination::NESTEDTABLEPROPERTIES == aDestination)
486 ? m_nNestedTRLeft
487 : m_nTopLevelTRLeft);
488 int& rCurrentCellX((Destination::NESTEDTABLEPROPERTIES == aDestination)
489 ? m_nNestedCurrentCellX
490 : m_nTopLevelCurrentCellX);
491 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblInd,
492 NS_ooxml::LN_CT_TblWidth_type,
493 new RTFValue(NS_ooxml::LN_Value_ST_TblWidth_dxa));
495 if (nKeyword == RTFKeyword::TBLIND)
497 RTFValue::Pointer_t pCellMargin
498 = m_aStates.top().getTableRowSprms().find(NS_ooxml::LN_CT_TblPrBase_tblCellMar);
499 if (pCellMargin)
501 RTFValue::Pointer_t pMarginLeft
502 = pCellMargin->getSprms().find(NS_ooxml::LN_CT_TcMar_left);
503 if (pMarginLeft)
504 nParam -= pMarginLeft->getAttributes()
505 .find(NS_ooxml::LN_CT_TblWidth_w)
506 ->getInt();
508 rCurrentTRLeft = nParam;
510 else
511 rCurrentTRLeft = rCurrentCellX = nParam;
513 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblInd,
514 +NS_ooxml::LN_CT_TblWidth_w, new RTFValue(nParam));
515 return true;
517 break;
518 case RTFKeyword::CLSHDNG:
520 int nValue = -1;
522 if (nParam < 1)
523 nValue = NS_ooxml::LN_Value_ST_Shd_clear;
524 else if (nParam < 750)
525 // Values in between 1 and 250 visually closer to 0% shading (white)
526 // But this will mean "no shading" while cell actually have some.
527 // So lets use minimal available value.
528 nValue = NS_ooxml::LN_Value_ST_Shd_pct5;
529 else if (nParam < 1100)
530 nValue = NS_ooxml::LN_Value_ST_Shd_pct10;
531 else if (nParam < 1350)
532 nValue = NS_ooxml::LN_Value_ST_Shd_pct12;
533 else if (nParam < 1750)
534 nValue = NS_ooxml::LN_Value_ST_Shd_pct15;
535 else if (nParam < 2250)
536 nValue = NS_ooxml::LN_Value_ST_Shd_pct20;
537 else if (nParam < 2750)
538 nValue = NS_ooxml::LN_Value_ST_Shd_pct25;
539 else if (nParam < 3250)
540 nValue = NS_ooxml::LN_Value_ST_Shd_pct30;
541 else if (nParam < 3600)
542 nValue = NS_ooxml::LN_Value_ST_Shd_pct35;
543 else if (nParam < 3850)
544 nValue = NS_ooxml::LN_Value_ST_Shd_pct37;
545 else if (nParam < 4250)
546 nValue = NS_ooxml::LN_Value_ST_Shd_pct40;
547 else if (nParam < 4750)
548 nValue = NS_ooxml::LN_Value_ST_Shd_pct45;
549 else if (nParam < 5250)
550 nValue = NS_ooxml::LN_Value_ST_Shd_pct50;
551 else if (nParam < 5750)
552 nValue = NS_ooxml::LN_Value_ST_Shd_pct55;
553 else if (nParam < 6100)
554 nValue = NS_ooxml::LN_Value_ST_Shd_pct60;
555 else if (nParam < 6350)
556 nValue = NS_ooxml::LN_Value_ST_Shd_pct62;
557 else if (nParam < 6750)
558 nValue = NS_ooxml::LN_Value_ST_Shd_pct65;
559 else if (nParam < 7250)
560 nValue = NS_ooxml::LN_Value_ST_Shd_pct70;
561 else if (nParam < 7750)
562 nValue = NS_ooxml::LN_Value_ST_Shd_pct75;
563 else if (nParam < 8250)
564 nValue = NS_ooxml::LN_Value_ST_Shd_pct80;
565 else if (nParam < 8600)
566 nValue = NS_ooxml::LN_Value_ST_Shd_pct85;
567 else if (nParam < 8850)
568 nValue = NS_ooxml::LN_Value_ST_Shd_pct87;
569 else if (nParam < 9250)
570 nValue = NS_ooxml::LN_Value_ST_Shd_pct90;
571 else if (nParam < 9750)
572 nValue = NS_ooxml::LN_Value_ST_Shd_pct95;
573 else
574 // Solid fill
575 nValue = NS_ooxml::LN_Value_ST_Shd_solid;
577 putNestedAttribute(m_aStates.top().getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_shd,
578 NS_ooxml::LN_CT_Shd_val, new RTFValue(nValue));
579 return true;
581 break;
582 case RTFKeyword::CLPADB:
583 case RTFKeyword::CLPADL:
584 case RTFKeyword::CLPADR:
585 case RTFKeyword::CLPADT:
587 RTFSprms aAttributes;
588 aAttributes.set(NS_ooxml::LN_CT_TblWidth_type,
589 new RTFValue(NS_ooxml::LN_Value_ST_TblWidth_dxa));
590 aAttributes.set(NS_ooxml::LN_CT_TblWidth_w, new RTFValue(nParam));
591 // Top and left is swapped, that's what Word does.
592 switch (nKeyword)
594 case RTFKeyword::CLPADB:
595 nSprm = NS_ooxml::LN_CT_TcMar_bottom;
596 break;
597 case RTFKeyword::CLPADL:
598 nSprm = NS_ooxml::LN_CT_TcMar_top;
599 break;
600 case RTFKeyword::CLPADR:
601 nSprm = NS_ooxml::LN_CT_TcMar_right;
602 break;
603 case RTFKeyword::CLPADT:
604 nSprm = NS_ooxml::LN_CT_TcMar_left;
605 break;
606 default:
607 break;
609 putNestedSprm(m_aStates.top().getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_tcMar,
610 nSprm, new RTFValue(aAttributes));
611 return true;
613 break;
614 case RTFKeyword::TRPADDFB:
615 case RTFKeyword::TRPADDFL:
616 case RTFKeyword::TRPADDFR:
617 case RTFKeyword::TRPADDFT:
619 RTFSprms aAttributes;
620 switch (nParam)
622 case 3:
623 aAttributes.set(NS_ooxml::LN_CT_TblWidth_type,
624 new RTFValue(NS_ooxml::LN_Value_ST_TblWidth_dxa));
625 break;
627 switch (nKeyword)
629 case RTFKeyword::TRPADDFB:
630 nSprm = NS_ooxml::LN_CT_TcMar_bottom;
631 break;
632 case RTFKeyword::TRPADDFL:
633 nSprm = NS_ooxml::LN_CT_TcMar_left;
634 break;
635 case RTFKeyword::TRPADDFR:
636 nSprm = NS_ooxml::LN_CT_TcMar_right;
637 break;
638 case RTFKeyword::TRPADDFT:
639 nSprm = NS_ooxml::LN_CT_TcMar_top;
640 break;
641 default:
642 break;
644 putNestedAttribute(m_aStates.top().getTableRowSprms(),
645 NS_ooxml::LN_CT_TblPrBase_tblCellMar, nSprm,
646 new RTFValue(aAttributes));
647 // tdf#74795 also set on current cell, and as default for table cells
648 // (why isn't this done by domainmapper?)
649 putNestedAttribute(m_aStates.top().getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_tcMar,
650 nSprm, new RTFValue(aAttributes));
651 putNestedAttribute(m_aDefaultState.getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_tcMar,
652 nSprm, new RTFValue(aAttributes));
653 return true;
655 break;
656 case RTFKeyword::TRPADDB:
657 case RTFKeyword::TRPADDL:
658 case RTFKeyword::TRPADDR:
659 case RTFKeyword::TRPADDT:
661 RTFSprms aAttributes;
662 aAttributes.set(NS_ooxml::LN_CT_TblWidth_w, new RTFValue(nParam));
663 switch (nKeyword)
665 case RTFKeyword::TRPADDB:
666 nSprm = NS_ooxml::LN_CT_TcMar_bottom;
667 break;
668 case RTFKeyword::TRPADDL:
669 nSprm = NS_ooxml::LN_CT_TcMar_left;
670 break;
671 case RTFKeyword::TRPADDR:
672 nSprm = NS_ooxml::LN_CT_TcMar_right;
673 break;
674 case RTFKeyword::TRPADDT:
675 nSprm = NS_ooxml::LN_CT_TcMar_top;
676 break;
677 default:
678 break;
680 putNestedSprm(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblCellMar,
681 nSprm, new RTFValue(aAttributes));
682 // tdf#74795 also set on current cell, and as default for table cells
683 // (why isn't this done by domainmapper?)
684 putNestedSprm(m_aStates.top().getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_tcMar,
685 nSprm, new RTFValue(aAttributes));
686 putNestedSprm(m_aDefaultState.getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_tcMar,
687 nSprm, new RTFValue(aAttributes));
688 return true;
690 case RTFKeyword::TRGAPH:
691 // Half of the space between the cells of a table row: default left/right table cell margin.
692 if (nParam > 0)
694 RTFSprms aAttributes;
695 aAttributes.set(NS_ooxml::LN_CT_TblWidth_type,
696 new RTFValue(NS_ooxml::LN_Value_ST_TblWidth_dxa));
697 aAttributes.set(NS_ooxml::LN_CT_TblWidth_w, pIntValue);
698 // FIXME: this is wrong, it is half-gap, needs to be distinguished from margin! depending on TRPADDFL/TRPADDFR
699 putNestedSprm(m_aStates.top().getTableRowSprms(),
700 NS_ooxml::LN_CT_TblPrBase_tblCellMar, NS_ooxml::LN_CT_TblCellMar_left,
701 new RTFValue(aAttributes));
702 putNestedSprm(m_aStates.top().getTableRowSprms(),
703 NS_ooxml::LN_CT_TblPrBase_tblCellMar,
704 NS_ooxml::LN_CT_TblCellMar_right, new RTFValue(aAttributes));
706 return true;
707 case RTFKeyword::TRFTSWIDTH:
708 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblW,
709 NS_ooxml::LN_CT_TblWidth_type, pIntValue);
710 return true;
711 case RTFKeyword::TRWWIDTH:
712 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblW,
713 NS_ooxml::LN_CT_TblWidth_w, pIntValue);
714 return true;
715 default:
716 break;
719 return false;
722 RTFError RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
724 setNeedSect(true);
725 checkUnicode(/*bUnicode =*/nKeyword != RTFKeyword::U, /*bHex =*/true);
726 RTFSkipDestination aSkip(*this);
727 int nSprm = 0;
728 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
729 // Trivial table sprms.
730 if (dispatchTableSprmValue(nKeyword, nParam))
732 return RTFError::OK;
735 // Trivial character sprms.
736 if (dispatchCharacterSprmValue(nKeyword, nParam))
738 return RTFError::OK;
741 // Trivial character attributes.
742 if (dispatchCharacterAttributeValue(nKeyword, nParam))
744 return RTFError::OK;
747 // Trivial paragraph sprms.
748 if (dispatchParagraphSprmValue(nKeyword, nParam))
750 return RTFError::OK;
753 // Info group.
754 if (dispatchInfoValue(nKeyword, nParam))
756 return RTFError::OK;
759 // Frame size / position.
760 if (dispatchFrameValue(nKeyword, nParam))
762 return RTFError::OK;
765 // Table-related values.
766 if (dispatchTableValue(nKeyword, nParam))
768 return RTFError::OK;
771 // Then check for the more complex ones.
772 switch (nKeyword)
774 case RTFKeyword::F:
775 case RTFKeyword::AF:
776 switch (m_aStates.top().getRunType())
778 case RTFParserState::RunType::RTLCH_LTRCH_1:
779 case RTFParserState::RunType::LTRCH_RTLCH_2:
780 nSprm = NS_ooxml::LN_CT_Fonts_cs;
781 break;
782 case RTFParserState::RunType::DBCH:
783 nSprm = NS_ooxml::LN_CT_Fonts_eastAsia;
784 break;
785 case RTFParserState::RunType::NONE:
786 case RTFParserState::RunType::LOCH:
787 case RTFParserState::RunType::HICH:
788 case RTFParserState::RunType::LTRCH_RTLCH_1:
789 case RTFParserState::RunType::RTLCH_LTRCH_2:
790 default:
791 nSprm = NS_ooxml::LN_CT_Fonts_ascii;
792 break;
795 if (m_aStates.top().getDestination() == Destination::FONTTABLE
796 || m_aStates.top().getDestination() == Destination::FONTENTRY)
798 // Some text in buffer? It is font name. So previous font definition is complete
799 if (m_aStates.top().getCurrentDestinationText()->getLength())
800 handleFontTableEntry();
802 m_aFontIndexes.push_back(nParam);
803 m_nCurrentFontIndex = getFontIndex(nParam);
805 else if (m_aStates.top().getDestination() == Destination::LISTLEVEL)
807 RTFSprms aFontAttributes;
808 aFontAttributes.set(nSprm, new RTFValue(m_aFontNames[getFontIndex(nParam)]));
809 RTFSprms aRunPropsSprms;
810 aRunPropsSprms.set(NS_ooxml::LN_EG_RPrBase_rFonts, new RTFValue(aFontAttributes));
811 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Lvl_rPr,
812 new RTFValue(RTFSprms(), aRunPropsSprms),
813 RTFOverwrite::NO_APPEND);
815 else
817 m_nCurrentFontIndex = getFontIndex(nParam);
818 auto pValue = new RTFValue(getFontName(m_nCurrentFontIndex));
819 putNestedAttribute(m_aStates.top().getCharacterSprms(),
820 NS_ooxml::LN_EG_RPrBase_rFonts, nSprm, pValue);
821 if (nKeyword == RTFKeyword::F)
822 m_aStates.top().setCurrentEncoding(getEncoding(m_nCurrentFontIndex));
824 break;
825 case RTFKeyword::RED:
826 m_aStates.top().getCurrentColor().SetRed(nParam);
827 break;
828 case RTFKeyword::GREEN:
829 m_aStates.top().getCurrentColor().SetGreen(nParam);
830 break;
831 case RTFKeyword::BLUE:
832 m_aStates.top().getCurrentColor().SetBlue(nParam);
833 break;
834 case RTFKeyword::FCHARSET:
836 // we always send text to the domain mapper in OUString, so no
837 // need to send encoding info
838 int i;
839 for (i = 0; i < nRTFEncodings; i++)
841 if (aRTFEncodings[i].charset == nParam)
842 break;
844 if (i == nRTFEncodings)
845 // not found
846 return RTFError::OK;
848 m_nCurrentEncoding
849 = aRTFEncodings[i].codepage == 0 // Default (CP_ACP)
850 ? osl_getThreadTextEncoding()
851 : rtl_getTextEncodingFromWindowsCodePage(aRTFEncodings[i].codepage);
852 m_aStates.top().setCurrentEncoding(m_nCurrentEncoding);
854 break;
855 case RTFKeyword::ANSICPG:
856 case RTFKeyword::CPG:
858 rtl_TextEncoding nEncoding
859 = (nParam == 0)
860 ? utl_getWinTextEncodingFromLangStr(utl_getLocaleForGlobalDefaultEncoding())
861 : rtl_getTextEncodingFromWindowsCodePage(nParam);
862 if (nKeyword == RTFKeyword::ANSICPG)
863 m_aDefaultState.setCurrentEncoding(nEncoding);
864 else
865 m_nCurrentEncoding = nEncoding;
866 m_aStates.top().setCurrentEncoding(nEncoding);
868 break;
869 case RTFKeyword::CF:
871 RTFSprms aAttributes;
872 auto pValue = new RTFValue(sal_uInt32(getColorTable(nParam)));
873 aAttributes.set(NS_ooxml::LN_CT_Color_val, pValue);
874 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_color,
875 new RTFValue(aAttributes));
877 break;
878 case RTFKeyword::S:
880 m_aStates.top().setCurrentStyleIndex(nParam);
882 if (m_aStates.top().getDestination() == Destination::STYLESHEET
883 || m_aStates.top().getDestination() == Destination::STYLEENTRY)
885 m_nCurrentStyleIndex = nParam;
886 auto pValue = new RTFValue(NS_ooxml::LN_Value_ST_StyleType_paragraph);
887 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_Style_type,
888 pValue); // paragraph style
890 else
892 OUString aName = getStyleName(nParam);
893 if (!aName.isEmpty())
895 if (m_aStates.top().getDestination() == Destination::LISTLEVEL)
896 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Lvl_pStyle,
897 new RTFValue(aName));
898 else
899 m_aStates.top().getParagraphSprms().set(NS_ooxml::LN_CT_PPrBase_pStyle,
900 new RTFValue(aName));
904 break;
905 case RTFKeyword::CS:
906 m_aStates.top().setCurrentCharacterStyleIndex(nParam);
907 if (m_aStates.top().getDestination() == Destination::STYLESHEET
908 || m_aStates.top().getDestination() == Destination::STYLEENTRY)
910 m_nCurrentStyleIndex = nParam;
911 auto pValue = new RTFValue(NS_ooxml::LN_Value_ST_StyleType_character);
912 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_Style_type,
913 pValue); // character style
915 else
917 OUString aName = getStyleName(nParam);
918 if (!aName.isEmpty())
919 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_rStyle,
920 new RTFValue(aName));
922 break;
923 case RTFKeyword::DS:
924 if (m_aStates.top().getDestination() == Destination::STYLESHEET
925 || m_aStates.top().getDestination() == Destination::STYLEENTRY)
927 m_nCurrentStyleIndex = nParam;
928 auto pValue = new RTFValue(0); // TODO no value in enum StyleType?
929 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_Style_type,
930 pValue); // section style
932 break;
933 case RTFKeyword::TS:
934 if (m_aStates.top().getDestination() == Destination::STYLESHEET
935 || m_aStates.top().getDestination() == Destination::STYLEENTRY)
937 m_nCurrentStyleIndex = nParam;
938 // 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
939 auto pValue = new RTFValue(0);
940 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_Style_type,
941 pValue); // table style
943 break;
944 case RTFKeyword::DEFF:
945 m_nDefaultFontIndex = nParam;
946 break;
947 case RTFKeyword::STSHFDBCH:
948 // tdf#123703 switch off longer space sequence except in the case of the fixed compatibility setting font id 31505
949 if (nParam != 31505)
950 m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_longerSpaceSequence,
951 new RTFValue(0));
952 break;
953 case RTFKeyword::DEFLANG:
954 case RTFKeyword::ADEFLANG:
956 LanguageTag aTag((LanguageType(static_cast<sal_uInt16>(nParam))));
957 auto pValue = new RTFValue(aTag.getBcp47());
958 putNestedAttribute(m_aStates.top().getCharacterSprms(),
959 (nKeyword == RTFKeyword::DEFLANG ? NS_ooxml::LN_EG_RPrBase_lang
960 : NS_ooxml::LN_CT_Language_bidi),
961 nSprm, pValue);
963 break;
964 case RTFKeyword::CHCBPAT:
966 auto pValue = new RTFValue(sal_uInt32(nParam ? getColorTable(nParam) : COL_AUTO));
967 putNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_EG_RPrBase_shd,
968 NS_ooxml::LN_CT_Shd_fill, pValue);
970 break;
971 case RTFKeyword::CLCBPAT:
972 case RTFKeyword::CLCBPATRAW:
974 auto pValue = new RTFValue(sal_uInt32(getColorTable(nParam)));
975 putNestedAttribute(m_aStates.top().getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_shd,
976 NS_ooxml::LN_CT_Shd_fill, pValue);
978 break;
979 case RTFKeyword::CBPAT:
980 if (nParam)
982 auto pValue = new RTFValue(sal_uInt32(getColorTable(nParam)));
983 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PrBase_shd,
984 NS_ooxml::LN_CT_Shd_fill, pValue);
986 break;
987 case RTFKeyword::ULC:
989 auto pValue = new RTFValue(sal_uInt32(getColorTable(nParam)));
990 m_aStates.top().getCharacterSprms().set(0x6877, pValue);
992 break;
993 case RTFKeyword::HIGHLIGHT:
995 auto pValue = new RTFValue(sal_uInt32(nParam ? getColorTable(nParam) : COL_AUTO));
996 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_highlight, pValue);
998 break;
999 case RTFKeyword::UP:
1000 case RTFKeyword::DN:
1002 auto pValue = new RTFValue(nParam * (nKeyword == RTFKeyword::UP ? 1 : -1));
1003 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_position, pValue);
1005 break;
1006 case RTFKeyword::HORZVERT:
1008 auto pValue = new RTFValue(int(true));
1009 m_aStates.top().getCharacterAttributes().set(NS_ooxml::LN_CT_EastAsianLayout_vert,
1010 pValue);
1011 if (nParam)
1012 // rotate fits to a single line
1013 m_aStates.top().getCharacterAttributes().set(
1014 NS_ooxml::LN_CT_EastAsianLayout_vertCompress, pValue);
1016 break;
1017 case RTFKeyword::EXPND:
1019 // Convert quarter-points to twentieths of a point
1020 auto pValue = new RTFValue(nParam * 5);
1021 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_spacing, pValue);
1023 break;
1024 case RTFKeyword::TWOINONE:
1026 auto pValue = new RTFValue(int(true));
1027 m_aStates.top().getCharacterAttributes().set(NS_ooxml::LN_CT_EastAsianLayout_combine,
1028 pValue);
1029 Id nId = 0;
1030 switch (nParam)
1032 case 0:
1033 nId = NS_ooxml::LN_Value_ST_CombineBrackets_none;
1034 break;
1035 case 1:
1036 nId = NS_ooxml::LN_Value_ST_CombineBrackets_round;
1037 break;
1038 case 2:
1039 nId = NS_ooxml::LN_Value_ST_CombineBrackets_square;
1040 break;
1041 case 3:
1042 nId = NS_ooxml::LN_Value_ST_CombineBrackets_angle;
1043 break;
1044 case 4:
1045 nId = NS_ooxml::LN_Value_ST_CombineBrackets_curly;
1046 break;
1048 if (nId > 0)
1049 m_aStates.top().getCharacterAttributes().set(
1050 NS_ooxml::LN_CT_EastAsianLayout_combineBrackets, new RTFValue(nId));
1052 break;
1053 case RTFKeyword::SL:
1055 // This is similar to RTFKeyword::ABSH, negative value means 'exact', positive means 'at least'.
1056 tools::SvRef<RTFValue> pValue(
1057 new RTFValue(NS_ooxml::LN_Value_doc_ST_LineSpacingRule_atLeast));
1058 if (nParam < 0)
1060 pValue = new RTFValue(NS_ooxml::LN_Value_doc_ST_LineSpacingRule_exact);
1061 pIntValue = new RTFValue(-nParam);
1063 m_aStates.top().getParagraphAttributes().set(NS_ooxml::LN_CT_Spacing_lineRule, pValue);
1064 m_aStates.top().getParagraphAttributes().set(NS_ooxml::LN_CT_Spacing_line, pIntValue);
1066 break;
1067 case RTFKeyword::SLMULT:
1068 if (nParam > 0)
1070 auto pValue = new RTFValue(NS_ooxml::LN_Value_doc_ST_LineSpacingRule_auto);
1071 m_aStates.top().getParagraphAttributes().set(NS_ooxml::LN_CT_Spacing_lineRule,
1072 pValue);
1074 break;
1075 case RTFKeyword::BRDRW:
1077 // dmapper expects it in 1/8 pt, we have it in twip - but avoid rounding 1 to 0
1078 if (nParam > 1)
1079 nParam = nParam * 2 / 5;
1080 auto pValue = new RTFValue(nParam);
1081 putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_sz, pValue);
1083 break;
1084 case RTFKeyword::BRDRCF:
1086 auto pValue = new RTFValue(sal_uInt32(getColorTable(nParam)));
1087 putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_color, pValue);
1089 break;
1090 case RTFKeyword::BRSP:
1092 // dmapper expects it in points, we have it in twip
1093 auto pValue = new RTFValue(nParam / 20);
1094 putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_space, pValue);
1096 break;
1097 case RTFKeyword::TX:
1099 m_aStates.top().getTabAttributes().set(NS_ooxml::LN_CT_TabStop_pos, pIntValue);
1100 auto pValue = new RTFValue(m_aStates.top().getTabAttributes());
1101 if (m_aStates.top().getDestination() == Destination::LISTLEVEL)
1102 putNestedSprm(m_aStates.top().getTableSprms(), NS_ooxml::LN_CT_PPrBase_tabs,
1103 NS_ooxml::LN_CT_Tabs_tab, pValue);
1104 else
1105 putNestedSprm(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_tabs,
1106 NS_ooxml::LN_CT_Tabs_tab, pValue);
1107 m_aStates.top().getTabAttributes().clear();
1109 break;
1110 case RTFKeyword::ILVL:
1111 putNestedSprm(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_numPr,
1112 NS_ooxml::LN_CT_NumPr_ilvl, pIntValue);
1113 break;
1114 case RTFKeyword::LISTTEMPLATEID:
1115 // This one is not referenced anywhere, so it's pointless to store it at the moment.
1116 break;
1117 case RTFKeyword::LISTID:
1119 if (m_aStates.top().getDestination() == Destination::LISTENTRY)
1120 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_AbstractNum_abstractNumId,
1121 pIntValue);
1122 else if (m_aStates.top().getDestination() == Destination::LISTOVERRIDEENTRY)
1123 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Num_abstractNumId, pIntValue);
1124 m_aStates.top().setCurrentListIndex(nParam);
1126 break;
1127 case RTFKeyword::LS:
1129 if (m_aStates.top().getDestination() == Destination::LISTOVERRIDEENTRY)
1131 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_AbstractNum_nsid,
1132 pIntValue);
1133 m_aStates.top().setCurrentListOverrideIndex(nParam);
1135 else
1137 // Insert at the start, so properties inherited from the list
1138 // can be overridden by direct formatting. But still allow the
1139 // case when old-style paragraph numbering is already
1140 // tokenized.
1141 putNestedSprm(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_numPr,
1142 NS_ooxml::LN_CT_NumPr_numId, pIntValue, RTFOverwrite::YES_PREPEND);
1145 break;
1146 case RTFKeyword::UC:
1147 if ((SAL_MIN_INT16 <= nParam) && (nParam <= SAL_MAX_INT16))
1148 m_aStates.top().setUc(nParam);
1149 break;
1150 case RTFKeyword::U:
1151 // sal_Unicode is unsigned 16-bit, RTF may represent that as a
1152 // signed SAL_MIN_INT16..SAL_MAX_INT16 or 0..SAL_MAX_UINT16. The
1153 // static_cast() will do the right thing.
1154 if ((SAL_MIN_INT16 <= nParam) && (nParam <= SAL_MAX_UINT16))
1156 if (m_aStates.top().getDestination() == Destination::LEVELNUMBERS)
1158 if (nParam != ';')
1159 m_aStates.top().getLevelNumbers().push_back(sal_Int32(nParam));
1160 else
1161 // ';' in \u form is not considered valid.
1162 m_aStates.top().setLevelNumbersValid(false);
1164 else
1165 m_aUnicodeBuffer.append(static_cast<sal_Unicode>(nParam));
1166 m_aStates.top().getCharsToSkip() = m_aStates.top().getUc();
1168 break;
1169 case RTFKeyword::LEVELFOLLOW:
1171 OUString sValue;
1172 switch (nParam)
1174 case 0:
1175 sValue = "tab";
1176 break;
1177 case 1:
1178 sValue = "space";
1179 break;
1180 case 2:
1181 sValue = "nothing";
1182 break;
1184 if (!sValue.isEmpty())
1185 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Lvl_suff, new RTFValue(sValue));
1187 break;
1188 case RTFKeyword::FPRQ:
1190 sal_Int32 nValue = 0;
1191 switch (nParam)
1193 case 0:
1194 nValue = NS_ooxml::LN_Value_ST_Pitch_default;
1195 break;
1196 case 1:
1197 nValue = NS_ooxml::LN_Value_ST_Pitch_fixed;
1198 break;
1199 case 2:
1200 nValue = NS_ooxml::LN_Value_ST_Pitch_variable;
1201 break;
1203 if (nValue)
1205 RTFSprms aAttributes;
1206 aAttributes.set(NS_ooxml::LN_CT_Pitch_val, new RTFValue(nValue));
1207 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Font_pitch,
1208 new RTFValue(aAttributes));
1211 break;
1212 case RTFKeyword::LISTOVERRIDECOUNT:
1213 // Ignore this for now, the exporter always emits it with a zero parameter.
1214 break;
1215 case RTFKeyword::PICSCALEX:
1216 m_aStates.top().getPicture().nScaleX = nParam;
1217 break;
1218 case RTFKeyword::PICSCALEY:
1219 m_aStates.top().getPicture().nScaleY = nParam;
1220 break;
1221 case RTFKeyword::PICW:
1222 m_aStates.top().getPicture().nWidth = nParam;
1223 break;
1224 case RTFKeyword::PICH:
1225 m_aStates.top().getPicture().nHeight = nParam;
1226 break;
1227 case RTFKeyword::PICWGOAL:
1228 m_aStates.top().getPicture().nGoalWidth = convertTwipToMm100(nParam);
1229 break;
1230 case RTFKeyword::PICHGOAL:
1231 m_aStates.top().getPicture().nGoalHeight = convertTwipToMm100(nParam);
1232 break;
1233 case RTFKeyword::PICCROPL:
1234 m_aStates.top().getPicture().nCropL = convertTwipToMm100(nParam);
1235 break;
1236 case RTFKeyword::PICCROPR:
1237 m_aStates.top().getPicture().nCropR = convertTwipToMm100(nParam);
1238 break;
1239 case RTFKeyword::PICCROPT:
1240 m_aStates.top().getPicture().nCropT = convertTwipToMm100(nParam);
1241 break;
1242 case RTFKeyword::PICCROPB:
1243 m_aStates.top().getPicture().nCropB = convertTwipToMm100(nParam);
1244 break;
1245 case RTFKeyword::SHPWRK:
1247 int nValue = 0;
1248 switch (nParam)
1250 case 0:
1251 nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_bothSides;
1252 break;
1253 case 1:
1254 nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_left;
1255 break;
1256 case 2:
1257 nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_right;
1258 break;
1259 case 3:
1260 nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_largest;
1261 break;
1262 default:
1263 break;
1265 auto pValue = new RTFValue(nValue);
1266 RTFValue::Pointer_t pTight
1267 = m_aStates.top().getCharacterSprms().find(NS_ooxml::LN_EG_WrapType_wrapTight);
1268 if (pTight)
1269 pTight->getAttributes().set(NS_ooxml::LN_CT_WrapTight_wrapText, pValue);
1270 else
1271 m_aStates.top().getCharacterAttributes().set(NS_ooxml::LN_CT_WrapSquare_wrapText,
1272 pValue);
1274 break;
1275 case RTFKeyword::SHPWR:
1277 switch (nParam)
1279 case 1:
1280 m_aStates.top().getShape().setWrap(text::WrapTextMode_NONE);
1281 break;
1282 case 2:
1283 m_aStates.top().getShape().setWrap(text::WrapTextMode_PARALLEL);
1284 break;
1285 case 3:
1286 m_aStates.top().getShape().setWrap(text::WrapTextMode_THROUGH);
1287 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_WrapType_wrapNone,
1288 new RTFValue());
1289 break;
1290 case 4:
1291 m_aStates.top().getShape().setWrap(text::WrapTextMode_PARALLEL);
1292 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_WrapType_wrapTight,
1293 new RTFValue());
1294 break;
1295 case 5:
1296 m_aStates.top().getShape().setWrap(text::WrapTextMode_THROUGH);
1297 break;
1300 break;
1301 case RTFKeyword::COLS:
1302 putNestedAttribute(m_aStates.top().getSectionSprms(),
1303 NS_ooxml::LN_EG_SectPrContents_cols, NS_ooxml::LN_CT_Columns_num,
1304 pIntValue);
1305 break;
1306 case RTFKeyword::COLSX:
1307 putNestedAttribute(m_aStates.top().getSectionSprms(),
1308 NS_ooxml::LN_EG_SectPrContents_cols, NS_ooxml::LN_CT_Columns_space,
1309 pIntValue);
1310 break;
1311 case RTFKeyword::COLNO:
1312 putNestedSprm(m_aStates.top().getSectionSprms(), NS_ooxml::LN_EG_SectPrContents_cols,
1313 NS_ooxml::LN_CT_Columns_col, pIntValue);
1314 break;
1315 case RTFKeyword::COLW:
1316 case RTFKeyword::COLSR:
1318 RTFSprms& rAttributes = getLastAttributes(m_aStates.top().getSectionSprms(),
1319 NS_ooxml::LN_EG_SectPrContents_cols);
1320 rAttributes.set((nKeyword == RTFKeyword::COLW ? NS_ooxml::LN_CT_Column_w
1321 : NS_ooxml::LN_CT_Column_space),
1322 pIntValue);
1324 break;
1325 case RTFKeyword::PAPERH:
1326 putNestedAttribute(m_aDefaultState.getSectionSprms(),
1327 NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_h,
1328 pIntValue);
1329 [[fallthrough]]; // set the default + current value
1330 case RTFKeyword::PGHSXN:
1331 putNestedAttribute(m_aStates.top().getSectionSprms(),
1332 NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_h,
1333 pIntValue);
1334 break;
1335 case RTFKeyword::PAPERW:
1336 putNestedAttribute(m_aDefaultState.getSectionSprms(),
1337 NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_w,
1338 pIntValue);
1339 [[fallthrough]]; // set the default + current value
1340 case RTFKeyword::PGWSXN:
1341 putNestedAttribute(m_aStates.top().getSectionSprms(),
1342 NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_w,
1343 pIntValue);
1344 break;
1345 case RTFKeyword::MARGL:
1346 putNestedAttribute(m_aDefaultState.getSectionSprms(),
1347 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_left,
1348 pIntValue);
1349 [[fallthrough]]; // set the default + current value
1350 case RTFKeyword::MARGLSXN:
1351 putNestedAttribute(m_aStates.top().getSectionSprms(),
1352 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_left,
1353 pIntValue);
1354 break;
1355 case RTFKeyword::MARGR:
1356 putNestedAttribute(m_aDefaultState.getSectionSprms(),
1357 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_right,
1358 pIntValue);
1359 [[fallthrough]]; // set the default + current value
1360 case RTFKeyword::MARGRSXN:
1361 putNestedAttribute(m_aStates.top().getSectionSprms(),
1362 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_right,
1363 pIntValue);
1364 break;
1365 case RTFKeyword::MARGT:
1366 putNestedAttribute(m_aDefaultState.getSectionSprms(),
1367 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_top,
1368 pIntValue);
1369 [[fallthrough]]; // set the default + current value
1370 case RTFKeyword::MARGTSXN:
1371 putNestedAttribute(m_aStates.top().getSectionSprms(),
1372 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_top,
1373 pIntValue);
1374 break;
1375 case RTFKeyword::MARGB:
1376 putNestedAttribute(m_aDefaultState.getSectionSprms(),
1377 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_bottom,
1378 pIntValue);
1379 [[fallthrough]]; // set the default + current value
1380 case RTFKeyword::MARGBSXN:
1381 putNestedAttribute(m_aStates.top().getSectionSprms(),
1382 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_bottom,
1383 pIntValue);
1384 break;
1385 case RTFKeyword::HEADERY:
1386 putNestedAttribute(m_aStates.top().getSectionSprms(),
1387 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_header,
1388 pIntValue);
1389 break;
1390 case RTFKeyword::FOOTERY:
1391 putNestedAttribute(m_aStates.top().getSectionSprms(),
1392 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_footer,
1393 pIntValue);
1394 break;
1395 case RTFKeyword::GUTTER:
1396 putNestedAttribute(m_aStates.top().getSectionSprms(),
1397 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_gutter,
1398 pIntValue);
1399 break;
1400 case RTFKeyword::DEFTAB:
1401 m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_defaultTabStop, pIntValue);
1402 break;
1403 case RTFKeyword::LINEMOD:
1404 putNestedAttribute(m_aStates.top().getSectionSprms(),
1405 NS_ooxml::LN_EG_SectPrContents_lnNumType,
1406 NS_ooxml::LN_CT_LineNumber_countBy, pIntValue);
1407 break;
1408 case RTFKeyword::LINEX:
1409 if (nParam)
1410 putNestedAttribute(m_aStates.top().getSectionSprms(),
1411 NS_ooxml::LN_EG_SectPrContents_lnNumType,
1412 NS_ooxml::LN_CT_LineNumber_distance, pIntValue);
1413 break;
1414 case RTFKeyword::LINESTARTS:
1416 // OOXML <w:lnNumType w:start="..."/> is 0-based, RTF is 1-based.
1417 auto pStart = tools::make_ref<RTFValue>(nParam - 1);
1418 putNestedAttribute(m_aStates.top().getSectionSprms(),
1419 NS_ooxml::LN_EG_SectPrContents_lnNumType,
1420 NS_ooxml::LN_CT_LineNumber_start, pStart);
1422 break;
1423 case RTFKeyword::REVAUTH:
1424 case RTFKeyword::REVAUTHDEL:
1426 auto pValue = new RTFValue(m_aAuthors[nParam]);
1427 putNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_trackchange,
1428 NS_ooxml::LN_CT_TrackChange_author, pValue);
1430 break;
1431 case RTFKeyword::REVDTTM:
1432 case RTFKeyword::REVDTTMDEL:
1434 OUString aStr(
1435 OStringToOUString(DTTM22OString(nParam), m_aStates.top().getCurrentEncoding()));
1436 auto pValue = new RTFValue(aStr);
1437 putNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_trackchange,
1438 NS_ooxml::LN_CT_TrackChange_date, pValue);
1440 break;
1441 case RTFKeyword::SHPLEFT:
1442 m_aStates.top().getShape().setLeft(convertTwipToMm100(nParam));
1443 break;
1444 case RTFKeyword::SHPTOP:
1445 m_aStates.top().getShape().setTop(convertTwipToMm100(nParam));
1446 break;
1447 case RTFKeyword::SHPRIGHT:
1448 m_aStates.top().getShape().setRight(convertTwipToMm100(nParam));
1449 break;
1450 case RTFKeyword::SHPBOTTOM:
1451 m_aStates.top().getShape().setBottom(convertTwipToMm100(nParam));
1452 break;
1453 case RTFKeyword::SHPZ:
1454 m_aStates.top().getShape().setZ(nParam);
1455 break;
1456 case RTFKeyword::FFTYPE:
1457 switch (nParam)
1459 case 0:
1460 m_nFormFieldType = RTFFormFieldType::TEXT;
1461 break;
1462 case 1:
1463 m_nFormFieldType = RTFFormFieldType::CHECKBOX;
1464 break;
1465 case 2:
1466 m_nFormFieldType = RTFFormFieldType::LIST;
1467 break;
1468 default:
1469 m_nFormFieldType = RTFFormFieldType::NONE;
1470 break;
1472 break;
1473 case RTFKeyword::FFDEFRES:
1474 if (m_nFormFieldType == RTFFormFieldType::CHECKBOX)
1475 m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFCheckBox_default, pIntValue);
1476 else if (m_nFormFieldType == RTFFormFieldType::LIST)
1477 m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_default, pIntValue);
1478 break;
1479 case RTFKeyword::FFRES:
1480 // 25 means undefined, see [MS-DOC] 2.9.79, FFDataBits.
1481 if (m_nFormFieldType == RTFFormFieldType::CHECKBOX && nParam != 25)
1482 m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFCheckBox_checked, pIntValue);
1483 else if (m_nFormFieldType == RTFFormFieldType::LIST)
1484 m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_result, pIntValue);
1485 break;
1486 case RTFKeyword::EDMINS:
1487 if (m_xDocumentProperties.is())
1489 // tdf#116851 some RTF may be malformed
1490 if (nParam < 0)
1491 nParam = -nParam;
1492 m_xDocumentProperties->setEditingDuration(nParam);
1494 break;
1495 case RTFKeyword::NOFPAGES:
1496 case RTFKeyword::NOFWORDS:
1497 case RTFKeyword::NOFCHARS:
1498 case RTFKeyword::NOFCHARSWS:
1499 if (m_xDocumentProperties.is())
1501 comphelper::SequenceAsHashMap aSeq = m_xDocumentProperties->getDocumentStatistics();
1502 OUString aName;
1503 switch (nKeyword)
1505 case RTFKeyword::NOFPAGES:
1506 aName = "PageCount";
1507 nParam = 99;
1508 break;
1509 case RTFKeyword::NOFWORDS:
1510 aName = "WordCount";
1511 break;
1512 case RTFKeyword::NOFCHARS:
1513 aName = "CharacterCount";
1514 break;
1515 case RTFKeyword::NOFCHARSWS:
1516 aName = "NonWhitespaceCharacterCount";
1517 break;
1518 default:
1519 break;
1521 if (!aName.isEmpty())
1523 aSeq[aName] <<= sal_Int32(nParam);
1524 m_xDocumentProperties->setDocumentStatistics(aSeq.getAsConstNamedValueList());
1527 break;
1528 case RTFKeyword::VERSION:
1529 if (m_xDocumentProperties.is())
1530 m_xDocumentProperties->setEditingCycles(nParam);
1531 break;
1532 case RTFKeyword::VERN:
1533 // Ignore this for now, later the RTF writer version could be used to add hacks for older buggy writers.
1534 break;
1535 case RTFKeyword::FTNSTART:
1536 putNestedSprm(m_aDefaultState.getParagraphSprms(),
1537 NS_ooxml::LN_EG_SectPrContents_footnotePr,
1538 NS_ooxml::LN_EG_FtnEdnNumProps_numStart, pIntValue);
1539 break;
1540 case RTFKeyword::AFTNSTART:
1541 putNestedSprm(m_aDefaultState.getParagraphSprms(),
1542 NS_ooxml::LN_EG_SectPrContents_endnotePr,
1543 NS_ooxml::LN_EG_FtnEdnNumProps_numStart, pIntValue);
1544 break;
1545 case RTFKeyword::DFRMTXTX:
1546 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_hSpace, nParam);
1547 break;
1548 case RTFKeyword::DFRMTXTY:
1549 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_vSpace, nParam);
1550 break;
1551 case RTFKeyword::DXFRTEXT:
1553 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_hSpace, nParam);
1554 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_vSpace, nParam);
1556 break;
1557 case RTFKeyword::FLYVERT:
1559 RTFVertOrient aVertOrient(nParam);
1560 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_yAlign,
1561 aVertOrient.GetAlign());
1562 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_vAnchor,
1563 aVertOrient.GetAnchor());
1565 break;
1566 case RTFKeyword::FLYHORZ:
1568 RTFHoriOrient aHoriOrient(nParam);
1569 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_xAlign,
1570 aHoriOrient.GetAlign());
1571 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_hAnchor,
1572 aHoriOrient.GetAnchor());
1574 break;
1575 case RTFKeyword::FLYANCHOR:
1576 break;
1577 case RTFKeyword::WMETAFILE:
1578 m_aStates.top().getPicture().eWMetafile = nParam;
1579 break;
1580 case RTFKeyword::SB:
1581 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_spacing,
1582 NS_ooxml::LN_CT_Spacing_before, pIntValue);
1583 break;
1584 case RTFKeyword::SA:
1585 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_spacing,
1586 NS_ooxml::LN_CT_Spacing_after, pIntValue);
1587 break;
1588 case RTFKeyword::DPX:
1589 m_aStates.top().getDrawingObject().setLeft(convertTwipToMm100(nParam));
1590 break;
1591 case RTFKeyword::DPY:
1592 m_aStates.top().getDrawingObject().setTop(convertTwipToMm100(nParam));
1593 break;
1594 case RTFKeyword::DPXSIZE:
1595 m_aStates.top().getDrawingObject().setRight(convertTwipToMm100(nParam));
1596 break;
1597 case RTFKeyword::DPYSIZE:
1598 m_aStates.top().getDrawingObject().setBottom(convertTwipToMm100(nParam));
1599 break;
1600 case RTFKeyword::PNSTART:
1601 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Lvl_start, pIntValue);
1602 break;
1603 case RTFKeyword::PNF:
1605 auto pValue = new RTFValue(m_aFontNames[getFontIndex(nParam)]);
1606 RTFSprms aAttributes;
1607 aAttributes.set(NS_ooxml::LN_CT_Fonts_ascii, pValue);
1608 putNestedSprm(m_aStates.top().getTableSprms(), NS_ooxml::LN_CT_Lvl_rPr,
1609 NS_ooxml::LN_EG_RPrBase_rFonts, new RTFValue(aAttributes));
1611 break;
1612 case RTFKeyword::VIEWSCALE:
1613 m_aSettingsTableAttributes.set(NS_ooxml::LN_CT_Zoom_percent, pIntValue);
1614 break;
1615 case RTFKeyword::BIN:
1617 m_aStates.top().setInternalState(RTFInternalState::BIN);
1618 m_aStates.top().setBinaryToRead(nParam);
1620 break;
1621 case RTFKeyword::DPLINECOR:
1622 m_aStates.top().getDrawingObject().setLineColorR(nParam);
1623 m_aStates.top().getDrawingObject().setHasLineColor(true);
1624 break;
1625 case RTFKeyword::DPLINECOG:
1626 m_aStates.top().getDrawingObject().setLineColorG(nParam);
1627 m_aStates.top().getDrawingObject().setHasLineColor(true);
1628 break;
1629 case RTFKeyword::DPLINECOB:
1630 m_aStates.top().getDrawingObject().setLineColorB(nParam);
1631 m_aStates.top().getDrawingObject().setHasLineColor(true);
1632 break;
1633 case RTFKeyword::DPFILLBGCR:
1634 m_aStates.top().getDrawingObject().setFillColorR(nParam);
1635 m_aStates.top().getDrawingObject().setHasFillColor(true);
1636 break;
1637 case RTFKeyword::DPFILLBGCG:
1638 m_aStates.top().getDrawingObject().setFillColorG(nParam);
1639 m_aStates.top().getDrawingObject().setHasFillColor(true);
1640 break;
1641 case RTFKeyword::DPFILLBGCB:
1642 m_aStates.top().getDrawingObject().setFillColorB(nParam);
1643 m_aStates.top().getDrawingObject().setHasFillColor(true);
1644 break;
1645 case RTFKeyword::DODHGT:
1646 m_aStates.top().getDrawingObject().setDhgt(nParam);
1647 break;
1648 case RTFKeyword::DPPOLYCOUNT:
1649 if (nParam >= 0)
1651 m_aStates.top().getDrawingObject().setPolyLineCount(nParam);
1653 break;
1654 case RTFKeyword::DPPTX:
1656 RTFDrawingObject& rDrawingObject = m_aStates.top().getDrawingObject();
1658 if (rDrawingObject.getPolyLinePoints().empty())
1659 dispatchValue(RTFKeyword::DPPOLYCOUNT, 2);
1661 rDrawingObject.getPolyLinePoints().emplace_back(convertTwipToMm100(nParam), 0);
1663 break;
1664 case RTFKeyword::DPPTY:
1666 RTFDrawingObject& rDrawingObject = m_aStates.top().getDrawingObject();
1667 if (!rDrawingObject.getPolyLinePoints().empty())
1669 rDrawingObject.getPolyLinePoints().back().Y = convertTwipToMm100(nParam);
1670 rDrawingObject.setPolyLineCount(rDrawingObject.getPolyLineCount() - 1);
1671 if (rDrawingObject.getPolyLineCount() == 0 && rDrawingObject.getPropertySet().is())
1673 uno::Sequence<uno::Sequence<awt::Point>> aPointSequenceSequence
1674 = { comphelper::containerToSequence(rDrawingObject.getPolyLinePoints()) };
1675 rDrawingObject.getPropertySet()->setPropertyValue(
1676 "PolyPolygon", uno::Any(aPointSequenceSequence));
1680 break;
1681 case RTFKeyword::SHPFBLWTXT:
1682 // Shape is below text -> send it to the background.
1683 m_aStates.top().getShape().setInBackground(nParam != 0);
1684 break;
1685 case RTFKeyword::FI:
1687 if (m_aStates.top().getDestination() == Destination::LISTLEVEL)
1689 if (m_aStates.top().getLevelNumbersValid())
1690 putNestedAttribute(m_aStates.top().getTableSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1691 NS_ooxml::LN_CT_Ind_firstLine, pIntValue);
1692 else
1693 m_aInvalidListLevelFirstIndents[m_nListLevel] = nParam;
1695 else
1696 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1697 NS_ooxml::LN_CT_Ind_firstLine, pIntValue);
1698 break;
1700 case RTFKeyword::LI:
1702 if (m_aStates.top().getDestination() == Destination::LISTLEVEL)
1704 if (m_aStates.top().getLevelNumbersValid())
1705 putNestedAttribute(m_aStates.top().getTableSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1706 NS_ooxml::LN_CT_Ind_left, pIntValue);
1708 else
1710 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1711 NS_ooxml::LN_CT_Ind_left, pIntValue);
1713 // It turns out \li should reset the \fi inherited from the stylesheet.
1714 // So set the direct formatting to zero, if we don't have such direct formatting yet.
1715 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1716 NS_ooxml::LN_CT_Ind_firstLine, new RTFValue(0),
1717 RTFOverwrite::NO_IGNORE);
1719 break;
1720 case RTFKeyword::RI:
1721 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1722 NS_ooxml::LN_CT_Ind_right, pIntValue);
1723 break;
1724 case RTFKeyword::LIN:
1725 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1726 NS_ooxml::LN_CT_Ind_start, pIntValue);
1727 break;
1728 case RTFKeyword::RIN:
1729 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1730 NS_ooxml::LN_CT_Ind_end, pIntValue);
1731 break;
1732 case RTFKeyword::OUTLINELEVEL:
1733 m_aStates.top().getParagraphSprms().set(NS_ooxml::LN_CT_PPrBase_outlineLvl, pIntValue);
1734 break;
1735 case RTFKeyword::PROPTYPE:
1737 switch (nParam)
1739 case 3:
1740 m_aStates.top().setPropType(cppu::UnoType<sal_Int32>::get());
1741 break;
1742 case 5:
1743 m_aStates.top().setPropType(cppu::UnoType<double>::get());
1744 break;
1745 case 11:
1746 m_aStates.top().setPropType(cppu::UnoType<bool>::get());
1747 break;
1748 case 30:
1749 m_aStates.top().setPropType(cppu::UnoType<OUString>::get());
1750 break;
1751 case 64:
1752 m_aStates.top().setPropType(cppu::UnoType<util::DateTime>::get());
1753 break;
1756 break;
1757 case RTFKeyword::DIBITMAP:
1758 m_aStates.top().getPicture().eStyle = RTFBmpStyle::DIBITMAP;
1759 break;
1760 case RTFKeyword::TRWWIDTHA:
1761 m_aStates.top().setTableRowWidthAfter(nParam);
1762 break;
1763 case RTFKeyword::ANIMTEXT:
1765 Id nId = 0;
1766 switch (nParam)
1768 case 0:
1769 nId = NS_ooxml::LN_Value_ST_TextEffect_none;
1770 break;
1771 case 2:
1772 nId = NS_ooxml::LN_Value_ST_TextEffect_blinkBackground;
1773 break;
1776 if (nId > 0)
1777 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_effect,
1778 new RTFValue(nId));
1779 break;
1781 case RTFKeyword::VIEWBKSP:
1783 m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_displayBackgroundShape, pIntValue);
1784 // Send this token immediately, if it only appears before the first
1785 // run, it will be too late, we ignored the background shape already by then.
1786 outputSettingsTable();
1787 break;
1789 case RTFKeyword::STEXTFLOW:
1791 Id nId = 0;
1792 switch (nParam)
1794 case 0:
1795 nId = NS_ooxml::LN_Value_ST_TextDirection_lrTb;
1796 break;
1797 case 1:
1798 nId = NS_ooxml::LN_Value_ST_TextDirection_tbRl;
1799 break;
1802 if (nId > 0)
1804 m_aStates.top().getSectionSprms().set(NS_ooxml::LN_EG_SectPrContents_textDirection,
1805 new RTFValue(nId));
1808 break;
1809 case RTFKeyword::LBR:
1811 Id nId = 0;
1812 switch (nParam)
1814 case 1:
1815 nId = NS_ooxml::LN_Value_ST_BrClear_left;
1816 break;
1817 case 2:
1818 nId = NS_ooxml::LN_Value_ST_BrClear_right;
1819 break;
1820 case 3:
1821 nId = NS_ooxml::LN_Value_ST_BrClear_all;
1822 break;
1825 if (nId > 0)
1827 m_aStates.top().getCharacterAttributes().set(NS_ooxml::LN_CT_Br_clear,
1828 new RTFValue(nId));
1831 break;
1832 case RTFKeyword::PGBRDROPT:
1834 sal_Int16 nOffsetFrom = (nParam & 0xe0) >> 5;
1835 bool bFromEdge = nOffsetFrom == 1;
1836 if (bFromEdge)
1838 Id nId = NS_ooxml::LN_Value_doc_ST_PageBorderOffset_page;
1839 putNestedAttribute(m_aStates.top().getSectionSprms(),
1840 NS_ooxml::LN_EG_SectPrContents_pgBorders,
1841 NS_ooxml::LN_CT_PageBorders_offsetFrom, new RTFValue(nId));
1844 break;
1845 case RTFKeyword::TPOSY:
1847 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
1848 NS_ooxml::LN_CT_TblPPr_tblpY, new RTFValue(nParam));
1850 break;
1851 case RTFKeyword::TPOSX:
1853 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
1854 NS_ooxml::LN_CT_TblPPr_tblpX, new RTFValue(nParam));
1856 break;
1857 case RTFKeyword::TDFRMTXTLEFT:
1859 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
1860 NS_ooxml::LN_CT_TblPPr_leftFromText, new RTFValue(nParam));
1862 break;
1863 case RTFKeyword::TDFRMTXTRIGHT:
1865 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
1866 NS_ooxml::LN_CT_TblPPr_rightFromText, new RTFValue(nParam));
1868 break;
1869 case RTFKeyword::TDFRMTXTTOP:
1871 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
1872 NS_ooxml::LN_CT_TblPPr_topFromText, new RTFValue(nParam));
1874 break;
1875 case RTFKeyword::TDFRMTXTBOTTOM:
1877 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
1878 NS_ooxml::LN_CT_TblPPr_bottomFromText, new RTFValue(nParam));
1880 break;
1881 default:
1883 SAL_INFO("writerfilter", "TODO handle value '" << keywordToString(nKeyword) << "'");
1884 aSkip.setParsed(false);
1886 break;
1888 return RTFError::OK;
1891 } // namespace rtftok
1892 } // namespace writerfilter
1894 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */