LibreOffice Module writerfilter (master) 1
rtfdispatchvalue.cxx
Go to the documentation of this file.
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>
17#include <osl/thread.h>
18#include <sal/log.hxx>
19#include <rtl/tencinfo.h>
21
22#include <ooxml/resourceids.hxx>
23
24#include "rtfcharsets.hxx"
25#include "rtffly.hxx"
28
31
32using namespace com::sun::star;
33
34namespace writerfilter
35{
36static int getNumberFormat(int nParam)
37{
38 static const int aMap[]
39 = { NS_ooxml::LN_Value_ST_NumberFormat_decimal,
40 NS_ooxml::LN_Value_ST_NumberFormat_upperRoman,
41 NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman,
42 NS_ooxml::LN_Value_ST_NumberFormat_upperLetter,
43 NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter,
44 NS_ooxml::LN_Value_ST_NumberFormat_ordinal,
45 NS_ooxml::LN_Value_ST_NumberFormat_cardinalText,
46 NS_ooxml::LN_Value_ST_NumberFormat_ordinalText,
47 NS_ooxml::LN_Value_ST_NumberFormat_none, // Undefined in RTF 1.8 spec.
48 NS_ooxml::LN_Value_ST_NumberFormat_none, // Undefined in RTF 1.8 spec.
49 NS_ooxml::LN_Value_ST_NumberFormat_ideographDigital,
50 NS_ooxml::LN_Value_ST_NumberFormat_japaneseCounting,
51 NS_ooxml::LN_Value_ST_NumberFormat_aiueo,
52 NS_ooxml::LN_Value_ST_NumberFormat_iroha,
53 NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth,
54 NS_ooxml::LN_Value_ST_NumberFormat_decimalHalfWidth,
55 NS_ooxml::LN_Value_ST_NumberFormat_japaneseLegal,
56 NS_ooxml::LN_Value_ST_NumberFormat_japaneseDigitalTenThousand,
57 NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircleChinese,
58 NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth2,
59 NS_ooxml::LN_Value_ST_NumberFormat_aiueoFullWidth,
60 NS_ooxml::LN_Value_ST_NumberFormat_irohaFullWidth,
61 NS_ooxml::LN_Value_ST_NumberFormat_decimalZero,
62 NS_ooxml::LN_Value_ST_NumberFormat_bullet,
63 NS_ooxml::LN_Value_ST_NumberFormat_ganada,
64 NS_ooxml::LN_Value_ST_NumberFormat_chosung,
65 NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedFullstop,
66 NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedParen,
67 NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircleChinese,
68 NS_ooxml::LN_Value_ST_NumberFormat_ideographEnclosedCircle,
69 NS_ooxml::LN_Value_ST_NumberFormat_ideographTraditional,
70 NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiac,
71 NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiacTraditional,
72 NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCounting,
73 NS_ooxml::LN_Value_ST_NumberFormat_ideographLegalTraditional,
74 NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCountingThousand,
75 NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseDigital,
76 NS_ooxml::LN_Value_ST_NumberFormat_chineseCounting,
77 NS_ooxml::LN_Value_ST_NumberFormat_chineseLegalSimplified,
78 NS_ooxml::LN_Value_ST_NumberFormat_chineseCountingThousand,
79 NS_ooxml::LN_Value_ST_NumberFormat_decimal,
80 NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital,
81 NS_ooxml::LN_Value_ST_NumberFormat_koreanCounting,
82 NS_ooxml::LN_Value_ST_NumberFormat_koreanLegal,
83 NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital2,
84 NS_ooxml::LN_Value_ST_NumberFormat_hebrew1,
85 NS_ooxml::LN_Value_ST_NumberFormat_arabicAlpha,
86 NS_ooxml::LN_Value_ST_NumberFormat_hebrew2,
87 NS_ooxml::LN_Value_ST_NumberFormat_arabicAbjad };
88 const int nLen = SAL_N_ELEMENTS(aMap);
89 int nValue = 0;
90 if (nParam >= 0 && nParam < nLen)
91 nValue = aMap[nParam];
92 else // 255 and the other cases.
93 nValue = NS_ooxml::LN_Value_ST_NumberFormat_none;
94 return nValue;
95}
96
97namespace rtftok
98{
100{
101 int nSprm = 0;
102 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
103 switch (nKeyword)
104 {
106 {
107 nSprm = NS_ooxml::LN_CT_Lvl_lvlJc;
108 int nValue = 0;
109 switch (nParam)
110 {
111 case 0:
112 nValue = NS_ooxml::LN_Value_ST_Jc_left;
113 break;
114 case 1:
115 nValue = NS_ooxml::LN_Value_ST_Jc_center;
116 break;
117 case 2:
118 nValue = NS_ooxml::LN_Value_ST_Jc_right;
119 break;
120 }
121 pIntValue = new RTFValue(nValue);
122 break;
123 }
125 nSprm = NS_ooxml::LN_CT_Lvl_start;
126 break;
128 nSprm = NS_ooxml::LN_CT_Lvl_lvlPicBulletId;
129 break;
131 nSprm = NS_ooxml::LN_CT_Style_basedOn;
132 pIntValue = new RTFValue(getStyleName(nParam));
133 break;
135 nSprm = NS_ooxml::LN_CT_Style_next;
136 pIntValue = new RTFValue(getStyleName(nParam));
137 break;
138 default:
139 break;
140 }
141 if (nSprm > 0)
142 {
143 m_aStates.top().getTableSprms().set(nSprm, pIntValue);
144 return true;
145 }
146 if (nKeyword == RTFKeyword::LEVELNFC)
147 {
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;
152 }
153
154 return false;
155}
156
158{
159 int nSprm = 0;
160 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
161
162 switch (nKeyword)
163 {
164 case RTFKeyword::FS:
165 case RTFKeyword::AFS:
166 switch (m_aStates.top().getRunType())
167 {
171 nSprm = NS_ooxml::LN_EG_RPrBase_szCs;
172 break;
178 default:
179 nSprm = NS_ooxml::LN_EG_RPrBase_sz;
180 break;
181 }
182 break;
184 nSprm = NS_ooxml::LN_EG_RPrBase_spacing;
185 break;
187 nSprm = NS_ooxml::LN_EG_RPrBase_kern;
188 break;
190 nSprm = NS_ooxml::LN_EG_RPrBase_w;
191 break;
192 default:
193 break;
194 }
195 if (nSprm > 0)
196 {
198 {
199 m_aStates.top().getTableSprms().set(nSprm, pIntValue);
200 }
201 else
202 {
203 m_aStates.top().getCharacterSprms().set(nSprm, pIntValue);
204 }
205 return true;
206 }
207
208 return false;
209}
210
212{
213 int nSprm = 0;
214
215 switch (nKeyword)
216 {
217 case RTFKeyword::LANG:
219 switch (m_aStates.top().getRunType())
220 {
224 nSprm = NS_ooxml::LN_CT_Language_bidi;
225 break;
227 nSprm = NS_ooxml::LN_CT_Language_eastAsia;
228 break;
233 default:
234 nSprm = NS_ooxml::LN_CT_Language_val;
235 break;
236 }
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;
243 }
244 if (nSprm > 0)
245 {
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;
255 }
256
257 return false;
258}
259
261{
262 int nSprm = 0;
263 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
264
265 switch (nKeyword)
266 {
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))
272 {
273 nParam = 1;
274 pIntValue = new RTFValue(nParam);
275 }
276 break;
277 default:
278 break;
279 }
280 if (nSprm > 0)
281 {
282 m_aStates.top().getParagraphSprms().set(nSprm, pIntValue);
283 if (nKeyword == RTFKeyword::ITAP && nParam > 0)
284 {
285 while (m_aTableBufferStack.size() < sal::static_int_cast<std::size_t>(nParam))
286 {
287 m_aTableBufferStack.emplace_back();
288 }
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());
292 }
293 return true;
294 }
295
296 return false;
297}
298
300{
301 int nSprm = 0;
302
303 switch (nKeyword)
304 {
305 case RTFKeyword::YR:
306 {
307 m_aStates.top().setYear(nParam);
308 nSprm = 1;
309 }
310 break;
311 case RTFKeyword::MO:
312 {
313 m_aStates.top().setMonth(nParam);
314 nSprm = 1;
315 }
316 break;
317 case RTFKeyword::DY:
318 {
319 m_aStates.top().setDay(nParam);
320 nSprm = 1;
321 }
322 break;
323 case RTFKeyword::HR:
324 {
325 m_aStates.top().setHour(nParam);
326 nSprm = 1;
327 }
328 break;
329 case RTFKeyword::MIN:
330 {
331 m_aStates.top().setMinute(nParam);
332 nSprm = 1;
333 }
334 break;
335 default:
336 break;
337 }
338
339 return nSprm > 0;
340}
341
343{
344 Id nId = 0;
345 switch (nKeyword)
346 {
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:
354 {
355 nId = NS_ooxml::LN_CT_FramePr_x;
356 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_xAlign, 0);
357 }
358 break;
359 case RTFKeyword::POSY:
360 {
361 nId = NS_ooxml::LN_CT_FramePr_y;
362 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_yAlign, 0);
363 }
364 break;
365 default:
366 break;
367 }
368
369 if (nId > 0)
370 {
371 m_bNeedPap = true;
372 // Don't try to support text frames inside tables for now.
374 m_aStates.top().getFrame().setSprm(nId, nParam);
375
376 return true;
377 }
378
379 return false;
380}
381
383{
384 int nSprm = 0;
385 tools::SvRef<RTFValue> pIntValue(new RTFValue(nParam));
386
387 switch (nKeyword)
388 {
390 {
391 int& rCurrentCellX(
395 int nCellX = nParam - rCurrentCellX;
396
397 if (!nCellX && nParam > 0)
398 {
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.
402
403 // sw/source/filter/inc/wrtswtbl.hxx, minimal possible width of cells.
404 const int COL_DFLT_WIDTH = 41;
405 nCellX = COL_DFLT_WIDTH;
406 }
407
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)
412 {
414 = pTblInd->getAttributes().find(NS_ooxml::LN_CT_TblWidth_w);
415 if (pWidth && pWidth->getInt() < 0)
416 nCellX = -1 * (pWidth->getInt() - nParam);
417 }
418
419 rCurrentCellX = nParam;
420 auto pXValue = new RTFValue(nCellX);
421 m_aStates.top().getTableRowSprms().set(NS_ooxml::LN_CT_TblGridBase_gridCol, pXValue,
424 {
426 // Push cell properties.
429 }
430 else
431 {
433 // Push cell properties.
436 }
437
440 // We assume text after a row definition always belongs to the table, to handle text before the real INTBL token
442 if (!m_nCellxMax)
443 {
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));
449 = new RTFReferenceProperties(std::move(aAttributes), std::move(aSprms));
450 Mapper().props(pProperties);
451 }
452 m_nCellxMax = std::max(m_nCellxMax, nParam);
453 return true;
454 }
455 break;
456 case RTFKeyword::TRRH:
457 {
458 OUString hRule("auto");
459 if (nParam < 0)
460 {
461 tools::SvRef<RTFValue> pAbsValue(new RTFValue(-nParam));
462 std::swap(pIntValue, pAbsValue);
463
464 hRule = "exact";
465 }
466 else if (nParam > 0)
467 hRule = "atLeast";
468
470 NS_ooxml::LN_CT_TrPrBase_trHeight, NS_ooxml::LN_CT_Height_val,
471 pIntValue);
472
473 auto pHRule = new RTFValue(hRule);
475 NS_ooxml::LN_CT_TrPrBase_trHeight, NS_ooxml::LN_CT_Height_hRule,
476 pHRule);
477 return true;
478 }
479 break;
482 {
483 // the value is in twips
484 auto const aDestination = m_aStates.top().getDestination();
485 int& rCurrentTRLeft((Destination::NESTEDTABLEPROPERTIES == aDestination)
488 int& rCurrentCellX((Destination::NESTEDTABLEPROPERTIES == aDestination)
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));
494
495 if (nKeyword == RTFKeyword::TBLIND)
496 {
497 RTFValue::Pointer_t pCellMargin
498 = m_aStates.top().getTableRowSprms().find(NS_ooxml::LN_CT_TblPrBase_tblCellMar);
499 if (pCellMargin)
500 {
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();
507 }
508 rCurrentTRLeft = nParam;
509 }
510 else
511 rCurrentTRLeft = rCurrentCellX = nParam;
512
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;
516 }
517 break;
519 {
520 int nValue = -1;
521
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;
576
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;
580 }
581 break;
586 {
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)
593 {
595 nSprm = NS_ooxml::LN_CT_TcMar_bottom;
596 break;
598 nSprm = NS_ooxml::LN_CT_TcMar_top;
599 break;
601 nSprm = NS_ooxml::LN_CT_TcMar_right;
602 break;
604 nSprm = NS_ooxml::LN_CT_TcMar_left;
605 break;
606 default:
607 break;
608 }
609 putNestedSprm(m_aStates.top().getTableCellSprms(), NS_ooxml::LN_CT_TcPrBase_tcMar,
610 nSprm, new RTFValue(aAttributes));
611 return true;
612 }
613 break;
618 {
619 RTFSprms aAttributes;
620 switch (nParam)
621 {
622 case 3:
623 aAttributes.set(NS_ooxml::LN_CT_TblWidth_type,
624 new RTFValue(NS_ooxml::LN_Value_ST_TblWidth_dxa));
625 break;
626 }
627 switch (nKeyword)
628 {
630 nSprm = NS_ooxml::LN_CT_TcMar_bottom;
631 break;
633 nSprm = NS_ooxml::LN_CT_TcMar_left;
634 break;
636 nSprm = NS_ooxml::LN_CT_TcMar_right;
637 break;
639 nSprm = NS_ooxml::LN_CT_TcMar_top;
640 break;
641 default:
642 break;
643 }
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;
654 }
655 break;
660 {
661 RTFSprms aAttributes;
662 aAttributes.set(NS_ooxml::LN_CT_TblWidth_w, new RTFValue(nParam));
663 switch (nKeyword)
664 {
666 nSprm = NS_ooxml::LN_CT_TcMar_bottom;
667 break;
669 nSprm = NS_ooxml::LN_CT_TcMar_left;
670 break;
672 nSprm = NS_ooxml::LN_CT_TcMar_right;
673 break;
675 nSprm = NS_ooxml::LN_CT_TcMar_top;
676 break;
677 default:
678 break;
679 }
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;
689 }
691 // Half of the space between the cells of a table row: default left/right table cell margin.
692 if (nParam > 0)
693 {
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
700 NS_ooxml::LN_CT_TblPrBase_tblCellMar, NS_ooxml::LN_CT_TblCellMar_left,
701 new RTFValue(aAttributes));
703 NS_ooxml::LN_CT_TblPrBase_tblCellMar,
704 NS_ooxml::LN_CT_TblCellMar_right, new RTFValue(aAttributes));
705 }
706 return true;
708 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblW,
709 NS_ooxml::LN_CT_TblWidth_type, pIntValue);
710 return true;
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;
717 }
718
719 return false;
720}
721
723{
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))
731 {
732 return RTFError::OK;
733 }
734
735 // Trivial character sprms.
736 if (dispatchCharacterSprmValue(nKeyword, nParam))
737 {
738 return RTFError::OK;
739 }
740
741 // Trivial character attributes.
742 if (dispatchCharacterAttributeValue(nKeyword, nParam))
743 {
744 return RTFError::OK;
745 }
746
747 // Trivial paragraph sprms.
748 if (dispatchParagraphSprmValue(nKeyword, nParam))
749 {
750 return RTFError::OK;
751 }
752
753 // Info group.
754 if (dispatchInfoValue(nKeyword, nParam))
755 {
756 return RTFError::OK;
757 }
758
759 // Frame size / position.
760 if (dispatchFrameValue(nKeyword, nParam))
761 {
762 return RTFError::OK;
763 }
764
765 // Table-related values.
766 if (dispatchTableValue(nKeyword, nParam))
767 {
768 return RTFError::OK;
769 }
770
771 // Then check for the more complex ones.
772 switch (nKeyword)
773 {
774 case RTFKeyword::F:
775 case RTFKeyword::AF:
776 switch (m_aStates.top().getRunType())
777 {
780 nSprm = NS_ooxml::LN_CT_Fonts_cs;
781 break;
783 nSprm = NS_ooxml::LN_CT_Fonts_eastAsia;
784 break;
790 default:
791 nSprm = NS_ooxml::LN_CT_Fonts_ascii;
792 break;
793 }
794
797 {
798 // Some text in buffer? It is font name. So previous font definition is complete
799 if (m_aStates.top().getCurrentDestinationText()->getLength())
801
802 m_aFontIndexes.push_back(nParam);
804 }
806 {
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),
814 }
815 else
816 {
818 auto pValue = new RTFValue(getFontName(m_nCurrentFontIndex));
820 NS_ooxml::LN_EG_RPrBase_rFonts, nSprm, pValue);
821 if (nKeyword == RTFKeyword::F)
823 }
824 break;
825 case RTFKeyword::RED:
827 break;
830 break;
831 case RTFKeyword::BLUE:
833 break;
835 {
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++)
840 {
841 if (aRTFEncodings[i].charset == nParam)
842 break;
843 }
844 if (i == nRTFEncodings)
845 // not found
846 return RTFError::OK;
847
849 = aRTFEncodings[i].codepage == 0 // Default (CP_ACP)
850 ? osl_getThreadTextEncoding()
851 : rtl_getTextEncodingFromWindowsCodePage(aRTFEncodings[i].codepage);
853 }
854 break;
856 case RTFKeyword::CPG:
857 {
858 rtl_TextEncoding nEncoding
859 = (nParam == 0)
861 : rtl_getTextEncodingFromWindowsCodePage(nParam);
862 if (nKeyword == RTFKeyword::ANSICPG)
864 else
865 m_nCurrentEncoding = nEncoding;
866 m_aStates.top().setCurrentEncoding(nEncoding);
867 }
868 break;
869 case RTFKeyword::CF:
870 {
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));
876 }
877 break;
878 case RTFKeyword::S:
879 {
881
884 {
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
889 }
890 else
891 {
892 OUString aName = getStyleName(nParam);
893 if (!aName.isEmpty())
894 {
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));
901 }
902 }
903 }
904 break;
905 case RTFKeyword::CS:
909 {
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
914 }
915 else
916 {
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));
921 }
922 break;
923 case RTFKeyword::DS:
926 {
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
931 }
932 break;
933 case RTFKeyword::TS:
936 {
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
942 }
943 break;
944 case RTFKeyword::DEFF:
945 m_nDefaultFontIndex = nParam;
946 break;
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;
955 {
956 LanguageTag aTag((LanguageType(static_cast<sal_uInt16>(nParam))));
957 auto pValue = new RTFValue(aTag.getBcp47());
959 (nKeyword == RTFKeyword::DEFLANG ? NS_ooxml::LN_EG_RPrBase_lang
960 : NS_ooxml::LN_CT_Language_bidi),
961 nSprm, pValue);
962 }
963 break;
965 {
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);
969 }
970 break;
973 {
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);
977 }
978 break;
980 if (nParam)
981 {
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);
985 }
986 break;
987 case RTFKeyword::ULC:
988 {
989 auto pValue = new RTFValue(sal_uInt32(getColorTable(nParam)));
990 m_aStates.top().getCharacterSprms().set(0x6877, pValue);
991 }
992 break;
994 {
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);
997 }
998 break;
999 case RTFKeyword::UP:
1000 case RTFKeyword::DN:
1001 {
1002 auto pValue = new RTFValue(nParam * (nKeyword == RTFKeyword::UP ? 1 : -1));
1003 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_position, pValue);
1004 }
1005 break;
1007 {
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
1014 NS_ooxml::LN_CT_EastAsianLayout_vertCompress, pValue);
1015 }
1016 break;
1017 case RTFKeyword::EXPND:
1018 {
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);
1022 }
1023 break;
1025 {
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)
1031 {
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;
1047 }
1048 if (nId > 0)
1050 NS_ooxml::LN_CT_EastAsianLayout_combineBrackets, new RTFValue(nId));
1051 }
1052 break;
1053 case RTFKeyword::SL:
1054 {
1055 // This is similar to RTFKeyword::ABSH, negative value means 'exact', positive means 'at least'.
1057 new RTFValue(NS_ooxml::LN_Value_doc_ST_LineSpacingRule_atLeast));
1058 if (nParam < 0)
1059 {
1060 pValue = new RTFValue(NS_ooxml::LN_Value_doc_ST_LineSpacingRule_exact);
1061 pIntValue = new RTFValue(-nParam);
1062 }
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);
1065 }
1066 break;
1067 case RTFKeyword::SLMULT:
1068 if (nParam > 0)
1069 {
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);
1073 }
1074 break;
1075 case RTFKeyword::BRDRW:
1076 {
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);
1082 }
1083 break;
1084 case RTFKeyword::BRDRCF:
1085 {
1086 auto pValue = new RTFValue(sal_uInt32(getColorTable(nParam)));
1087 putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_color, pValue);
1088 }
1089 break;
1090 case RTFKeyword::BRSP:
1091 {
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);
1095 }
1096 break;
1097 case RTFKeyword::TX:
1098 {
1099 m_aStates.top().getTabAttributes().set(NS_ooxml::LN_CT_TabStop_pos, pIntValue);
1100 auto pValue = new RTFValue(m_aStates.top().getTabAttributes());
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);
1108 }
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;
1115 // This one is not referenced anywhere, so it's pointless to store it at the moment.
1116 break;
1117 case RTFKeyword::LISTID:
1118 {
1120 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_AbstractNum_abstractNumId,
1121 pIntValue);
1123 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Num_abstractNumId, pIntValue);
1125 }
1126 break;
1127 case RTFKeyword::LS:
1128 {
1130 {
1131 m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_AbstractNum_nsid,
1132 pIntValue);
1134 }
1135 else
1136 {
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);
1143 }
1144 }
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))
1155 {
1157 {
1158 if (nParam != ';')
1159 m_aStates.top().getLevelNumbers().push_back(sal_Int32(nParam));
1160 else
1161 // ';' in \u form is not considered valid.
1163 }
1164 else
1165 m_aUnicodeBuffer.append(static_cast<sal_Unicode>(nParam));
1167 }
1168 break;
1170 {
1171 OUString sValue;
1172 switch (nParam)
1173 {
1174 case 0:
1175 sValue = "tab";
1176 break;
1177 case 1:
1178 sValue = "space";
1179 break;
1180 case 2:
1181 sValue = "nothing";
1182 break;
1183 }
1184 if (!sValue.isEmpty())
1185 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Lvl_suff, new RTFValue(sValue));
1186 }
1187 break;
1188 case RTFKeyword::FPRQ:
1189 {
1190 sal_Int32 nValue = 0;
1191 switch (nParam)
1192 {
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;
1202 }
1203 if (nValue)
1204 {
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));
1209 }
1210 }
1211 break;
1213 // Ignore this for now, the exporter always emits it with a zero parameter.
1214 break;
1216 m_aStates.top().getPicture().nScaleX = nParam;
1217 break;
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;
1229 break;
1232 break;
1235 break;
1238 break;
1241 break;
1244 break;
1245 case RTFKeyword::SHPWRK:
1246 {
1247 int nValue = 0;
1248 switch (nParam)
1249 {
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;
1264 }
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);
1273 }
1274 break;
1275 case RTFKeyword::SHPWR:
1276 {
1277 switch (nParam)
1278 {
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;
1298 }
1299 }
1300 break;
1301 case RTFKeyword::COLS:
1303 NS_ooxml::LN_EG_SectPrContents_cols, NS_ooxml::LN_CT_Columns_num,
1304 pIntValue);
1305 break;
1306 case RTFKeyword::COLSX:
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:
1317 {
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);
1323 }
1324 break;
1325 case RTFKeyword::PAPERH:
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:
1332 NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_h,
1333 pIntValue);
1334 break;
1335 case RTFKeyword::PAPERW:
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:
1342 NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_w,
1343 pIntValue);
1344 break;
1345 case RTFKeyword::MARGL:
1347 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_left,
1348 pIntValue);
1349 [[fallthrough]]; // set the default + current value
1352 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_left,
1353 pIntValue);
1354 break;
1355 case RTFKeyword::MARGR:
1357 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_right,
1358 pIntValue);
1359 [[fallthrough]]; // set the default + current value
1362 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_right,
1363 pIntValue);
1364 break;
1365 case RTFKeyword::MARGT:
1367 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_top,
1368 pIntValue);
1369 [[fallthrough]]; // set the default + current value
1372 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_top,
1373 pIntValue);
1374 break;
1375 case RTFKeyword::MARGB:
1377 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_bottom,
1378 pIntValue);
1379 [[fallthrough]]; // set the default + current value
1382 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_bottom,
1383 pIntValue);
1384 break;
1387 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_header,
1388 pIntValue);
1389 break;
1392 NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_footer,
1393 pIntValue);
1394 break;
1395 case RTFKeyword::GUTTER:
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;
1405 NS_ooxml::LN_EG_SectPrContents_lnNumType,
1406 NS_ooxml::LN_CT_LineNumber_countBy, pIntValue);
1407 break;
1408 case RTFKeyword::LINEX:
1409 if (nParam)
1411 NS_ooxml::LN_EG_SectPrContents_lnNumType,
1412 NS_ooxml::LN_CT_LineNumber_distance, pIntValue);
1413 break;
1415 {
1416 // OOXML <w:lnNumType w:start="..."/> is 0-based, RTF is 1-based.
1417 auto pStart = tools::make_ref<RTFValue>(nParam - 1);
1419 NS_ooxml::LN_EG_SectPrContents_lnNumType,
1420 NS_ooxml::LN_CT_LineNumber_start, pStart);
1421 }
1422 break;
1425 {
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);
1429 }
1430 break;
1433 {
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);
1439 }
1440 break;
1443 break;
1444 case RTFKeyword::SHPTOP:
1446 break;
1449 break;
1452 break;
1453 case RTFKeyword::SHPZ:
1454 m_aStates.top().getShape().setZ(nParam);
1455 break;
1456 case RTFKeyword::FFTYPE:
1457 switch (nParam)
1458 {
1459 case 0:
1461 break;
1462 case 1:
1464 break;
1465 case 2:
1467 break;
1468 default:
1470 break;
1471 }
1472 break;
1475 m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFCheckBox_default, pIntValue);
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);
1484 m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_result, pIntValue);
1485 break;
1486 case RTFKeyword::EDMINS:
1487 if (m_xDocumentProperties.is())
1488 {
1489 // tdf#116851 some RTF may be malformed
1490 if (nParam < 0)
1491 nParam = -nParam;
1492 m_xDocumentProperties->setEditingDuration(nParam);
1493 }
1494 break;
1499 if (m_xDocumentProperties.is())
1500 {
1501 comphelper::SequenceAsHashMap aSeq = m_xDocumentProperties->getDocumentStatistics();
1502 OUString aName;
1503 switch (nKeyword)
1504 {
1506 aName = "PageCount";
1507 nParam = 99;
1508 break;
1510 aName = "WordCount";
1511 break;
1513 aName = "CharacterCount";
1514 break;
1516 aName = "NonWhitespaceCharacterCount";
1517 break;
1518 default:
1519 break;
1520 }
1521 if (!aName.isEmpty())
1522 {
1523 aSeq[aName] <<= sal_Int32(nParam);
1524 m_xDocumentProperties->setDocumentStatistics(aSeq.getAsConstNamedValueList());
1525 }
1526 }
1527 break;
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;
1537 NS_ooxml::LN_EG_SectPrContents_footnotePr,
1538 NS_ooxml::LN_EG_FtnEdnNumProps_numStart, pIntValue);
1539 break;
1542 NS_ooxml::LN_EG_SectPrContents_endnotePr,
1543 NS_ooxml::LN_EG_FtnEdnNumProps_numStart, pIntValue);
1544 break;
1546 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_hSpace, nParam);
1547 break;
1549 m_aStates.top().getFrame().setSprm(NS_ooxml::LN_CT_FramePr_vSpace, nParam);
1550 break;
1552 {
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);
1555 }
1556 break;
1558 {
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());
1564 }
1565 break;
1567 {
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());
1573 }
1574 break;
1576 break;
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:
1590 break;
1591 case RTFKeyword::DPY:
1593 break;
1596 break;
1599 break;
1601 m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Lvl_start, pIntValue);
1602 break;
1603 case RTFKeyword::PNF:
1604 {
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));
1610 }
1611 break;
1613 m_aSettingsTableAttributes.set(NS_ooxml::LN_CT_Zoom_percent, pIntValue);
1614 break;
1615 case RTFKeyword::BIN:
1616 {
1618 m_aStates.top().setBinaryToRead(nParam);
1619 }
1620 break;
1624 break;
1628 break;
1632 break;
1636 break;
1640 break;
1644 break;
1645 case RTFKeyword::DODHGT:
1647 break;
1649 if (nParam >= 0)
1650 {
1652 }
1653 break;
1654 case RTFKeyword::DPPTX:
1655 {
1656 RTFDrawingObject& rDrawingObject = m_aStates.top().getDrawingObject();
1657
1658 if (rDrawingObject.getPolyLinePoints().empty())
1660
1661 rDrawingObject.getPolyLinePoints().emplace_back(convertTwipToMm100(nParam), 0);
1662 }
1663 break;
1664 case RTFKeyword::DPPTY:
1665 {
1666 RTFDrawingObject& rDrawingObject = m_aStates.top().getDrawingObject();
1667 if (!rDrawingObject.getPolyLinePoints().empty())
1668 {
1669 rDrawingObject.getPolyLinePoints().back().Y = convertTwipToMm100(nParam);
1670 rDrawingObject.setPolyLineCount(rDrawingObject.getPolyLineCount() - 1);
1671 if (rDrawingObject.getPolyLineCount() == 0 && rDrawingObject.getPropertySet().is())
1672 {
1673 uno::Sequence<uno::Sequence<awt::Point>> aPointSequenceSequence
1674 = { comphelper::containerToSequence(rDrawingObject.getPolyLinePoints()) };
1675 rDrawingObject.getPropertySet()->setPropertyValue(
1676 "PolyPolygon", uno::Any(aPointSequenceSequence));
1677 }
1678 }
1679 }
1680 break;
1682 // Shape is below text -> send it to the background.
1683 m_aStates.top().getShape().setInBackground(nParam != 0);
1684 break;
1685 case RTFKeyword::FI:
1686 {
1688 {
1690 putNestedAttribute(m_aStates.top().getTableSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1691 NS_ooxml::LN_CT_Ind_firstLine, pIntValue);
1692 else
1694 }
1695 else
1696 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1697 NS_ooxml::LN_CT_Ind_firstLine, pIntValue);
1698 break;
1699 }
1700 case RTFKeyword::LI:
1701 {
1703 {
1705 putNestedAttribute(m_aStates.top().getTableSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1706 NS_ooxml::LN_CT_Ind_left, pIntValue);
1707 }
1708 else
1709 {
1710 putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_ind,
1711 NS_ooxml::LN_CT_Ind_left, pIntValue);
1712 }
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),
1718 }
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;
1733 m_aStates.top().getParagraphSprms().set(NS_ooxml::LN_CT_PPrBase_outlineLvl, pIntValue);
1734 break;
1736 {
1737 switch (nParam)
1738 {
1739 case 3:
1741 break;
1742 case 5:
1744 break;
1745 case 11:
1747 break;
1748 case 30:
1750 break;
1751 case 64:
1753 break;
1754 }
1755 }
1756 break;
1759 break;
1762 break;
1764 {
1765 Id nId = 0;
1766 switch (nParam)
1767 {
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;
1774 }
1775
1776 if (nId > 0)
1777 m_aStates.top().getCharacterSprms().set(NS_ooxml::LN_EG_RPrBase_effect,
1778 new RTFValue(nId));
1779 break;
1780 }
1782 {
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.
1787 break;
1788 }
1790 {
1791 Id nId = 0;
1792 switch (nParam)
1793 {
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;
1800 }
1801
1802 if (nId > 0)
1803 {
1804 m_aStates.top().getSectionSprms().set(NS_ooxml::LN_EG_SectPrContents_textDirection,
1805 new RTFValue(nId));
1806 }
1807 }
1808 break;
1809 case RTFKeyword::LBR:
1810 {
1811 Id nId = 0;
1812 switch (nParam)
1813 {
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;
1823 }
1824
1825 if (nId > 0)
1826 {
1827 m_aStates.top().getCharacterAttributes().set(NS_ooxml::LN_CT_Br_clear,
1828 new RTFValue(nId));
1829 }
1830 }
1831 break;
1833 {
1834 sal_Int16 nOffsetFrom = (nParam & 0xe0) >> 5;
1835 bool bFromEdge = nOffsetFrom == 1;
1836 if (bFromEdge)
1837 {
1838 Id nId = NS_ooxml::LN_Value_doc_ST_PageBorderOffset_page;
1840 NS_ooxml::LN_EG_SectPrContents_pgBorders,
1841 NS_ooxml::LN_CT_PageBorders_offsetFrom, new RTFValue(nId));
1842 }
1843 }
1844 break;
1845 case RTFKeyword::TPOSY:
1846 {
1847 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
1848 NS_ooxml::LN_CT_TblPPr_tblpY, new RTFValue(nParam));
1849 }
1850 break;
1851 case RTFKeyword::TPOSX:
1852 {
1853 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
1854 NS_ooxml::LN_CT_TblPPr_tblpX, new RTFValue(nParam));
1855 }
1856 break;
1858 {
1859 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
1860 NS_ooxml::LN_CT_TblPPr_leftFromText, new RTFValue(nParam));
1861 }
1862 break;
1864 {
1865 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
1866 NS_ooxml::LN_CT_TblPPr_rightFromText, new RTFValue(nParam));
1867 }
1868 break;
1870 {
1871 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
1872 NS_ooxml::LN_CT_TblPPr_topFromText, new RTFValue(nParam));
1873 }
1874 break;
1876 {
1877 putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
1878 NS_ooxml::LN_CT_TblPPr_bottomFromText, new RTFValue(nParam));
1879 }
1880 break;
1881 default:
1882 {
1883 SAL_INFO("writerfilter", "TODO handle value '" << keywordToString(nKeyword) << "'");
1884 aSkip.setParsed(false);
1885 }
1886 break;
1887 }
1888 return RTFError::OK;
1889}
1890
1891} // namespace rtftok
1892} // namespace writerfilter
1893
1894/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr auto convertTwipToMm100(N n)
const OUString & getBcp47(bool bResolveSystem=true) const
virtual void props(writerfilter::Reference< Properties >::Pointer_t ref)=0
Receives properties of the current run of text.
int m_nNestedCurrentCellX
Current cellx value (nested table)
void setNeedSect(bool bNeedSect)
If we need a final section break at the end of the document.
RTFSprms m_aSettingsTableAttributes
The settings table attributes.
bool dispatchCharacterSprmValue(RTFKeyword nKeyword, int nParam)
bool dispatchTableValue(RTFKeyword nKeyword, int nParam)
std::deque< RTFBuffer_t > m_aTableBufferStack
Buffered table cells, till cell definitions are not reached.
RTFError dispatchValue(RTFKeyword nKeyword, int nParam) override
int m_nDefaultFontIndex
Raw default font index, use getFont() on it to get a real one.
std::map< int, OUString > m_aFontNames
Font index <-> name map.
std::map< int, int > m_aInvalidListLevelFirstIndents
Maps List level indexes to removed values in the current list entry.
std::deque< RTFSprms > m_aTopLevelTableCellsAttributes
bool dispatchCharacterAttributeValue(RTFKeyword nKeyword, int nParam)
RTFSprms m_aSettingsTableSprms
The settings table sprms.
int m_nCurrentEncoding
Used only during font table parsing till we don't know the font name.
OUString getFontName(int nIndex)
Return the name of the font, based on a dmapper index.
int m_nTopLevelCurrentCellX
Current cellx value (top-level table)
std::deque< RTFSprms > m_aNestedTableCellsAttributes
std::deque< RTFSprms > m_aTopLevelTableCellsSprms
void checkUnicode(bool bUnicode, bool bHex)
If we have some unicode or hex characters to send.
std::deque< RTFSprms > m_aNestedTableCellsSprms
int m_nNestedCells
cell props buffer for nested tables, reset by \nestrow the \nesttableprops is a destination and must ...
int m_nListLevel
Index of the current list level in a list table entry.
OUString getStyleName(int nIndex)
Return the style name of an RTF style index.
int getFontIndex(int nIndex)
Return the dmapper index of an RTF index for fonts.
int m_nTopLevelCells
cell props buffer for top-level table, reset by \row
RTFParserState m_aDefaultState
Read by RTF_PARD.
bool dispatchInfoValue(RTFKeyword nKeyword, int nParam)
std::map< int, OUString > m_aAuthors
Revision index <-> author map.
RTFError dispatchFlag(RTFKeyword nKeyword) override
rtl_TextEncoding getEncoding(int nFontIndex)
Return the encoding associated with a font index.
bool m_bNeedPap
If paragraph properties should be emitted on next run.
bool dispatchTableSprmValue(RTFKeyword nKeyword, int nParam)
bool dispatchParagraphSprmValue(RTFKeyword nKeyword, int nParam)
std::vector< int > m_aFontIndexes
Maps the non-continuous font indexes to the continuous dmapper indexes.
void outputSettingsTable()
Send NS_ooxml::LN_settings_settings to dmapper.
int m_nCellxMax
Max width of the rows in the current table.
Color getColorTable(sal_uInt32 nIndex)
bool dispatchFrameValue(RTFKeyword nKeyword, int nParam)
css::uno::Reference< css::document::XDocumentProperties > m_xDocumentProperties
Stores the properties of a drawing object.
void setFillColorG(sal_uInt8 nFillColorG)
void setHasLineColor(bool bHasLineColor)
const css::uno::Reference< css::beans::XPropertySet > & getPropertySet() const
void setHasFillColor(bool bHasFillColor)
void setLineColorR(sal_uInt8 nLineColorR)
void setPolyLineCount(sal_Int32 nPolyLineCount)
void setLineColorG(sal_uInt8 nLineColorG)
std::vector< css::awt::Point > & getPolyLinePoints()
void setFillColorB(sal_uInt8 nFillColorB)
void setFillColorR(sal_uInt8 nFillColorR)
void setLineColorB(sal_uInt8 nLineColorB)
void setSprm(Id nId, Id nValue)
Store a property.
Stores the horizontal orientation properties of an RTF fly frame.
Definition: rtffly.hxx:78
void setCurrentListIndex(int nCurrentListIndex)
void setCurrentCharacterStyleIndex(int nCurrentCharacterStyleIndex)
void setCurrentEncoding(rtl_TextEncoding nCurrentEncoding)
void setPropType(const css::uno::Type &rPropType)
void setCurrentStyleIndex(int nCurrentStyleIndex)
void setLevelNumbersValid(bool bLevelNumbersValid)
rtl_TextEncoding getCurrentEncoding() const
void setTableRowWidthAfter(int nTableRowWidthAfter)
OUStringBuffer * getCurrentDestinationText() const
void setBinaryToRead(int nBinaryToRead)
void setCurrentListOverrideIndex(int nCurrentListOverrideIndex)
std::vector< sal_Int32 > & getLevelNumbers()
void setInternalState(RTFInternalState nInternalState)
Sends RTFSprm instances to DomainMapper.
void setBottom(sal_Int32 nBottom)
void setInBackground(bool bInBackground)
void setWrap(css::text::WrapTextMode nWrap)
void setRight(sal_Int32 nRight)
Skips a destination after a not parsed control word if it was prefixed with *.
A list of RTFSprm with a copy constructor that performs a deep copy.
Definition: rtfsprm.hxx:39
RTFValue::Pointer_t find(Id nKeyword, bool bFirst=true, bool bForWrite=false)
Definition: rtfsprm.cxx:74
void set(Id nKeyword, const RTFValue::Pointer_t &pValue, RTFOverwrite eOverwrite=RTFOverwrite::YES)
Does the same as ->push_back(), except that it can overwrite or ignore existing entries.
Definition: rtfsprm.cxx:98
Value of an RTF keyword.
Definition: rtfvalue.hxx:33
Stores the vertical orientation properties of an RTF fly frame.
Definition: rtffly.hxx:23
constexpr ::Color COL_AUTO(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
UNOTOOLS_DLLPUBLIC OUString utl_getLocaleForGlobalDefaultEncoding()
sal_Int16 nValue
OUString aName
Sequence< sal_Int8 > aSeq
#define SAL_INFO(area, stream)
#define SAL_N_ELEMENTS(arr)
aStr
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
int i
RTFEncoding const aRTFEncodings[]
Definition: rtfcharsets.cxx:19
void putNestedAttribute(RTFSprms &rSprms, Id nParent, Id nId, const RTFValue::Pointer_t &pValue, RTFOverwrite eOverwrite, bool bAttribute)
@ NO_IGNORE
No, if the key is already in the list, then ignore, otherwise append.
@ NO_APPEND
No, always append the value to the end of the list.
@ YES_PREPEND
Yes, always prepend the value to the start of the list and remove existing entries.
void putNestedSprm(RTFSprms &rSprms, Id nParent, Id nId, const RTFValue::Pointer_t &pValue, RTFOverwrite eOverwrite)
OString DTTM22OString(tools::Long nDTTM)
RTFSprms & getLastAttributes(RTFSprms &rSprms, Id nId)
const char * keywordToString(RTFKeyword nKeyword)
void putBorderProperty(RTFStack &aStates, Id nId, const RTFValue::Pointer_t &pValue)
static int getNumberFormat(int nParam)
HashMap_OWString_Interface aMap
sal_Int16 nId
sal_uInt32 Id
#define SAL_MAX_UINT16
#define SAL_MIN_INT16
#define SAL_MAX_INT16
sal_uInt16 sal_Unicode
UNOTOOLS_DLLPUBLIC rtl_TextEncoding utl_getWinTextEncodingFromLangStr(const OUString &sLanguage, bool bOEM=false)
#define COL_DFLT_WIDTH