Line data Source code
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 <com/sun/star/beans/PropertyAttribute.hpp>
11 : #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
12 : #include <com/sun/star/graphic/GraphicProvider.hpp>
13 : #include <com/sun/star/lang/XServiceInfo.hpp>
14 : #include <com/sun/star/text/HoriOrientation.hpp>
15 : #include <com/sun/star/text/VertOrientation.hpp>
16 : #include <com/sun/star/text/RelOrientation.hpp>
17 : #include <com/sun/star/text/WrapTextMode.hpp>
18 : #include <com/sun/star/text/TextContentAnchorType.hpp>
19 : #include <svl/lngmisc.hxx>
20 : #include <unotools/ucbstreamhelper.hxx>
21 : #include <unotools/streamwrap.hxx>
22 : #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
23 : #include <vcl/wmf.hxx>
24 : #include <filter/msfilter/util.hxx>
25 : #include <comphelper/string.hxx>
26 : #include <tools/globname.hxx>
27 : #include <tools/datetimeutils.hxx>
28 : #include <comphelper/classids.hxx>
29 : #include <comphelper/embeddedobjectcontainer.hxx>
30 : #include <comphelper/sequenceashashmap.hxx>
31 : #include <comphelper/sequence.hxx>
32 : #include <sfx2/sfxbasemodel.hxx>
33 : #include <oox/mathml/import.hxx>
34 : #include <ooxml/resourceids.hxx>
35 : #include <oox/token/namespaces.hxx>
36 : #include <oox/drawingml/drawingmltypes.hxx>
37 : #include <rtfsdrimport.hxx>
38 : #include <rtflookahead.hxx>
39 : #include <rtfcharsets.hxx>
40 : #include <rtfreferenceproperties.hxx>
41 : #include <rtfskipdestination.hxx>
42 : #include <rtffly.hxx>
43 :
44 : using namespace com::sun::star;
45 :
46 : namespace writerfilter
47 : {
48 : namespace rtftok
49 : {
50 :
51 26 : static Id lcl_getParagraphBorder(sal_uInt32 nIndex)
52 : {
53 : static const Id aBorderIds[] =
54 : {
55 : NS_ooxml::LN_CT_PBdr_top, NS_ooxml::LN_CT_PBdr_left, NS_ooxml::LN_CT_PBdr_bottom, NS_ooxml::LN_CT_PBdr_right
56 : };
57 :
58 26 : return aBorderIds[nIndex];
59 : }
60 :
61 36040 : static void lcl_putNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId, RTFValue::Pointer_t pValue,
62 : RTFOverwrite eOverwrite = RTFOverwrite::YES, bool bAttribute = true)
63 : {
64 36040 : RTFValue::Pointer_t pParent = rSprms.find(nParent, /*bFirst=*/true, /*bForWrite=*/true);
65 36040 : if (!pParent.get())
66 : {
67 9596 : RTFSprms aAttributes;
68 9596 : if (nParent == NS_ooxml::LN_CT_TcPrBase_shd)
69 : {
70 : // RTF default is 'auto', see writerfilter::dmapper::CellColorHandler
71 8 : aAttributes.set(NS_ooxml::LN_CT_Shd_color, std::make_shared<RTFValue>(0x0a));
72 8 : aAttributes.set(NS_ooxml::LN_CT_Shd_fill, std::make_shared<RTFValue>(0x0a));
73 : }
74 19192 : auto pParentValue = std::make_shared<RTFValue>(aAttributes);
75 9596 : rSprms.set(nParent, pParentValue, eOverwrite);
76 19192 : pParent = pParentValue;
77 : }
78 36040 : RTFSprms& rAttributes = (bAttribute ? pParent->getAttributes() : pParent->getSprms());
79 36040 : rAttributes.set(nId, pValue, eOverwrite);
80 36040 : }
81 :
82 2951 : static void lcl_putNestedSprm(RTFSprms& rSprms, Id nParent, Id nId, RTFValue::Pointer_t pValue, RTFOverwrite eOverwrite = RTFOverwrite::NO_APPEND)
83 : {
84 2951 : lcl_putNestedAttribute(rSprms, nParent, nId, pValue, eOverwrite, false);
85 2951 : }
86 :
87 990 : static RTFValue::Pointer_t lcl_getNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId)
88 : {
89 990 : RTFValue::Pointer_t pParent = rSprms.find(nParent);
90 990 : if (!pParent)
91 607 : return RTFValue::Pointer_t();
92 383 : RTFSprms& rAttributes = pParent->getAttributes();
93 383 : return rAttributes.find(nId);
94 : }
95 :
96 279 : static bool lcl_eraseNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId)
97 : {
98 279 : RTFValue::Pointer_t pParent = rSprms.find(nParent);
99 279 : if (!pParent.get())
100 : // It doesn't even have a parent, we're done!
101 279 : return false;
102 0 : RTFSprms& rAttributes = pParent->getAttributes();
103 0 : return rAttributes.erase(nId);
104 : }
105 :
106 1731 : static RTFSprms& lcl_getLastAttributes(RTFSprms& rSprms, Id nId)
107 : {
108 1731 : RTFValue::Pointer_t p = rSprms.find(nId);
109 1731 : if (p.get() && p->getSprms().size())
110 1599 : return p->getSprms().back().second->getAttributes();
111 : else
112 : {
113 : SAL_WARN("writerfilter", "trying to set property when no type is defined");
114 132 : return rSprms;
115 1731 : }
116 : }
117 :
118 : static void
119 1874 : lcl_putBorderProperty(RTFStack& aStates, Id nId, RTFValue::Pointer_t pValue)
120 : {
121 1874 : RTFSprms* pAttributes = nullptr;
122 1874 : if (aStates.top().nBorderState == RTFBorderState::PARAGRAPH_BOX)
123 5 : for (int i = 0; i < 4; i++)
124 : {
125 4 : RTFValue::Pointer_t p = aStates.top().aParagraphSprms.find(lcl_getParagraphBorder(i));
126 4 : if (p.get())
127 : {
128 4 : RTFSprms& rAttributes = p->getAttributes();
129 4 : rAttributes.set(nId, pValue);
130 : }
131 4 : }
132 1873 : else if (aStates.top().nBorderState == RTFBorderState::CHARACTER)
133 : {
134 14 : RTFValue::Pointer_t pPointer = aStates.top().aCharacterSprms.find(NS_ooxml::LN_EG_RPrBase_bdr);
135 14 : if (pPointer.get())
136 : {
137 14 : RTFSprms& rAttributes = pPointer->getAttributes();
138 14 : rAttributes.set(nId, pValue);
139 14 : }
140 : }
141 : // Attributes of the last border type
142 1859 : else if (aStates.top().nBorderState == RTFBorderState::PARAGRAPH)
143 83 : pAttributes = &lcl_getLastAttributes(aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PrBase_pBdr);
144 1776 : else if (aStates.top().nBorderState == RTFBorderState::CELL)
145 1648 : pAttributes = &lcl_getLastAttributes(aStates.top().aTableCellSprms, NS_ooxml::LN_CT_TcPrBase_tcBorders);
146 128 : else if (aStates.top().nBorderState == RTFBorderState::PAGE)
147 0 : pAttributes = &lcl_getLastAttributes(aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgBorders);
148 1874 : if (pAttributes)
149 1731 : pAttributes->set(nId, pValue);
150 1874 : }
151 :
152 8 : static OString lcl_DTTM22OString(long lDTTM)
153 : {
154 8 : return DateTimeToOString(msfilter::util::DTTM2DateTime(lDTTM));
155 : }
156 :
157 33 : static writerfilter::Reference<Properties>::Pointer_t lcl_getBookmarkProperties(int nPos, OUString& rString)
158 : {
159 33 : RTFSprms aAttributes;
160 66 : auto pPos = std::make_shared<RTFValue>(nPos);
161 33 : if (!rString.isEmpty())
162 : {
163 : // If present, this should be sent first.
164 33 : auto pString = std::make_shared<RTFValue>(rString);
165 33 : aAttributes.set(NS_ooxml::LN_CT_Bookmark_name, pString);
166 : }
167 33 : aAttributes.set(NS_ooxml::LN_CT_MarkupRangeBookmark_id, pPos);
168 66 : return std::make_shared<RTFReferenceProperties>(aAttributes);
169 : }
170 :
171 0 : static const char* lcl_RtfToString(RTFKeyword nKeyword)
172 : {
173 0 : for (int i = 0; i < nRTFControlWords; i++)
174 : {
175 0 : if (nKeyword == aRTFControlWords[i].nIndex)
176 0 : return aRTFControlWords[i].sKeyword;
177 : }
178 0 : return nullptr;
179 : }
180 :
181 345 : static util::DateTime lcl_getDateTime(RTFParserState& aState)
182 : {
183 : return util::DateTime(0 /*100sec*/, 0 /*sec*/, aState.nMinute, aState.nHour,
184 345 : aState.nDay, aState.nMonth, aState.nYear, false);
185 : }
186 :
187 1610 : static void lcl_DestinationToMath(OUStringBuffer& rDestinationText, oox::formulaimport::XmlStreamBuilder& rMathBuffer, bool& rMathNor)
188 : {
189 1610 : OUString aStr = rDestinationText.makeStringAndClear();
190 1610 : if (!aStr.isEmpty())
191 : {
192 589 : rMathBuffer.appendOpeningTag(M_TOKEN(r));
193 589 : if (rMathNor)
194 : {
195 9 : rMathBuffer.appendOpeningTag(M_TOKEN(rPr));
196 : // Same as M_TOKEN(lit)
197 9 : rMathBuffer.appendOpeningTag(M_TOKEN(nor));
198 9 : rMathBuffer.appendClosingTag(M_TOKEN(nor));
199 9 : rMathBuffer.appendClosingTag(M_TOKEN(rPr));
200 9 : rMathNor = false;
201 : }
202 589 : rMathBuffer.appendOpeningTag(M_TOKEN(t));
203 589 : rMathBuffer.appendCharacters(aStr);
204 589 : rMathBuffer.appendClosingTag(M_TOKEN(t));
205 589 : rMathBuffer.appendClosingTag(M_TOKEN(r));
206 1610 : }
207 1610 : }
208 :
209 504 : RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& xContext,
210 : uno::Reference<io::XInputStream> const& xInputStream,
211 : uno::Reference<lang::XComponent> const& xDstDoc,
212 : uno::Reference<frame::XFrame> const& xFrame,
213 : uno::Reference<task::XStatusIndicator> const& xStatusIndicator,
214 : bool bIsNewDoc)
215 : : m_xContext(xContext),
216 : m_xInputStream(xInputStream),
217 : m_xDstDoc(xDstDoc),
218 : m_xFrame(xFrame),
219 : m_xStatusIndicator(xStatusIndicator),
220 : m_pMapperStream(nullptr),
221 : m_aDefaultState(this),
222 : m_bSkipUnknown(false),
223 : m_aFontIndexes(),
224 : m_aColorTable(),
225 : m_bFirstRun(true),
226 : m_bNeedPap(true),
227 : m_bNeedCr(false),
228 : m_bNeedCrOrig(false),
229 : m_bNeedPar(true),
230 : m_bNeedFinalPar(false),
231 : m_aListTableSprms(),
232 : m_aSettingsTableAttributes(),
233 : m_aSettingsTableSprms(),
234 : m_xStorage(),
235 : m_nNestedCells(0),
236 : m_nTopLevelCells(0),
237 : m_nInheritingCells(0),
238 : m_nNestedCurrentCellX(0),
239 : m_nTopLevelCurrentCellX(0),
240 : m_nBackupTopLevelCurrentCellX(0),
241 : m_aTableBufferStack(1), // create top-level buffer already
242 : m_aSuperBuffer(),
243 : m_bHasFootnote(false),
244 : m_pSuperstream(nullptr),
245 : m_nStreamType(0),
246 : m_nHeaderFooterPositions(),
247 : m_nGroupStartPos(0),
248 : m_aBookmarks(),
249 : m_aAuthors(),
250 : m_aFormfieldSprms(),
251 : m_aFormfieldAttributes(),
252 : m_nFormFieldType(RTFFormFieldType::NONE),
253 : m_aOLEAttributes(),
254 : m_aObjectAttributes(),
255 : m_bObject(false),
256 : m_aFontTableEntries(),
257 : m_nCurrentFontIndex(0),
258 : m_nCurrentEncoding(-1),
259 : m_nDefaultFontIndex(-1),
260 : m_aStyleTableEntries(),
261 : m_nCurrentStyleIndex(0),
262 : m_bFormField(false),
263 : m_bIsInFrame(false),
264 : m_aUnicodeBuffer(),
265 : m_aHexBuffer(),
266 : m_bMathNor(false),
267 : m_bIgnoreNextContSectBreak(false),
268 : m_nResetBreakOnSectBreak(RTF_invalid),
269 : m_bNeedSect(false), // done by checkFirstRun
270 : m_bWasInFrame(false),
271 : m_bHadPicture(false),
272 : m_bHadSect(false),
273 : m_nCellxMax(0),
274 : m_nListPictureId(0),
275 504 : m_bIsNewDoc(bIsNewDoc)
276 : {
277 : OSL_ASSERT(xInputStream.is());
278 504 : m_pInStream.reset(utl::UcbStreamHelper::CreateStream(xInputStream, true));
279 :
280 504 : m_xModelFactory.set(m_xDstDoc, uno::UNO_QUERY);
281 :
282 504 : uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier(m_xDstDoc, uno::UNO_QUERY);
283 504 : if (xDocumentPropertiesSupplier.is())
284 478 : m_xDocumentProperties.set(xDocumentPropertiesSupplier->getDocumentProperties(), uno::UNO_QUERY);
285 :
286 504 : m_pGraphicHelper.reset(new oox::GraphicHelper(m_xContext, xFrame, m_xStorage));
287 :
288 504 : m_pTokenizer.reset(new RTFTokenizer(*this, m_pInStream.get(), m_xStatusIndicator));
289 504 : m_pSdrImport.reset(new RTFSdrImport(*this, m_xDstDoc));
290 504 : }
291 :
292 504 : RTFDocumentImpl::~RTFDocumentImpl()
293 : {
294 504 : }
295 :
296 31209114 : SvStream& RTFDocumentImpl::Strm()
297 : {
298 31209114 : return *m_pInStream;
299 : }
300 :
301 :
302 44 : void RTFDocumentImpl::setSuperstream(RTFDocumentImpl* pSuperstream)
303 : {
304 44 : m_pSuperstream = pSuperstream;
305 44 : }
306 :
307 44 : void RTFDocumentImpl::setStreamType(Id nId)
308 : {
309 44 : m_nStreamType = nId;
310 44 : }
311 :
312 6 : void RTFDocumentImpl::setAuthor(OUString& rAuthor)
313 : {
314 6 : m_aAuthor = rAuthor;
315 6 : }
316 :
317 5 : void RTFDocumentImpl::setAuthorInitials(OUString& rAuthorInitials)
318 : {
319 5 : m_aAuthorInitials = rAuthorInitials;
320 5 : }
321 :
322 527 : bool RTFDocumentImpl::isSubstream() const
323 : {
324 527 : return m_pSuperstream != nullptr;
325 : }
326 :
327 44 : void RTFDocumentImpl::finishSubstream()
328 : {
329 44 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
330 44 : }
331 :
332 44 : void RTFDocumentImpl::setIgnoreFirst(OUString& rIgnoreFirst)
333 : {
334 44 : m_aIgnoreFirst = rIgnoreFirst;
335 44 : }
336 :
337 32 : void RTFDocumentImpl::resolveSubstream(sal_Size nPos, Id nId)
338 : {
339 32 : OUString aStr;
340 32 : resolveSubstream(nPos, nId, aStr);
341 32 : }
342 44 : void RTFDocumentImpl::resolveSubstream(sal_Size nPos, Id nId, OUString& rIgnoreFirst)
343 : {
344 44 : sal_Size nCurrent = Strm().Tell();
345 : // Seek to header position, parse, then seek back.
346 44 : auto pImpl = std::make_shared<RTFDocumentImpl>(m_xContext, m_xInputStream, m_xDstDoc, m_xFrame, m_xStatusIndicator, m_bIsNewDoc);
347 44 : pImpl->setSuperstream(this);
348 44 : pImpl->setStreamType(nId);
349 44 : pImpl->setIgnoreFirst(rIgnoreFirst);
350 44 : if (!m_aAuthor.isEmpty())
351 : {
352 6 : pImpl->setAuthor(m_aAuthor);
353 6 : m_aAuthor.clear();
354 : }
355 44 : if (!m_aAuthorInitials.isEmpty())
356 : {
357 5 : pImpl->setAuthorInitials(m_aAuthorInitials);
358 5 : m_aAuthorInitials.clear();
359 : }
360 44 : pImpl->m_nDefaultFontIndex = m_nDefaultFontIndex;
361 44 : pImpl->seek(nPos);
362 : SAL_INFO("writerfilter", "substream start");
363 44 : Mapper().substream(nId, pImpl);
364 : SAL_INFO("writerfilter", "substream end");
365 44 : Strm().Seek(nCurrent);
366 44 : }
367 :
368 8489 : void RTFDocumentImpl::checkFirstRun()
369 : {
370 8489 : if (m_bFirstRun)
371 : {
372 : // output settings table
373 495 : writerfilter::Reference<Properties>::Pointer_t pProp = std::make_shared<RTFReferenceProperties>(m_aSettingsTableAttributes, m_aSettingsTableSprms);
374 990 : RTFReferenceTable::Entries_t aSettingsTableEntries;
375 495 : aSettingsTableEntries.insert(std::make_pair(0, pProp));
376 990 : writerfilter::Reference<Table>::Pointer_t pTable = std::make_shared<RTFReferenceTable>(aSettingsTableEntries);
377 495 : Mapper().table(NS_ooxml::LN_settings_settings, pTable);
378 : // start initial paragraph
379 495 : m_bFirstRun = false;
380 : assert(!m_bNeedSect);
381 495 : setNeedSect(); // first call that succeeds
382 :
383 : // set the requested default font, if there are none
384 990 : RTFValue::Pointer_t pFont = lcl_getNestedAttribute(m_aDefaultState.aCharacterSprms, NS_ooxml::LN_EG_RPrBase_rFonts, NS_ooxml::LN_CT_Fonts_ascii);
385 990 : RTFValue::Pointer_t pCurrentFont = lcl_getNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_EG_RPrBase_rFonts, NS_ooxml::LN_CT_Fonts_ascii);
386 495 : if (pFont && !pCurrentFont)
387 512 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_EG_RPrBase_rFonts, NS_ooxml::LN_CT_Fonts_ascii, pFont);
388 : }
389 8489 : }
390 :
391 :
392 521 : void RTFDocumentImpl::setNeedPar(bool bNeedPar)
393 : {
394 521 : m_bNeedPar = bNeedPar;
395 521 : }
396 :
397 170987 : void RTFDocumentImpl::setNeedSect(bool bNeedSect)
398 : {
399 : // ignore setting before checkFirstRun - every keyword calls setNeedSect!
400 170987 : if (!m_bNeedSect && bNeedSect && !m_bFirstRun)
401 : {
402 509 : if (!m_pSuperstream) // no sections in header/footer!
403 : {
404 467 : Mapper().startSectionGroup();
405 : }
406 : // set flag in substream too - otherwise multiple startParagraphGroup
407 509 : m_bNeedSect = bNeedSect;
408 509 : Mapper().startParagraphGroup();
409 509 : setNeedPar(true);
410 : }
411 170478 : else if (m_bNeedSect && !bNeedSect)
412 : {
413 0 : m_bNeedSect = bNeedSect;
414 : }
415 170987 : }
416 :
417 : /// Copy rProps to rStyleAttributes and rStyleSprms, but in case of nested sprms, copy their children as toplevel sprms/attributes.
418 3098 : static void lcl_copyFlatten(RTFReferenceProperties& rProps, RTFSprms& rStyleAttributes, RTFSprms& rStyleSprms)
419 : {
420 14189 : for (RTFSprms::Iterator_t it = rProps.getSprms().begin(); it != rProps.getSprms().end(); ++it)
421 : {
422 : // createStyleProperties() puts properties to rPr, but here we need a flat list.
423 11091 : if (it->first == NS_ooxml::LN_CT_Style_rPr)
424 : {
425 : // rPr can have both attributes and SPRMs, copy over both types.
426 3098 : RTFSprms& rRPrSprms = it->second->getSprms();
427 19964 : for (RTFSprms::Iterator_t itRPrSprm = rRPrSprms.begin(); itRPrSprm != rRPrSprms.end(); ++itRPrSprm)
428 16866 : rStyleSprms.set(itRPrSprm->first, itRPrSprm->second);
429 :
430 3098 : RTFSprms& rRPrAttributes = it->second->getAttributes();
431 3099 : for (RTFSprms::Iterator_t itRPrAttribute = rRPrAttributes.begin(); itRPrAttribute != rRPrAttributes.end(); ++itRPrAttribute)
432 1 : rStyleAttributes.set(itRPrAttribute->first, itRPrAttribute->second);
433 : }
434 : else
435 7993 : rStyleSprms.set(it->first, it->second);
436 : }
437 :
438 3098 : RTFSprms& rAttributes = rProps.getAttributes();
439 9294 : for (RTFSprms::Iterator_t itAttr = rAttributes.begin(); itAttr != rAttributes.end(); ++itAttr)
440 6196 : rStyleAttributes.set(itAttr->first, itAttr->second);
441 3098 : }
442 :
443 7032 : writerfilter::Reference<Properties>::Pointer_t RTFDocumentImpl::getProperties(RTFSprms& rAttributes, RTFSprms& rSprms)
444 : {
445 7032 : int nStyle = 0;
446 7032 : if (!m_aStates.empty())
447 7031 : nStyle = m_aStates.top().nCurrentStyleIndex;
448 7032 : RTFReferenceTable::Entries_t::iterator it = m_aStyleTableEntries.find(nStyle);
449 7032 : if (it != m_aStyleTableEntries.end())
450 : {
451 3090 : RTFReferenceProperties& rProps = *static_cast<RTFReferenceProperties*>(it->second.get());
452 :
453 : // cloneAndDeduplicate() wants to know about only a single "style", so
454 : // let's merge paragraph and character style properties here.
455 3090 : int nCharStyle = m_aStates.top().nCurrentCharacterStyleIndex;
456 3090 : RTFReferenceTable::Entries_t::iterator itChar = m_aStyleTableEntries.find(nCharStyle);
457 3090 : RTFSprms aStyleSprms;
458 6180 : RTFSprms aStyleAttributes;
459 :
460 : // Ensure the paragraph style is a flat list.
461 3090 : lcl_copyFlatten(rProps, aStyleAttributes, aStyleSprms);
462 :
463 3090 : if (itChar != m_aStyleTableEntries.end())
464 : {
465 : // Found active character style, then update aStyleSprms/Attributes.
466 8 : RTFReferenceProperties& rCharProps = *static_cast<RTFReferenceProperties*>(itChar->second.get());
467 8 : lcl_copyFlatten(rCharProps, aStyleAttributes, aStyleSprms);
468 : }
469 :
470 : // Get rid of direct formatting what is already in the style.
471 6180 : RTFSprms const sprms(rSprms.cloneAndDeduplicate(aStyleSprms));
472 6180 : RTFSprms const attributes(rAttributes.cloneAndDeduplicate(aStyleAttributes));
473 6180 : return std::make_shared<RTFReferenceProperties>(attributes, sprms);
474 : }
475 3942 : writerfilter::Reference<Properties>::Pointer_t pRet = std::make_shared<RTFReferenceProperties>(rAttributes, rSprms);
476 3942 : return pRet;
477 : }
478 :
479 7998 : void RTFDocumentImpl::checkNeedPap()
480 : {
481 7998 : if (m_bNeedPap)
482 : {
483 2016 : m_bNeedPap = false; // reset early, so we can avoid recursion when calling ourselves
484 :
485 2016 : if (m_aStates.empty())
486 7999 : return;
487 :
488 2015 : if (!m_aStates.top().pCurrentBuffer)
489 : {
490 : writerfilter::Reference<Properties>::Pointer_t const pParagraphProperties(
491 3424 : getProperties(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms)
492 3424 : );
493 :
494 : // Writer will ignore a page break before a text frame, so guard it with empty paragraphs
495 1772 : bool hasBreakBeforeFrame = m_aStates.top().aFrame.hasProperties() &&
496 1772 : m_aStates.top().aParagraphSprms.find(NS_ooxml::LN_CT_PPrBase_pageBreakBefore).get();
497 1712 : if (hasBreakBeforeFrame)
498 : {
499 0 : dispatchSymbol(RTF_PAR);
500 0 : m_bNeedPap = false;
501 : }
502 1712 : Mapper().props(pParagraphProperties);
503 1712 : if (hasBreakBeforeFrame)
504 0 : dispatchSymbol(RTF_PAR);
505 :
506 1712 : if (m_aStates.top().aFrame.hasProperties())
507 : {
508 : writerfilter::Reference<Properties>::Pointer_t const pFrameProperties(
509 30 : new RTFReferenceProperties(RTFSprms(), m_aStates.top().aFrame.getSprms()));
510 30 : Mapper().props(pFrameProperties);
511 1712 : }
512 : }
513 : else
514 : {
515 303 : auto pValue = std::make_shared<RTFValue>(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms);
516 303 : m_aStates.top().pCurrentBuffer->push_back(
517 606 : Buf_t(BUFFER_PROPS, pValue));
518 : }
519 : }
520 : }
521 :
522 4677 : void RTFDocumentImpl::runProps()
523 : {
524 4677 : if (!m_aStates.top().pCurrentBuffer)
525 : {
526 4189 : writerfilter::Reference<Properties>::Pointer_t const pProperties = getProperties(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms);
527 4189 : Mapper().props(pProperties);
528 : }
529 : else
530 : {
531 488 : auto pValue = std::make_shared<RTFValue>(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms);
532 488 : m_aStates.top().pCurrentBuffer->push_back(Buf_t(BUFFER_PROPS, pValue));
533 : }
534 :
535 : // Delete the sprm, so the trackchange range will be started only once.
536 : // OTOH set a boolean flag, so we'll know we need to end the range later.
537 4677 : RTFValue::Pointer_t pTrackchange = m_aStates.top().aCharacterSprms.find(NS_ooxml::LN_trackchange);
538 4677 : if (pTrackchange.get())
539 : {
540 2 : m_aStates.top().bStartedTrackchange = true;
541 2 : m_aStates.top().aCharacterSprms.erase(NS_ooxml::LN_trackchange);
542 4677 : }
543 4677 : }
544 :
545 2216 : void RTFDocumentImpl::runBreak()
546 : {
547 2216 : sal_uInt8 sBreak[] = { 0xd };
548 2216 : Mapper().text(sBreak, 1);
549 2216 : m_bNeedCr = false;
550 2216 : }
551 :
552 508 : void RTFDocumentImpl::tableBreak()
553 : {
554 508 : runBreak();
555 508 : Mapper().endParagraphGroup();
556 508 : Mapper().startParagraphGroup();
557 508 : }
558 :
559 1708 : void RTFDocumentImpl::parBreak()
560 : {
561 1708 : checkFirstRun();
562 1708 : checkNeedPap();
563 : // end previous paragraph
564 1708 : Mapper().startCharacterGroup();
565 1708 : runBreak();
566 1708 : Mapper().endCharacterGroup();
567 1708 : Mapper().endParagraphGroup();
568 :
569 1708 : m_bHadPicture = false;
570 :
571 : // start new one
572 1708 : Mapper().startParagraphGroup();
573 1708 : }
574 :
575 505 : void RTFDocumentImpl::sectBreak(bool bFinal = false)
576 : {
577 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": final? " << bFinal << ", needed? " << m_bNeedSect);
578 505 : bool bNeedSect = m_bNeedSect;
579 505 : RTFValue::Pointer_t pBreak = m_aStates.top().aSectionSprms.find(NS_ooxml::LN_EG_SectPrContents_type);
580 505 : bool bContinuous = pBreak.get() && pBreak->getInt() == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_continuous);
581 : // If there is no paragraph in this section, then insert a dummy one, as required by Writer,
582 : // unless this is the end of the doc, we had nothing since the last section break and this is not a continuous one.
583 : // Also, when pasting, it's fine to not have any paragraph inside the document at all.
584 505 : if (m_bNeedPar && !(bFinal && !m_bNeedSect && !bContinuous) && !isSubstream() && m_bIsNewDoc)
585 13 : dispatchSymbol(RTF_PAR);
586 : // It's allowed to not have a non-table paragraph at the end of an RTF doc, add it now if required.
587 505 : if (m_bNeedFinalPar && bFinal)
588 : {
589 5 : dispatchFlag(RTF_PARD);
590 5 : dispatchSymbol(RTF_PAR);
591 5 : m_bNeedSect = bNeedSect;
592 : }
593 1035 : while (!m_nHeaderFooterPositions.empty())
594 : {
595 25 : std::pair<Id, sal_Size> aPair = m_nHeaderFooterPositions.front();
596 25 : m_nHeaderFooterPositions.pop();
597 25 : resolveSubstream(aPair.second, aPair.first);
598 : }
599 :
600 : // Normally a section break at the end of the doc is necessary. Unless the
601 : // last control word in the document is a section break itself.
602 505 : if (!bNeedSect || !m_bHadSect)
603 : {
604 : // In case the last section is a continuous one, we don't need to output a section break.
605 486 : if (bFinal && bContinuous)
606 113 : m_aStates.top().aSectionSprms.erase(NS_ooxml::LN_EG_SectPrContents_type);
607 : }
608 :
609 : // Section properties are a paragraph sprm.
610 1010 : auto pValue = std::make_shared<RTFValue>(m_aStates.top().aSectionAttributes, m_aStates.top().aSectionSprms);
611 1010 : RTFSprms aAttributes;
612 1010 : RTFSprms aSprms;
613 505 : aSprms.set(NS_ooxml::LN_CT_PPr_sectPr, pValue);
614 1010 : writerfilter::Reference<Properties>::Pointer_t pProperties = std::make_shared<RTFReferenceProperties>(aAttributes, aSprms);
615 :
616 505 : if (bFinal && !m_pSuperstream)
617 : // This is the end of the document, not just the end of e.g. a header.
618 : // This makes sure that dmapper can set DontBalanceTextColumns=true for this section if necessary.
619 447 : Mapper().markLastSectionGroup();
620 :
621 : // The trick is that we send properties of the previous section right now, which will be exactly what dmapper expects.
622 505 : Mapper().props(pProperties);
623 505 : Mapper().endParagraphGroup();
624 505 : if (!m_pSuperstream)
625 463 : Mapper().endSectionGroup();
626 505 : m_bNeedPar = false;
627 1010 : m_bNeedSect = false;
628 505 : }
629 :
630 44 : void RTFDocumentImpl::seek(sal_Size nPos)
631 : {
632 44 : Strm().Seek(nPos);
633 44 : }
634 :
635 1126 : sal_uInt32 RTFDocumentImpl::getColorTable(sal_uInt32 nIndex)
636 : {
637 1126 : if (!m_pSuperstream)
638 : {
639 1119 : if (nIndex < m_aColorTable.size())
640 931 : return m_aColorTable[nIndex];
641 188 : return 0;
642 : }
643 : else
644 7 : return m_pSuperstream->getColorTable(nIndex);
645 : }
646 :
647 4241 : rtl_TextEncoding RTFDocumentImpl::getEncoding(int nFontIndex)
648 : {
649 4241 : if (!m_pSuperstream)
650 : {
651 4208 : std::map<int, rtl_TextEncoding>::iterator it = m_aFontEncodings.find(nFontIndex);
652 4208 : if (it != m_aFontEncodings.end())
653 : // We have a font encoding associated to this font.
654 3104 : return it->second;
655 1104 : else if (m_aDefaultState.nCurrentEncoding != rtl_getTextEncodingFromWindowsCharset(0))
656 : // We have a default encoding.
657 46 : return m_aDefaultState.nCurrentEncoding;
658 : else
659 : // Guess based on locale.
660 1058 : return msfilter::util::getBestTextEncodingFromLocale(Application::GetSettings().GetLanguageTag().getLocale());
661 : }
662 : else
663 33 : return m_pSuperstream->getEncoding(nFontIndex);
664 : }
665 :
666 11865 : OUString RTFDocumentImpl::getFontName(int nIndex)
667 : {
668 11865 : if (!m_pSuperstream)
669 11820 : return m_aFontNames[nIndex];
670 : else
671 45 : return m_pSuperstream->getFontName(nIndex);
672 : }
673 :
674 16788 : int RTFDocumentImpl::getFontIndex(int nIndex)
675 : {
676 16788 : if (!m_pSuperstream)
677 16719 : return std::find(m_aFontIndexes.begin(), m_aFontIndexes.end(), nIndex) - m_aFontIndexes.begin();
678 : else
679 69 : return m_pSuperstream->getFontIndex(nIndex);
680 : }
681 :
682 2994 : OUString RTFDocumentImpl::getStyleName(int nIndex)
683 : {
684 2994 : if (!m_pSuperstream)
685 : {
686 2941 : OUString aRet;
687 2941 : if (m_aStyleNames.find(nIndex) != m_aStyleNames.end())
688 2394 : aRet = m_aStyleNames[nIndex];
689 2941 : return aRet;
690 : }
691 : else
692 53 : return m_pSuperstream->getStyleName(nIndex);
693 : }
694 :
695 1844 : RTFParserState& RTFDocumentImpl::getDefaultState()
696 : {
697 1844 : if (!m_pSuperstream)
698 1796 : return m_aDefaultState;
699 : else
700 48 : return m_pSuperstream->getDefaultState();
701 : }
702 :
703 18 : oox::GraphicHelper& RTFDocumentImpl::getGraphicHelper()
704 : {
705 18 : return *m_pGraphicHelper;
706 : }
707 :
708 504 : void RTFDocumentImpl::resolve(Stream& rMapper)
709 : {
710 504 : m_pMapperStream = &rMapper;
711 504 : switch (m_pTokenizer->resolveParse())
712 : {
713 : case RTFError::OK:
714 : SAL_INFO("writerfilter", "RTFDocumentImpl::resolve: finished without errors");
715 500 : break;
716 : case RTFError::GROUP_UNDER:
717 : SAL_INFO("writerfilter", "RTFDocumentImpl::resolve: unmatched '}'");
718 0 : break;
719 : case RTFError::GROUP_OVER:
720 : SAL_INFO("writerfilter", "RTFDocumentImpl::resolve: unmatched '{'");
721 3 : throw io::WrongFormatException(m_pTokenizer->getPosition());
722 : break;
723 : case RTFError::UNEXPECTED_EOF:
724 : SAL_INFO("writerfilter", "RTFDocumentImpl::resolve: unexpected end of file");
725 0 : throw io::WrongFormatException(m_pTokenizer->getPosition());
726 : break;
727 : case RTFError::HEX_INVALID:
728 : SAL_INFO("writerfilter", "RTFDocumentImpl::resolve: invalid hex char");
729 0 : throw io::WrongFormatException(m_pTokenizer->getPosition());
730 : break;
731 : case RTFError::CHAR_OVER:
732 : SAL_INFO("writerfilter", "RTFDocumentImpl::resolve: characters after last '}'");
733 0 : break;
734 : }
735 500 : }
736 :
737 41 : RTFError RTFDocumentImpl::resolvePict(bool const bInline, uno::Reference<drawing::XShape> const& i_xShape)
738 : {
739 41 : SvMemoryStream aStream;
740 41 : SvStream* pStream = nullptr;
741 41 : if (!m_pBinaryData.get())
742 : {
743 39 : pStream = &aStream;
744 39 : int b = 0, count = 2;
745 :
746 : // Feed the destination text to a stream.
747 39 : OString aStr = OUStringToOString(m_aStates.top().aDestinationText.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
748 39 : const char* str = aStr.getStr();
749 1794373 : for (int i = 0; i < aStr.getLength(); ++i)
750 : {
751 1794334 : char ch = str[i];
752 1794334 : if (ch != 0x0d && ch != 0x0a && ch != 0x20)
753 : {
754 1794334 : b = b << 4;
755 1794334 : sal_Int8 parsed = RTFTokenizer::asHex(ch);
756 1794334 : if (parsed == -1)
757 0 : return RTFError::HEX_INVALID;
758 1794334 : b += parsed;
759 1794334 : count--;
760 1794334 : if (!count)
761 : {
762 897167 : aStream.WriteChar((char)b);
763 897167 : count = 2;
764 897167 : b = 0;
765 : }
766 : }
767 39 : }
768 : }
769 : else
770 2 : pStream = m_pBinaryData.get();
771 :
772 41 : if (!pStream->Tell())
773 : // No destination text? Then we'll get it later.
774 1 : return RTFError::OK;
775 :
776 : // Store, and get its URL.
777 40 : pStream->Seek(0);
778 80 : uno::Reference<io::XInputStream> xInputStream(new utl::OInputStreamWrapper(pStream));
779 40 : WMF_EXTERNALHEADER aExtHeader;
780 40 : aExtHeader.mapMode = m_aStates.top().aPicture.eWMetafile;
781 40 : aExtHeader.xExt = m_aStates.top().aPicture.nWidth;
782 40 : aExtHeader.yExt = m_aStates.top().aPicture.nHeight;
783 40 : WMF_EXTERNALHEADER* pExtHeader = &aExtHeader;
784 80 : uno::Reference<lang::XServiceInfo> xServiceInfo(m_aStates.top().aDrawingObject.xShape, uno::UNO_QUERY);
785 40 : if (xServiceInfo.is() && xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
786 0 : pExtHeader = nullptr;
787 80 : OUString aGraphicUrl = m_pGraphicHelper->importGraphicObject(xInputStream, pExtHeader);
788 :
789 40 : if (m_aStates.top().aPicture.eStyle != RTFBmpStyle::NONE)
790 : {
791 : // In case of PNG/JPEG, the real size is known, don't use the values
792 : // provided by picw and pich.
793 32 : OString aURLBS(OUStringToOString(aGraphicUrl, RTL_TEXTENCODING_UTF8));
794 32 : const char aURLBegin[] = "vnd.sun.star.GraphicObject:";
795 32 : if (aURLBS.startsWith(aURLBegin))
796 : {
797 32 : Graphic aGraphic = GraphicObject(aURLBS.copy(RTL_CONSTASCII_LENGTH(aURLBegin))).GetTransformedGraphic();
798 32 : Size aSize(aGraphic.GetPrefSize());
799 64 : MapMode aMap(MAP_100TH_MM);
800 32 : if (aGraphic.GetPrefMapMode().GetMapUnit() == MAP_PIXEL)
801 21 : aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMap);
802 : else
803 11 : aSize = OutputDevice::LogicToLogic(aSize, aGraphic.GetPrefMapMode(), aMap);
804 32 : m_aStates.top().aPicture.nWidth = aSize.Width();
805 64 : m_aStates.top().aPicture.nHeight = aSize.Height();
806 32 : }
807 : }
808 :
809 : // Wrap it in an XShape.
810 80 : uno::Reference<drawing::XShape> xShape(i_xShape);
811 40 : if (xShape.is())
812 : {
813 25 : uno::Reference<lang::XServiceInfo> xSI(xShape, uno::UNO_QUERY_THROW);
814 25 : if (!xSI->supportsService("com.sun.star.drawing.GraphicObjectShape"))
815 : {
816 : // it's sometimes an error to get here - but it's possible to have
817 : // a \pict inside the \shptxt of a \shp of shapeType 202 "TextBox"
818 : // and in that case xShape is the text frame; we actually need a
819 : // new GraphicObject then (example: fdo37691-1.rtf)
820 : SAL_INFO("writerfilter.rtf", "cannot set graphic on existing shape, creating a new GraphicObjectShape");
821 1 : xShape.clear();
822 25 : }
823 : }
824 40 : if (!xShape.is())
825 : {
826 16 : if (m_xModelFactory.is())
827 14 : xShape.set(m_xModelFactory->createInstance("com.sun.star.drawing.GraphicObjectShape"), uno::UNO_QUERY);
828 16 : uno::Reference<drawing::XDrawPageSupplier> const xDrawSupplier(m_xDstDoc, uno::UNO_QUERY);
829 16 : if (xDrawSupplier.is())
830 : {
831 14 : uno::Reference<drawing::XShapes> xShapes(xDrawSupplier->getDrawPage(), uno::UNO_QUERY);
832 14 : if (xShapes.is())
833 14 : xShapes->add(xShape);
834 16 : }
835 : }
836 :
837 80 : uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
838 :
839 : // check if the picture is in an OLE object and if the \objdata element is used
840 : // (see RTF_OBJECT in RTFDocumentImpl::dispatchDestination)
841 40 : if (m_bObject)
842 : {
843 : // Set bitmap
844 2 : beans::PropertyValues aMediaProperties(1);
845 2 : aMediaProperties[0].Name = "URL";
846 2 : aMediaProperties[0].Value <<= aGraphicUrl;
847 4 : uno::Reference<graphic::XGraphicProvider> xGraphicProvider(graphic::GraphicProvider::create(m_xContext));
848 4 : uno::Reference<graphic::XGraphic> xGraphic = xGraphicProvider->queryGraphic(aMediaProperties);
849 2 : xPropertySet->setPropertyValue("Graphic", uno::Any(xGraphic));
850 :
851 : // Set the object size
852 2 : awt::Size aSize;
853 2 : aSize.Width = (m_aStates.top().aPicture.nGoalWidth ? m_aStates.top().aPicture.nGoalWidth : m_aStates.top().aPicture.nWidth);
854 2 : aSize.Height = (m_aStates.top().aPicture.nGoalHeight ? m_aStates.top().aPicture.nGoalHeight : m_aStates.top().aPicture.nHeight);
855 2 : xShape->setSize(aSize);
856 :
857 : // Replacement graphic is inline by default, see oox::vml::SimpleShape::implConvertAndInsert().
858 2 : xPropertySet->setPropertyValue("AnchorType", uno::makeAny(text::TextContentAnchorType_AS_CHARACTER));
859 :
860 4 : auto pShapeValue = std::make_shared<RTFValue>(xShape);
861 2 : m_aObjectAttributes.set(NS_ooxml::LN_shape, pShapeValue);
862 4 : return RTFError::OK;
863 : }
864 :
865 38 : if (xPropertySet.is())
866 36 : xPropertySet->setPropertyValue("GraphicURL", uno::Any(aGraphicUrl));
867 :
868 38 : if (m_aStates.top().bInListpicture)
869 : {
870 : // Send the shape directly, no section is started, to additional properties will be ignored anyway.
871 3 : Mapper().startShape(xShape);
872 3 : Mapper().endShape();
873 3 : return RTFError::OK;
874 : }
875 :
876 : // Send it to the dmapper.
877 70 : RTFSprms aSprms;
878 70 : RTFSprms aAttributes;
879 : // shape attribute
880 70 : RTFSprms aPicAttributes;
881 70 : auto pShapeValue = std::make_shared<RTFValue>(xShape);
882 35 : aPicAttributes.set(NS_ooxml::LN_shape, pShapeValue);
883 : // pic sprm
884 70 : RTFSprms aGraphicDataAttributes;
885 70 : RTFSprms aGraphicDataSprms;
886 70 : auto pPicValue = std::make_shared<RTFValue>(aPicAttributes);
887 35 : aGraphicDataSprms.set(NS_ooxml::LN_pic_pic, pPicValue);
888 : // graphicData sprm
889 70 : RTFSprms aGraphicAttributes;
890 70 : RTFSprms aGraphicSprms;
891 70 : auto pGraphicDataValue = std::make_shared<RTFValue>(aGraphicDataAttributes, aGraphicDataSprms);
892 35 : aGraphicSprms.set(NS_ooxml::LN_CT_GraphicalObject_graphicData, pGraphicDataValue);
893 : // graphic sprm
894 70 : auto pGraphicValue = std::make_shared<RTFValue>(aGraphicAttributes, aGraphicSprms);
895 : // extent sprm
896 70 : RTFSprms aExtentAttributes;
897 : int nXExt, nYExt;
898 35 : nXExt = (m_aStates.top().aPicture.nGoalWidth ? m_aStates.top().aPicture.nGoalWidth : m_aStates.top().aPicture.nWidth);
899 35 : nYExt = (m_aStates.top().aPicture.nGoalHeight ? m_aStates.top().aPicture.nGoalHeight : m_aStates.top().aPicture.nHeight);
900 35 : if (m_aStates.top().aPicture.nScaleX != 100)
901 16 : nXExt = (((long)m_aStates.top().aPicture.nScaleX) * (nXExt - (m_aStates.top().aPicture.nCropL + m_aStates.top().aPicture.nCropR))) / 100L;
902 35 : if (m_aStates.top().aPicture.nScaleY != 100)
903 16 : nYExt = (((long)m_aStates.top().aPicture.nScaleY) * (nYExt - (m_aStates.top().aPicture.nCropT + m_aStates.top().aPicture.nCropB))) / 100L;
904 35 : if (m_aStates.top().bInShape)
905 : {
906 : // Picture in shape: it looks like pib picture, so we will stretch the picture to shape size (tdf#49893)
907 22 : nXExt = m_aStates.top().aShape.nRight - m_aStates.top().aShape.nLeft;
908 22 : nYExt = m_aStates.top().aShape.nBottom - m_aStates.top().aShape.nTop;
909 : }
910 70 : auto pXExtValue = std::make_shared<RTFValue>(oox::drawingml::convertHmmToEmu(nXExt));
911 70 : auto pYExtValue = std::make_shared<RTFValue>(oox::drawingml::convertHmmToEmu(nYExt));
912 35 : aExtentAttributes.set(NS_ooxml::LN_CT_PositiveSize2D_cx, pXExtValue);
913 35 : aExtentAttributes.set(NS_ooxml::LN_CT_PositiveSize2D_cy, pYExtValue);
914 70 : auto pExtentValue = std::make_shared<RTFValue>(aExtentAttributes);
915 : // docpr sprm
916 70 : RTFSprms aDocprAttributes;
917 50 : for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterAttributes.begin(); i != m_aStates.top().aCharacterAttributes.end(); ++i)
918 15 : if (i->first == NS_ooxml::LN_CT_NonVisualDrawingProps_name || i->first == NS_ooxml::LN_CT_NonVisualDrawingProps_descr)
919 0 : aDocprAttributes.set(i->first, i->second);
920 70 : auto pDocprValue = std::make_shared<RTFValue>(aDocprAttributes);
921 35 : if (bInline)
922 : {
923 14 : RTFSprms aInlineAttributes;
924 14 : aInlineAttributes.set(NS_ooxml::LN_CT_Inline_distT, std::make_shared<RTFValue>(0));
925 14 : aInlineAttributes.set(NS_ooxml::LN_CT_Inline_distB, std::make_shared<RTFValue>(0));
926 14 : aInlineAttributes.set(NS_ooxml::LN_CT_Inline_distL, std::make_shared<RTFValue>(0));
927 14 : aInlineAttributes.set(NS_ooxml::LN_CT_Inline_distR, std::make_shared<RTFValue>(0));
928 28 : RTFSprms aInlineSprms;
929 14 : aInlineSprms.set(NS_ooxml::LN_CT_Inline_extent, pExtentValue);
930 14 : aInlineSprms.set(NS_ooxml::LN_CT_Inline_docPr, pDocprValue);
931 14 : aInlineSprms.set(NS_ooxml::LN_graphic_graphic, pGraphicValue);
932 : // inline sprm
933 28 : auto pValue = std::make_shared<RTFValue>(aInlineAttributes, aInlineSprms);
934 28 : aSprms.set(NS_ooxml::LN_inline_inline, pValue);
935 : }
936 : else // anchored
937 : {
938 : // wrap sprm
939 21 : RTFSprms aAnchorWrapAttributes;
940 21 : m_aStates.top().aShape.aAnchorAttributes.set(NS_ooxml::LN_CT_Anchor_behindDoc, std::make_shared<RTFValue>((m_aStates.top().aShape.bInBackground) ? 1 : 0));
941 42 : RTFSprms aAnchorSprms;
942 36 : for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterAttributes.begin(); i != m_aStates.top().aCharacterAttributes.end(); ++i)
943 : {
944 15 : if (i->first == NS_ooxml::LN_CT_WrapSquare_wrapText)
945 15 : aAnchorWrapAttributes.set(i->first, i->second);
946 : }
947 21 : sal_Int32 nWrap = -1;
948 86 : for (RTFSprms::Iterator_t i = m_aStates.top().aCharacterSprms.begin(); i != m_aStates.top().aCharacterSprms.end(); ++i)
949 : {
950 65 : if (i->first == NS_ooxml::LN_EG_WrapType_wrapNone || i->first == NS_ooxml::LN_EG_WrapType_wrapTight)
951 : {
952 12 : nWrap = i->first;
953 :
954 : // If there is a wrap polygon prepared by RTFSdrImport, pick it up here.
955 12 : if (i->first == NS_ooxml::LN_EG_WrapType_wrapTight && !m_aStates.top().aShape.aWrapPolygonSprms.empty())
956 3 : i->second->getSprms().set(NS_ooxml::LN_CT_WrapTight_wrapPolygon, std::make_shared<RTFValue>(RTFSprms(), m_aStates.top().aShape.aWrapPolygonSprms));
957 :
958 12 : aAnchorSprms.set(i->first, i->second);
959 : }
960 : }
961 42 : auto pAnchorWrapValue = std::make_shared<RTFValue>(aAnchorWrapAttributes);
962 21 : aAnchorSprms.set(NS_ooxml::LN_CT_Anchor_extent, pExtentValue);
963 21 : if (aAnchorWrapAttributes.size() && nWrap == -1)
964 7 : aAnchorSprms.set(NS_ooxml::LN_EG_WrapType_wrapSquare, pAnchorWrapValue);
965 :
966 : // See OOXMLFastContextHandler::positionOffset(), we can't just put offset values in an RTFValue.
967 42 : RTFSprms aPoshAttributes;
968 42 : RTFSprms aPoshSprms;
969 21 : if (m_aStates.top().aShape.nHoriOrientRelationToken > 0)
970 4 : aPoshAttributes.set(NS_ooxml::LN_CT_PosH_relativeFrom, std::make_shared<RTFValue>(m_aStates.top().aShape.nHoriOrientRelationToken));
971 21 : if (m_aStates.top().aShape.nLeft != 0)
972 : {
973 18 : Mapper().positionOffset(OUString::number(oox::drawingml::convertHmmToEmu(m_aStates.top().aShape.nLeft)), /*bVertical=*/false);
974 18 : aPoshSprms.set(NS_ooxml::LN_CT_PosH_posOffset, std::make_shared<RTFValue>());
975 : }
976 21 : aAnchorSprms.set(NS_ooxml::LN_CT_Anchor_positionH, std::make_shared<RTFValue>(aPoshAttributes, aPoshSprms));
977 :
978 42 : RTFSprms aPosvAttributes;
979 42 : RTFSprms aPosvSprms;
980 21 : if (m_aStates.top().aShape.nVertOrientRelationToken > 0)
981 4 : aPosvAttributes.set(NS_ooxml::LN_CT_PosV_relativeFrom, std::make_shared<RTFValue>(m_aStates.top().aShape.nVertOrientRelationToken));
982 21 : if (m_aStates.top().aShape.nTop != 0)
983 : {
984 16 : Mapper().positionOffset(OUString::number(oox::drawingml::convertHmmToEmu(m_aStates.top().aShape.nTop)), /*bVertical=*/true);
985 16 : aPosvSprms.set(NS_ooxml::LN_CT_PosV_posOffset, std::make_shared<RTFValue>());
986 : }
987 21 : aAnchorSprms.set(NS_ooxml::LN_CT_Anchor_positionV, std::make_shared<RTFValue>(aPosvAttributes, aPosvSprms));
988 :
989 21 : aAnchorSprms.set(NS_ooxml::LN_CT_Anchor_docPr, pDocprValue);
990 21 : aAnchorSprms.set(NS_ooxml::LN_graphic_graphic, pGraphicValue);
991 : // anchor sprm
992 42 : auto pValue = std::make_shared<RTFValue>(m_aStates.top().aShape.aAnchorAttributes, aAnchorSprms);
993 42 : aSprms.set(NS_ooxml::LN_anchor_anchor, pValue);
994 : }
995 70 : writerfilter::Reference<Properties>::Pointer_t pProperties = std::make_shared<RTFReferenceProperties>(aAttributes, aSprms);
996 35 : checkFirstRun();
997 :
998 35 : if (!m_aStates.top().pCurrentBuffer)
999 : {
1000 31 : Mapper().props(pProperties);
1001 : // Make sure we don't lose these properties with a too early reset.
1002 31 : m_bHadPicture = true;
1003 : }
1004 : else
1005 : {
1006 4 : auto pValue = std::make_shared<RTFValue>(aAttributes, aSprms);
1007 4 : m_aStates.top().pCurrentBuffer->push_back(Buf_t(BUFFER_PROPS, pValue));
1008 : }
1009 :
1010 76 : return RTFError::OK;
1011 : }
1012 :
1013 60269 : RTFError RTFDocumentImpl::resolveChars(char ch)
1014 : {
1015 60269 : if (m_aStates.top().nInternalState == RTFInternalState::BIN)
1016 : {
1017 2 : m_pBinaryData.reset(new SvMemoryStream());
1018 2 : m_pBinaryData->WriteChar(ch);
1019 25604 : for (int i = 0; i < m_aStates.top().nBinaryToRead - 1; ++i)
1020 : {
1021 25602 : Strm().ReadChar(ch);
1022 25602 : m_pBinaryData->WriteChar(ch);
1023 : }
1024 2 : m_aStates.top().nInternalState = RTFInternalState::NORMAL;
1025 2 : return RTFError::OK;
1026 : }
1027 :
1028 :
1029 60267 : OStringBuffer aBuf;
1030 :
1031 60267 : bool bUnicodeChecked = false;
1032 60267 : bool bSkipped = false;
1033 :
1034 15635954 : while (!Strm().IsEof() && (m_aStates.top().nInternalState == RTFInternalState::HEX || (ch != '{' && ch != '}' && ch != '\\')))
1035 : {
1036 15542733 : if (m_aStates.top().nInternalState == RTFInternalState::HEX || (ch != 0x0d && ch != 0x0a))
1037 : {
1038 15420906 : if (m_aStates.top().nCharsToSkip == 0)
1039 : {
1040 15420326 : if (!bUnicodeChecked)
1041 : {
1042 59774 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ false);
1043 59774 : bUnicodeChecked = true;
1044 : }
1045 15420326 : aBuf.append(ch);
1046 : }
1047 : else
1048 : {
1049 580 : bSkipped = true;
1050 580 : m_aStates.top().nCharsToSkip--;
1051 : }
1052 : }
1053 :
1054 : // read a single char if we're in hex mode
1055 15542733 : if (m_aStates.top().nInternalState == RTFInternalState::HEX)
1056 27313 : break;
1057 :
1058 15515420 : if (RTL_TEXTENCODING_MS_932 == m_aStates.top().nCurrentEncoding)
1059 : {
1060 2606 : unsigned char uch = ch;
1061 2606 : if ((uch >= 0x80 && uch <= 0x9F) || uch >= 0xE0)
1062 : {
1063 : // read second byte of 2-byte Shift-JIS - may be \ { }
1064 28 : Strm().ReadChar(ch);
1065 28 : if (m_aStates.top().nCharsToSkip == 0)
1066 : {
1067 : // fdo#79384: Word will reject Shift-JIS following \loch
1068 : // but apparently OOo could read and (worse) write such documents
1069 : SAL_INFO_IF(m_aStates.top().eRunType != RTFParserState::DBCH, "writerfilter.rtf", "invalid Shift-JIS without DBCH");
1070 : assert(bUnicodeChecked);
1071 28 : aBuf.append(ch);
1072 : }
1073 : else
1074 : {
1075 : assert(bSkipped);
1076 : // anybody who uses \ucN with Shift-JIS is insane
1077 0 : m_aStates.top().nCharsToSkip--;
1078 : }
1079 : }
1080 : }
1081 :
1082 15515420 : Strm().ReadChar(ch);
1083 : }
1084 60267 : if (m_aStates.top().nInternalState != RTFInternalState::HEX && !Strm().IsEof())
1085 32954 : Strm().SeekRel(-1);
1086 :
1087 60267 : if (m_aStates.top().nInternalState == RTFInternalState::HEX && m_aStates.top().eDestination != Destination::LEVELNUMBERS)
1088 : {
1089 26837 : if (!bSkipped)
1090 26651 : m_aHexBuffer.append(ch);
1091 26837 : return RTFError::OK;
1092 : }
1093 :
1094 33430 : if (m_aStates.top().eDestination == Destination::SKIP)
1095 16264 : return RTFError::OK;
1096 34332 : OString aStr = aBuf.makeStringAndClear();
1097 17166 : if (m_aStates.top().eDestination == Destination::LEVELNUMBERS)
1098 : {
1099 1109 : if (aStr.toChar() != ';')
1100 485 : m_aStates.top().aLevelNumbers.push_back(sal_Int32(ch));
1101 1109 : return RTFError::OK;
1102 : }
1103 :
1104 32114 : OUString aOUStr(OStringToOUString(aStr, m_aStates.top().nCurrentEncoding));
1105 : SAL_INFO("writerfilter", "RTFDocumentImpl::resolveChars: collected '" << aOUStr << "'");
1106 :
1107 16057 : if (m_aStates.top().eDestination == Destination::COLORTABLE)
1108 : {
1109 : // we hit a ';' at the end of each color entry
1110 2349 : sal_uInt32 color = (m_aStates.top().aCurrentColor.nRed << 16) | (m_aStates.top().aCurrentColor.nGreen << 8)
1111 2349 : | m_aStates.top().aCurrentColor.nBlue;
1112 2349 : m_aColorTable.push_back(color);
1113 : // set components back to zero
1114 2349 : m_aStates.top().aCurrentColor = RTFColorTableEntry();
1115 : }
1116 13708 : else if (!aStr.isEmpty())
1117 13404 : m_aHexBuffer.append(aStr);
1118 :
1119 16057 : checkUnicode(/*bUnicode =*/ false, /*bHex =*/ true);
1120 76324 : return RTFError::OK;
1121 : }
1122 :
1123 27199 : bool RTFFrame::inFrame()
1124 : {
1125 27199 : return nW > 0
1126 27047 : || nH > 0
1127 27047 : || nX > 0
1128 54246 : || nY > 0;
1129 : }
1130 :
1131 168 : void RTFDocumentImpl::singleChar(sal_uInt8 nValue, bool bRunProps)
1132 : {
1133 168 : sal_uInt8 sValue[] = { nValue };
1134 168 : RTFBuffer_t* pCurrentBuffer = m_aStates.top().pCurrentBuffer;
1135 :
1136 168 : if (!pCurrentBuffer)
1137 : {
1138 158 : Mapper().startCharacterGroup();
1139 : // Should we send run properties?
1140 158 : if (bRunProps)
1141 2 : runProps();
1142 158 : Mapper().text(sValue, 1);
1143 158 : Mapper().endCharacterGroup();
1144 : }
1145 : else
1146 : {
1147 10 : pCurrentBuffer->push_back(Buf_t(BUFFER_STARTRUN));
1148 10 : auto pValue = std::make_shared<RTFValue>(*sValue);
1149 10 : pCurrentBuffer->push_back(Buf_t(BUFFER_TEXT, pValue));
1150 10 : pCurrentBuffer->push_back(Buf_t(BUFFER_ENDRUN));
1151 : }
1152 168 : }
1153 :
1154 14987 : void RTFDocumentImpl::text(OUString& rString)
1155 : {
1156 14987 : if (rString.getLength() == 1 && m_aStates.top().eDestination != Destination::DOCCOMM)
1157 : {
1158 : // No cheating! Tokenizer ignores bare \r and \n, their hex \'0d / \'0a form doesn't count, either.
1159 3476 : sal_Unicode ch = rString[0];
1160 3476 : if (ch == 0x0d || ch == 0x0a)
1161 1 : return;
1162 : }
1163 :
1164 14986 : bool bRet = true;
1165 14986 : switch (m_aStates.top().eDestination)
1166 : {
1167 : // Note: in fonttbl there may or may not be groups; in stylesheet
1168 : // and revtbl groups are mandatory
1169 : case Destination::FONTTABLE:
1170 : case Destination::FONTENTRY:
1171 : case Destination::STYLEENTRY:
1172 : case Destination::LISTNAME:
1173 : case Destination::REVISIONENTRY:
1174 : {
1175 : // ; is the end of the entry
1176 5480 : bool bEnd = false;
1177 5480 : if (rString.endsWith(";"))
1178 : {
1179 4734 : rString = rString.copy(0, rString.getLength() - 1);
1180 4734 : bEnd = true;
1181 : }
1182 5480 : m_aStates.top().pDestinationText->append(rString);
1183 5480 : if (bEnd)
1184 : {
1185 : // always clear, necessary in case of group-less fonttable
1186 4734 : OUString const aName = m_aStates.top().pDestinationText->makeStringAndClear();
1187 4734 : switch (m_aStates.top().eDestination)
1188 : {
1189 : case Destination::FONTTABLE:
1190 : case Destination::FONTENTRY:
1191 : {
1192 3378 : m_aFontNames[m_nCurrentFontIndex] = aName;
1193 3378 : if (m_nCurrentEncoding >= 0)
1194 : {
1195 3362 : m_aFontEncodings[m_nCurrentFontIndex] = m_nCurrentEncoding;
1196 3362 : m_nCurrentEncoding = -1;
1197 : }
1198 3378 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Font_name, std::make_shared<RTFValue>(aName));
1199 :
1200 : writerfilter::Reference<Properties>::Pointer_t const pProp(
1201 10134 : new RTFReferenceProperties(m_aStates.top().aTableAttributes, m_aStates.top().aTableSprms)
1202 10134 : );
1203 :
1204 : //See fdo#47347 initial invalid font entry properties are inserted first,
1205 : //so when we attempt to insert the correct ones, there's already an
1206 : //entry in the map for them, so the new ones aren't inserted.
1207 3378 : RTFReferenceTable::Entries_t::iterator lb = m_aFontTableEntries.lower_bound(m_nCurrentFontIndex);
1208 3378 : if (lb != m_aFontTableEntries.end() && !(m_aFontTableEntries.key_comp()(m_nCurrentFontIndex, lb->first)))
1209 59 : lb->second = pProp;
1210 : else
1211 3319 : m_aFontTableEntries.insert(lb, std::make_pair(m_nCurrentFontIndex, pProp));
1212 : }
1213 3378 : break;
1214 : case Destination::STYLEENTRY:
1215 1313 : if (m_aStates.top().aTableAttributes.find(NS_ooxml::LN_CT_Style_type))
1216 : {
1217 : // Word strips whitespace around style names.
1218 1313 : m_aStyleNames[m_nCurrentStyleIndex] = aName.trim();
1219 1313 : auto pValue = std::make_shared<RTFValue>(aName.trim());
1220 1313 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Style_styleId, pValue);
1221 1313 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Style_name, pValue);
1222 :
1223 2626 : writerfilter::Reference<Properties>::Pointer_t const pProp(createStyleProperties());
1224 2626 : m_aStyleTableEntries.insert(std::make_pair(m_nCurrentStyleIndex, pProp));
1225 : }
1226 : else
1227 : SAL_INFO("writerfilter", "no RTF style type defined, ignoring");
1228 1313 : break;
1229 : case Destination::LISTNAME:
1230 : // TODO: what can be done with a list name?
1231 39 : break;
1232 : case Destination::REVISIONENTRY:
1233 4 : m_aAuthors[m_aAuthors.size()] = aName;
1234 4 : break;
1235 : default:
1236 0 : break;
1237 : }
1238 4734 : resetAttributes();
1239 4734 : resetSprms();
1240 : }
1241 : }
1242 5480 : break;
1243 : case Destination::LEVELTEXT:
1244 : case Destination::SHAPEPROPERTYNAME:
1245 : case Destination::SHAPEPROPERTYVALUE:
1246 : case Destination::BOOKMARKEND:
1247 : case Destination::PICT:
1248 : case Destination::SHAPEPROPERTYVALUEPICT:
1249 : case Destination::FORMFIELDNAME:
1250 : case Destination::FORMFIELDLIST:
1251 : case Destination::DATAFIELD:
1252 : case Destination::AUTHOR:
1253 : case Destination::KEYWORDS:
1254 : case Destination::OPERATOR:
1255 : case Destination::COMPANY:
1256 : case Destination::COMMENT:
1257 : case Destination::OBJDATA:
1258 : case Destination::OBJCLASS:
1259 : case Destination::ANNOTATIONDATE:
1260 : case Destination::ANNOTATIONAUTHOR:
1261 : case Destination::ANNOTATIONREFERENCE:
1262 : case Destination::FALT:
1263 : case Destination::PARAGRAPHNUMBERING_TEXTAFTER:
1264 : case Destination::PARAGRAPHNUMBERING_TEXTBEFORE:
1265 : case Destination::TITLE:
1266 : case Destination::SUBJECT:
1267 : case Destination::DOCCOMM:
1268 : case Destination::ATNID:
1269 : case Destination::ANNOTATIONREFERENCESTART:
1270 : case Destination::ANNOTATIONREFERENCEEND:
1271 : case Destination::MR:
1272 : case Destination::MCHR:
1273 : case Destination::MPOS:
1274 : case Destination::MVERTJC:
1275 : case Destination::MSTRIKEH:
1276 : case Destination::MDEGHIDE:
1277 : case Destination::MBEGCHR:
1278 : case Destination::MSEPCHR:
1279 : case Destination::MENDCHR:
1280 : case Destination::MSUBHIDE:
1281 : case Destination::MSUPHIDE:
1282 : case Destination::MTYPE:
1283 : case Destination::MGROW:
1284 : case Destination::INDEXENTRY:
1285 : case Destination::TOCENTRY:
1286 4923 : m_aStates.top().pDestinationText->append(rString);
1287 4923 : break;
1288 : default:
1289 4583 : bRet = false;
1290 4583 : break;
1291 : }
1292 14986 : if (bRet)
1293 10403 : return;
1294 :
1295 4583 : if (!m_aIgnoreFirst.isEmpty() && m_aIgnoreFirst.equals(rString))
1296 : {
1297 0 : m_aIgnoreFirst.clear();
1298 0 : return;
1299 : }
1300 :
1301 : // Are we in the middle of the table definition? (No cell defs yet, but we already have some cell props.)
1302 4584 : if (m_aStates.top().aTableCellSprms.find(NS_ooxml::LN_CT_TcPrBase_vAlign).get() &&
1303 1 : m_nTopLevelCells == 0)
1304 : {
1305 1 : m_aTableBufferStack.back().push_back(Buf_t(BUFFER_UTEXT, std::make_shared<RTFValue>(rString)));
1306 1 : return;
1307 : }
1308 :
1309 4582 : checkFirstRun();
1310 4582 : checkNeedPap();
1311 :
1312 : // Don't return earlier, a bookmark start has to be in a paragraph group.
1313 4582 : if (m_aStates.top().eDestination == Destination::BOOKMARKSTART)
1314 : {
1315 17 : m_aStates.top().pDestinationText->append(rString);
1316 17 : return;
1317 : }
1318 :
1319 4565 : RTFBuffer_t* pCurrentBuffer = m_aStates.top().pCurrentBuffer;
1320 :
1321 4565 : if (!pCurrentBuffer && m_aStates.top().eDestination != Destination::FOOTNOTE)
1322 4078 : Mapper().startCharacterGroup();
1323 487 : else if (pCurrentBuffer)
1324 : {
1325 487 : RTFValue::Pointer_t pValue;
1326 487 : pCurrentBuffer->push_back(Buf_t(BUFFER_STARTRUN, pValue));
1327 : }
1328 :
1329 9130 : if (m_aStates.top().eDestination == Destination::NORMAL
1330 277 : || m_aStates.top().eDestination == Destination::FIELDRESULT
1331 4831 : || m_aStates.top().eDestination == Destination::SHAPETEXT)
1332 4328 : runProps();
1333 :
1334 4565 : if (!pCurrentBuffer)
1335 4078 : Mapper().utext(reinterpret_cast<sal_uInt8 const*>(rString.getStr()), rString.getLength());
1336 : else
1337 : {
1338 487 : auto pValue = std::make_shared<RTFValue>(rString);
1339 487 : pCurrentBuffer->push_back(Buf_t(BUFFER_UTEXT, pValue));
1340 : }
1341 :
1342 4565 : m_bNeedCr = true;
1343 :
1344 4565 : if (!pCurrentBuffer && m_aStates.top().eDestination != Destination::FOOTNOTE)
1345 4078 : Mapper().endCharacterGroup();
1346 487 : else if (pCurrentBuffer)
1347 : {
1348 487 : RTFValue::Pointer_t pValue;
1349 487 : pCurrentBuffer->push_back(Buf_t(BUFFER_ENDRUN, pValue));
1350 : }
1351 : }
1352 :
1353 136 : void RTFDocumentImpl::prepareProperties(
1354 : RTFParserState& rState,
1355 : writerfilter::Reference<Properties>::Pointer_t& o_rpParagraphProperties,
1356 : writerfilter::Reference<Properties>::Pointer_t& o_rpFrameProperties,
1357 : writerfilter::Reference<Properties>::Pointer_t& o_rpTableRowProperties,
1358 : int const nCells, int const nCurrentCellX)
1359 : {
1360 136 : o_rpParagraphProperties = getProperties(rState.aParagraphAttributes, rState.aParagraphSprms);
1361 :
1362 136 : if (rState.aFrame.hasProperties())
1363 : {
1364 0 : o_rpFrameProperties = std::make_shared<RTFReferenceProperties>(RTFSprms(), rState.aFrame.getSprms());
1365 : }
1366 :
1367 : // Table width.
1368 136 : auto pUnitValue = std::make_shared<RTFValue>(3);
1369 136 : lcl_putNestedAttribute(rState.aTableRowSprms, NS_ooxml::LN_CT_TblPrBase_tblW, NS_ooxml::LN_CT_TblWidth_type, pUnitValue);
1370 272 : auto pWValue = std::make_shared<RTFValue>(nCurrentCellX);
1371 136 : lcl_putNestedAttribute(rState.aTableRowSprms, NS_ooxml::LN_CT_TblPrBase_tblW, NS_ooxml::LN_CT_TblWidth_w, pWValue);
1372 :
1373 272 : auto pRowValue = std::make_shared<RTFValue>(1);
1374 136 : if (nCells > 0)
1375 136 : rState.aTableRowSprms.set(NS_ooxml::LN_tblRow, pRowValue);
1376 :
1377 272 : RTFValue::Pointer_t const pCellMar = rState.aTableRowSprms.find(NS_ooxml::LN_CT_TblPrBase_tblCellMar);
1378 136 : if (!pCellMar.get())
1379 : {
1380 : // If no cell margins are defined, the default left/right margin is 0 in Word, but not in Writer.
1381 115 : RTFSprms aAttributes;
1382 115 : aAttributes.set(NS_ooxml::LN_CT_TblWidth_type, std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_TblWidth_dxa));
1383 115 : aAttributes.set(NS_ooxml::LN_CT_TblWidth_w, std::make_shared<RTFValue>(0));
1384 115 : lcl_putNestedSprm(rState.aTableRowSprms, NS_ooxml::LN_CT_TblPrBase_tblCellMar, NS_ooxml::LN_CT_TblCellMar_left, std::make_shared<RTFValue>(aAttributes));
1385 115 : lcl_putNestedSprm(rState.aTableRowSprms, NS_ooxml::LN_CT_TblPrBase_tblCellMar, NS_ooxml::LN_CT_TblCellMar_right, std::make_shared<RTFValue>(aAttributes));
1386 : }
1387 :
1388 272 : o_rpTableRowProperties = std::make_shared<RTFReferenceProperties>(rState.aTableRowAttributes, rState.aTableRowSprms);
1389 136 : }
1390 :
1391 136 : void RTFDocumentImpl::sendProperties(
1392 : writerfilter::Reference<Properties>::Pointer_t const& pParagraphProperties,
1393 : writerfilter::Reference<Properties>::Pointer_t const& pFrameProperties,
1394 : writerfilter::Reference<Properties>::Pointer_t const& pTableRowProperties)
1395 : {
1396 136 : Mapper().props(pParagraphProperties);
1397 :
1398 136 : if (pFrameProperties)
1399 : {
1400 0 : Mapper().props(pFrameProperties);
1401 : }
1402 :
1403 136 : Mapper().props(pTableRowProperties);
1404 :
1405 136 : tableBreak();
1406 136 : }
1407 :
1408 136 : void RTFDocumentImpl::replayRowBuffer(
1409 : RTFBuffer_t& rBuffer,
1410 : ::std::deque<RTFSprms>& rCellsSrpms,
1411 : ::std::deque<RTFSprms>& rCellsAttributes,
1412 : int const nCells)
1413 : {
1414 633 : for (int i = 0; i < nCells; ++i)
1415 : {
1416 497 : replayBuffer(rBuffer, &rCellsSrpms.front(), &rCellsAttributes.front());
1417 497 : rCellsSrpms.pop_front();
1418 497 : rCellsAttributes.pop_front();
1419 : }
1420 136 : for (size_t i = 0; i < rBuffer.size(); ++i)
1421 : {
1422 : SAL_WARN_IF(BUFFER_CELLEND == boost::get<0>(rBuffer[i]),
1423 : "writerfilter.rtf", "dropping table cell!");
1424 : }
1425 : assert(0 == rCellsSrpms.size());
1426 : assert(0 == rCellsAttributes.size());
1427 136 : }
1428 :
1429 520 : void RTFDocumentImpl::replayBuffer(RTFBuffer_t& rBuffer,
1430 : RTFSprms* const pSprms, RTFSprms const* const pAttributes)
1431 : {
1432 3556 : while (rBuffer.size())
1433 : {
1434 2888 : Buf_t aTuple(rBuffer.front());
1435 2888 : rBuffer.pop_front();
1436 2888 : if (boost::get<0>(aTuple) == BUFFER_PROPS)
1437 : {
1438 : // Construct properties via getProperties() and not directly, to take care of deduplication.
1439 : writerfilter::Reference<Properties>::Pointer_t const pProp(
1440 995 : getProperties(boost::get<1>(aTuple)->getAttributes(), boost::get<1>(aTuple)->getSprms())
1441 995 : );
1442 995 : Mapper().props(pProp);
1443 : }
1444 1893 : else if (boost::get<0>(aTuple) == BUFFER_NESTROW)
1445 : {
1446 6 : TableRowBuffer& rRowBuffer(*boost::get<2>(aTuple));
1447 :
1448 : replayRowBuffer(rRowBuffer.buffer, rRowBuffer.cellsSprms,
1449 6 : rRowBuffer.cellsAttributes, rRowBuffer.nCells);
1450 :
1451 : sendProperties(rRowBuffer.pParaProperties,
1452 6 : rRowBuffer.pFrameProperties, rRowBuffer.pRowProperties);
1453 : }
1454 1887 : else if (boost::get<0>(aTuple) == BUFFER_CELLEND)
1455 : {
1456 : assert(pSprms && pAttributes);
1457 372 : auto pValue = std::make_shared<RTFValue>(1);
1458 372 : pSprms->set(NS_ooxml::LN_tblCell, pValue);
1459 : writerfilter::Reference<Properties>::Pointer_t const pTableCellProperties(
1460 744 : new RTFReferenceProperties(*pAttributes, *pSprms));
1461 372 : Mapper().props(pTableCellProperties);
1462 372 : tableBreak();
1463 744 : break;
1464 : }
1465 1515 : else if (boost::get<0>(aTuple) == BUFFER_STARTRUN)
1466 497 : Mapper().startCharacterGroup();
1467 1018 : else if (boost::get<0>(aTuple) == BUFFER_TEXT)
1468 : {
1469 10 : sal_uInt8 const nValue = boost::get<1>(aTuple)->getInt();
1470 10 : Mapper().text(&nValue, 1);
1471 : }
1472 1008 : else if (boost::get<0>(aTuple) == BUFFER_UTEXT)
1473 : {
1474 488 : OUString const aString(boost::get<1>(aTuple)->getString());
1475 488 : Mapper().utext(reinterpret_cast<sal_uInt8 const*>(aString.getStr()), aString.getLength());
1476 : }
1477 520 : else if (boost::get<0>(aTuple) == BUFFER_ENDRUN)
1478 497 : Mapper().endCharacterGroup();
1479 23 : else if (boost::get<0>(aTuple) == BUFFER_PAR)
1480 20 : parBreak();
1481 3 : else if (boost::get<0>(aTuple) == BUFFER_STARTSHAPE)
1482 1 : m_pSdrImport->resolve(boost::get<1>(aTuple)->getShape(), false, RTFSdrImport::SHAPE);
1483 2 : else if (boost::get<0>(aTuple) == BUFFER_ENDSHAPE)
1484 1 : m_pSdrImport->close();
1485 1 : else if (boost::get<0>(aTuple) == BUFFER_RESOLVESUBSTREAM)
1486 : {
1487 1 : RTFSprms& rAttributes = boost::get<1>(aTuple)->getAttributes();
1488 1 : sal_Size nPos = rAttributes.find(0)->getInt();
1489 1 : Id nId = rAttributes.find(1)->getInt();
1490 1 : OUString aCustomMark = rAttributes.find(2)->getString();
1491 1 : resolveSubstream(nPos, nId, aCustomMark);
1492 : }
1493 : else
1494 : assert(false);
1495 2516 : }
1496 :
1497 520 : }
1498 :
1499 12590 : RTFError RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword)
1500 : {
1501 12590 : setNeedSect();
1502 12590 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
1503 12590 : RTFSkipDestination aSkip(*this);
1504 : // special case \upr: ignore everything except nested \ud
1505 12590 : if (Destination::UPR == m_aStates.top().eDestination && RTF_UD != nKeyword)
1506 : {
1507 57 : m_aStates.top().eDestination = Destination::SKIP;
1508 57 : aSkip.setParsed(false);
1509 : }
1510 : else
1511 12533 : switch (nKeyword)
1512 : {
1513 : case RTF_RTF:
1514 458 : break;
1515 : case RTF_FONTTBL:
1516 195 : m_aStates.top().eDestination = Destination::FONTTABLE;
1517 195 : break;
1518 : case RTF_COLORTBL:
1519 159 : m_aStates.top().eDestination = Destination::COLORTABLE;
1520 159 : break;
1521 : case RTF_STYLESHEET:
1522 172 : m_aStates.top().eDestination = Destination::STYLESHEET;
1523 172 : break;
1524 : case RTF_FIELD:
1525 32 : m_aStates.top().eDestination = Destination::FIELD;
1526 32 : break;
1527 : case RTF_FLDINST:
1528 : {
1529 : // Look for the field type
1530 32 : sal_Size nPos = Strm().Tell();
1531 32 : OStringBuffer aBuf;
1532 32 : char ch = 0;
1533 32 : bool bFoundCode = false;
1534 32 : bool bInKeyword = false;
1535 787 : while (!bFoundCode && ch != '}')
1536 : {
1537 723 : Strm().ReadChar(ch);
1538 723 : if ('\\' == ch)
1539 63 : bInKeyword = true;
1540 723 : if (!bInKeyword && isalnum(ch))
1541 221 : aBuf.append(ch);
1542 502 : else if (bInKeyword && isspace(ch))
1543 31 : bInKeyword = false;
1544 723 : if (!aBuf.isEmpty() && !isalnum(ch))
1545 32 : bFoundCode = true;
1546 : }
1547 32 : Strm().Seek(nPos);
1548 :
1549 : // Form data should be handled only for form fields if any
1550 32 : if (aBuf.toString().indexOf(OString("FORM")) != -1)
1551 1 : m_bFormField = true;
1552 :
1553 32 : singleChar(cFieldStart);
1554 32 : m_aStates.top().eDestination = Destination::FIELDINSTRUCTION;
1555 : }
1556 32 : break;
1557 : case RTF_FLDRSLT:
1558 30 : m_aStates.top().eDestination = Destination::FIELDRESULT;
1559 30 : break;
1560 : case RTF_LISTTABLE:
1561 63 : m_aStates.top().eDestination = Destination::LISTTABLE;
1562 63 : break;
1563 : case RTF_LISTPICTURE:
1564 3 : m_aStates.top().eDestination = Destination::LISTPICTURE;
1565 3 : m_aStates.top().bInListpicture = true;
1566 3 : break;
1567 : case RTF_LIST:
1568 90 : m_aStates.top().eDestination = Destination::LISTENTRY;
1569 90 : break;
1570 : case RTF_LISTNAME:
1571 39 : m_aStates.top().eDestination = Destination::LISTNAME;
1572 39 : break;
1573 : case RTF_LFOLEVEL:
1574 73 : m_aStates.top().eDestination = Destination::LFOLEVEL;
1575 73 : m_aStates.top().aTableSprms.clear();
1576 73 : break;
1577 : case RTF_LISTOVERRIDETABLE:
1578 61 : m_aStates.top().eDestination = Destination::LISTOVERRIDETABLE;
1579 61 : break;
1580 : case RTF_LISTOVERRIDE:
1581 125 : m_aStates.top().eDestination = Destination::LISTOVERRIDEENTRY;
1582 125 : break;
1583 : case RTF_LISTLEVEL:
1584 634 : m_aStates.top().eDestination = Destination::LISTLEVEL;
1585 634 : break;
1586 : case RTF_LEVELTEXT:
1587 678 : m_aStates.top().eDestination = Destination::LEVELTEXT;
1588 678 : break;
1589 : case RTF_LEVELNUMBERS:
1590 633 : m_aStates.top().eDestination = Destination::LEVELNUMBERS;
1591 633 : break;
1592 : case RTF_SHPPICT:
1593 13 : m_aStates.top().resetFrame();
1594 13 : m_aStates.top().eDestination = Destination::SHPPICT;
1595 13 : break;
1596 : case RTF_PICT:
1597 44 : if (m_aStates.top().eDestination != Destination::SHAPEPROPERTYVALUE)
1598 21 : m_aStates.top().eDestination = Destination::PICT; // as character
1599 : else
1600 23 : m_aStates.top().eDestination = Destination::SHAPEPROPERTYVALUEPICT; // anchored inside a shape
1601 44 : break;
1602 : case RTF_PICPROP:
1603 11 : m_aStates.top().eDestination = Destination::PICPROP;
1604 11 : break;
1605 : case RTF_SP:
1606 969 : m_aStates.top().eDestination = Destination::SHAPEPROPERTY;
1607 969 : break;
1608 : case RTF_SN:
1609 968 : m_aStates.top().eDestination = Destination::SHAPEPROPERTYNAME;
1610 968 : break;
1611 : case RTF_SV:
1612 968 : m_aStates.top().eDestination = Destination::SHAPEPROPERTYVALUE;
1613 968 : break;
1614 : case RTF_SHP:
1615 102 : m_bNeedCrOrig = m_bNeedCr;
1616 102 : m_aStates.top().eDestination = Destination::SHAPE;
1617 102 : m_aStates.top().bInShape = true;
1618 102 : break;
1619 : case RTF_SHPINST:
1620 110 : m_aStates.top().eDestination = Destination::SHAPEINSTRUCTION;
1621 110 : break;
1622 : case RTF_NESTTABLEPROPS:
1623 : // do not set any properties of outer table at nested table!
1624 6 : m_aStates.top().aTableCellSprms = m_aDefaultState.aTableCellSprms;
1625 6 : m_aStates.top().aTableCellAttributes =
1626 6 : m_aDefaultState.aTableCellAttributes;
1627 6 : m_aNestedTableCellsSprms.clear();
1628 6 : m_aNestedTableCellsAttributes.clear();
1629 6 : m_nNestedCells = 0;
1630 6 : m_aStates.top().eDestination = Destination::NESTEDTABLEPROPERTIES;
1631 6 : break;
1632 : case RTF_HEADER:
1633 : case RTF_FOOTER:
1634 : case RTF_HEADERL:
1635 : case RTF_HEADERR:
1636 : case RTF_HEADERF:
1637 : case RTF_FOOTERL:
1638 : case RTF_FOOTERR:
1639 : case RTF_FOOTERF:
1640 50 : if (!m_pSuperstream)
1641 : {
1642 25 : Id nId = 0;
1643 25 : sal_Size nPos = m_nGroupStartPos - 1;
1644 25 : switch (nKeyword)
1645 : {
1646 : case RTF_HEADER:
1647 9 : nId = NS_ooxml::LN_headerr;
1648 9 : break;
1649 : case RTF_FOOTER:
1650 1 : nId = NS_ooxml::LN_footerr;
1651 1 : break;
1652 : case RTF_HEADERL:
1653 2 : nId = NS_ooxml::LN_headerl;
1654 2 : break;
1655 : case RTF_HEADERR:
1656 3 : nId = NS_ooxml::LN_headerr;
1657 3 : break;
1658 : case RTF_HEADERF:
1659 4 : nId = NS_ooxml::LN_headerf;
1660 4 : break;
1661 : case RTF_FOOTERL:
1662 2 : nId = NS_ooxml::LN_footerl;
1663 2 : break;
1664 : case RTF_FOOTERR:
1665 2 : nId = NS_ooxml::LN_footerr;
1666 2 : break;
1667 : case RTF_FOOTERF:
1668 2 : nId = NS_ooxml::LN_footerf;
1669 2 : break;
1670 : default:
1671 0 : break;
1672 : }
1673 25 : m_nHeaderFooterPositions.push(std::make_pair(nId, nPos));
1674 25 : m_aStates.top().eDestination = Destination::SKIP;
1675 : }
1676 50 : break;
1677 : case RTF_FOOTNOTE:
1678 24 : if (!m_pSuperstream)
1679 : {
1680 12 : Id nId = NS_ooxml::LN_footnote;
1681 :
1682 : // Check if this is an endnote.
1683 12 : OStringBuffer aBuf;
1684 : char ch;
1685 96 : for (int i = 0; i < 7; ++i)
1686 : {
1687 84 : Strm().ReadChar(ch);
1688 84 : aBuf.append(ch);
1689 : }
1690 24 : OString aKeyword = aBuf.makeStringAndClear();
1691 12 : if (aKeyword.equals("\\ftnalt"))
1692 0 : nId = NS_ooxml::LN_endnote;
1693 :
1694 12 : m_bHasFootnote = true;
1695 12 : if (m_aStates.top().pCurrentBuffer == &m_aSuperBuffer)
1696 0 : m_aStates.top().pCurrentBuffer = nullptr;
1697 12 : bool bCustomMark = false;
1698 24 : OUString aCustomMark;
1699 24 : while (m_aSuperBuffer.size())
1700 : {
1701 0 : Buf_t aTuple = m_aSuperBuffer.front();
1702 0 : m_aSuperBuffer.pop_front();
1703 0 : if (boost::get<0>(aTuple) == BUFFER_UTEXT)
1704 : {
1705 0 : aCustomMark = boost::get<1>(aTuple)->getString();
1706 0 : bCustomMark = true;
1707 : }
1708 0 : }
1709 12 : m_aStates.top().eDestination = Destination::FOOTNOTE;
1710 12 : if (bCustomMark)
1711 0 : Mapper().startCharacterGroup();
1712 12 : if (!m_aStates.top().pCurrentBuffer)
1713 11 : resolveSubstream(m_nGroupStartPos - 1, nId, aCustomMark);
1714 : else
1715 : {
1716 1 : RTFSprms aAttributes;
1717 1 : aAttributes.set(Id(0), std::make_shared<RTFValue>(m_nGroupStartPos - 1));
1718 1 : aAttributes.set(Id(1), std::make_shared<RTFValue>(nId));
1719 1 : aAttributes.set(Id(2), std::make_shared<RTFValue>(aCustomMark));
1720 1 : m_aStates.top().pCurrentBuffer->push_back(Buf_t(BUFFER_RESOLVESUBSTREAM, std::make_shared<RTFValue>(aAttributes)));
1721 : }
1722 12 : if (bCustomMark)
1723 : {
1724 0 : m_aStates.top().aCharacterAttributes.clear();
1725 0 : m_aStates.top().aCharacterSprms.clear();
1726 0 : auto pValue = std::make_shared<RTFValue>(1);
1727 0 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_FtnEdnRef_customMarkFollows, pValue);
1728 0 : text(aCustomMark);
1729 0 : Mapper().endCharacterGroup();
1730 : }
1731 24 : m_aStates.top().eDestination = Destination::SKIP;
1732 : }
1733 24 : break;
1734 : case RTF_BKMKSTART:
1735 17 : m_aStates.top().eDestination = Destination::BOOKMARKSTART;
1736 17 : break;
1737 : case RTF_BKMKEND:
1738 16 : m_aStates.top().eDestination = Destination::BOOKMARKEND;
1739 16 : break;
1740 : case RTF_XE:
1741 1 : m_aStates.top().eDestination = Destination::INDEXENTRY;
1742 1 : break;
1743 : case RTF_TC:
1744 : case RTF_TCN:
1745 1 : m_aStates.top().eDestination = Destination::TOCENTRY;
1746 1 : break;
1747 : case RTF_REVTBL:
1748 3 : m_aStates.top().eDestination = Destination::REVISIONTABLE;
1749 3 : break;
1750 : case RTF_ANNOTATION:
1751 14 : if (!m_pSuperstream)
1752 : {
1753 7 : resolveSubstream(m_nGroupStartPos - 1, NS_ooxml::LN_annotation);
1754 7 : m_aStates.top().eDestination = Destination::SKIP;
1755 : }
1756 : else
1757 : {
1758 : // If there is an author set, emit it now.
1759 7 : if (!m_aAuthor.isEmpty() || !m_aAuthorInitials.isEmpty())
1760 : {
1761 6 : RTFSprms aAttributes;
1762 6 : if (!m_aAuthor.isEmpty())
1763 : {
1764 6 : auto pValue = std::make_shared<RTFValue>(m_aAuthor);
1765 6 : aAttributes.set(NS_ooxml::LN_CT_TrackChange_author, pValue);
1766 : }
1767 6 : if (!m_aAuthorInitials.isEmpty())
1768 : {
1769 5 : auto pValue = std::make_shared<RTFValue>(m_aAuthorInitials);
1770 5 : aAttributes.set(NS_ooxml::LN_CT_Comment_initials, pValue);
1771 : }
1772 12 : writerfilter::Reference<Properties>::Pointer_t pProperties = std::make_shared<RTFReferenceProperties>(aAttributes);
1773 12 : Mapper().props(pProperties);
1774 : }
1775 : }
1776 14 : break;
1777 : case RTF_SHPTXT:
1778 : case RTF_DPTXBXTEXT:
1779 : {
1780 57 : bool bPictureFrame = false;
1781 521 : for (size_t i = 0; i < m_aStates.top().aShape.aProperties.size(); ++i)
1782 : {
1783 465 : std::pair<OUString, OUString>& rProperty = m_aStates.top().aShape.aProperties[i];
1784 465 : if (rProperty.first == "shapeType" && rProperty.second == OUString::number(ESCHER_ShpInst_PictureFrame))
1785 : {
1786 1 : bPictureFrame = true;
1787 1 : break;
1788 : }
1789 : }
1790 57 : if (bPictureFrame)
1791 : // Skip text on picture frames.
1792 1 : m_aStates.top().eDestination = Destination::SKIP;
1793 : else
1794 : {
1795 56 : m_aStates.top().eDestination = Destination::SHAPETEXT;
1796 56 : checkFirstRun();
1797 56 : dispatchFlag(RTF_PARD);
1798 56 : m_bNeedPap = true;
1799 56 : if (nKeyword == RTF_SHPTXT)
1800 : {
1801 44 : if (!m_aStates.top().pCurrentBuffer)
1802 43 : m_pSdrImport->resolve(m_aStates.top().aShape, false, RTFSdrImport::SHAPE);
1803 : else
1804 : {
1805 1 : auto pValue = std::make_shared<RTFValue>(m_aStates.top().aShape);
1806 1 : m_aStates.top().pCurrentBuffer->push_back(Buf_t(BUFFER_STARTSHAPE, pValue));
1807 : }
1808 : }
1809 : }
1810 : }
1811 57 : break;
1812 : case RTF_FORMFIELD:
1813 1 : if (m_aStates.top().eDestination == Destination::FIELDINSTRUCTION)
1814 0 : m_aStates.top().eDestination = Destination::FORMFIELD;
1815 1 : break;
1816 : case RTF_FFNAME:
1817 1 : m_aStates.top().eDestination = Destination::FORMFIELDNAME;
1818 1 : break;
1819 : case RTF_FFL:
1820 0 : m_aStates.top().eDestination = Destination::FORMFIELDLIST;
1821 0 : break;
1822 : case RTF_DATAFIELD:
1823 1 : m_aStates.top().eDestination = Destination::DATAFIELD;
1824 1 : break;
1825 : case RTF_INFO:
1826 184 : m_aStates.top().eDestination = Destination::INFO;
1827 184 : break;
1828 : case RTF_CREATIM:
1829 166 : m_aStates.top().eDestination = Destination::CREATIONTIME;
1830 166 : break;
1831 : case RTF_REVTIM:
1832 168 : m_aStates.top().eDestination = Destination::REVISIONTIME;
1833 168 : break;
1834 : case RTF_PRINTIM:
1835 100 : m_aStates.top().eDestination = Destination::PRINTTIME;
1836 100 : break;
1837 : case RTF_AUTHOR:
1838 103 : m_aStates.top().eDestination = Destination::AUTHOR;
1839 103 : break;
1840 : case RTF_KEYWORDS:
1841 3 : m_aStates.top().eDestination = Destination::KEYWORDS;
1842 3 : break;
1843 : case RTF_OPERATOR:
1844 70 : m_aStates.top().eDestination = Destination::OPERATOR;
1845 70 : break;
1846 : case RTF_COMPANY:
1847 55 : m_aStates.top().eDestination = Destination::COMPANY;
1848 55 : break;
1849 : case RTF_COMMENT:
1850 11 : m_aStates.top().eDestination = Destination::COMMENT;
1851 11 : break;
1852 : case RTF_OBJECT:
1853 : {
1854 : // beginning of an OLE Object
1855 5 : m_aStates.top().eDestination = Destination::OBJECT;
1856 :
1857 : // check if the object is in a special container (e.g. a table)
1858 5 : if (!m_aStates.top().pCurrentBuffer)
1859 : {
1860 : // the object is in a table or another container.
1861 : // Don't try to treate it as an OLE object (fdo#53594).
1862 : // Use the \result (RTF_RESULT) element of the object instead,
1863 : // the result element contain picture representing the OLE Object.
1864 4 : m_bObject = true;
1865 : }
1866 : }
1867 5 : break;
1868 : case RTF_OBJDATA:
1869 : // check if the object is in a special container (e.g. a table)
1870 5 : if (m_aStates.top().pCurrentBuffer)
1871 : {
1872 : // the object is in a table or another container.
1873 : // Use the \result (RTF_RESULT) element of the object instead,
1874 : // of the \objdata.
1875 1 : m_aStates.top().eDestination = Destination::SKIP;
1876 : }
1877 : else
1878 : {
1879 4 : m_aStates.top().eDestination = Destination::OBJDATA;
1880 : }
1881 5 : break;
1882 : case RTF_OBJCLASS:
1883 4 : m_aStates.top().eDestination = Destination::OBJCLASS;
1884 4 : break;
1885 : case RTF_RESULT:
1886 3 : m_aStates.top().eDestination = Destination::RESULT;
1887 3 : break;
1888 : case RTF_ATNDATE:
1889 6 : m_aStates.top().eDestination = Destination::ANNOTATIONDATE;
1890 6 : break;
1891 : case RTF_ATNAUTHOR:
1892 6 : m_aStates.top().eDestination = Destination::ANNOTATIONAUTHOR;
1893 6 : break;
1894 : case RTF_ATNREF:
1895 6 : m_aStates.top().eDestination = Destination::ANNOTATIONREFERENCE;
1896 6 : break;
1897 : case RTF_FALT:
1898 473 : m_aStates.top().eDestination = Destination::FALT;
1899 473 : break;
1900 : case RTF_FLYMAINCNT:
1901 9 : m_aStates.top().eDestination = Destination::FLYMAINCONTENT;
1902 9 : break;
1903 : case RTF_LISTTEXT:
1904 : // Should be ignored by any reader that understands Word 97 through Word 2007 numbering.
1905 : case RTF_NONESTTABLES:
1906 : // This destination should be ignored by readers that support nested tables.
1907 700 : m_aStates.top().eDestination = Destination::SKIP;
1908 700 : break;
1909 : case RTF_DO:
1910 26 : m_aStates.top().eDestination = Destination::DRAWINGOBJECT;
1911 26 : break;
1912 : case RTF_PN:
1913 5 : m_aStates.top().eDestination = Destination::PARAGRAPHNUMBERING;
1914 5 : break;
1915 : case RTF_PNTEXT:
1916 : // This destination should be ignored by readers that support paragraph numbering.
1917 0 : m_aStates.top().eDestination = Destination::SKIP;
1918 0 : break;
1919 : case RTF_PNTXTA:
1920 4 : m_aStates.top().eDestination = Destination::PARAGRAPHNUMBERING_TEXTAFTER;
1921 4 : break;
1922 : case RTF_PNTXTB:
1923 4 : m_aStates.top().eDestination = Destination::PARAGRAPHNUMBERING_TEXTBEFORE;
1924 4 : break;
1925 : case RTF_TITLE:
1926 13 : m_aStates.top().eDestination = Destination::TITLE;
1927 13 : break;
1928 : case RTF_SUBJECT:
1929 4 : m_aStates.top().eDestination = Destination::SUBJECT;
1930 4 : break;
1931 : case RTF_DOCCOMM:
1932 6 : m_aStates.top().eDestination = Destination::DOCCOMM;
1933 6 : break;
1934 : case RTF_ATRFSTART:
1935 6 : m_aStates.top().eDestination = Destination::ANNOTATIONREFERENCESTART;
1936 6 : break;
1937 : case RTF_ATRFEND:
1938 6 : m_aStates.top().eDestination = Destination::ANNOTATIONREFERENCEEND;
1939 6 : break;
1940 : case RTF_ATNID:
1941 6 : m_aStates.top().eDestination = Destination::ATNID;
1942 6 : break;
1943 : case RTF_MMATH:
1944 : case RTF_MOMATHPARA:
1945 : // Nothing to do here (just enter the destination) till RTF_MMATHPR is implemented.
1946 113 : break;
1947 : case RTF_MR:
1948 585 : m_aStates.top().eDestination = Destination::MR;
1949 585 : break;
1950 : case RTF_MCHR:
1951 57 : m_aStates.top().eDestination = Destination::MCHR;
1952 57 : break;
1953 : case RTF_MPOS:
1954 5 : m_aStates.top().eDestination = Destination::MPOS;
1955 5 : break;
1956 : case RTF_MVERTJC:
1957 4 : m_aStates.top().eDestination = Destination::MVERTJC;
1958 4 : break;
1959 : case RTF_MSTRIKEH:
1960 3 : m_aStates.top().eDestination = Destination::MSTRIKEH;
1961 3 : break;
1962 : case RTF_MDEGHIDE:
1963 4 : m_aStates.top().eDestination = Destination::MDEGHIDE;
1964 4 : break;
1965 : case RTF_MTYPE:
1966 6 : m_aStates.top().eDestination = Destination::MTYPE;
1967 6 : break;
1968 : case RTF_MGROW:
1969 2 : m_aStates.top().eDestination = Destination::MGROW;
1970 2 : break;
1971 : case RTF_MHIDETOP:
1972 : case RTF_MHIDEBOT:
1973 : case RTF_MHIDELEFT:
1974 : case RTF_MHIDERIGHT:
1975 : // SmOoxmlImport::handleBorderBox will ignore these anyway, so silently ignore for now.
1976 12 : m_aStates.top().eDestination = Destination::SKIP;
1977 12 : break;
1978 : case RTF_MSUBHIDE:
1979 2 : m_aStates.top().eDestination = Destination::MSUBHIDE;
1980 2 : break;
1981 : case RTF_MSUPHIDE:
1982 2 : m_aStates.top().eDestination = Destination::MSUPHIDE;
1983 2 : break;
1984 : case RTF_MBEGCHR:
1985 40 : m_aStates.top().eDestination = Destination::MBEGCHR;
1986 40 : break;
1987 : case RTF_MSEPCHR:
1988 4 : m_aStates.top().eDestination = Destination::MSEPCHR;
1989 4 : break;
1990 : case RTF_MENDCHR:
1991 40 : m_aStates.top().eDestination = Destination::MENDCHR;
1992 40 : break;
1993 : case RTF_UPR:
1994 57 : m_aStates.top().eDestination = Destination::UPR;
1995 57 : break;
1996 : case RTF_UD:
1997 : // Anything inside \ud is just normal Unicode content.
1998 57 : m_aStates.top().eDestination = Destination::NORMAL;
1999 57 : break;
2000 : case RTF_BACKGROUND:
2001 1 : m_aStates.top().eDestination = Destination::BACKGROUND;
2002 1 : m_aStates.top().bInBackground = true;
2003 1 : break;
2004 : case RTF_SHPGRP:
2005 : {
2006 8 : RTFLookahead aLookahead(Strm(), m_pTokenizer->getGroupStart());
2007 8 : if (!aLookahead.hasTable())
2008 : {
2009 6 : uno::Reference<drawing::XShapes> xGroupShape(m_xModelFactory->createInstance("com.sun.star.drawing.GroupShape"), uno::UNO_QUERY);
2010 12 : uno::Reference<drawing::XDrawPageSupplier> xDrawSupplier(m_xDstDoc, uno::UNO_QUERY);
2011 6 : if (xDrawSupplier.is())
2012 : {
2013 6 : uno::Reference<drawing::XShape> xShape(xGroupShape, uno::UNO_QUERY);
2014 6 : xDrawSupplier->getDrawPage()->add(xShape);
2015 : }
2016 6 : m_pSdrImport->pushParent(xGroupShape);
2017 12 : m_aStates.top().bCreatedShapeGroup = true;
2018 : }
2019 8 : m_aStates.top().eDestination = Destination::SHAPEGROUP;
2020 8 : m_aStates.top().bInShapeGroup = true;
2021 : }
2022 8 : break;
2023 : case RTF_FTNSEP:
2024 119 : m_aStates.top().eDestination = Destination::FOOTNOTESEPARATOR;
2025 119 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_FtnEdn_type, std::make_shared<RTFValue>(NS_ooxml::LN_Value_doc_ST_FtnEdn_separator));
2026 119 : break;
2027 : default:
2028 : {
2029 : // Check if it's a math token.
2030 : RTFMathSymbol aSymbol;
2031 2401 : aSymbol.eKeyword = nKeyword;
2032 2401 : if (RTFTokenizer::lookupMathKeyword(aSymbol))
2033 : {
2034 1159 : m_aMathBuffer.appendOpeningTag(aSymbol.nToken);
2035 1159 : m_aStates.top().eDestination = aSymbol.eDestination;
2036 1159 : return RTFError::OK;
2037 : }
2038 :
2039 : SAL_INFO("writerfilter", "TODO handle destination '" << lcl_RtfToString(nKeyword) << "'");
2040 : // Make sure we skip destinations (even without \*) till we don't handle them
2041 1242 : m_aStates.top().eDestination = Destination::SKIP;
2042 1242 : aSkip.setParsed(false);
2043 : }
2044 1242 : break;
2045 : }
2046 :
2047 : // new destination => use new destination text
2048 11431 : m_aStates.top().pDestinationText = &m_aStates.top().aDestinationText;
2049 :
2050 11431 : return RTFError::OK;
2051 : }
2052 :
2053 33188 : RTFError RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
2054 : {
2055 33188 : setNeedSect();
2056 33188 : if (nKeyword != RTF_HEXCHAR)
2057 5875 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
2058 : else
2059 27313 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ false);
2060 33188 : RTFSkipDestination aSkip(*this);
2061 :
2062 33188 : if (RTF_LINE == nKeyword)
2063 : {
2064 : // very special handling since text() will eat lone '\n'
2065 60 : singleChar('\n');
2066 60 : return RTFError::OK;
2067 : }
2068 : // Trivial symbols
2069 33128 : sal_uInt8 cCh = 0;
2070 33128 : switch (nKeyword)
2071 : {
2072 : case RTF_TAB:
2073 90 : cCh = '\t';
2074 90 : break;
2075 : case RTF_BACKSLASH:
2076 32 : cCh = '\\';
2077 32 : break;
2078 : case RTF_LBRACE:
2079 44 : cCh = '{';
2080 44 : break;
2081 : case RTF_RBRACE:
2082 20 : cCh = '}';
2083 20 : break;
2084 : case RTF_EMDASH:
2085 10 : cCh = 151;
2086 10 : break;
2087 : case RTF_ENDASH:
2088 11 : cCh = 150;
2089 11 : break;
2090 : case RTF_BULLET:
2091 15 : cCh = 149;
2092 15 : break;
2093 : case RTF_LQUOTE:
2094 16 : cCh = 145;
2095 16 : break;
2096 : case RTF_RQUOTE:
2097 13 : cCh = 146;
2098 13 : break;
2099 : case RTF_LDBLQUOTE:
2100 22 : cCh = 147;
2101 22 : break;
2102 : case RTF_RDBLQUOTE:
2103 9 : cCh = 148;
2104 9 : break;
2105 : default:
2106 32846 : break;
2107 : }
2108 33128 : if (cCh > 0)
2109 : {
2110 282 : OUString aStr(OStringToOUString(OString(cCh), RTL_TEXTENCODING_MS_1252));
2111 282 : text(aStr);
2112 282 : return RTFError::OK;
2113 : }
2114 :
2115 32846 : switch (nKeyword)
2116 : {
2117 : case RTF_IGNORE:
2118 : {
2119 3135 : m_bSkipUnknown = true;
2120 3135 : aSkip.setReset(false);
2121 3135 : return RTFError::OK;
2122 : }
2123 : break;
2124 : case RTF_PAR:
2125 : {
2126 1671 : if (m_aStates.top().eDestination == Destination::FOOTNOTESEPARATOR)
2127 28 : break; // just ignore it - only thing we read in here is CHFTNSEP
2128 1643 : checkFirstRun();
2129 1643 : bool bNeedPap = m_bNeedPap;
2130 1643 : checkNeedPap();
2131 1643 : if (bNeedPap)
2132 347 : runProps();
2133 1643 : if (!m_aStates.top().pCurrentBuffer)
2134 : {
2135 1621 : parBreak();
2136 : // Not in table? Reset max width.
2137 1621 : m_nCellxMax = 0;
2138 : }
2139 22 : else if (m_aStates.top().eDestination != Destination::SHAPETEXT)
2140 : {
2141 22 : RTFValue::Pointer_t pValue;
2142 22 : m_aStates.top().pCurrentBuffer->push_back(
2143 44 : Buf_t(BUFFER_PAR, pValue));
2144 : }
2145 : // but don't emit properties yet, since they may change till the first text token arrives
2146 1643 : m_bNeedPap = true;
2147 1643 : if (!m_aStates.top().aFrame.inFrame())
2148 1614 : m_bNeedPar = false;
2149 1643 : m_bNeedFinalPar = false;
2150 : }
2151 1643 : break;
2152 : case RTF_SECT:
2153 : {
2154 16 : m_bHadSect = true;
2155 16 : if (m_bIgnoreNextContSectBreak)
2156 3 : m_bIgnoreNextContSectBreak = false;
2157 : else
2158 : {
2159 13 : sectBreak();
2160 13 : if (m_nResetBreakOnSectBreak != RTF_invalid)
2161 : {
2162 : // this should run on _second_ \sect after \page
2163 2 : dispatchSymbol(m_nResetBreakOnSectBreak); // lazy reset
2164 2 : m_nResetBreakOnSectBreak = RTF_invalid;
2165 2 : m_bNeedSect = false; // dispatchSymbol set it
2166 : }
2167 : }
2168 : }
2169 16 : break;
2170 : case RTF_NOBREAK:
2171 : {
2172 25 : OUString aStr(SVT_HARD_SPACE);
2173 25 : text(aStr);
2174 : }
2175 25 : break;
2176 : case RTF_NOBRKHYPH:
2177 : {
2178 3 : OUString aStr(SVT_HARD_HYPHEN);
2179 3 : text(aStr);
2180 : }
2181 3 : break;
2182 : case RTF_OPTHYPH:
2183 : {
2184 14 : OUString aStr(SVT_SOFT_HYPHEN);
2185 14 : text(aStr);
2186 : }
2187 14 : break;
2188 : case RTF_HEXCHAR:
2189 27313 : m_aStates.top().nInternalState = RTFInternalState::HEX;
2190 27313 : break;
2191 : case RTF_CELL:
2192 : case RTF_NESTCELL:
2193 : {
2194 372 : checkFirstRun();
2195 372 : if (m_bNeedPap)
2196 : {
2197 : // There were no runs in the cell, so we need to send paragraph and character properties here.
2198 104 : auto pPValue = std::make_shared<RTFValue>(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms);
2199 104 : m_aTableBufferStack.back().push_back(Buf_t(BUFFER_PROPS, pPValue));
2200 208 : auto pCValue = std::make_shared<RTFValue>(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms);
2201 208 : m_aTableBufferStack.back().push_back(Buf_t(BUFFER_PROPS, pCValue));
2202 : }
2203 :
2204 372 : RTFValue::Pointer_t pValue;
2205 372 : m_aTableBufferStack.back().push_back(Buf_t(BUFFER_CELLEND, pValue));
2206 372 : m_bNeedPap = true;
2207 : }
2208 372 : break;
2209 : case RTF_NESTROW:
2210 : {
2211 : std::shared_ptr<TableRowBuffer> const pBuffer(
2212 : new TableRowBuffer(
2213 6 : m_aTableBufferStack.back(),
2214 : m_aNestedTableCellsSprms,
2215 : m_aNestedTableCellsAttributes,
2216 6 : m_nNestedCells));
2217 6 : prepareProperties(m_aStates.top(),
2218 6 : pBuffer->pParaProperties,
2219 6 : pBuffer->pFrameProperties,
2220 6 : pBuffer->pRowProperties,
2221 30 : m_nNestedCells, m_nNestedCurrentCellX);
2222 :
2223 : assert(m_aStates.top().pCurrentBuffer == &m_aTableBufferStack.back());
2224 6 : if (m_aTableBufferStack.size() == 1)
2225 : {
2226 : throw io::WrongFormatException(
2227 0 : "mismatch between \\itap and number of \\nestrow", nullptr);
2228 : }
2229 : // note: there may be several states pointing to table buffer!
2230 21 : for (size_t i = 0; i < m_aStates.size(); ++i)
2231 : {
2232 15 : if (m_aStates[i].pCurrentBuffer == &m_aTableBufferStack.back())
2233 : {
2234 15 : m_aStates[i].pCurrentBuffer =
2235 15 : &m_aTableBufferStack[m_aTableBufferStack.size()-2];
2236 : }
2237 : }
2238 6 : m_aTableBufferStack.pop_back();
2239 6 : m_aTableBufferStack.back().push_back(
2240 12 : Buf_t(BUFFER_NESTROW, RTFValue::Pointer_t(), pBuffer));
2241 :
2242 6 : m_aNestedTableCellsSprms.clear();
2243 6 : m_aNestedTableCellsAttributes.clear();
2244 6 : m_nNestedCells = 0;
2245 6 : m_bNeedPap = true;
2246 : }
2247 6 : break;
2248 : case RTF_ROW:
2249 : {
2250 130 : bool bRestored = false;
2251 : // Ending a row, but no cells defined?
2252 : // See if there was an invalid table row reset, so we can restore cell infos to help invalid documents.
2253 130 : if (!m_nTopLevelCurrentCellX && m_nBackupTopLevelCurrentCellX)
2254 : {
2255 2 : restoreTableRowProperties();
2256 2 : bRestored = true;
2257 : }
2258 :
2259 : // If the right edge of the last cell (row width) is smaller than the width of some other row, mimic WW8TabDesc::CalcDefaults(): add a fake cell.
2260 130 : const int MINLAY = 23; // sw/inc/swtypes.hxx, minimal possible size of frames.
2261 130 : if ((m_nCellxMax - m_nTopLevelCurrentCellX) >= MINLAY)
2262 1 : dispatchValue(RTF_CELLX, m_nCellxMax);
2263 :
2264 130 : if (m_nTopLevelCells)
2265 : {
2266 : // Make a backup before we start popping elements
2267 129 : m_aTableInheritingCellsSprms = m_aTopLevelTableCellsSprms;
2268 129 : m_aTableInheritingCellsAttributes = m_aTopLevelTableCellsAttributes;
2269 129 : m_nInheritingCells = m_nTopLevelCells;
2270 : }
2271 : else
2272 : {
2273 : // No table definition? Then inherit from the previous row
2274 1 : m_aTopLevelTableCellsSprms = m_aTableInheritingCellsSprms;
2275 1 : m_aTopLevelTableCellsAttributes = m_aTableInheritingCellsAttributes;
2276 1 : m_nTopLevelCells = m_nInheritingCells;
2277 : }
2278 :
2279 260 : while (m_aTableBufferStack.size() > 1)
2280 : {
2281 : SAL_WARN("writerfilter.rtf", "dropping extra table buffer");
2282 : // note: there may be several states pointing to table buffer!
2283 0 : for (size_t i = 0; i < m_aStates.size(); ++i)
2284 : {
2285 0 : if (m_aStates[i].pCurrentBuffer == &m_aTableBufferStack.back())
2286 : {
2287 0 : m_aStates[i].pCurrentBuffer =
2288 0 : &m_aTableBufferStack.front();
2289 : }
2290 : }
2291 0 : m_aTableBufferStack.pop_back();
2292 : }
2293 :
2294 130 : replayRowBuffer(m_aTableBufferStack.back(),
2295 : m_aTopLevelTableCellsSprms, m_aTopLevelTableCellsAttributes,
2296 260 : m_nTopLevelCells);
2297 :
2298 130 : m_aStates.top().aTableCellSprms = m_aDefaultState.aTableCellSprms;
2299 130 : m_aStates.top().aTableCellAttributes = m_aDefaultState.aTableCellAttributes;
2300 :
2301 130 : writerfilter::Reference<Properties>::Pointer_t paraProperties;
2302 260 : writerfilter::Reference<Properties>::Pointer_t frameProperties;
2303 260 : writerfilter::Reference<Properties>::Pointer_t rowProperties;
2304 130 : prepareProperties(m_aStates.top(),
2305 : paraProperties, frameProperties, rowProperties,
2306 260 : m_nTopLevelCells, m_nTopLevelCurrentCellX);
2307 130 : sendProperties(paraProperties, frameProperties, rowProperties);
2308 :
2309 130 : m_bNeedPap = true;
2310 130 : m_bNeedFinalPar = true;
2311 130 : m_aTableBufferStack.back().clear();
2312 130 : m_nTopLevelCells = 0;
2313 :
2314 130 : if (bRestored)
2315 : // We restored cell definitions, clear these now.
2316 : // This is necessary, as later cell definitions want to overwrite the restored ones.
2317 132 : resetTableRowProperties();
2318 : }
2319 130 : break;
2320 : case RTF_COLUMN:
2321 : {
2322 3 : bool bColumns = false; // If we have multiple columns
2323 3 : RTFValue::Pointer_t pCols = m_aStates.top().aSectionSprms.find(NS_ooxml::LN_EG_SectPrContents_cols);
2324 3 : if (pCols.get())
2325 : {
2326 2 : RTFValue::Pointer_t pNum = pCols->getAttributes().find(NS_ooxml::LN_CT_Columns_num);
2327 2 : if (pNum.get() && pNum->getInt() > 1)
2328 2 : bColumns = true;
2329 : }
2330 3 : checkFirstRun();
2331 3 : if (bColumns)
2332 : {
2333 2 : sal_uInt8 sBreak[] = { 0xe };
2334 2 : Mapper().startCharacterGroup();
2335 2 : Mapper().text(sBreak, 1);
2336 2 : Mapper().endCharacterGroup();
2337 : }
2338 : else
2339 1 : dispatchSymbol(RTF_PAGE);
2340 : }
2341 3 : break;
2342 : case RTF_CHFTN:
2343 : {
2344 18 : if (m_aStates.top().pCurrentBuffer == &m_aSuperBuffer)
2345 : // Stop buffering, there will be no custom mark for this footnote or endnote.
2346 7 : m_aStates.top().pCurrentBuffer = 0;
2347 18 : break;
2348 : }
2349 : case RTF_PAGE:
2350 : {
2351 : // Ignore page breaks inside tables.
2352 69 : if (m_aStates.top().pCurrentBuffer == &m_aTableBufferStack.back())
2353 1 : break;
2354 :
2355 : // If we're inside a continuous section, we should send a section break, not a page one.
2356 68 : RTFValue::Pointer_t pBreak = m_aStates.top().aSectionSprms.find(NS_ooxml::LN_EG_SectPrContents_type);
2357 : // Unless we're on a title page.
2358 136 : RTFValue::Pointer_t pTitlePg = m_aStates.top().aSectionSprms.find(NS_ooxml::LN_EG_SectPrContents_titlePg);
2359 140 : if (((pBreak.get() && pBreak->getInt() == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_continuous))
2360 65 : || m_nResetBreakOnSectBreak == RTF_SBKNONE)
2361 72 : && !(pTitlePg.get() && pTitlePg->getInt()))
2362 : {
2363 3 : if (m_bWasInFrame)
2364 : {
2365 2 : dispatchSymbol(RTF_PAR);
2366 2 : m_bWasInFrame = false;
2367 : }
2368 3 : sectBreak();
2369 : // note: this will not affect the following section break
2370 : // but the one just pushed
2371 3 : dispatchFlag(RTF_SBKPAGE);
2372 3 : if (m_bNeedPar)
2373 3 : dispatchSymbol(RTF_PAR);
2374 3 : m_bIgnoreNextContSectBreak = true;
2375 : // arrange to clean up the syntetic RTF_SBKPAGE
2376 3 : m_nResetBreakOnSectBreak = RTF_SBKNONE;
2377 : }
2378 : else
2379 : {
2380 65 : checkFirstRun();
2381 65 : checkNeedPap();
2382 65 : sal_uInt8 sBreak[] = { 0xc };
2383 65 : Mapper().text(sBreak, 1);
2384 65 : if (!m_bNeedPap)
2385 : {
2386 65 : parBreak();
2387 65 : m_bNeedPap = true;
2388 : }
2389 65 : m_bNeedCr = true;
2390 68 : }
2391 : }
2392 68 : break;
2393 : case RTF_CHPGN:
2394 : {
2395 2 : OUString aStr("PAGE");
2396 2 : singleChar(cFieldStart);
2397 2 : text(aStr);
2398 2 : singleChar(cFieldSep, true);
2399 2 : singleChar(cFieldEnd);
2400 : }
2401 2 : break;
2402 : case RTF_CHFTNSEP:
2403 : {
2404 : static const sal_Unicode uFtnEdnSep = 0x3;
2405 59 : Mapper().utext(reinterpret_cast<const sal_uInt8*>(&uFtnEdnSep), 1);
2406 : }
2407 59 : break;
2408 : default:
2409 : {
2410 : SAL_INFO("writerfilter", "TODO handle symbol '" << lcl_RtfToString(nKeyword) << "'");
2411 10 : aSkip.setParsed(false);
2412 : }
2413 10 : break;
2414 : }
2415 29711 : return RTFError::OK;
2416 : }
2417 :
2418 :
2419 636 : static int lcl_getNumberFormat(int nParam)
2420 : {
2421 : static const int aMap[] =
2422 : {
2423 : NS_ooxml::LN_Value_ST_NumberFormat_decimal,
2424 : NS_ooxml::LN_Value_ST_NumberFormat_upperRoman,
2425 : NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman,
2426 : NS_ooxml::LN_Value_ST_NumberFormat_upperLetter,
2427 : NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter,
2428 : NS_ooxml::LN_Value_ST_NumberFormat_ordinal,
2429 : NS_ooxml::LN_Value_ST_NumberFormat_cardinalText,
2430 : NS_ooxml::LN_Value_ST_NumberFormat_ordinalText,
2431 : NS_ooxml::LN_Value_ST_NumberFormat_none, // Undefined in RTF 1.8 spec.
2432 : NS_ooxml::LN_Value_ST_NumberFormat_none, // Undefined in RTF 1.8 spec.
2433 : NS_ooxml::LN_Value_ST_NumberFormat_ideographDigital,
2434 : NS_ooxml::LN_Value_ST_NumberFormat_japaneseCounting,
2435 : NS_ooxml::LN_Value_ST_NumberFormat_aiueo,
2436 : NS_ooxml::LN_Value_ST_NumberFormat_iroha,
2437 : NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth,
2438 : NS_ooxml::LN_Value_ST_NumberFormat_decimalHalfWidth,
2439 : NS_ooxml::LN_Value_ST_NumberFormat_japaneseLegal,
2440 : NS_ooxml::LN_Value_ST_NumberFormat_japaneseDigitalTenThousand ,
2441 : NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircleChinese,
2442 : NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth2,
2443 : NS_ooxml::LN_Value_ST_NumberFormat_aiueoFullWidth,
2444 : NS_ooxml::LN_Value_ST_NumberFormat_irohaFullWidth,
2445 : NS_ooxml::LN_Value_ST_NumberFormat_decimalZero,
2446 : NS_ooxml::LN_Value_ST_NumberFormat_bullet,
2447 : NS_ooxml::LN_Value_ST_NumberFormat_ganada,
2448 : NS_ooxml::LN_Value_ST_NumberFormat_chosung,
2449 : NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedFullstop,
2450 : NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedParen,
2451 : NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircleChinese,
2452 : NS_ooxml::LN_Value_ST_NumberFormat_ideographEnclosedCircle,
2453 : NS_ooxml::LN_Value_ST_NumberFormat_ideographTraditional,
2454 : NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiac,
2455 : NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiacTraditional,
2456 : NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCounting,
2457 : NS_ooxml::LN_Value_ST_NumberFormat_ideographLegalTraditional,
2458 : NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCountingThousand,
2459 : NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseDigital,
2460 : NS_ooxml::LN_Value_ST_NumberFormat_chineseCounting,
2461 : NS_ooxml::LN_Value_ST_NumberFormat_chineseLegalSimplified,
2462 : NS_ooxml::LN_Value_ST_NumberFormat_chineseCountingThousand,
2463 : NS_ooxml::LN_Value_ST_NumberFormat_decimal,
2464 : NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital,
2465 : NS_ooxml::LN_Value_ST_NumberFormat_koreanCounting,
2466 : NS_ooxml::LN_Value_ST_NumberFormat_koreanLegal,
2467 : NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital2,
2468 : NS_ooxml::LN_Value_ST_NumberFormat_hebrew1,
2469 : NS_ooxml::LN_Value_ST_NumberFormat_arabicAlpha,
2470 : NS_ooxml::LN_Value_ST_NumberFormat_hebrew2,
2471 : NS_ooxml::LN_Value_ST_NumberFormat_arabicAbjad
2472 : };
2473 636 : const int nLen = SAL_N_ELEMENTS(aMap);
2474 636 : int nValue = 0;
2475 636 : if (nParam >= 0 && nParam < nLen)
2476 477 : nValue = aMap[nParam];
2477 : else // 255 and the other cases.
2478 159 : nValue = NS_ooxml::LN_Value_ST_NumberFormat_none;
2479 636 : return nValue;
2480 : }
2481 :
2482 :
2483 : // Checks if rName is contained at least once in rProperties as a key.
2484 130 : bool lcl_findPropertyName(const std::vector<beans::PropertyValue>& rProperties, const OUString& rName)
2485 : {
2486 715 : for (std::vector<beans::PropertyValue>::const_iterator it = rProperties.begin(); it != rProperties.end(); ++it)
2487 : {
2488 611 : if (it->Name == rName)
2489 26 : return true;
2490 : }
2491 104 : return false;
2492 : }
2493 :
2494 175 : void RTFDocumentImpl::backupTableRowProperties()
2495 : {
2496 175 : if (m_nTopLevelCurrentCellX)
2497 : {
2498 117 : m_aBackupTableRowSprms = m_aStates.top().aTableRowSprms;
2499 117 : m_aBackupTableRowAttributes = m_aStates.top().aTableRowAttributes;
2500 117 : m_nBackupTopLevelCurrentCellX = m_nTopLevelCurrentCellX;
2501 : }
2502 175 : }
2503 :
2504 2 : void RTFDocumentImpl::restoreTableRowProperties()
2505 : {
2506 2 : m_aStates.top().aTableRowSprms = m_aBackupTableRowSprms;
2507 2 : m_aStates.top().aTableRowAttributes = m_aBackupTableRowAttributes;
2508 2 : m_nTopLevelCurrentCellX = m_nBackupTopLevelCurrentCellX;
2509 2 : }
2510 :
2511 177 : void RTFDocumentImpl::resetTableRowProperties()
2512 : {
2513 177 : m_aStates.top().aTableRowSprms = m_aDefaultState.aTableRowSprms;
2514 177 : m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TblGridBase_gridCol, std::make_shared<RTFValue>(-1), RTFOverwrite::NO_APPEND);
2515 177 : m_aStates.top().aTableRowAttributes = m_aDefaultState.aTableRowAttributes;
2516 177 : if (Destination::NESTEDTABLEPROPERTIES == m_aStates.top().eDestination)
2517 6 : m_nNestedCurrentCellX = 0;
2518 : else
2519 171 : m_nTopLevelCurrentCellX = 0;
2520 177 : }
2521 :
2522 41411 : RTFError RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
2523 : {
2524 41411 : setNeedSect();
2525 41411 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
2526 41411 : RTFSkipDestination aSkip(*this);
2527 41411 : int nParam = -1;
2528 41411 : int nSprm = -1;
2529 :
2530 : // Underline flags.
2531 41411 : switch (nKeyword)
2532 : {
2533 : case RTF_ULD:
2534 2 : nSprm = NS_ooxml::LN_Value_ST_Underline_dotted;
2535 2 : break;
2536 : case RTF_ULW:
2537 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_words;
2538 0 : break;
2539 : default:
2540 41409 : break;
2541 : }
2542 41411 : if (nSprm >= 0)
2543 : {
2544 2 : auto pValue = std::make_shared<RTFValue>(nSprm);
2545 2 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_Underline_val, pValue);
2546 2 : return RTFError::OK;
2547 : }
2548 :
2549 : // Indentation
2550 41409 : switch (nKeyword)
2551 : {
2552 : case RTF_QC:
2553 87 : nParam = NS_ooxml::LN_Value_ST_Jc_center;
2554 87 : break;
2555 : case RTF_QJ:
2556 40 : nParam = NS_ooxml::LN_Value_ST_Jc_both;
2557 40 : break;
2558 : case RTF_QL:
2559 1227 : nParam = NS_ooxml::LN_Value_ST_Jc_left;
2560 1227 : break;
2561 : case RTF_QR:
2562 54 : nParam = NS_ooxml::LN_Value_ST_Jc_right;
2563 54 : break;
2564 : case RTF_QD:
2565 0 : nParam = NS_ooxml::LN_Value_ST_Jc_both;
2566 0 : break;
2567 : default:
2568 40001 : break;
2569 : }
2570 41409 : if (nParam >= 0)
2571 : {
2572 1408 : auto pValue = std::make_shared<RTFValue>(nParam);
2573 1408 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_jc, pValue);
2574 1408 : m_bNeedPap = true;
2575 1408 : return RTFError::OK;
2576 : }
2577 :
2578 : // Font Alignment
2579 40001 : switch (nKeyword)
2580 : {
2581 : case RTF_FAFIXED:
2582 : case RTF_FAAUTO:
2583 1131 : nParam = NS_ooxml::LN_Value_doc_ST_TextAlignment_auto;
2584 1131 : break;
2585 : case RTF_FAHANG:
2586 0 : nParam = NS_ooxml::LN_Value_doc_ST_TextAlignment_top;
2587 0 : break;
2588 : case RTF_FACENTER:
2589 0 : nParam = NS_ooxml::LN_Value_doc_ST_TextAlignment_center;
2590 0 : break;
2591 : case RTF_FAROMAN:
2592 1 : nParam = NS_ooxml::LN_Value_doc_ST_TextAlignment_baseline;
2593 1 : break;
2594 : case RTF_FAVAR:
2595 0 : nParam = NS_ooxml::LN_Value_doc_ST_TextAlignment_bottom;
2596 0 : break;
2597 : default:
2598 38869 : break;
2599 : }
2600 40001 : if (nParam >= 0)
2601 : {
2602 1132 : auto pValue = std::make_shared<RTFValue>(nParam);
2603 1132 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_textAlignment, pValue);
2604 1132 : return RTFError::OK;
2605 : }
2606 :
2607 : // Tab kind.
2608 38869 : switch (nKeyword)
2609 : {
2610 : case RTF_TQR:
2611 106 : nParam = NS_ooxml::LN_Value_ST_TabJc_right;
2612 106 : break;
2613 : case RTF_TQC:
2614 84 : nParam = NS_ooxml::LN_Value_ST_TabJc_center;
2615 84 : break;
2616 : case RTF_TQDEC:
2617 0 : nParam = NS_ooxml::LN_Value_ST_TabJc_decimal;
2618 0 : break;
2619 : default:
2620 38679 : break;
2621 : }
2622 38869 : if (nParam >= 0)
2623 : {
2624 190 : auto pValue = std::make_shared<RTFValue>(nParam);
2625 190 : m_aStates.top().aTabAttributes.set(NS_ooxml::LN_CT_TabStop_val, pValue);
2626 190 : return RTFError::OK;
2627 : }
2628 :
2629 : // Tab lead.
2630 38679 : switch (nKeyword)
2631 : {
2632 : case RTF_TLDOT:
2633 8 : nParam = NS_ooxml::LN_Value_ST_TabTlc_dot;
2634 8 : break;
2635 : case RTF_TLMDOT:
2636 0 : nParam = NS_ooxml::LN_Value_ST_TabTlc_middleDot;
2637 0 : break;
2638 : case RTF_TLHYPH:
2639 0 : nParam = NS_ooxml::LN_Value_ST_TabTlc_hyphen;
2640 0 : break;
2641 : case RTF_TLUL:
2642 1 : nParam = NS_ooxml::LN_Value_ST_TabTlc_underscore;
2643 1 : break;
2644 : case RTF_TLTH:
2645 0 : nParam = NS_ooxml::LN_Value_ST_TabTlc_hyphen;
2646 0 : break; // thick line is not supported by dmapper, this is just a hack
2647 : case RTF_TLEQ:
2648 0 : nParam = NS_ooxml::LN_Value_ST_TabTlc_none;
2649 0 : break; // equal sign isn't, either
2650 : default:
2651 38670 : break;
2652 : }
2653 38679 : if (nParam >= 0)
2654 : {
2655 9 : auto pValue = std::make_shared<RTFValue>(nParam);
2656 9 : m_aStates.top().aTabAttributes.set(NS_ooxml::LN_CT_TabStop_leader, pValue);
2657 9 : return RTFError::OK;
2658 : }
2659 :
2660 : // Border types
2661 : {
2662 38670 : switch (nKeyword)
2663 : {
2664 : // brdrhair and brdrs are the same, brdrw will make a difference
2665 : // map to values in ooxml/model.xml resource ST_Border
2666 : case RTF_BRDRHAIR:
2667 : case RTF_BRDRS:
2668 488 : nParam = NS_ooxml::LN_Value_ST_Border_single;
2669 488 : break;
2670 : case RTF_BRDRDOT:
2671 4 : nParam = NS_ooxml::LN_Value_ST_Border_dotted;
2672 4 : break;
2673 : case RTF_BRDRDASH:
2674 0 : nParam = NS_ooxml::LN_Value_ST_Border_dashed;
2675 0 : break;
2676 : case RTF_BRDRDB:
2677 52 : nParam = NS_ooxml::LN_Value_ST_Border_double;
2678 52 : break;
2679 : case RTF_BRDRTNTHSG:
2680 0 : nParam = NS_ooxml::LN_Value_ST_Border_thinThickSmallGap;
2681 0 : break;
2682 : case RTF_BRDRTNTHMG:
2683 4 : nParam = NS_ooxml::LN_Value_ST_Border_thinThickMediumGap;
2684 4 : break;
2685 : case RTF_BRDRTNTHLG:
2686 0 : nParam = NS_ooxml::LN_Value_ST_Border_thinThickLargeGap;
2687 0 : break;
2688 : case RTF_BRDRTHTNSG:
2689 10 : nParam = NS_ooxml::LN_Value_ST_Border_thickThinSmallGap;
2690 10 : break;
2691 : case RTF_BRDRTHTNMG:
2692 20 : nParam = NS_ooxml::LN_Value_ST_Border_thickThinMediumGap;
2693 20 : break;
2694 : case RTF_BRDRTHTNLG:
2695 18 : nParam = NS_ooxml::LN_Value_ST_Border_thickThinLargeGap;
2696 18 : break;
2697 : case RTF_BRDREMBOSS:
2698 12 : nParam = NS_ooxml::LN_Value_ST_Border_threeDEmboss;
2699 12 : break;
2700 : case RTF_BRDRENGRAVE:
2701 12 : nParam = NS_ooxml::LN_Value_ST_Border_threeDEngrave;
2702 12 : break;
2703 : case RTF_BRDROUTSET:
2704 22 : nParam = NS_ooxml::LN_Value_ST_Border_outset;
2705 22 : break;
2706 : case RTF_BRDRINSET:
2707 20 : nParam = NS_ooxml::LN_Value_ST_Border_inset;
2708 20 : break;
2709 : case RTF_BRDRNONE:
2710 207 : nParam = NS_ooxml::LN_Value_ST_Border_none;
2711 207 : break;
2712 : default:
2713 37801 : break;
2714 : }
2715 38670 : if (nParam >= 0)
2716 : {
2717 869 : auto pValue = std::make_shared<RTFValue>(nParam);
2718 869 : lcl_putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_val, pValue);
2719 869 : return RTFError::OK;
2720 : }
2721 : }
2722 :
2723 : // Section breaks
2724 37801 : switch (nKeyword)
2725 : {
2726 : case RTF_SBKNONE:
2727 121 : nParam = NS_ooxml::LN_Value_ST_SectionMark_continuous;
2728 121 : break;
2729 : case RTF_SBKCOL:
2730 0 : nParam = NS_ooxml::LN_Value_ST_SectionMark_nextColumn;
2731 0 : break;
2732 : case RTF_SBKPAGE:
2733 6 : nParam = NS_ooxml::LN_Value_ST_SectionMark_nextPage;
2734 6 : break;
2735 : case RTF_SBKEVEN:
2736 0 : nParam = NS_ooxml::LN_Value_ST_SectionMark_evenPage;
2737 0 : break;
2738 : case RTF_SBKODD:
2739 0 : nParam = NS_ooxml::LN_Value_ST_SectionMark_oddPage;
2740 0 : break;
2741 : default:
2742 37674 : break;
2743 : }
2744 37801 : if (nParam >= 0)
2745 : {
2746 127 : if (m_nResetBreakOnSectBreak != RTF_invalid)
2747 : {
2748 1 : m_nResetBreakOnSectBreak = nKeyword;
2749 : }
2750 127 : auto pValue = std::make_shared<RTFValue>(nParam);
2751 127 : m_aStates.top().aSectionSprms.set(NS_ooxml::LN_EG_SectPrContents_type, pValue);
2752 127 : return RTFError::OK;
2753 : }
2754 :
2755 : // Footnote numbering
2756 37674 : switch (nKeyword)
2757 : {
2758 : case RTF_FTNNAR:
2759 109 : nParam = NS_ooxml::LN_Value_ST_NumberFormat_decimal;
2760 109 : break;
2761 : case RTF_FTNNALC:
2762 0 : nParam = NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter;
2763 0 : break;
2764 : case RTF_FTNNAUC:
2765 0 : nParam = NS_ooxml::LN_Value_ST_NumberFormat_upperLetter;
2766 0 : break;
2767 : case RTF_FTNNRLC:
2768 0 : nParam = NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman;
2769 0 : break;
2770 : case RTF_FTNNRUC:
2771 0 : nParam = NS_ooxml::LN_Value_ST_NumberFormat_upperRoman;
2772 0 : break;
2773 : case RTF_FTNNCHI:
2774 0 : nParam = NS_ooxml::LN_Value_ST_NumberFormat_chicago;
2775 0 : break;
2776 : default:
2777 37565 : break;
2778 : }
2779 37674 : if (nParam >= 0)
2780 : {
2781 109 : auto pValue = std::make_shared<RTFValue>(nParam);
2782 109 : lcl_putNestedSprm(m_aDefaultState.aParagraphSprms, NS_ooxml::LN_EG_SectPrContents_footnotePr, NS_ooxml::LN_CT_FtnProps_numFmt, pValue);
2783 109 : return RTFError::OK;
2784 : }
2785 :
2786 : // Footnote restart type
2787 37565 : switch (nKeyword)
2788 : {
2789 : case RTF_FTNRSTPG:
2790 1 : nParam = NS_ooxml::LN_Value_ST_RestartNumber_eachPage;
2791 1 : break;
2792 : case RTF_FTNRESTART:
2793 0 : nParam = NS_ooxml::LN_Value_ST_RestartNumber_eachSect;
2794 0 : break;
2795 : case RTF_FTNRSTCONT:
2796 104 : nParam = NS_ooxml::LN_Value_ST_RestartNumber_continuous;
2797 104 : break;
2798 : default:
2799 37460 : break;
2800 : }
2801 37565 : if (nParam >= 0)
2802 : {
2803 105 : auto pValue = std::make_shared<RTFValue>(nParam);
2804 105 : lcl_putNestedSprm(m_aDefaultState.aParagraphSprms, NS_ooxml::LN_EG_SectPrContents_footnotePr, NS_ooxml::LN_EG_FtnEdnNumProps_numRestart, pValue);
2805 105 : return RTFError::OK;
2806 : }
2807 :
2808 : // Endnote numbering
2809 37460 : switch (nKeyword)
2810 : {
2811 : case RTF_AFTNNAR:
2812 6 : nParam = NS_ooxml::LN_Value_ST_NumberFormat_decimal;
2813 6 : break;
2814 : case RTF_AFTNNALC:
2815 0 : nParam = NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter;
2816 0 : break;
2817 : case RTF_AFTNNAUC:
2818 0 : nParam = NS_ooxml::LN_Value_ST_NumberFormat_upperLetter;
2819 0 : break;
2820 : case RTF_AFTNNRLC:
2821 105 : nParam = NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman;
2822 105 : break;
2823 : case RTF_AFTNNRUC:
2824 0 : nParam = NS_ooxml::LN_Value_ST_NumberFormat_upperRoman;
2825 0 : break;
2826 : case RTF_AFTNNCHI:
2827 0 : nParam = NS_ooxml::LN_Value_ST_NumberFormat_chicago;
2828 0 : break;
2829 : default:
2830 37349 : break;
2831 : }
2832 37460 : if (nParam >= 0)
2833 : {
2834 111 : auto pValue = std::make_shared<RTFValue>(nParam);
2835 111 : lcl_putNestedSprm(m_aDefaultState.aParagraphSprms, NS_ooxml::LN_EG_SectPrContents_endnotePr, NS_ooxml::LN_CT_EdnProps_numFmt, pValue);
2836 111 : return RTFError::OK;
2837 : }
2838 :
2839 37349 : switch (nKeyword)
2840 : {
2841 : case RTF_TRQL:
2842 60 : nParam = NS_ooxml::LN_Value_ST_Jc_left;
2843 60 : break;
2844 : case RTF_TRQC:
2845 2 : nParam = NS_ooxml::LN_Value_ST_Jc_center;
2846 2 : break;
2847 : case RTF_TRQR:
2848 0 : nParam = NS_ooxml::LN_Value_ST_Jc_right;
2849 0 : break;
2850 : default:
2851 37287 : break;
2852 : }
2853 37349 : if (nParam >= 0)
2854 : {
2855 62 : auto pValue = std::make_shared<RTFValue>(nParam);
2856 62 : m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TrPrBase_jc, pValue);
2857 62 : return RTFError::OK;
2858 : }
2859 :
2860 : // Cell Text Flow
2861 37287 : switch (nKeyword)
2862 : {
2863 : case RTF_CLTXLRTB:
2864 222 : nParam = NS_ooxml::LN_Value_ST_TextDirection_lrTb;
2865 222 : break;
2866 : case RTF_CLTXTBRL:
2867 0 : nParam = NS_ooxml::LN_Value_ST_TextDirection_tbRl;
2868 0 : break;
2869 : case RTF_CLTXBTLR:
2870 0 : nParam = NS_ooxml::LN_Value_ST_TextDirection_btLr;
2871 0 : break;
2872 : case RTF_CLTXLRTBV:
2873 0 : nParam = NS_ooxml::LN_Value_ST_TextDirection_lrTbV;
2874 0 : break;
2875 : case RTF_CLTXTBRLV:
2876 0 : nParam = NS_ooxml::LN_Value_ST_TextDirection_tbRlV;
2877 0 : break;
2878 : default:
2879 37065 : break;
2880 : }
2881 37287 : if (nParam >= 0)
2882 : {
2883 222 : auto pValue = std::make_shared<RTFValue>(nParam);
2884 222 : m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_textDirection, pValue);
2885 : }
2886 :
2887 : // Trivial paragraph flags
2888 37287 : switch (nKeyword)
2889 : {
2890 : case RTF_KEEP:
2891 35 : if (m_aStates.top().pCurrentBuffer != &m_aTableBufferStack.back())
2892 35 : nParam = NS_ooxml::LN_CT_PPrBase_keepLines;
2893 35 : break;
2894 : case RTF_KEEPN:
2895 194 : if (m_aStates.top().pCurrentBuffer != &m_aTableBufferStack.back())
2896 168 : nParam = NS_ooxml::LN_CT_PPrBase_keepNext;
2897 194 : break;
2898 : case RTF_INTBL:
2899 : {
2900 793 : m_aStates.top().pCurrentBuffer = &m_aTableBufferStack.back();
2901 793 : nParam = NS_ooxml::LN_inTbl;
2902 : }
2903 793 : break;
2904 : case RTF_PAGEBB:
2905 9 : nParam = NS_ooxml::LN_CT_PPrBase_pageBreakBefore;
2906 9 : break;
2907 : default:
2908 36256 : break;
2909 : }
2910 37287 : if (nParam >= 0)
2911 : {
2912 1227 : auto pValue = std::make_shared<RTFValue>(1);
2913 1227 : m_aStates.top().aParagraphSprms.erase(NS_ooxml::LN_inTbl);
2914 1227 : m_aStates.top().aParagraphSprms.set(nParam, pValue);
2915 1227 : return RTFError::OK;
2916 : }
2917 :
2918 36060 : switch (nKeyword)
2919 : {
2920 : case RTF_FNIL:
2921 : case RTF_FROMAN:
2922 : case RTF_FSWISS:
2923 : case RTF_FMODERN:
2924 : case RTF_FSCRIPT:
2925 : case RTF_FDECOR:
2926 : case RTF_FTECH:
2927 : case RTF_FBIDI:
2928 : // TODO ooxml:CT_Font_family seems to be ignored by the domain mapper
2929 5591 : break;
2930 : case RTF_ANSI:
2931 222 : m_aStates.top().nCurrentEncoding = RTL_TEXTENCODING_MS_1252;
2932 222 : break;
2933 : case RTF_MAC:
2934 1 : m_aDefaultState.nCurrentEncoding = RTL_TEXTENCODING_APPLE_ROMAN;
2935 1 : m_aStates.top().nCurrentEncoding = m_aDefaultState.nCurrentEncoding;
2936 1 : break;
2937 : case RTF_PC:
2938 1 : m_aDefaultState.nCurrentEncoding = RTL_TEXTENCODING_IBM_437;
2939 1 : m_aStates.top().nCurrentEncoding = m_aDefaultState.nCurrentEncoding;
2940 1 : break;
2941 : case RTF_PCA:
2942 1 : m_aDefaultState.nCurrentEncoding = RTL_TEXTENCODING_IBM_850;
2943 1 : m_aStates.top().nCurrentEncoding = m_aDefaultState.nCurrentEncoding;
2944 1 : break;
2945 : case RTF_PLAIN:
2946 : {
2947 898 : m_aStates.top().aCharacterSprms = getDefaultState().aCharacterSprms;
2948 898 : m_aStates.top().nCurrentEncoding = getEncoding(getFontIndex(m_nDefaultFontIndex));
2949 898 : m_aStates.top().aCharacterAttributes = getDefaultState().aCharacterAttributes;
2950 898 : m_aStates.top().nCurrentCharacterStyleIndex = -1;
2951 898 : m_aStates.top().isRightToLeft = false;
2952 898 : m_aStates.top().eRunType = RTFParserState::LOCH;
2953 : }
2954 898 : break;
2955 : case RTF_PARD:
2956 1259 : if (m_bHadPicture)
2957 1 : dispatchSymbol(RTF_PAR);
2958 : // \pard is allowed between \cell and \row, but in that case it should not reset the fact that we're inside a table.
2959 1259 : m_aStates.top().aParagraphSprms = m_aDefaultState.aParagraphSprms;
2960 1259 : m_aStates.top().aParagraphAttributes = m_aDefaultState.aParagraphAttributes;
2961 :
2962 1259 : if (m_nTopLevelCells == 0 && m_nNestedCells == 0)
2963 : {
2964 : // Reset that we're in a table.
2965 1020 : m_aStates.top().pCurrentBuffer = nullptr;
2966 : }
2967 : else
2968 : {
2969 : // We are still in a table.
2970 239 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_inTbl, std::make_shared<RTFValue>(1));
2971 : }
2972 1259 : m_aStates.top().resetFrame();
2973 :
2974 : // Reset currently selected paragraph style as well.
2975 : // By default the style with index 0 is applied.
2976 : {
2977 1259 : OUString const aName = getStyleName(0);
2978 1259 : if (!aName.isEmpty())
2979 : {
2980 843 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_pStyle, std::make_shared<RTFValue>(aName));
2981 843 : m_aStates.top().nCurrentStyleIndex = 0;
2982 : }
2983 : else
2984 : {
2985 416 : m_aStates.top().nCurrentStyleIndex = -1;
2986 1259 : }
2987 : }
2988 : // Need to send paragraph properties again, if there will be any.
2989 1259 : m_bNeedPap = true;
2990 1259 : break;
2991 : case RTF_SECTD:
2992 : {
2993 171 : m_aStates.top().aSectionSprms = m_aDefaultState.aSectionSprms;
2994 171 : m_aStates.top().aSectionAttributes = m_aDefaultState.aSectionAttributes;
2995 : }
2996 171 : break;
2997 : case RTF_TROWD:
2998 : {
2999 : // Back these up, in case later we still need this info.
3000 175 : backupTableRowProperties();
3001 175 : resetTableRowProperties();
3002 : // In case the table definition is in the middle of the row
3003 : // (invalid), make sure table definition is emitted.
3004 175 : m_bNeedPap = true;
3005 : }
3006 175 : break;
3007 : case RTF_WIDCTLPAR:
3008 : case RTF_NOWIDCTLPAR:
3009 : {
3010 1644 : auto pValue = std::make_shared<RTFValue>(int(nKeyword == RTF_WIDCTLPAR));
3011 1644 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_widowControl, pValue);
3012 : }
3013 1644 : break;
3014 : case RTF_BOX:
3015 : {
3016 1 : RTFSprms aAttributes;
3017 2 : auto pValue = std::make_shared<RTFValue>(aAttributes);
3018 5 : for (int i = 0; i < 4; i++)
3019 4 : m_aStates.top().aParagraphSprms.set(lcl_getParagraphBorder(i), pValue);
3020 2 : m_aStates.top().nBorderState = RTFBorderState::PARAGRAPH_BOX;
3021 : }
3022 1 : break;
3023 : case RTF_LTRSECT:
3024 : case RTF_RTLSECT:
3025 : {
3026 72 : auto pValue = std::make_shared<RTFValue>(nKeyword == RTF_LTRSECT ? 0 : 1);
3027 72 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_EG_SectPrContents_textDirection, pValue);
3028 : }
3029 72 : break;
3030 : case RTF_LTRPAR:
3031 : case RTF_RTLPAR:
3032 : {
3033 1128 : auto pValue = std::make_shared<RTFValue>(nKeyword == RTF_LTRPAR ? 0 : 1);
3034 1128 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_bidi, pValue);
3035 : }
3036 1128 : break;
3037 : case RTF_LTRROW:
3038 : case RTF_RTLROW:
3039 147 : m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TblPrBase_bidiVisual, std::make_shared<RTFValue>(int(nKeyword == RTF_RTLROW)));
3040 147 : break;
3041 : case RTF_LTRCH:
3042 : // dmapper does not support this.
3043 3349 : m_aStates.top().isRightToLeft = false;
3044 3349 : break;
3045 : case RTF_RTLCH:
3046 3341 : m_aStates.top().isRightToLeft = true;
3047 3341 : if (m_aDefaultState.nCurrentEncoding == RTL_TEXTENCODING_MS_1255)
3048 1 : m_aStates.top().nCurrentEncoding = m_aDefaultState.nCurrentEncoding;
3049 3341 : break;
3050 : case RTF_ULNONE:
3051 : {
3052 12 : auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_Underline_none);
3053 12 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_Underline_val, pValue);
3054 : }
3055 12 : break;
3056 : case RTF_NONSHPPICT:
3057 : case RTF_MMATHPICT: // Picture group used by readers not understanding \moMath group
3058 1 : m_aStates.top().eDestination = Destination::SKIP;
3059 1 : break;
3060 : case RTF_CLBRDRT:
3061 : case RTF_CLBRDRL:
3062 : case RTF_CLBRDRB:
3063 : case RTF_CLBRDRR:
3064 : {
3065 1110 : RTFSprms aAttributes;
3066 2220 : RTFSprms aSprms;
3067 2220 : auto pValue = std::make_shared<RTFValue>(aAttributes, aSprms);
3068 1110 : switch (nKeyword)
3069 : {
3070 : case RTF_CLBRDRT:
3071 268 : nParam = NS_ooxml::LN_CT_TcBorders_top;
3072 268 : break;
3073 : case RTF_CLBRDRL:
3074 291 : nParam = NS_ooxml::LN_CT_TcBorders_left;
3075 291 : break;
3076 : case RTF_CLBRDRB:
3077 274 : nParam = NS_ooxml::LN_CT_TcBorders_bottom;
3078 274 : break;
3079 : case RTF_CLBRDRR:
3080 277 : nParam = NS_ooxml::LN_CT_TcBorders_right;
3081 277 : break;
3082 : default:
3083 0 : break;
3084 : }
3085 1110 : lcl_putNestedSprm(m_aStates.top().aTableCellSprms, NS_ooxml::LN_CT_TcPrBase_tcBorders, nParam, pValue);
3086 2220 : m_aStates.top().nBorderState = RTFBorderState::CELL;
3087 : }
3088 1110 : break;
3089 : case RTF_PGBRDRT:
3090 : case RTF_PGBRDRL:
3091 : case RTF_PGBRDRB:
3092 : case RTF_PGBRDRR:
3093 : {
3094 0 : RTFSprms aAttributes;
3095 0 : RTFSprms aSprms;
3096 0 : auto pValue = std::make_shared<RTFValue>(aAttributes, aSprms);
3097 0 : switch (nKeyword)
3098 : {
3099 : case RTF_PGBRDRT:
3100 0 : nParam = NS_ooxml::LN_CT_PageBorders_top;
3101 0 : break;
3102 : case RTF_PGBRDRL:
3103 0 : nParam = NS_ooxml::LN_CT_PageBorders_left;
3104 0 : break;
3105 : case RTF_PGBRDRB:
3106 0 : nParam = NS_ooxml::LN_CT_PageBorders_bottom;
3107 0 : break;
3108 : case RTF_PGBRDRR:
3109 0 : nParam = NS_ooxml::LN_CT_PageBorders_right;
3110 0 : break;
3111 : default:
3112 0 : break;
3113 : }
3114 0 : lcl_putNestedSprm(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgBorders, nParam, pValue);
3115 0 : m_aStates.top().nBorderState = RTFBorderState::PAGE;
3116 : }
3117 0 : break;
3118 : case RTF_BRDRT:
3119 : case RTF_BRDRL:
3120 : case RTF_BRDRB:
3121 : case RTF_BRDRR:
3122 : {
3123 18 : RTFSprms aAttributes;
3124 36 : RTFSprms aSprms;
3125 36 : auto pValue = std::make_shared<RTFValue>(aAttributes, aSprms);
3126 18 : switch (nKeyword)
3127 : {
3128 : case RTF_BRDRT:
3129 5 : nParam = lcl_getParagraphBorder(0);
3130 5 : break;
3131 : case RTF_BRDRL:
3132 3 : nParam = lcl_getParagraphBorder(1);
3133 3 : break;
3134 : case RTF_BRDRB:
3135 7 : nParam = lcl_getParagraphBorder(2);
3136 7 : break;
3137 : case RTF_BRDRR:
3138 3 : nParam = lcl_getParagraphBorder(3);
3139 3 : break;
3140 : default:
3141 0 : break;
3142 : }
3143 18 : lcl_putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PrBase_pBdr, nParam, pValue);
3144 36 : m_aStates.top().nBorderState = RTFBorderState::PARAGRAPH;
3145 : }
3146 18 : break;
3147 : case RTF_CHBRDR:
3148 : {
3149 4 : RTFSprms aAttributes;
3150 8 : auto pValue = std::make_shared<RTFValue>(aAttributes);
3151 4 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_bdr, pValue);
3152 8 : m_aStates.top().nBorderState = RTFBorderState::CHARACTER;
3153 : }
3154 4 : break;
3155 : case RTF_CLMGF:
3156 : {
3157 1 : auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_Merge_restart);
3158 1 : m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_hMerge, pValue);
3159 : }
3160 1 : break;
3161 : case RTF_CLMRG:
3162 : {
3163 1 : auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_Merge_continue);
3164 1 : m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_hMerge, pValue);
3165 : }
3166 1 : break;
3167 : case RTF_CLVMGF:
3168 : {
3169 3 : auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_Merge_restart);
3170 3 : m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_vMerge, pValue);
3171 : }
3172 3 : break;
3173 : case RTF_CLVMRG:
3174 : {
3175 0 : auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_Merge_continue);
3176 0 : m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_vMerge, pValue);
3177 : }
3178 0 : break;
3179 : case RTF_CLVERTALT:
3180 : case RTF_CLVERTALC:
3181 : case RTF_CLVERTALB:
3182 : {
3183 331 : switch (nKeyword)
3184 : {
3185 : case RTF_CLVERTALT:
3186 324 : nParam = NS_ooxml::LN_Value_ST_VerticalJc_top;
3187 324 : break;
3188 : case RTF_CLVERTALC:
3189 2 : nParam = NS_ooxml::LN_Value_ST_VerticalJc_center;
3190 2 : break;
3191 : case RTF_CLVERTALB:
3192 5 : nParam = NS_ooxml::LN_Value_ST_VerticalJc_bottom;
3193 5 : break;
3194 : default:
3195 0 : break;
3196 : }
3197 331 : auto pValue = std::make_shared<RTFValue>(nParam);
3198 331 : m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_vAlign, pValue);
3199 : }
3200 331 : break;
3201 : case RTF_TRKEEP:
3202 : {
3203 8 : auto pValue = std::make_shared<RTFValue>(1);
3204 8 : m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TrPrBase_cantSplit, pValue);
3205 : }
3206 8 : break;
3207 : case RTF_SECTUNLOCKED:
3208 : {
3209 106 : auto pValue = std::make_shared<RTFValue>(int(!nParam));
3210 106 : m_aStates.top().aSectionSprms.set(NS_ooxml::LN_EG_SectPrContents_formProt, pValue);
3211 : }
3212 106 : break;
3213 : case RTF_PGNDEC:
3214 : case RTF_PGNUCRM:
3215 : case RTF_PGNLCRM:
3216 : case RTF_PGNUCLTR:
3217 : case RTF_PGNLCLTR:
3218 : case RTF_PGNBIDIA:
3219 : case RTF_PGNBIDIB:
3220 : // These should be mapped to NS_ooxml::LN_EG_SectPrContents_pgNumType, but dmapper has no API for that at the moment.
3221 210 : break;
3222 : case RTF_LOCH:
3223 3504 : m_aStates.top().eRunType = RTFParserState::LOCH;
3224 3504 : break;
3225 : case RTF_HICH:
3226 1953 : m_aStates.top().eRunType = RTFParserState::HICH;
3227 1953 : break;
3228 : case RTF_DBCH:
3229 3917 : m_aStates.top().eRunType = RTFParserState::DBCH;
3230 3917 : break;
3231 : case RTF_TITLEPG:
3232 : {
3233 17 : auto pValue = std::make_shared<RTFValue>(1);
3234 17 : m_aStates.top().aSectionSprms.set(NS_ooxml::LN_EG_SectPrContents_titlePg, pValue);
3235 : }
3236 17 : break;
3237 : case RTF_SUPER:
3238 : {
3239 29 : if (!m_aStates.top().pCurrentBuffer)
3240 29 : m_aStates.top().pCurrentBuffer = &m_aSuperBuffer;
3241 :
3242 29 : auto pValue = std::make_shared<RTFValue>("superscript");
3243 29 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue);
3244 : }
3245 29 : break;
3246 : case RTF_SUB:
3247 : {
3248 1 : auto pValue = std::make_shared<RTFValue>("subscript");
3249 1 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue);
3250 : }
3251 1 : break;
3252 : case RTF_NOSUPERSUB:
3253 : {
3254 6 : if (m_aStates.top().pCurrentBuffer == &m_aSuperBuffer)
3255 : {
3256 1 : replayBuffer(m_aSuperBuffer, nullptr, nullptr);
3257 1 : m_aStates.top().pCurrentBuffer = nullptr;
3258 : }
3259 6 : m_aStates.top().aCharacterSprms.erase(NS_ooxml::LN_EG_RPrBase_vertAlign);
3260 : }
3261 6 : break;
3262 : case RTF_LINEPPAGE:
3263 : case RTF_LINECONT:
3264 : {
3265 3 : auto pValue = std::make_shared<RTFValue>(nKeyword == RTF_LINEPPAGE ? NS_ooxml::LN_Value_ST_LineNumberRestart_newPage : NS_ooxml::LN_Value_ST_LineNumberRestart_continuous);
3266 3 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_lnNumType, NS_ooxml::LN_CT_LineNumber_restart, pValue);
3267 : }
3268 3 : break;
3269 : case RTF_AENDDOC:
3270 : // Noop, this is the default in Writer.
3271 144 : break;
3272 : case RTF_AENDNOTES:
3273 : // Noop, Writer does not support having endnotes at the end of section.
3274 0 : break;
3275 : case RTF_AFTNRSTCONT:
3276 : // Noop, this is the default in Writer.
3277 105 : break;
3278 : case RTF_AFTNRESTART:
3279 : // Noop, Writer does not support restarting endnotes at each section.
3280 0 : break;
3281 : case RTF_FTNBJ:
3282 : // Noop, this is the default in Writer.
3283 155 : break;
3284 : case RTF_ENDDOC:
3285 : {
3286 0 : auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_RestartNumber_eachSect);
3287 0 : lcl_putNestedSprm(m_aDefaultState.aParagraphSprms, NS_ooxml::LN_EG_SectPrContents_footnotePr, NS_ooxml::LN_EG_FtnEdnNumProps_numRestart, pValue);
3288 : }
3289 0 : break;
3290 : case RTF_NOLINE:
3291 279 : lcl_eraseNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_lnNumType, NS_ooxml::LN_CT_LineNumber_distance);
3292 279 : break;
3293 : case RTF_FORMSHADE:
3294 : // Noop, this is the default in Writer.
3295 136 : break;
3296 : case RTF_PNGBLIP:
3297 26 : m_aStates.top().aPicture.eStyle = RTFBmpStyle::PNG;
3298 26 : break;
3299 : case RTF_JPEGBLIP:
3300 8 : m_aStates.top().aPicture.eStyle = RTFBmpStyle::JPEG;
3301 8 : break;
3302 : case RTF_POSYT:
3303 0 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_doc_ST_YAlign_top);
3304 0 : break;
3305 : case RTF_POSYB:
3306 0 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_doc_ST_YAlign_bottom);
3307 0 : break;
3308 : case RTF_POSYC:
3309 0 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_doc_ST_YAlign_center);
3310 0 : break;
3311 : case RTF_POSYIN:
3312 0 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_doc_ST_YAlign_inside);
3313 0 : break;
3314 : case RTF_POSYOUT:
3315 0 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_doc_ST_YAlign_outside);
3316 0 : break;
3317 : case RTF_POSYIL:
3318 0 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_doc_ST_YAlign_inline);
3319 0 : break;
3320 :
3321 : case RTF_PHMRG:
3322 5 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hAnchor, NS_ooxml::LN_Value_doc_ST_HAnchor_margin);
3323 5 : break;
3324 : case RTF_PVMRG:
3325 4 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vAnchor, NS_ooxml::LN_Value_doc_ST_VAnchor_margin);
3326 4 : break;
3327 : case RTF_PHPG:
3328 12 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hAnchor, NS_ooxml::LN_Value_doc_ST_HAnchor_page);
3329 12 : break;
3330 : case RTF_PVPG:
3331 14 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vAnchor, NS_ooxml::LN_Value_doc_ST_VAnchor_page);
3332 14 : break;
3333 : case RTF_PHCOL:
3334 0 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hAnchor, NS_ooxml::LN_Value_doc_ST_HAnchor_text);
3335 0 : break;
3336 : case RTF_PVPARA:
3337 0 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vAnchor, NS_ooxml::LN_Value_doc_ST_VAnchor_text);
3338 0 : break;
3339 :
3340 : case RTF_POSXC:
3341 0 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_doc_ST_XAlign_center);
3342 0 : break;
3343 : case RTF_POSXI:
3344 0 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_doc_ST_XAlign_inside);
3345 0 : break;
3346 : case RTF_POSXO:
3347 0 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_doc_ST_XAlign_outside);
3348 0 : break;
3349 : case RTF_POSXL:
3350 0 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_doc_ST_XAlign_left);
3351 0 : break;
3352 : case RTF_POSXR:
3353 0 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_doc_ST_XAlign_right);
3354 0 : break;
3355 :
3356 : case RTF_DPLINE:
3357 : case RTF_DPRECT:
3358 : case RTF_DPELLIPSE:
3359 : case RTF_DPTXBX:
3360 : case RTF_DPPOLYLINE:
3361 : {
3362 26 : sal_Int32 nType = 0;
3363 26 : switch (nKeyword)
3364 : {
3365 : case RTF_DPLINE:
3366 4 : m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.drawing.LineShape"), uno::UNO_QUERY);
3367 4 : break;
3368 : case RTF_DPPOLYLINE:
3369 : // The reason this is not a simple CustomShape is that in the old syntax we have no ViewBox info.
3370 4 : m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.drawing.PolyLineShape"), uno::UNO_QUERY);
3371 4 : break;
3372 : case RTF_DPRECT:
3373 5 : m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY);
3374 5 : break;
3375 : case RTF_DPELLIPSE:
3376 0 : nType = ESCHER_ShpInst_Ellipse;
3377 0 : break;
3378 : case RTF_DPTXBX:
3379 : {
3380 13 : m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.text.TextFrame"), uno::UNO_QUERY);
3381 13 : std::vector<beans::PropertyValue> aDefaults = RTFSdrImport::getTextFrameDefaults(false);
3382 143 : for (size_t i = 0; i < aDefaults.size(); ++i)
3383 : {
3384 130 : if (!lcl_findPropertyName(m_aStates.top().aDrawingObject.aPendingProperties, aDefaults[i].Name))
3385 104 : m_aStates.top().aDrawingObject.aPendingProperties.push_back(aDefaults[i]);
3386 : }
3387 13 : checkFirstRun();
3388 13 : Mapper().startShape(m_aStates.top().aDrawingObject.xShape);
3389 13 : m_aStates.top().aDrawingObject.bHadShapeText = true;
3390 : }
3391 13 : break;
3392 : default:
3393 0 : break;
3394 : }
3395 26 : if (nType)
3396 0 : m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.drawing.CustomShape"), uno::UNO_QUERY);
3397 26 : uno::Reference<drawing::XDrawPageSupplier> xDrawSupplier(m_xDstDoc, uno::UNO_QUERY);
3398 26 : if (xDrawSupplier.is())
3399 : {
3400 26 : uno::Reference<drawing::XShapes> xShapes(xDrawSupplier->getDrawPage(), uno::UNO_QUERY);
3401 26 : if (xShapes.is() && nKeyword != RTF_DPTXBX)
3402 13 : xShapes->add(m_aStates.top().aDrawingObject.xShape);
3403 : }
3404 26 : if (nType)
3405 : {
3406 0 : uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(m_aStates.top().aDrawingObject.xShape, uno::UNO_QUERY);
3407 0 : xDefaulter->createCustomShapeDefaults(OUString::number(nType));
3408 : }
3409 26 : m_aStates.top().aDrawingObject.xPropertySet.set(m_aStates.top().aDrawingObject.xShape, uno::UNO_QUERY);
3410 26 : std::vector<beans::PropertyValue>& rPendingProperties = m_aStates.top().aDrawingObject.aPendingProperties;
3411 179 : for (std::vector<beans::PropertyValue>::iterator i = rPendingProperties.begin(); i != rPendingProperties.end(); ++i)
3412 153 : m_aStates.top().aDrawingObject.xPropertySet->setPropertyValue(i->Name, i->Value);
3413 26 : m_pSdrImport->resolveDhgt(m_aStates.top().aDrawingObject.xPropertySet, m_aStates.top().aDrawingObject.nDhgt, /*bOldStyle=*/true);
3414 : }
3415 26 : break;
3416 : case RTF_DOBXMARGIN:
3417 : case RTF_DOBYMARGIN:
3418 : {
3419 1 : beans::PropertyValue aPropertyValue;
3420 1 : aPropertyValue.Name = (nKeyword == RTF_DOBXMARGIN ? OUString("HoriOrientRelation") : OUString("VertOrientRelation"));
3421 1 : aPropertyValue.Value <<= text::RelOrientation::PAGE_PRINT_AREA;
3422 1 : m_aStates.top().aDrawingObject.aPendingProperties.push_back(aPropertyValue);
3423 : }
3424 1 : break;
3425 : case RTF_DOBXPAGE:
3426 : case RTF_DOBYPAGE:
3427 : {
3428 33 : beans::PropertyValue aPropertyValue;
3429 33 : aPropertyValue.Name = (nKeyword == RTF_DOBXPAGE ? OUString("HoriOrientRelation") : OUString("VertOrientRelation"));
3430 33 : aPropertyValue.Value <<= text::RelOrientation::PAGE_FRAME;
3431 33 : m_aStates.top().aDrawingObject.aPendingProperties.push_back(aPropertyValue);
3432 : }
3433 33 : break;
3434 : case RTF_DOBYPARA:
3435 : {
3436 15 : beans::PropertyValue aPropertyValue;
3437 15 : aPropertyValue.Name = "VertOrientRelation";
3438 15 : aPropertyValue.Value <<= text::RelOrientation::FRAME;
3439 15 : m_aStates.top().aDrawingObject.aPendingProperties.push_back(aPropertyValue);
3440 : }
3441 15 : break;
3442 : case RTF_CONTEXTUALSPACE:
3443 : {
3444 2 : auto pValue = std::make_shared<RTFValue>(1);
3445 2 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_contextualSpacing, pValue);
3446 : }
3447 2 : break;
3448 : case RTF_LINKSTYLES:
3449 : {
3450 1 : auto pValue = std::make_shared<RTFValue>(1);
3451 1 : m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_linkStyles, pValue);
3452 : }
3453 1 : break;
3454 : case RTF_PNLVLBODY:
3455 : {
3456 4 : auto pValue = std::make_shared<RTFValue>(2);
3457 4 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_AbstractNum_nsid, pValue);
3458 : }
3459 4 : break;
3460 : case RTF_PNDEC:
3461 : {
3462 4 : auto pValue = std::make_shared<RTFValue>(0); // decimal, same as \levelnfc0
3463 4 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_numFmt, pValue);
3464 : }
3465 4 : break;
3466 : case RTF_PNLVLBLT:
3467 : {
3468 1 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_AbstractNum_nsid, std::make_shared<RTFValue>(1));
3469 1 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_numFmt, std::make_shared<RTFValue>(23)); // bullets, same as \levelnfc23
3470 : }
3471 1 : break;
3472 : case RTF_LANDSCAPE:
3473 : {
3474 3 : auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_PageOrientation_landscape);
3475 3 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_orient, pValue);
3476 : }
3477 3 : break;
3478 : case RTF_SHPBXPAGE:
3479 23 : m_aStates.top().aShape.nHoriOrientRelation = text::RelOrientation::PAGE_FRAME;
3480 23 : m_aStates.top().aShape.nHoriOrientRelationToken = NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_page;
3481 23 : break;
3482 : case RTF_SHPBYPAGE:
3483 22 : m_aStates.top().aShape.nVertOrientRelation = text::RelOrientation::PAGE_FRAME;
3484 22 : m_aStates.top().aShape.nVertOrientRelationToken = NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_page;
3485 22 : break;
3486 : case RTF_DPLINEHOLLOW:
3487 14 : m_aStates.top().aDrawingObject.nFLine = 0;
3488 14 : break;
3489 : case RTF_DPROUNDR:
3490 2 : if (m_aStates.top().aDrawingObject.xPropertySet.is())
3491 : // Seems this old syntax has no way to specify a custom radius, and this is the default
3492 2 : m_aStates.top().aDrawingObject.xPropertySet->setPropertyValue("CornerRadius", uno::makeAny(sal_Int32(83)));
3493 2 : break;
3494 : case RTF_NOWRAP:
3495 2 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_wrap, NS_ooxml::LN_Value_doc_ST_Wrap_notBeside);
3496 2 : break;
3497 : case RTF_MNOR:
3498 9 : m_bMathNor = true;
3499 9 : break;
3500 : case RTF_REVISIONS:
3501 3 : m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_trackRevisions, std::make_shared<RTFValue>(1));
3502 3 : break;
3503 : case RTF_BRDRSH:
3504 14 : lcl_putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_shadow, std::make_shared<RTFValue>(1));
3505 14 : break;
3506 : case RTF_NOCOLBAL:
3507 1 : m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Compat_noColumnBalance, std::make_shared<RTFValue>(1));
3508 1 : break;
3509 : case RTF_MARGMIRROR:
3510 4 : m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_mirrorMargins, std::make_shared<RTFValue>(1));
3511 4 : break;
3512 : case RTF_SAUTOUPD:
3513 10 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Style_autoRedefine, std::make_shared<RTFValue>(1));
3514 10 : break;
3515 : default:
3516 : {
3517 : SAL_INFO("writerfilter", "TODO handle flag '" << lcl_RtfToString(nKeyword) << "'");
3518 5742 : aSkip.setParsed(false);
3519 : }
3520 5742 : break;
3521 : }
3522 36060 : return RTFError::OK;
3523 : }
3524 :
3525 80963 : RTFError RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
3526 : {
3527 80963 : setNeedSect();
3528 80963 : checkUnicode(/*bUnicode =*/ nKeyword != RTF_U, /*bHex =*/ true);
3529 80963 : RTFSkipDestination aSkip(*this);
3530 80963 : int nSprm = 0;
3531 161926 : auto pIntValue = std::make_shared<RTFValue>(nParam);
3532 : // Trivial table sprms.
3533 80963 : switch (nKeyword)
3534 : {
3535 : case RTF_LEVELJC:
3536 : {
3537 630 : nSprm = NS_ooxml::LN_CT_Lvl_lvlJc;
3538 630 : int nValue = 0;
3539 630 : switch (nParam)
3540 : {
3541 : case 0:
3542 519 : nValue = NS_ooxml::LN_Value_ST_Jc_left;
3543 519 : break;
3544 : case 1:
3545 0 : nValue = NS_ooxml::LN_Value_ST_Jc_center;
3546 0 : break;
3547 : case 2:
3548 111 : nValue = NS_ooxml::LN_Value_ST_Jc_right;
3549 111 : break;
3550 : }
3551 630 : pIntValue = std::make_shared<RTFValue>(nValue);
3552 630 : break;
3553 : }
3554 : case RTF_LEVELNFC:
3555 636 : nSprm = NS_ooxml::LN_CT_Lvl_numFmt;
3556 636 : pIntValue = std::make_shared<RTFValue>(lcl_getNumberFormat(nParam));
3557 636 : break;
3558 : case RTF_LEVELSTARTAT:
3559 641 : nSprm = NS_ooxml::LN_CT_Lvl_start;
3560 641 : break;
3561 : case RTF_LEVELPICTURE:
3562 13 : nSprm = NS_ooxml::LN_CT_Lvl_lvlPicBulletId;
3563 13 : break;
3564 : case RTF_SBASEDON:
3565 907 : nSprm = NS_ooxml::LN_CT_Style_basedOn;
3566 907 : pIntValue = std::make_shared<RTFValue>(getStyleName(nParam));
3567 907 : break;
3568 : default:
3569 78136 : break;
3570 : }
3571 80963 : if (nSprm > 0)
3572 : {
3573 2827 : m_aStates.top().aTableSprms.set(nSprm, pIntValue);
3574 2827 : return RTFError::OK;
3575 : }
3576 : // Trivial character sprms.
3577 78136 : switch (nKeyword)
3578 : {
3579 : case RTF_FS:
3580 : case RTF_AFS:
3581 3553 : nSprm = (m_aStates.top().isRightToLeft || m_aStates.top().eRunType == RTFParserState::HICH) ? NS_ooxml::LN_EG_RPrBase_szCs : NS_ooxml::LN_EG_RPrBase_sz;
3582 3553 : break;
3583 : case RTF_ANIMTEXT:
3584 0 : nSprm = NS_ooxml::LN_EG_RPrBase_effect;
3585 0 : break;
3586 : case RTF_EXPNDTW:
3587 14 : nSprm = NS_ooxml::LN_EG_RPrBase_spacing;
3588 14 : break;
3589 : case RTF_KERNING:
3590 947 : nSprm = NS_ooxml::LN_EG_RPrBase_kern;
3591 947 : break;
3592 : case RTF_CHARSCALEX:
3593 0 : nSprm = NS_ooxml::LN_EG_RPrBase_w;
3594 0 : break;
3595 : default:
3596 73622 : break;
3597 : }
3598 78136 : if (nSprm > 0)
3599 : {
3600 4514 : m_aStates.top().aCharacterSprms.set(nSprm, pIntValue);
3601 4514 : return RTFError::OK;
3602 : }
3603 : // Trivial character attributes.
3604 73622 : switch (nKeyword)
3605 : {
3606 : case RTF_LANG:
3607 : case RTF_ALANG:
3608 2565 : if (m_aStates.top().isRightToLeft || m_aStates.top().eRunType == RTFParserState::HICH)
3609 : {
3610 353 : nSprm = NS_ooxml::LN_CT_Language_bidi;
3611 : }
3612 2212 : else if (m_aStates.top().eRunType == RTFParserState::DBCH)
3613 : {
3614 825 : nSprm = NS_ooxml::LN_CT_Language_eastAsia;
3615 : }
3616 : else
3617 : {
3618 : assert(m_aStates.top().eRunType == RTFParserState::LOCH);
3619 1387 : nSprm = NS_ooxml::LN_CT_Language_val;
3620 : }
3621 2565 : break;
3622 : case RTF_LANGFE: // this one is always CJK apparently
3623 1323 : nSprm = NS_ooxml::LN_CT_Language_eastAsia;
3624 1323 : break;
3625 : default:
3626 69734 : break;
3627 : }
3628 73622 : if (nSprm > 0)
3629 : {
3630 3888 : LanguageTag aTag((LanguageType)nParam);
3631 7776 : auto pValue = std::make_shared<RTFValue>(aTag.getBcp47());
3632 3888 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_EG_RPrBase_lang, nSprm, pValue);
3633 : // Language is a character property, but we should store it at a paragraph level as well for fields.
3634 3888 : if (nKeyword == RTF_LANG && m_bNeedPap)
3635 1352 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_EG_RPrBase_lang, nSprm, pValue);
3636 7776 : return RTFError::OK;
3637 : }
3638 : // Trivial paragraph sprms.
3639 69734 : switch (nKeyword)
3640 : {
3641 : case RTF_ITAP:
3642 406 : nSprm = NS_ooxml::LN_tblDepth;
3643 406 : break;
3644 : default:
3645 69328 : break;
3646 : }
3647 69734 : if (nSprm > 0)
3648 : {
3649 406 : m_aStates.top().aParagraphSprms.set(nSprm, pIntValue);
3650 406 : if (nKeyword == RTF_ITAP && nParam > 0)
3651 : {
3652 34 : while (m_aTableBufferStack.size() < sal::static_int_cast<size_t>(nParam))
3653 : {
3654 6 : m_aTableBufferStack.push_back(RTFBuffer_t());
3655 : }
3656 : // Invalid tables may omit INTBL after ITAP
3657 14 : dispatchFlag(RTF_INTBL); // sets newly pushed buffer as current
3658 : assert(m_aStates.top().pCurrentBuffer == &m_aTableBufferStack.back());
3659 : }
3660 406 : return RTFError::OK;
3661 : }
3662 :
3663 : // Info group.
3664 69328 : switch (nKeyword)
3665 : {
3666 : case RTF_YR:
3667 : {
3668 460 : m_aStates.top().nYear = nParam;
3669 460 : nSprm = 1;
3670 : }
3671 460 : break;
3672 : case RTF_MO:
3673 : {
3674 456 : m_aStates.top().nMonth = nParam;
3675 456 : nSprm = 1;
3676 : }
3677 456 : break;
3678 : case RTF_DY:
3679 : {
3680 462 : m_aStates.top().nDay = nParam;
3681 462 : nSprm = 1;
3682 : }
3683 462 : break;
3684 : case RTF_HR:
3685 : {
3686 460 : m_aStates.top().nHour = nParam;
3687 460 : nSprm = 1;
3688 : }
3689 460 : break;
3690 : case RTF_MIN:
3691 : {
3692 462 : m_aStates.top().nMinute = nParam;
3693 462 : nSprm = 1;
3694 : }
3695 462 : break;
3696 : default:
3697 67028 : break;
3698 : }
3699 69328 : if (nSprm > 0)
3700 2300 : return RTFError::OK;
3701 :
3702 : // Frame size / position.
3703 67028 : Id nId = 0;
3704 67028 : switch (nKeyword)
3705 : {
3706 : case RTF_ABSW:
3707 19 : nId = NS_ooxml::LN_CT_FramePr_w;
3708 19 : break;
3709 : case RTF_ABSH:
3710 19 : nId = NS_ooxml::LN_CT_FramePr_h;
3711 19 : break;
3712 : case RTF_POSX:
3713 : {
3714 19 : nId = NS_ooxml::LN_CT_FramePr_x;
3715 19 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, 0);
3716 : }
3717 19 : break;
3718 : case RTF_POSY:
3719 : {
3720 19 : nId = NS_ooxml::LN_CT_FramePr_y;
3721 19 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, 0);
3722 : }
3723 19 : break;
3724 : default:
3725 66952 : break;
3726 : }
3727 :
3728 67028 : if (nId > 0)
3729 : {
3730 76 : m_bNeedPap = true;
3731 : // Don't try to support text frames inside tables for now.
3732 76 : if (m_aStates.top().pCurrentBuffer != &m_aTableBufferStack.back())
3733 76 : m_aStates.top().aFrame.setSprm(nId, nParam);
3734 :
3735 76 : return RTFError::OK;
3736 : }
3737 :
3738 : // Then check for the more complex ones.
3739 66952 : switch (nKeyword)
3740 : {
3741 : case RTF_F:
3742 : case RTF_AF:
3743 15645 : if (m_aStates.top().isRightToLeft || m_aStates.top().eRunType == RTFParserState::HICH)
3744 : {
3745 4596 : nSprm = NS_ooxml::LN_CT_Fonts_cs;
3746 : }
3747 11049 : else if (m_aStates.top().eRunType == RTFParserState::DBCH)
3748 : {
3749 3907 : nSprm = NS_ooxml::LN_CT_Fonts_eastAsia;
3750 : }
3751 : else
3752 : {
3753 : assert(m_aStates.top().eRunType == RTFParserState::LOCH);
3754 7142 : nSprm = NS_ooxml::LN_CT_Fonts_ascii;
3755 : }
3756 15645 : if (m_aStates.top().eDestination == Destination::FONTTABLE || m_aStates.top().eDestination == Destination::FONTENTRY)
3757 : {
3758 3378 : m_aFontIndexes.push_back(nParam);
3759 3378 : m_nCurrentFontIndex = getFontIndex(nParam);
3760 : }
3761 12267 : else if (m_aStates.top().eDestination == Destination::LISTLEVEL)
3762 : {
3763 447 : RTFSprms aFontAttributes;
3764 447 : aFontAttributes.set(nSprm, std::make_shared<RTFValue>(m_aFontNames[getFontIndex(nParam)]));
3765 894 : RTFSprms aRunPropsSprms;
3766 447 : aRunPropsSprms.set(NS_ooxml::LN_EG_RPrBase_rFonts, std::make_shared<RTFValue>(aFontAttributes));
3767 894 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_rPr, std::make_shared<RTFValue>(RTFSprms(), aRunPropsSprms), RTFOverwrite::NO_APPEND);
3768 : }
3769 : else
3770 : {
3771 11820 : m_nCurrentFontIndex = getFontIndex(nParam);
3772 11820 : auto pValue = std::make_shared<RTFValue>(getFontName(m_nCurrentFontIndex));
3773 11820 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_EG_RPrBase_rFonts, nSprm, pValue);
3774 11820 : if (nKeyword == RTF_F)
3775 3310 : m_aStates.top().nCurrentEncoding = getEncoding(m_nCurrentFontIndex);
3776 : }
3777 15645 : break;
3778 : case RTF_RED:
3779 2200 : m_aStates.top().aCurrentColor.nRed = nParam;
3780 2200 : break;
3781 : case RTF_GREEN:
3782 2200 : m_aStates.top().aCurrentColor.nGreen = nParam;
3783 2200 : break;
3784 : case RTF_BLUE:
3785 2200 : m_aStates.top().aCurrentColor.nBlue = nParam;
3786 2200 : break;
3787 : case RTF_FCHARSET:
3788 : {
3789 : // we always send text to the domain mapper in OUString, so no
3790 : // need to send encoding info
3791 : int i;
3792 51474 : for (i = 0; i < nRTFEncodings; i++)
3793 : {
3794 51474 : if (aRTFEncodings[i].charset == nParam)
3795 3361 : break;
3796 : }
3797 3361 : if (i == nRTFEncodings)
3798 : // not found
3799 0 : return RTFError::OK;
3800 :
3801 3361 : m_nCurrentEncoding = rtl_getTextEncodingFromWindowsCodePage(aRTFEncodings[i].codepage);
3802 3361 : m_aStates.top().nCurrentEncoding = m_nCurrentEncoding;
3803 : }
3804 3361 : break;
3805 : case RTF_ANSICPG:
3806 : {
3807 81 : m_aDefaultState.nCurrentEncoding = rtl_getTextEncodingFromWindowsCodePage(nParam);
3808 81 : m_aStates.top().nCurrentEncoding = rtl_getTextEncodingFromWindowsCodePage(nParam);
3809 : }
3810 81 : break;
3811 : case RTF_CPG:
3812 4 : m_nCurrentEncoding = rtl_getTextEncodingFromWindowsCodePage(nParam);
3813 4 : m_aStates.top().nCurrentEncoding = m_nCurrentEncoding;
3814 4 : break;
3815 : case RTF_CF:
3816 : {
3817 654 : RTFSprms aAttributes;
3818 1308 : auto pValue = std::make_shared<RTFValue>(getColorTable(nParam));
3819 654 : aAttributes.set(NS_ooxml::LN_CT_Color_val, pValue);
3820 1308 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_color, std::make_shared<RTFValue>(aAttributes));
3821 : }
3822 654 : break;
3823 : case RTF_S:
3824 : {
3825 1753 : m_aStates.top().nCurrentStyleIndex = nParam;
3826 :
3827 1753 : if (m_aStates.top().eDestination == Destination::STYLESHEET || m_aStates.top().eDestination == Destination::STYLEENTRY)
3828 : {
3829 990 : m_nCurrentStyleIndex = nParam;
3830 990 : auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_StyleType_paragraph);
3831 990 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Style_type, pValue); // paragraph style
3832 : }
3833 : else
3834 : {
3835 763 : OUString aName = getStyleName(nParam);
3836 763 : if (!aName.isEmpty())
3837 : {
3838 707 : if (m_aStates.top().eDestination == Destination::LISTLEVEL)
3839 11 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_pStyle, std::make_shared<RTFValue>(aName));
3840 : else
3841 696 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_pStyle, std::make_shared<RTFValue>(aName));
3842 :
3843 763 : }
3844 : }
3845 : }
3846 1753 : break;
3847 : case RTF_CS:
3848 256 : m_aStates.top().nCurrentCharacterStyleIndex = nParam;
3849 256 : if (m_aStates.top().eDestination == Destination::STYLESHEET || m_aStates.top().eDestination == Destination::STYLEENTRY)
3850 : {
3851 244 : m_nCurrentStyleIndex = nParam;
3852 244 : auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_StyleType_character);
3853 244 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Style_type, pValue); // character style
3854 : }
3855 : else
3856 : {
3857 12 : OUString aName = getStyleName(nParam);
3858 12 : if (!aName.isEmpty())
3859 9 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_rStyle, std::make_shared<RTFValue>(aName));
3860 : }
3861 256 : break;
3862 : case RTF_DS:
3863 0 : if (m_aStates.top().eDestination == Destination::STYLESHEET || m_aStates.top().eDestination == Destination::STYLEENTRY)
3864 : {
3865 0 : m_nCurrentStyleIndex = nParam;
3866 0 : auto pValue = std::make_shared<RTFValue>(0); // TODO no value in enum StyleType?
3867 0 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Style_type, pValue); // section style
3868 : }
3869 0 : break;
3870 : case RTF_TS:
3871 88 : if (m_aStates.top().eDestination == Destination::STYLESHEET || m_aStates.top().eDestination == Destination::STYLEENTRY)
3872 : {
3873 35 : m_nCurrentStyleIndex = nParam;
3874 : // 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
3875 35 : auto pValue = std::make_shared<RTFValue>(0);
3876 35 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Style_type, pValue); // table style
3877 : }
3878 88 : break;
3879 : case RTF_DEFF:
3880 203 : m_nDefaultFontIndex = nParam;
3881 203 : break;
3882 : case RTF_DEFLANG:
3883 : case RTF_ADEFLANG:
3884 : {
3885 223 : LanguageTag aTag((LanguageType)nParam);
3886 446 : auto pValue = std::make_shared<RTFValue>(aTag.getBcp47());
3887 446 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms, (nKeyword == RTF_DEFLANG ? NS_ooxml::LN_EG_RPrBase_lang : NS_ooxml::LN_CT_Language_bidi), nSprm, pValue);
3888 : }
3889 223 : break;
3890 : case RTF_CHCBPAT:
3891 : {
3892 40 : auto pValue = std::make_shared<RTFValue>(nParam ? getColorTable(nParam) : COL_AUTO);
3893 40 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_EG_RPrBase_shd, NS_ooxml::LN_CT_Shd_fill, pValue);
3894 : }
3895 40 : break;
3896 : case RTF_CLCBPAT:
3897 : {
3898 6 : auto pValue = std::make_shared<RTFValue>(getColorTable(nParam));
3899 6 : lcl_putNestedAttribute(m_aStates.top().aTableCellSprms, NS_ooxml::LN_CT_TcPrBase_shd, NS_ooxml::LN_CT_Shd_fill, pValue);
3900 : }
3901 6 : break;
3902 : case RTF_CBPAT:
3903 5 : if (nParam)
3904 : {
3905 4 : auto pValue = std::make_shared<RTFValue>(getColorTable(nParam));
3906 4 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PrBase_shd, NS_ooxml::LN_CT_Shd_fill, pValue);
3907 : }
3908 5 : break;
3909 : case RTF_ULC:
3910 : {
3911 20 : auto pValue = std::make_shared<RTFValue>(getColorTable(nParam));
3912 20 : m_aStates.top().aCharacterSprms.set(0x6877, pValue);
3913 : }
3914 20 : break;
3915 : case RTF_HIGHLIGHT:
3916 : {
3917 59 : auto pValue = std::make_shared<RTFValue>(nParam ? getColorTable(nParam) : COL_AUTO);
3918 59 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_highlight, pValue);
3919 : }
3920 59 : break;
3921 : case RTF_UP:
3922 : case RTF_DN:
3923 : {
3924 3 : auto pValue = std::make_shared<RTFValue>(nParam * (nKeyword == RTF_UP ? 1 : -1));
3925 3 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_position, pValue);
3926 : }
3927 3 : break;
3928 : case RTF_HORZVERT:
3929 : {
3930 1 : auto pValue = std::make_shared<RTFValue>(int(true));
3931 1 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_EastAsianLayout_vert, pValue);
3932 1 : if (nParam)
3933 : // rotate fits to a single line
3934 0 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_EastAsianLayout_vertCompress, pValue);
3935 : }
3936 1 : break;
3937 : case RTF_EXPND:
3938 : {
3939 14 : auto pValue = std::make_shared<RTFValue>(nParam/5);
3940 14 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_spacing, pValue);
3941 : }
3942 14 : break;
3943 : case RTF_TWOINONE:
3944 : {
3945 0 : auto pValue = std::make_shared<RTFValue>(int(true));
3946 0 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_EastAsianLayout_combine, pValue);
3947 0 : nId = 0;
3948 0 : switch (nParam)
3949 : {
3950 : case 0:
3951 0 : nId = NS_ooxml::LN_Value_ST_CombineBrackets_none;
3952 0 : break;
3953 : case 1:
3954 0 : nId = NS_ooxml::LN_Value_ST_CombineBrackets_round;
3955 0 : break;
3956 : case 2:
3957 0 : nId = NS_ooxml::LN_Value_ST_CombineBrackets_square;
3958 0 : break;
3959 : case 3:
3960 0 : nId = NS_ooxml::LN_Value_ST_CombineBrackets_angle;
3961 0 : break;
3962 : case 4:
3963 0 : nId = NS_ooxml::LN_Value_ST_CombineBrackets_curly;
3964 0 : break;
3965 : }
3966 0 : if (nId > 0)
3967 0 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_EastAsianLayout_combineBrackets, std::make_shared<RTFValue>(nId));
3968 : }
3969 0 : break;
3970 : case RTF_SL:
3971 : {
3972 : // This is similar to RTF_ABSH, negative value means 'exact', positive means 'at least'.
3973 335 : auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_doc_ST_LineSpacingRule_atLeast);
3974 335 : if (nParam < 0)
3975 : {
3976 9 : pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_doc_ST_LineSpacingRule_exact);
3977 9 : pIntValue = std::make_shared<RTFValue>(-nParam);
3978 : }
3979 335 : m_aStates.top().aParagraphAttributes.set(NS_ooxml::LN_CT_Spacing_lineRule, pValue);
3980 335 : m_aStates.top().aParagraphAttributes.set(NS_ooxml::LN_CT_Spacing_line, pIntValue);
3981 : }
3982 335 : break;
3983 : case RTF_SLMULT:
3984 325 : if (nParam > 0)
3985 : {
3986 285 : auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_doc_ST_LineSpacingRule_auto);
3987 285 : m_aStates.top().aParagraphAttributes.set(NS_ooxml::LN_CT_Spacing_lineRule, pValue);
3988 : }
3989 325 : break;
3990 : case RTF_BRDRW:
3991 : {
3992 : // dmapper expects it in 1/8 pt, we have it in twip - but avoid rounding 1 to 0
3993 633 : if (nParam > 1)
3994 593 : nParam = nParam * 2 / 5;
3995 633 : auto pValue = std::make_shared<RTFValue>(nParam);
3996 633 : lcl_putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_sz, pValue);
3997 : }
3998 633 : break;
3999 : case RTF_BRDRCF:
4000 : {
4001 338 : auto pValue = std::make_shared<RTFValue>(getColorTable(nParam));
4002 338 : lcl_putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_color, pValue);
4003 : }
4004 338 : break;
4005 : case RTF_BRSP:
4006 : {
4007 : // dmapper expects it in points, we have it in twip
4008 20 : auto pValue = std::make_shared<RTFValue>(nParam / 20);
4009 20 : lcl_putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_space, pValue);
4010 : }
4011 20 : break;
4012 : case RTF_TX:
4013 : {
4014 361 : m_aStates.top().aTabAttributes.set(NS_ooxml::LN_CT_TabStop_pos, pIntValue);
4015 361 : auto pValue = std::make_shared<RTFValue>(m_aStates.top().aTabAttributes);
4016 361 : lcl_putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_tabs, NS_ooxml::LN_CT_Tabs_tab, pValue);
4017 361 : m_aStates.top().aTabAttributes.clear();
4018 : }
4019 361 : break;
4020 : case RTF_ILVL:
4021 255 : lcl_putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_numPr, NS_ooxml::LN_CT_NumPr_ilvl, pIntValue);
4022 255 : break;
4023 : case RTF_LISTTEMPLATEID:
4024 : // This one is not referenced anywhere, so it's pointless to store it at the moment.
4025 88 : break;
4026 : case RTF_LISTID:
4027 : {
4028 213 : if (m_aStates.top().eDestination == Destination::LISTENTRY)
4029 87 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_AbstractNum_abstractNumId, pIntValue);
4030 126 : else if (m_aStates.top().eDestination == Destination::LISTOVERRIDEENTRY)
4031 125 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Num_abstractNumId, pIntValue);
4032 : }
4033 213 : break;
4034 : case RTF_LS:
4035 : {
4036 471 : if (m_aStates.top().eDestination == Destination::LISTOVERRIDEENTRY)
4037 125 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_AbstractNum_nsid, pIntValue);
4038 : else
4039 346 : lcl_putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_tabs, NS_ooxml::LN_CT_NumPr_numId, pIntValue);
4040 : }
4041 471 : break;
4042 : case RTF_UC:
4043 234 : if ((SAL_MIN_INT16 <= nParam) && (nParam <= SAL_MAX_INT16))
4044 234 : m_aStates.top().nUc = nParam;
4045 234 : break;
4046 : case RTF_U:
4047 : // sal_Unicode is unsigned 16-bit, RTF may represent that as a
4048 : // signed SAL_MIN_INT16..SAL_MAX_INT16 or 0..SAL_MAX_UINT16. The
4049 : // static_cast() will do the right thing.
4050 857 : if ((SAL_MIN_INT16 <= nParam) && (nParam <= SAL_MAX_UINT16))
4051 : {
4052 579 : if (m_aStates.top().eDestination == Destination::LEVELNUMBERS)
4053 : {
4054 3 : if (nParam != ';')
4055 0 : m_aStates.top().aLevelNumbers.push_back(sal_Int32(nParam));
4056 : }
4057 : else
4058 576 : m_aUnicodeBuffer.append(static_cast<sal_Unicode>(nParam));
4059 579 : m_aStates.top().nCharsToSkip = m_aStates.top().nUc;
4060 : }
4061 857 : break;
4062 : case RTF_LEVELFOLLOW:
4063 : {
4064 637 : OUString sValue;
4065 637 : switch (nParam)
4066 : {
4067 : case 0:
4068 465 : sValue = "tab";
4069 465 : break;
4070 : case 1:
4071 2 : sValue = "space";
4072 2 : break;
4073 : case 2:
4074 160 : sValue = "nothing";
4075 160 : break;
4076 : }
4077 637 : if (!sValue.isEmpty())
4078 627 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_suff, std::make_shared<RTFValue>(sValue));
4079 : }
4080 637 : break;
4081 : case RTF_FPRQ:
4082 : {
4083 3330 : sal_Int32 nValue = 0;
4084 3330 : switch (nParam)
4085 : {
4086 : case 0:
4087 155 : nValue = NS_ooxml::LN_Value_ST_Pitch_default;
4088 155 : break;
4089 : case 1:
4090 59 : nValue = NS_ooxml::LN_Value_ST_Pitch_fixed;
4091 59 : break;
4092 : case 2:
4093 3116 : nValue = NS_ooxml::LN_Value_ST_Pitch_variable;
4094 3116 : break;
4095 : }
4096 3330 : if (nValue)
4097 : {
4098 3330 : RTFSprms aAttributes;
4099 3330 : aAttributes.set(NS_ooxml::LN_CT_Pitch_val, std::make_shared<RTFValue>(nValue));
4100 3330 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Font_pitch, std::make_shared<RTFValue>(aAttributes));
4101 : }
4102 : }
4103 3330 : break;
4104 : case RTF_LISTOVERRIDECOUNT:
4105 : // Ignore this for now, the exporter always emits it with a zero parameter.
4106 125 : break;
4107 : case RTF_PICSCALEX:
4108 34 : m_aStates.top().aPicture.nScaleX = nParam;
4109 34 : break;
4110 : case RTF_PICSCALEY:
4111 34 : m_aStates.top().aPicture.nScaleY = nParam;
4112 34 : break;
4113 : case RTF_PICW:
4114 38 : m_aStates.top().aPicture.nWidth = nParam;
4115 38 : break;
4116 : case RTF_PICH:
4117 38 : m_aStates.top().aPicture.nHeight = nParam;
4118 38 : break;
4119 : case RTF_PICWGOAL:
4120 37 : m_aStates.top().aPicture.nGoalWidth = convertTwipToMm100(nParam);
4121 37 : break;
4122 : case RTF_PICHGOAL:
4123 37 : m_aStates.top().aPicture.nGoalHeight = convertTwipToMm100(nParam);
4124 37 : break;
4125 : case RTF_PICCROPL:
4126 31 : m_aStates.top().aPicture.nCropL = convertTwipToMm100(nParam);
4127 31 : break;
4128 : case RTF_PICCROPR:
4129 31 : m_aStates.top().aPicture.nCropR = convertTwipToMm100(nParam);
4130 31 : break;
4131 : case RTF_PICCROPT:
4132 31 : m_aStates.top().aPicture.nCropT = convertTwipToMm100(nParam);
4133 31 : break;
4134 : case RTF_PICCROPB:
4135 31 : m_aStates.top().aPicture.nCropB = convertTwipToMm100(nParam);
4136 31 : break;
4137 : case RTF_SHPWRK:
4138 : {
4139 79 : int nValue = 0;
4140 79 : switch (nParam)
4141 : {
4142 : case 0:
4143 68 : nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_bothSides;
4144 68 : break;
4145 : case 1:
4146 0 : nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_left;
4147 0 : break;
4148 : case 2:
4149 1 : nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_right;
4150 1 : break;
4151 : case 3:
4152 10 : nValue = NS_ooxml::LN_Value_wordprocessingDrawing_ST_WrapText_largest;
4153 10 : break;
4154 : default:
4155 0 : break;
4156 : }
4157 79 : auto pValue = std::make_shared<RTFValue>(nValue);
4158 79 : RTFValue::Pointer_t pTight = m_aStates.top().aCharacterSprms.find(NS_ooxml::LN_EG_WrapType_wrapTight);
4159 79 : if (pTight)
4160 5 : pTight->getAttributes().set(NS_ooxml::LN_CT_WrapTight_wrapText, pValue);
4161 : else
4162 74 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_WrapSquare_wrapText, pValue);
4163 : }
4164 79 : break;
4165 : case RTF_SHPWR:
4166 : {
4167 98 : switch (nParam)
4168 : {
4169 : case 1:
4170 0 : m_aStates.top().aShape.nWrap = css::text::WrapTextMode_NONE;
4171 0 : break;
4172 : case 2:
4173 25 : m_aStates.top().aShape.nWrap = css::text::WrapTextMode_PARALLEL;
4174 25 : break;
4175 : case 3:
4176 63 : m_aStates.top().aShape.nWrap = css::text::WrapTextMode_THROUGHT;
4177 63 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_WrapType_wrapNone, std::make_shared<RTFValue>());
4178 63 : break;
4179 : case 4:
4180 5 : m_aStates.top().aShape.nWrap = css::text::WrapTextMode_PARALLEL;
4181 5 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_WrapType_wrapTight, std::make_shared<RTFValue>());
4182 5 : break;
4183 : case 5:
4184 4 : m_aStates.top().aShape.nWrap = css::text::WrapTextMode_THROUGHT;
4185 4 : break;
4186 : }
4187 : }
4188 98 : break;
4189 : case RTF_CELLX:
4190 : {
4191 495 : int& rCurrentCellX((Destination::NESTEDTABLEPROPERTIES == m_aStates.top().eDestination) ? m_nNestedCurrentCellX : m_nTopLevelCurrentCellX);
4192 495 : int nCellX = nParam - rCurrentCellX;
4193 495 : const int COL_DFLT_WIDTH = 41; // sw/source/filter/inc/wrtswtbl.hxx, minimal possible width of cells.
4194 495 : if (!nCellX)
4195 1 : nCellX = COL_DFLT_WIDTH;
4196 :
4197 : // If there is a negative left margin, then the first cellx is relative to that.
4198 495 : RTFValue::Pointer_t pTblInd = m_aStates.top().aTableRowSprms.find(NS_ooxml::LN_CT_TblPrBase_tblInd);
4199 495 : if (rCurrentCellX == 0 && pTblInd.get())
4200 : {
4201 115 : RTFValue::Pointer_t pWidth = pTblInd->getAttributes().find(NS_ooxml::LN_CT_TblWidth_w);
4202 115 : if (pWidth.get() && pWidth->getInt() < 0)
4203 75 : nCellX = -1 * (pWidth->getInt() - nParam);
4204 : }
4205 :
4206 495 : rCurrentCellX = nParam;
4207 990 : auto pXValue = std::make_shared<RTFValue>(nCellX);
4208 495 : m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TblGridBase_gridCol, pXValue, RTFOverwrite::NO_APPEND);
4209 495 : if (Destination::NESTEDTABLEPROPERTIES == m_aStates.top().eDestination)
4210 : {
4211 6 : m_nNestedCells++;
4212 : // Push cell properties.
4213 : m_aNestedTableCellsSprms.push_back(
4214 6 : m_aStates.top().aTableCellSprms);
4215 : m_aNestedTableCellsAttributes.push_back(
4216 6 : m_aStates.top().aTableCellAttributes);
4217 : }
4218 : else
4219 : {
4220 489 : m_nTopLevelCells++;
4221 : // Push cell properties.
4222 : m_aTopLevelTableCellsSprms.push_back(
4223 489 : m_aStates.top().aTableCellSprms);
4224 : m_aTopLevelTableCellsAttributes.push_back(
4225 489 : m_aStates.top().aTableCellAttributes);
4226 : }
4227 :
4228 495 : m_aStates.top().aTableCellSprms = m_aDefaultState.aTableCellSprms;
4229 495 : m_aStates.top().aTableCellAttributes = m_aDefaultState.aTableCellAttributes;
4230 : // We assume text after a row definition always belongs to the table, to handle text before the real INTBL token
4231 495 : dispatchFlag(RTF_INTBL);
4232 990 : m_nCellxMax = std::max(m_nCellxMax, nParam);
4233 : }
4234 495 : break;
4235 : case RTF_TRRH:
4236 : {
4237 14 : OUString hRule("auto");
4238 14 : if (nParam < 0)
4239 : {
4240 6 : auto pAbsValue = std::make_shared<RTFValue>(-nParam);
4241 6 : pIntValue.swap(pAbsValue);
4242 :
4243 6 : hRule = "exact";
4244 : }
4245 8 : else if (nParam > 0)
4246 8 : hRule = "atLeast";
4247 :
4248 14 : lcl_putNestedAttribute(m_aStates.top().aTableRowSprms, NS_ooxml::LN_CT_TrPrBase_trHeight, NS_ooxml::LN_CT_Height_val, pIntValue);
4249 :
4250 28 : auto pHRule = std::make_shared<RTFValue>(hRule);
4251 28 : lcl_putNestedAttribute(m_aStates.top().aTableRowSprms, NS_ooxml::LN_CT_TrPrBase_trHeight, NS_ooxml::LN_CT_Height_hRule, pHRule);
4252 : }
4253 14 : break;
4254 : case RTF_TRLEFT:
4255 : {
4256 : // the value is in twips
4257 115 : lcl_putNestedAttribute(m_aStates.top().aTableRowSprms,
4258 : NS_ooxml::LN_CT_TblPrBase_tblInd, NS_ooxml::LN_CT_TblWidth_type,
4259 230 : std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_TblWidth_dxa));
4260 115 : lcl_putNestedAttribute(m_aStates.top().aTableRowSprms,
4261 : NS_ooxml::LN_CT_TblPrBase_tblInd, NS_ooxml::LN_CT_TblWidth_w,
4262 230 : std::make_shared<RTFValue>(nParam));
4263 : }
4264 115 : break;
4265 : case RTF_COLS:
4266 6 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_cols, NS_ooxml::LN_CT_Columns_num, pIntValue);
4267 6 : break;
4268 : case RTF_COLSX:
4269 38 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_cols, NS_ooxml::LN_CT_Columns_space, pIntValue);
4270 38 : break;
4271 : case RTF_COLNO:
4272 0 : lcl_putNestedSprm(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_cols, NS_ooxml::LN_CT_Columns_col, pIntValue);
4273 0 : break;
4274 : case RTF_COLW:
4275 : case RTF_COLSR:
4276 : {
4277 0 : RTFSprms& rAttributes = lcl_getLastAttributes(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_cols);
4278 0 : rAttributes.set((nKeyword == RTF_COLW ? NS_ooxml::LN_CT_Column_w : NS_ooxml::LN_CT_Column_space), pIntValue);
4279 : }
4280 0 : break;
4281 : case RTF_PAPERH: // fall through: set the default + current value
4282 : lcl_putNestedAttribute(m_aDefaultState.aSectionSprms,
4283 178 : NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_h, pIntValue, RTFOverwrite::YES);
4284 : case RTF_PGHSXN:
4285 289 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
4286 578 : NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_h, pIntValue, RTFOverwrite::YES);
4287 289 : break;
4288 : case RTF_PAPERW: // fall through: set the default + current value
4289 : lcl_putNestedAttribute(m_aDefaultState.aSectionSprms,
4290 178 : NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_w, pIntValue, RTFOverwrite::YES);
4291 : case RTF_PGWSXN:
4292 289 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
4293 578 : NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_w, pIntValue, RTFOverwrite::YES);
4294 289 : break;
4295 : case RTF_MARGL: // fall through: set the default + current value
4296 : lcl_putNestedAttribute(m_aDefaultState.aSectionSprms,
4297 177 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_left, pIntValue, RTFOverwrite::YES);
4298 : case RTF_MARGLSXN:
4299 292 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
4300 584 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_left, pIntValue, RTFOverwrite::YES);
4301 292 : break;
4302 : case RTF_MARGR: // fall through: set the default + current value
4303 : lcl_putNestedAttribute(m_aDefaultState.aSectionSprms,
4304 177 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_right, pIntValue, RTFOverwrite::YES);
4305 : case RTF_MARGRSXN:
4306 292 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
4307 584 : NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_right, pIntValue, RTFOverwrite::YES);
4308 292 : break;
4309 : case RTF_MARGT: // fall through: set the default + current value
4310 174 : lcl_putNestedAttribute(m_aDefaultState.aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_top, pIntValue, RTFOverwrite::YES);
4311 : case RTF_MARGTSXN:
4312 288 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_top, pIntValue, RTFOverwrite::YES);
4313 288 : break;
4314 : case RTF_MARGB: // fall through: set the default + current value
4315 173 : lcl_putNestedAttribute(m_aDefaultState.aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_bottom, pIntValue, RTFOverwrite::YES);
4316 : case RTF_MARGBSXN:
4317 287 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_bottom, pIntValue, RTFOverwrite::YES);
4318 287 : break;
4319 : case RTF_HEADERY:
4320 44 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_header, pIntValue, RTFOverwrite::YES);
4321 44 : break;
4322 : case RTF_FOOTERY:
4323 44 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_footer, pIntValue, RTFOverwrite::YES);
4324 44 : break;
4325 : case RTF_DEFTAB:
4326 176 : m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_defaultTabStop, pIntValue);
4327 176 : break;
4328 : case RTF_LINEMOD:
4329 3 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
4330 6 : NS_ooxml::LN_EG_SectPrContents_lnNumType, NS_ooxml::LN_CT_LineNumber_countBy, pIntValue);
4331 3 : break;
4332 : case RTF_LINEX:
4333 49 : if (nParam)
4334 3 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
4335 6 : NS_ooxml::LN_EG_SectPrContents_lnNumType, NS_ooxml::LN_CT_LineNumber_distance, pIntValue);
4336 49 : break;
4337 : case RTF_LINESTARTS:
4338 0 : lcl_putNestedAttribute(m_aStates.top().aSectionSprms,
4339 0 : NS_ooxml::LN_EG_SectPrContents_lnNumType, NS_ooxml::LN_CT_LineNumber_start, pIntValue);
4340 0 : break;
4341 : case RTF_REVAUTH:
4342 : case RTF_REVAUTHDEL:
4343 : {
4344 2 : auto pValue = std::make_shared<RTFValue>(m_aAuthors[nParam]);
4345 2 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_trackchange, NS_ooxml::LN_CT_TrackChange_author, pValue);
4346 : }
4347 2 : break;
4348 : case RTF_REVDTTM:
4349 : case RTF_REVDTTMDEL:
4350 : {
4351 2 : OUString aStr(OStringToOUString(lcl_DTTM22OString(nParam), m_aStates.top().nCurrentEncoding));
4352 4 : auto pValue = std::make_shared<RTFValue>(aStr);
4353 4 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_trackchange, NS_ooxml::LN_CT_TrackChange_date, pValue);
4354 : }
4355 2 : break;
4356 : case RTF_SHPLEFT:
4357 105 : m_aStates.top().aShape.nLeft = convertTwipToMm100(nParam);
4358 105 : break;
4359 : case RTF_SHPTOP:
4360 105 : m_aStates.top().aShape.nTop = convertTwipToMm100(nParam);
4361 105 : break;
4362 : case RTF_SHPRIGHT:
4363 96 : m_aStates.top().aShape.nRight = convertTwipToMm100(nParam);
4364 96 : break;
4365 : case RTF_SHPBOTTOM:
4366 96 : m_aStates.top().aShape.nBottom = convertTwipToMm100(nParam);
4367 96 : break;
4368 : case RTF_SHPZ:
4369 63 : m_aStates.top().aShape.oZ.reset(nParam);
4370 63 : break;
4371 : case RTF_FFTYPE:
4372 1 : switch (nParam)
4373 : {
4374 : case 0:
4375 0 : m_nFormFieldType = RTFFormFieldType::TEXT;
4376 0 : break;
4377 : case 1:
4378 1 : m_nFormFieldType = RTFFormFieldType::CHECKBOX;
4379 1 : break;
4380 : case 2:
4381 0 : m_nFormFieldType = RTFFormFieldType::LIST;
4382 0 : break;
4383 : default:
4384 0 : m_nFormFieldType = RTFFormFieldType::NONE;
4385 0 : break;
4386 : }
4387 1 : break;
4388 : case RTF_FFDEFRES:
4389 1 : if (m_nFormFieldType == RTFFormFieldType::CHECKBOX)
4390 1 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFCheckBox_default, pIntValue);
4391 0 : else if (m_nFormFieldType == RTFFormFieldType::LIST)
4392 0 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_default, pIntValue);
4393 1 : break;
4394 : case RTF_FFRES:
4395 1 : if (m_nFormFieldType == RTFFormFieldType::CHECKBOX)
4396 1 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFCheckBox_checked, pIntValue);
4397 0 : else if (m_nFormFieldType == RTFFormFieldType::LIST)
4398 0 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_result, pIntValue);
4399 1 : break;
4400 : case RTF_EDMINS:
4401 30 : if (m_xDocumentProperties.is())
4402 28 : m_xDocumentProperties->setEditingDuration(nParam);
4403 30 : break;
4404 : case RTF_NOFPAGES:
4405 : case RTF_NOFWORDS:
4406 : case RTF_NOFCHARS:
4407 : case RTF_NOFCHARSWS:
4408 150 : if (m_xDocumentProperties.is())
4409 : {
4410 112 : comphelper::SequenceAsHashMap aSeq = m_xDocumentProperties->getDocumentStatistics();
4411 224 : OUString aName;
4412 112 : switch (nKeyword)
4413 : {
4414 : case RTF_NOFPAGES:
4415 28 : aName = "PageCount";
4416 28 : nParam = 99;
4417 28 : break;
4418 : case RTF_NOFWORDS:
4419 28 : aName = "WordCount";
4420 28 : break;
4421 : case RTF_NOFCHARS:
4422 28 : aName = "CharacterCount";
4423 28 : break;
4424 : case RTF_NOFCHARSWS:
4425 28 : aName = "NonWhitespaceCharacterCount";
4426 28 : break;
4427 : default:
4428 0 : break;
4429 : }
4430 112 : if (!aName.isEmpty())
4431 : {
4432 112 : aSeq[aName] = uno::makeAny(sal_Int32(nParam));
4433 112 : m_xDocumentProperties->setDocumentStatistics(aSeq.getAsConstNamedValueList());
4434 112 : }
4435 : }
4436 150 : break;
4437 : case RTF_VERSION:
4438 30 : if (m_xDocumentProperties.is())
4439 28 : m_xDocumentProperties->setEditingCycles(nParam);
4440 30 : break;
4441 : case RTF_VERN:
4442 : // Ignore this for now, later the RTF writer version could be used to add hacks for older buggy writers.
4443 41 : break;
4444 : case RTF_FTNSTART:
4445 : lcl_putNestedSprm(m_aDefaultState.aParagraphSprms,
4446 112 : NS_ooxml::LN_EG_SectPrContents_footnotePr, NS_ooxml::LN_EG_FtnEdnNumProps_numStart, pIntValue);
4447 112 : break;
4448 : case RTF_AFTNSTART:
4449 : lcl_putNestedSprm(m_aDefaultState.aParagraphSprms,
4450 109 : NS_ooxml::LN_EG_SectPrContents_endnotePr, NS_ooxml::LN_EG_FtnEdnNumProps_numStart, pIntValue);
4451 109 : break;
4452 : case RTF_DFRMTXTX:
4453 6 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hSpace, nParam);
4454 6 : break;
4455 : case RTF_DFRMTXTY:
4456 6 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vSpace, nParam);
4457 6 : break;
4458 : case RTF_DXFRTEXT:
4459 : {
4460 4 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hSpace, nParam);
4461 4 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vSpace, nParam);
4462 : }
4463 4 : break;
4464 : case RTF_FLYVERT:
4465 : {
4466 2 : RTFVertOrient aVertOrient(nParam);
4467 2 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, aVertOrient.GetAlign());
4468 2 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vAnchor, aVertOrient.GetAnchor());
4469 : }
4470 2 : break;
4471 : case RTF_FLYHORZ:
4472 : {
4473 2 : RTFHoriOrient aHoriOrient(nParam);
4474 2 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, aHoriOrient.GetAlign());
4475 2 : m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hAnchor, aHoriOrient.GetAnchor());
4476 : }
4477 2 : break;
4478 : case RTF_FLYANCHOR:
4479 9 : m_aStates.top().aFrame.nAnchorType = nParam;
4480 9 : break;
4481 : case RTF_WMETAFILE:
4482 7 : m_aStates.top().aPicture.eWMetafile = nParam;
4483 7 : break;
4484 : case RTF_SB:
4485 689 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_spacing, NS_ooxml::LN_CT_Spacing_before, pIntValue, RTFOverwrite::YES);
4486 689 : break;
4487 : case RTF_SA:
4488 708 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_spacing, NS_ooxml::LN_CT_Spacing_after, pIntValue, RTFOverwrite::YES);
4489 708 : break;
4490 : case RTF_DPX:
4491 26 : m_aStates.top().aDrawingObject.nLeft = convertTwipToMm100(nParam);
4492 26 : break;
4493 : case RTF_DPY:
4494 26 : m_aStates.top().aDrawingObject.nTop = convertTwipToMm100(nParam);
4495 26 : break;
4496 : case RTF_DPXSIZE:
4497 26 : m_aStates.top().aDrawingObject.nRight = convertTwipToMm100(nParam);
4498 26 : break;
4499 : case RTF_DPYSIZE:
4500 26 : m_aStates.top().aDrawingObject.nBottom = convertTwipToMm100(nParam);
4501 26 : break;
4502 : case RTF_PNSTART:
4503 5 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_start, pIntValue);
4504 5 : break;
4505 : case RTF_PNF:
4506 : {
4507 1 : auto pValue = std::make_shared<RTFValue>(m_aFontNames[getFontIndex(nParam)]);
4508 2 : RTFSprms aAttributes;
4509 1 : aAttributes.set(NS_ooxml::LN_CT_Fonts_ascii, pValue);
4510 2 : lcl_putNestedSprm(m_aStates.top().aTableSprms, NS_ooxml::LN_CT_Lvl_rPr, NS_ooxml::LN_EG_RPrBase_rFonts, std::make_shared<RTFValue>(aAttributes));
4511 : }
4512 1 : break;
4513 : case RTF_VIEWSCALE:
4514 143 : m_aSettingsTableAttributes.set(NS_ooxml::LN_CT_Zoom_percent, pIntValue);
4515 143 : break;
4516 : case RTF_BIN:
4517 : {
4518 2 : m_aStates.top().nInternalState = RTFInternalState::BIN;
4519 2 : m_aStates.top().nBinaryToRead = nParam;
4520 : }
4521 2 : break;
4522 : case RTF_DPLINECOR:
4523 10 : m_aStates.top().aDrawingObject.nLineColorR = nParam;
4524 10 : m_aStates.top().aDrawingObject.bHasLineColor = true;
4525 10 : break;
4526 : case RTF_DPLINECOG:
4527 10 : m_aStates.top().aDrawingObject.nLineColorG = nParam;
4528 10 : m_aStates.top().aDrawingObject.bHasLineColor = true;
4529 10 : break;
4530 : case RTF_DPLINECOB:
4531 10 : m_aStates.top().aDrawingObject.nLineColorB = nParam;
4532 10 : m_aStates.top().aDrawingObject.bHasLineColor = true;
4533 10 : break;
4534 : case RTF_DPFILLBGCR:
4535 6 : m_aStates.top().aDrawingObject.nFillColorR = nParam;
4536 6 : m_aStates.top().aDrawingObject.bHasFillColor = true;
4537 6 : break;
4538 : case RTF_DPFILLBGCG:
4539 6 : m_aStates.top().aDrawingObject.nFillColorG = nParam;
4540 6 : m_aStates.top().aDrawingObject.bHasFillColor = true;
4541 6 : break;
4542 : case RTF_DPFILLBGCB:
4543 6 : m_aStates.top().aDrawingObject.nFillColorB = nParam;
4544 6 : m_aStates.top().aDrawingObject.bHasFillColor = true;
4545 6 : break;
4546 : case RTF_CLSHDNG:
4547 : {
4548 2 : int nValue = -1;
4549 2 : switch (nParam)
4550 : {
4551 : case 500:
4552 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct5;
4553 0 : break;
4554 : case 1000:
4555 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct10;
4556 0 : break;
4557 : case 1200:
4558 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct12;
4559 0 : break;
4560 : case 1500:
4561 2 : nValue = NS_ooxml::LN_Value_ST_Shd_pct15;
4562 2 : break;
4563 : case 2000:
4564 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct20;
4565 0 : break;
4566 : case 2500:
4567 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct25;
4568 0 : break;
4569 : case 3000:
4570 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct30;
4571 0 : break;
4572 : case 3500:
4573 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct35;
4574 0 : break;
4575 : case 3700:
4576 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct37;
4577 0 : break;
4578 : case 4000:
4579 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct40;
4580 0 : break;
4581 : case 4500:
4582 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct45;
4583 0 : break;
4584 : case 5000:
4585 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct50;
4586 0 : break;
4587 : case 5500:
4588 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct55;
4589 0 : break;
4590 : case 6000:
4591 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct60;
4592 0 : break;
4593 : case 6200:
4594 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct62;
4595 0 : break;
4596 : case 6500:
4597 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct65;
4598 0 : break;
4599 : case 7000:
4600 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct70;
4601 0 : break;
4602 : case 7500:
4603 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct75;
4604 0 : break;
4605 : case 8000:
4606 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct80;
4607 0 : break;
4608 : case 8500:
4609 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct85;
4610 0 : break;
4611 : case 8700:
4612 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct87;
4613 0 : break;
4614 : case 9000:
4615 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct90;
4616 0 : break;
4617 : case 9500:
4618 0 : nValue = NS_ooxml::LN_Value_ST_Shd_pct95;
4619 0 : break;
4620 : default:
4621 0 : break;
4622 : }
4623 2 : if (nValue != -1)
4624 2 : lcl_putNestedAttribute(m_aStates.top().aTableCellSprms, NS_ooxml::LN_CT_TcPrBase_shd, NS_ooxml::LN_CT_Shd_val, std::make_shared<RTFValue>(nValue));
4625 : }
4626 2 : break;
4627 : case RTF_DODHGT:
4628 17 : m_aStates.top().aDrawingObject.nDhgt = nParam;
4629 17 : break;
4630 : case RTF_DPPOLYCOUNT:
4631 11 : if (nParam >= 0)
4632 : {
4633 11 : m_aStates.top().aDrawingObject.nPolyLineCount = nParam;
4634 : }
4635 11 : break;
4636 : case RTF_DPPTX:
4637 : {
4638 14 : RTFDrawingObject& rDrawingObject = m_aStates.top().aDrawingObject;
4639 :
4640 14 : if (rDrawingObject.aPolyLinePoints.empty())
4641 7 : dispatchValue(RTF_DPPOLYCOUNT, 2);
4642 :
4643 14 : rDrawingObject.aPolyLinePoints.push_back(awt::Point(convertTwipToMm100(nParam), 0));
4644 : }
4645 14 : break;
4646 : case RTF_DPPTY:
4647 : {
4648 14 : RTFDrawingObject& rDrawingObject = m_aStates.top().aDrawingObject;
4649 14 : if (!rDrawingObject.aPolyLinePoints.empty())
4650 : {
4651 14 : rDrawingObject.aPolyLinePoints.back().Y = convertTwipToMm100(nParam);
4652 14 : rDrawingObject.nPolyLineCount--;
4653 14 : if (rDrawingObject.nPolyLineCount == 0)
4654 : {
4655 : uno::Sequence< uno::Sequence<awt::Point> >aPointSequenceSequence =
4656 : {
4657 : comphelper::containerToSequence(rDrawingObject.aPolyLinePoints)
4658 7 : };
4659 7 : rDrawingObject.xPropertySet->setPropertyValue("PolyPolygon", uno::Any(aPointSequenceSequence));
4660 : }
4661 : }
4662 : }
4663 14 : break;
4664 : case RTF_SHPFBLWTXT:
4665 : // Shape is below text -> send it to the background.
4666 62 : m_aStates.top().aShape.bInBackground = nParam;
4667 62 : break;
4668 : case RTF_CLPADB:
4669 : case RTF_CLPADL:
4670 : case RTF_CLPADR:
4671 : case RTF_CLPADT:
4672 : {
4673 12 : RTFSprms aAttributes;
4674 12 : aAttributes.set(NS_ooxml::LN_CT_TblWidth_type, std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_TblWidth_dxa));
4675 12 : aAttributes.set(NS_ooxml::LN_CT_TblWidth_w, std::make_shared<RTFValue>(nParam));
4676 12 : switch (nKeyword)
4677 : {
4678 : case RTF_CLPADB:
4679 3 : nSprm = NS_ooxml::LN_CT_TcMar_bottom;
4680 3 : break;
4681 : case RTF_CLPADL:
4682 3 : nSprm = NS_ooxml::LN_CT_TcMar_left;
4683 3 : break;
4684 : case RTF_CLPADR:
4685 3 : nSprm = NS_ooxml::LN_CT_TcMar_right;
4686 3 : break;
4687 : case RTF_CLPADT:
4688 3 : nSprm = NS_ooxml::LN_CT_TcMar_top;
4689 3 : break;
4690 : default:
4691 0 : break;
4692 : }
4693 12 : lcl_putNestedSprm(m_aStates.top().aTableCellSprms, NS_ooxml::LN_CT_TcPrBase_tcMar, nSprm, std::make_shared<RTFValue>(aAttributes));
4694 : }
4695 12 : break;
4696 : case RTF_FI:
4697 1772 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_firstLine, pIntValue);
4698 1772 : break;
4699 : case RTF_LI:
4700 : {
4701 2156 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_left, pIntValue);
4702 : // It turns out \li should reset the \fi inherited from the stylesheet.
4703 : // So set the direct formatting to zero, if we don't have such direct formatting yet.
4704 2156 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_firstLine, std::make_shared<RTFValue>(0),
4705 4312 : RTFOverwrite::NO_IGNORE, /*bAttribute=*/true);
4706 : }
4707 2156 : break;
4708 : case RTF_RI:
4709 1445 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_right, pIntValue);
4710 1445 : break;
4711 : case RTF_LIN:
4712 1722 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_start, pIntValue);
4713 1722 : break;
4714 : case RTF_RIN:
4715 1429 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_end, pIntValue);
4716 1429 : break;
4717 : case RTF_OUTLINELEVEL:
4718 27 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_outlineLvl, pIntValue);
4719 27 : break;
4720 : case RTF_TRGAPH:
4721 : // Half of the space between the cells of a table row: default left/right table cell margin.
4722 31 : if (nParam > 0)
4723 : {
4724 31 : RTFSprms aAttributes;
4725 31 : aAttributes.set(NS_ooxml::LN_CT_TblWidth_type, std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_TblWidth_dxa));
4726 31 : aAttributes.set(NS_ooxml::LN_CT_TblWidth_w, pIntValue);
4727 31 : lcl_putNestedSprm(m_aStates.top().aTableRowSprms, NS_ooxml::LN_CT_TblPrBase_tblCellMar, NS_ooxml::LN_CT_TblCellMar_left, std::make_shared<RTFValue>(aAttributes));
4728 31 : lcl_putNestedSprm(m_aStates.top().aTableRowSprms, NS_ooxml::LN_CT_TblPrBase_tblCellMar, NS_ooxml::LN_CT_TblCellMar_right, std::make_shared<RTFValue>(aAttributes));
4729 : }
4730 31 : break;
4731 : default:
4732 : {
4733 : SAL_INFO("writerfilter", "TODO handle value '" << lcl_RtfToString(nKeyword) << "'");
4734 15080 : aSkip.setParsed(false);
4735 : }
4736 15080 : break;
4737 : }
4738 147915 : return RTFError::OK;
4739 : }
4740 :
4741 2340 : RTFError RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int nParam)
4742 : {
4743 2340 : setNeedSect();
4744 2340 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
4745 2340 : RTFSkipDestination aSkip(*this);
4746 2340 : int nSprm = -1;
4747 4680 : auto pBoolValue = std::make_shared<RTFValue>(int(!bParam || nParam != 0));
4748 :
4749 : // Underline toggles.
4750 2340 : switch (nKeyword)
4751 : {
4752 : case RTF_UL:
4753 34 : nSprm = NS_ooxml::LN_Value_ST_Underline_single;
4754 34 : break;
4755 : case RTF_ULDASH:
4756 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_dash;
4757 0 : break;
4758 : case RTF_ULDASHD:
4759 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_dotDash;
4760 0 : break;
4761 : case RTF_ULDASHDD:
4762 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_dotDotDash;
4763 0 : break;
4764 : case RTF_ULDB:
4765 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_double;
4766 0 : break;
4767 : case RTF_ULHWAVE:
4768 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_wavyHeavy;
4769 0 : break;
4770 : case RTF_ULLDASH:
4771 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_dashLong;
4772 0 : break;
4773 : case RTF_ULTH:
4774 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_thick;
4775 0 : break;
4776 : case RTF_ULTHD:
4777 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_dottedHeavy;
4778 0 : break;
4779 : case RTF_ULTHDASH:
4780 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_dashedHeavy;
4781 0 : break;
4782 : case RTF_ULTHDASHD:
4783 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_dashDotHeavy;
4784 0 : break;
4785 : case RTF_ULTHDASHDD:
4786 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_dashDotDotHeavy;
4787 0 : break;
4788 : case RTF_ULTHLDASH:
4789 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_dashLongHeavy;
4790 0 : break;
4791 : case RTF_ULULDBWAVE:
4792 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_wavyDouble;
4793 0 : break;
4794 : case RTF_ULWAVE:
4795 0 : nSprm = NS_ooxml::LN_Value_ST_Underline_wave;
4796 0 : break;
4797 : default:
4798 2306 : break;
4799 : }
4800 2340 : if (nSprm >= 0)
4801 : {
4802 34 : auto pValue = std::make_shared<RTFValue>((!bParam || nParam != 0) ? nSprm : NS_ooxml::LN_Value_ST_Underline_none);
4803 34 : m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_Underline_val, pValue);
4804 34 : return RTFError::OK;
4805 : }
4806 :
4807 : // Accent characters (over dot / over comma).
4808 2306 : switch (nKeyword)
4809 : {
4810 : case RTF_ACCNONE:
4811 10 : nSprm = NS_ooxml::LN_Value_ST_Em_none;
4812 10 : break;
4813 : case RTF_ACCDOT:
4814 3 : nSprm = NS_ooxml::LN_Value_ST_Em_dot;
4815 3 : break;
4816 : case RTF_ACCCOMMA:
4817 3 : nSprm = NS_ooxml::LN_Value_ST_Em_comma;
4818 3 : break;
4819 : case RTF_ACCCIRCLE:
4820 3 : nSprm = NS_ooxml::LN_Value_ST_Em_circle;
4821 3 : break;
4822 : case RTF_ACCUNDERDOT:
4823 3 : nSprm = NS_ooxml::LN_Value_ST_Em_underDot;
4824 3 : break;
4825 : default:
4826 2284 : break;
4827 : }
4828 2306 : if (nSprm >= 0)
4829 : {
4830 22 : auto pValue = std::make_shared<RTFValue>((!bParam || nParam != 0) ? nSprm : 0);
4831 22 : m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_em, pValue);
4832 22 : return RTFError::OK;
4833 : }
4834 :
4835 : // Trivial character sprms.
4836 2284 : switch (nKeyword)
4837 : {
4838 : case RTF_B:
4839 : case RTF_AB:
4840 318 : nSprm = (m_aStates.top().isRightToLeft || m_aStates.top().eRunType == RTFParserState::HICH) ? NS_ooxml::LN_EG_RPrBase_bCs : NS_ooxml::LN_EG_RPrBase_b;
4841 318 : break;
4842 : case RTF_I:
4843 : case RTF_AI:
4844 621 : nSprm = (m_aStates.top().isRightToLeft || m_aStates.top().eRunType == RTFParserState::HICH) ? NS_ooxml::LN_EG_RPrBase_iCs : NS_ooxml::LN_EG_RPrBase_i;
4845 621 : break;
4846 : case RTF_OUTL:
4847 14 : nSprm = NS_ooxml::LN_EG_RPrBase_outline;
4848 14 : break;
4849 : case RTF_SHAD:
4850 11 : nSprm = NS_ooxml::LN_EG_RPrBase_shadow;
4851 11 : break;
4852 : case RTF_V:
4853 7 : nSprm = NS_ooxml::LN_EG_RPrBase_vanish;
4854 7 : break;
4855 : case RTF_STRIKE:
4856 19 : nSprm = NS_ooxml::LN_EG_RPrBase_strike;
4857 19 : break;
4858 : case RTF_STRIKED:
4859 2 : nSprm = NS_ooxml::LN_EG_RPrBase_dstrike;
4860 2 : break;
4861 : case RTF_SCAPS:
4862 27 : nSprm = NS_ooxml::LN_EG_RPrBase_smallCaps;
4863 27 : break;
4864 : case RTF_IMPR:
4865 2 : nSprm = NS_ooxml::LN_EG_RPrBase_imprint;
4866 2 : break;
4867 : case RTF_CAPS:
4868 6 : nSprm = NS_ooxml::LN_EG_RPrBase_caps;
4869 6 : break;
4870 : default:
4871 1257 : break;
4872 : }
4873 2284 : if (nSprm >= 0)
4874 : {
4875 1027 : m_aStates.top().aCharacterSprms.set(nSprm, pBoolValue);
4876 1027 : return RTFError::OK;
4877 : }
4878 :
4879 1257 : switch (nKeyword)
4880 : {
4881 : case RTF_ASPALPHA:
4882 512 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_autoSpaceDE, pBoolValue);
4883 512 : break;
4884 : case RTF_DELETED:
4885 : case RTF_REVISED:
4886 : {
4887 2 : auto pValue = std::make_shared<RTFValue>(nKeyword == RTF_DELETED ? oox::XML_del : oox::XML_ins);
4888 2 : lcl_putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_trackchange, NS_ooxml::LN_token, pValue);
4889 : }
4890 2 : break;
4891 : case RTF_SBAUTO:
4892 5 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_spacing, NS_ooxml::LN_CT_Spacing_beforeAutospacing, pBoolValue, RTFOverwrite::YES);
4893 5 : break;
4894 : case RTF_SAAUTO:
4895 6 : lcl_putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_spacing, NS_ooxml::LN_CT_Spacing_afterAutospacing, pBoolValue, RTFOverwrite::YES);
4896 6 : break;
4897 : case RTF_FACINGP:
4898 5 : m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_evenAndOddHeaders, pBoolValue);
4899 5 : break;
4900 : case RTF_HYPHAUTO:
4901 9 : m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_autoHyphenation, pBoolValue);
4902 9 : break;
4903 : case RTF_HYPHPAR:
4904 294 : m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_suppressAutoHyphens, std::make_shared<RTFValue>(int(bParam && nParam == 0)));
4905 294 : break;
4906 : default:
4907 : {
4908 : SAL_INFO("writerfilter", "TODO handle toggle '" << lcl_RtfToString(nKeyword) << "'");
4909 424 : aSkip.setParsed(false);
4910 : }
4911 424 : break;
4912 : }
4913 3597 : return RTFError::OK;
4914 : }
4915 :
4916 25458 : RTFError RTFDocumentImpl::pushState()
4917 : {
4918 : //SAL_INFO("writerfilter", OSL_THIS_FUNC << " before push: " << m_pTokenizer->getGroup());
4919 :
4920 25458 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
4921 25458 : m_nGroupStartPos = Strm().Tell();
4922 :
4923 25458 : if (m_aStates.empty())
4924 504 : m_aStates.push(m_aDefaultState);
4925 : else
4926 : {
4927 : // fdo#85812 group resets run type of _current_ and new state (but not RTL)
4928 24954 : m_aStates.top().eRunType = RTFParserState::LOCH;
4929 :
4930 24954 : if (m_aStates.top().eDestination == Destination::MR)
4931 299 : lcl_DestinationToMath(*m_aStates.top().pDestinationText, m_aMathBuffer, m_bMathNor);
4932 24954 : m_aStates.push(m_aStates.top());
4933 : }
4934 25458 : m_aStates.top().aDestinationText.setLength(0); // was copied: always reset!
4935 :
4936 25458 : m_pTokenizer->pushGroup();
4937 :
4938 25458 : switch (m_aStates.top().eDestination)
4939 : {
4940 : case Destination::FONTTABLE:
4941 : // this is a "faked" destination for the font entry
4942 3366 : m_aStates.top().pDestinationText = &m_aStates.top().aDestinationText;
4943 3366 : m_aStates.top().eDestination = Destination::FONTENTRY;
4944 3366 : break;
4945 : case Destination::STYLESHEET:
4946 : // this is a "faked" destination for the style sheet entry
4947 1313 : m_aStates.top().pDestinationText = &m_aStates.top().aDestinationText;
4948 1313 : m_aStates.top().eDestination = Destination::STYLEENTRY;
4949 : {
4950 : // the *default* is \s0 i.e. paragraph style default
4951 : // this will be overwritten by \sN \csN \dsN \tsN
4952 1313 : m_nCurrentStyleIndex = 0;
4953 1313 : auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_StyleType_paragraph);
4954 1313 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Style_type, pValue);
4955 : }
4956 1313 : break;
4957 : case Destination::FIELDRESULT:
4958 : case Destination::SHAPETEXT:
4959 : case Destination::FORMFIELD:
4960 : case Destination::FIELDINSTRUCTION:
4961 : case Destination::PICT:
4962 151 : m_aStates.top().eDestination = Destination::NORMAL;
4963 151 : break;
4964 : case Destination::MNUM:
4965 : case Destination::MDEN:
4966 : case Destination::ME:
4967 : case Destination::MFNAME:
4968 : case Destination::MLIM:
4969 : case Destination::MSUB:
4970 : case Destination::MSUP:
4971 : case Destination::MDEG:
4972 : case Destination::MOMATH:
4973 1272 : m_aStates.top().eDestination = Destination::MR;
4974 1272 : break;
4975 : case Destination::REVISIONTABLE:
4976 : // this is a "faked" destination for the revision table entry
4977 4 : m_aStates.top().pDestinationText = &m_aStates.top().aDestinationText;
4978 4 : m_aStates.top().eDestination = Destination::REVISIONENTRY;
4979 4 : break;
4980 : default:
4981 19352 : break;
4982 : }
4983 :
4984 : // If this is true, then ooxml:endtrackchange will be generated. Make sure
4985 : // we don't generate more ooxml:endtrackchange than ooxml:trackchange: new
4986 : // state does not inherit this flag.
4987 25458 : m_aStates.top().bStartedTrackchange = false;
4988 :
4989 25458 : return RTFError::OK;
4990 : }
4991 :
4992 : writerfilter::Reference<Properties>::Pointer_t
4993 1313 : RTFDocumentImpl::createStyleProperties()
4994 : {
4995 1313 : RTFValue::Pointer_t pParaProps = std::make_shared<RTFValue>(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms);
4996 2626 : RTFValue::Pointer_t pCharProps = std::make_shared<RTFValue>(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms);
4997 :
4998 : // resetSprms will clean up this modification
4999 1313 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Style_pPr, pParaProps);
5000 1313 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Style_rPr, pCharProps);
5001 :
5002 : writerfilter::Reference<Properties>::Pointer_t const pProps(
5003 1313 : new RTFReferenceProperties(m_aStates.top().aTableAttributes, m_aStates.top().aTableSprms));
5004 2626 : return pProps;
5005 : }
5006 :
5007 4734 : void RTFDocumentImpl::resetSprms()
5008 : {
5009 4734 : m_aStates.top().aTableSprms.clear();
5010 4734 : m_aStates.top().aCharacterSprms.clear();
5011 4734 : m_aStates.top().aParagraphSprms.clear();
5012 4734 : }
5013 :
5014 4734 : void RTFDocumentImpl::resetAttributes()
5015 : {
5016 4734 : m_aStates.top().aTableAttributes.clear();
5017 4734 : m_aStates.top().aCharacterAttributes.clear();
5018 4734 : m_aStates.top().aParagraphAttributes.clear();
5019 4734 : }
5020 :
5021 25454 : RTFError RTFDocumentImpl::popState()
5022 : {
5023 : //SAL_INFO("writerfilter", OSL_THIS_FUNC << " before pop: m_pTokenizer->getGroup() " << m_pTokenizer->getGroup() <<
5024 : // ", dest state: " << m_aStates.top().eDestination);
5025 :
5026 25454 : checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
5027 25454 : RTFParserState aState(m_aStates.top());
5028 25454 : m_bWasInFrame = aState.aFrame.inFrame();
5029 :
5030 : // dmapper expects some content in header/footer, so if there would be nothing, add an empty paragraph.
5031 25454 : if (m_pTokenizer->getGroup() == 1 && m_bFirstRun)
5032 : {
5033 9 : switch (m_nStreamType)
5034 : {
5035 : case NS_ooxml::LN_headerl:
5036 : case NS_ooxml::LN_headerr:
5037 : case NS_ooxml::LN_headerf:
5038 : case NS_ooxml::LN_footerl:
5039 : case NS_ooxml::LN_footerr:
5040 : case NS_ooxml::LN_footerf:
5041 2 : dispatchSymbol(RTF_PAR);
5042 2 : break;
5043 : }
5044 : }
5045 :
5046 25454 : switch (aState.eDestination)
5047 : {
5048 : case Destination::FONTTABLE:
5049 : {
5050 195 : writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(m_aFontTableEntries));
5051 195 : Mapper().table(NS_ooxml::LN_FONTTABLE, pTable);
5052 195 : if (m_nDefaultFontIndex >= 0)
5053 : {
5054 175 : auto pValue = std::make_shared<RTFValue>(m_aFontNames[getFontIndex(m_nDefaultFontIndex)]);
5055 175 : lcl_putNestedAttribute(m_aDefaultState.aCharacterSprms, NS_ooxml::LN_EG_RPrBase_rFonts, NS_ooxml::LN_CT_Fonts_ascii, pValue);
5056 195 : }
5057 : }
5058 195 : break;
5059 : case Destination::STYLESHEET:
5060 : {
5061 172 : writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(m_aStyleTableEntries));
5062 172 : Mapper().table(NS_ooxml::LN_STYLESHEET, pTable);
5063 : }
5064 172 : break;
5065 : case Destination::LISTOVERRIDETABLE:
5066 : {
5067 61 : RTFSprms aListTableAttributes;
5068 122 : writerfilter::Reference<Properties>::Pointer_t pProp = std::make_shared<RTFReferenceProperties>(aListTableAttributes, m_aListTableSprms);
5069 122 : RTFReferenceTable::Entries_t aListTableEntries;
5070 61 : aListTableEntries.insert(std::make_pair(0, pProp));
5071 122 : writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(aListTableEntries));
5072 122 : Mapper().table(NS_ooxml::LN_NUMBERING, pTable);
5073 : }
5074 61 : break;
5075 : case Destination::LISTENTRY:
5076 721 : for (RTFSprms::Iterator_t i = aState.aListLevelEntries.begin(); i != aState.aListLevelEntries.end(); ++i)
5077 623 : aState.aTableSprms.set(i->first, i->second, RTFOverwrite::NO_APPEND);
5078 98 : break;
5079 : case Destination::FIELDINSTRUCTION:
5080 : {
5081 32 : auto pValue = std::make_shared<RTFValue>(m_aFormfieldAttributes, m_aFormfieldSprms);
5082 64 : RTFSprms aFFAttributes;
5083 64 : RTFSprms aFFSprms;
5084 32 : aFFSprms.set(NS_ooxml::LN_ffdata, pValue);
5085 32 : if (!m_aStates.top().pCurrentBuffer)
5086 : {
5087 29 : writerfilter::Reference<Properties>::Pointer_t pProperties = std::make_shared<RTFReferenceProperties>(aFFAttributes, aFFSprms);
5088 29 : Mapper().props(pProperties);
5089 : }
5090 : else
5091 : {
5092 3 : auto pFFValue = std::make_shared<RTFValue>(aFFAttributes, aFFSprms);
5093 3 : m_aStates.top().pCurrentBuffer->push_back(Buf_t(BUFFER_PROPS, pFFValue));
5094 : }
5095 32 : m_aFormfieldAttributes.clear();
5096 32 : m_aFormfieldSprms.clear();
5097 64 : singleChar(cFieldSep);
5098 : }
5099 32 : break;
5100 : case Destination::FIELDRESULT:
5101 30 : singleChar(cFieldEnd);
5102 30 : break;
5103 : case Destination::LEVELTEXT:
5104 : {
5105 688 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5106 10 : break; // not for nested group
5107 678 : OUString aStr = m_aStates.top().pDestinationText->makeStringAndClear();
5108 :
5109 : // The first character is the length of the string (the rest should be ignored).
5110 678 : sal_Int32 nLength(aStr.toChar());
5111 1356 : OUString aValue;
5112 678 : if (nLength < aStr.getLength())
5113 626 : aValue = aStr.copy(1, nLength);
5114 : else
5115 52 : aValue = aStr;
5116 1356 : auto pValue = std::make_shared<RTFValue>(aValue, true);
5117 1356 : aState.aTableAttributes.set(NS_ooxml::LN_CT_LevelText_val, pValue);
5118 : }
5119 678 : break;
5120 : case Destination::LEVELNUMBERS:
5121 636 : if (aState.aTableSprms.find(NS_ooxml::LN_CT_Lvl_lvlText))
5122 : {
5123 631 : RTFSprms& rAttributes = aState.aTableSprms.find(NS_ooxml::LN_CT_Lvl_lvlText)->getAttributes();
5124 631 : RTFValue::Pointer_t pValue = rAttributes.find(NS_ooxml::LN_CT_LevelText_val);
5125 631 : if (pValue)
5126 : {
5127 630 : OUString aOrig = pValue->getString();
5128 :
5129 1260 : OUStringBuffer aBuf;
5130 630 : sal_Int32 nReplaces = 1;
5131 2049 : for (int i = 0; i < aOrig.getLength(); i++)
5132 : {
5133 5676 : if (std::find(aState.aLevelNumbers.begin(), aState.aLevelNumbers.end(), i+1)
5134 5676 : != aState.aLevelNumbers.end())
5135 : {
5136 473 : aBuf.append('%');
5137 : // '1.1.1' -> '%1.%2.%3', but '1.' (with '2.' prefix omitted) is %2.
5138 473 : aBuf.append(sal_Int32(nReplaces++ + aState.nListLevelNum + 1 - aState.aLevelNumbers.size()));
5139 : }
5140 : else
5141 946 : aBuf.append(aOrig.copy(i, 1));
5142 : }
5143 :
5144 1260 : pValue->setString(aBuf.makeStringAndClear());
5145 631 : }
5146 : }
5147 636 : break;
5148 : case Destination::SHAPEPROPERTYNAME:
5149 968 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5150 0 : break; // not for nested group
5151 968 : aState.aShape.aProperties.push_back(std::make_pair(m_aStates.top().pDestinationText->makeStringAndClear(), OUString()));
5152 968 : break;
5153 : case Destination::SHAPEPROPERTYVALUE:
5154 968 : if (aState.aShape.aProperties.size())
5155 : {
5156 966 : aState.aShape.aProperties.back().second = m_aStates.top().pDestinationText->makeStringAndClear();
5157 966 : if (m_aStates.top().bHadShapeText)
5158 10 : m_pSdrImport->append(aState.aShape.aProperties.back().first, aState.aShape.aProperties.back().second);
5159 956 : else if (aState.bInShapeGroup && !aState.bInShape && aState.aShape.aProperties.back().first == "rotation")
5160 : {
5161 : // Rotation should be applied on the groupshape itself, not on each shape.
5162 2 : aState.aShape.aGroupProperties.push_back(aState.aShape.aProperties.back());
5163 2 : aState.aShape.aProperties.pop_back();
5164 : }
5165 : }
5166 968 : break;
5167 : case Destination::PICPROP:
5168 : case Destination::SHAPEINSTRUCTION:
5169 : // Don't trigger a shape import in case we're only leaving the \shpinst of the groupshape itself.
5170 121 : if (!m_bObject && !aState.bInListpicture && !aState.bHadShapeText && !(aState.bInShapeGroup && !aState.bInShape))
5171 : {
5172 65 : RTFSdrImport::ShapeOrPict eType = (aState.eDestination == Destination::SHAPEINSTRUCTION) ? RTFSdrImport::SHAPE : RTFSdrImport::PICT;
5173 65 : m_pSdrImport->resolve(m_aStates.top().aShape, true, eType);
5174 : }
5175 56 : else if (aState.bInShapeGroup && !aState.bInShape)
5176 : {
5177 : // End of a groupshape, as we're in shapegroup, but not in a real shape.
5178 10 : for (std::vector< std::pair<OUString, OUString> >::iterator i = aState.aShape.aGroupProperties.begin(); i != aState.aShape.aGroupProperties.end(); ++i)
5179 2 : m_pSdrImport->appendGroupProperty(i->first, i->second);
5180 8 : aState.aShape.aGroupProperties.clear();
5181 : }
5182 121 : break;
5183 : case Destination::BOOKMARKSTART:
5184 : {
5185 17 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5186 0 : break; // not for nested group
5187 17 : OUString aStr = m_aStates.top().pDestinationText->makeStringAndClear();
5188 17 : int nPos = m_aBookmarks.size();
5189 17 : m_aBookmarks[aStr] = nPos;
5190 17 : Mapper().props(lcl_getBookmarkProperties(nPos, aStr));
5191 : }
5192 17 : break;
5193 : case Destination::BOOKMARKEND:
5194 : {
5195 16 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5196 0 : break; // not for nested group
5197 16 : OUString aStr = m_aStates.top().pDestinationText->makeStringAndClear();
5198 16 : Mapper().props(lcl_getBookmarkProperties(m_aBookmarks[aStr], aStr));
5199 : }
5200 16 : break;
5201 : case Destination::INDEXENTRY:
5202 : case Destination::TOCENTRY:
5203 : {
5204 6 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5205 4 : break; // not for nested group
5206 2 : OUString str(m_aStates.top().pDestinationText->makeStringAndClear());
5207 : // dmapper expects this as a field, so let's fake something...
5208 : OUString const field(
5209 4 : (Destination::INDEXENTRY == aState.eDestination) ? OUStringLiteral("XE") : OUStringLiteral("TC"));
5210 2 : str = field + " \"" + str.replaceAll("\"", "\\\"") + "\"";
5211 2 : singleChar(cFieldStart);
5212 2 : Mapper().utext(reinterpret_cast<sal_uInt8 const*>(str.getStr()), str.getLength());
5213 2 : singleChar(cFieldSep);
5214 : // no result
5215 4 : singleChar(cFieldEnd);
5216 : }
5217 2 : break;
5218 : case Destination::FORMFIELDNAME:
5219 : {
5220 1 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5221 0 : break; // not for nested group
5222 1 : auto pValue = std::make_shared<RTFValue>(m_aStates.top().pDestinationText->makeStringAndClear());
5223 1 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFData_name, pValue);
5224 : }
5225 1 : break;
5226 : case Destination::FORMFIELDLIST:
5227 : {
5228 0 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5229 0 : break; // not for nested group
5230 0 : auto pValue = std::make_shared<RTFValue>(m_aStates.top().pDestinationText->makeStringAndClear());
5231 0 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_listEntry, pValue);
5232 : }
5233 0 : break;
5234 : case Destination::DATAFIELD:
5235 : {
5236 1 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5237 0 : break; // not for nested group
5238 1 : OString aStr = OUStringToOString(m_aStates.top().pDestinationText->makeStringAndClear(), aState.nCurrentEncoding);
5239 : // decode hex dump
5240 2 : OStringBuffer aBuf;
5241 1 : const char* str = aStr.getStr();
5242 1 : int b = 0, count = 2;
5243 79 : for (int i = 0; i < aStr.getLength(); ++i)
5244 : {
5245 78 : char ch = str[i];
5246 78 : if (ch != 0x0d && ch != 0x0a)
5247 : {
5248 78 : b = b << 4;
5249 78 : sal_Int8 parsed = RTFTokenizer::asHex(ch);
5250 78 : if (parsed == -1)
5251 0 : return RTFError::HEX_INVALID;
5252 78 : b += parsed;
5253 78 : count--;
5254 78 : if (!count)
5255 : {
5256 39 : aBuf.append((char)b);
5257 39 : count = 2;
5258 39 : b = 0;
5259 : }
5260 : }
5261 : }
5262 1 : aStr = aBuf.makeStringAndClear();
5263 :
5264 : // ignore the first bytes
5265 1 : if (aStr.getLength() > 8)
5266 1 : aStr = aStr.copy(8);
5267 : // extract name
5268 1 : sal_Int32 nLength = aStr.toChar();
5269 1 : if (!aStr.isEmpty())
5270 1 : aStr = aStr.copy(1);
5271 1 : nLength = std::min(nLength, aStr.getLength());
5272 2 : OString aName = aStr.copy(0, nLength);
5273 1 : if (aStr.getLength() > nLength)
5274 1 : aStr = aStr.copy(nLength+1); // zero-terminated string
5275 : else
5276 0 : aStr.clear();
5277 : // extract default text
5278 1 : nLength = aStr.toChar();
5279 1 : if (!aStr.isEmpty())
5280 1 : aStr = aStr.copy(1);
5281 2 : auto pNValue = std::make_shared<RTFValue>(OStringToOUString(aName, aState.nCurrentEncoding));
5282 1 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFData_name, pNValue);
5283 1 : if (nLength > 0)
5284 : {
5285 0 : OString aDefaultText = aStr.copy(0, std::min(nLength, aStr.getLength()));
5286 0 : auto pDValue = std::make_shared<RTFValue>(OStringToOUString(aDefaultText, aState.nCurrentEncoding));
5287 0 : m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFTextInput_default, pDValue);
5288 : }
5289 :
5290 2 : m_bFormField = false;
5291 : }
5292 1 : break;
5293 : case Destination::CREATIONTIME:
5294 178 : if (m_xDocumentProperties.is())
5295 124 : m_xDocumentProperties->setCreationDate(lcl_getDateTime(aState));
5296 178 : break;
5297 : case Destination::REVISIONTIME:
5298 170 : if (m_xDocumentProperties.is())
5299 124 : m_xDocumentProperties->setModificationDate(lcl_getDateTime(aState));
5300 170 : break;
5301 : case Destination::PRINTTIME:
5302 100 : if (m_xDocumentProperties.is())
5303 97 : m_xDocumentProperties->setPrintDate(lcl_getDateTime(aState));
5304 100 : break;
5305 : case Destination::AUTHOR:
5306 151 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5307 48 : break; // not for nested group
5308 103 : if (m_xDocumentProperties.is())
5309 67 : m_xDocumentProperties->setAuthor(m_aStates.top().pDestinationText->makeStringAndClear());
5310 103 : break;
5311 : case Destination::KEYWORDS:
5312 3 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5313 0 : break; // not for nested group
5314 3 : if (m_xDocumentProperties.is())
5315 3 : m_xDocumentProperties->setKeywords(comphelper::string::convertCommaSeparated(m_aStates.top().pDestinationText->makeStringAndClear()));
5316 3 : break;
5317 : case Destination::COMMENT:
5318 11 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5319 0 : break; // not for nested group
5320 11 : if (m_xDocumentProperties.is())
5321 7 : m_xDocumentProperties->setGenerator(m_aStates.top().pDestinationText->makeStringAndClear());
5322 11 : break;
5323 : case Destination::SUBJECT:
5324 4 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5325 0 : break; // not for nested group
5326 4 : if (m_xDocumentProperties.is())
5327 4 : m_xDocumentProperties->setSubject(m_aStates.top().pDestinationText->makeStringAndClear());
5328 4 : break;
5329 : case Destination::TITLE:
5330 : {
5331 25 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5332 12 : break; // not for nested group
5333 13 : if (m_xDocumentProperties.is())
5334 11 : m_xDocumentProperties->setTitle(aState.pDestinationText->makeStringAndClear());
5335 : }
5336 13 : break;
5337 :
5338 : case Destination::DOCCOMM:
5339 6 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5340 0 : break; // not for nested group
5341 6 : if (m_xDocumentProperties.is())
5342 6 : m_xDocumentProperties->setDescription(m_aStates.top().pDestinationText->makeStringAndClear());
5343 6 : break;
5344 : case Destination::OPERATOR:
5345 : case Destination::COMPANY:
5346 : {
5347 126 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5348 3 : break; // not for nested group
5349 123 : OUString aName = aState.eDestination == Destination::OPERATOR ? OUString("Operator") : OUString("Company");
5350 246 : uno::Any aValue = uno::makeAny(m_aStates.top().pDestinationText->makeStringAndClear());
5351 123 : if (m_xDocumentProperties.is())
5352 : {
5353 31 : uno::Reference<beans::XPropertyContainer> xUserDefinedProperties = m_xDocumentProperties->getUserDefinedProperties();
5354 62 : uno::Reference<beans::XPropertySet> xPropertySet(xUserDefinedProperties, uno::UNO_QUERY);
5355 62 : uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
5356 31 : if (xPropertySetInfo->hasPropertyByName(aName))
5357 0 : xPropertySet->setPropertyValue(aName, aValue);
5358 : else
5359 62 : xUserDefinedProperties->addProperty(aName, beans::PropertyAttribute::REMOVABLE, aValue);
5360 123 : }
5361 : }
5362 123 : break;
5363 : case Destination::OBJDATA:
5364 : {
5365 4 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5366 0 : break; // not for nested group
5367 :
5368 4 : RTFError eError = handleEmbeddedObject();
5369 4 : if (eError != RTFError::OK)
5370 0 : return eError;
5371 : }
5372 4 : break;
5373 : case Destination::OBJCLASS:
5374 : {
5375 4 : auto pValue = std::make_shared<RTFValue>(m_aStates.top().pDestinationText->makeStringAndClear());
5376 4 : m_aOLEAttributes.set(NS_ooxml::LN_CT_OLEObject_ProgID, pValue);
5377 4 : break;
5378 : }
5379 : case Destination::OBJECT:
5380 : {
5381 5 : if (!m_bObject)
5382 : {
5383 : // if the object is in a special container we will use the \result
5384 : // element instead of the \objdata
5385 : // (see RTF_OBJECT in RTFDocumentImpl::dispatchDestination)
5386 1 : break;
5387 : }
5388 :
5389 4 : RTFSprms aObjectSprms;
5390 8 : auto pOLEValue = std::make_shared<RTFValue>(m_aOLEAttributes);
5391 4 : aObjectSprms.set(NS_ooxml::LN_OLEObject_OLEObject, pOLEValue);
5392 :
5393 8 : RTFSprms aObjAttributes;
5394 8 : RTFSprms aObjSprms;
5395 8 : auto pValue = std::make_shared<RTFValue>(m_aObjectAttributes, aObjectSprms);
5396 4 : aObjSprms.set(NS_ooxml::LN_object, pValue);
5397 8 : writerfilter::Reference<Properties>::Pointer_t pProperties = std::make_shared<RTFReferenceProperties>(aObjAttributes, aObjSprms);
5398 8 : uno::Reference<drawing::XShape> xShape;
5399 8 : RTFValue::Pointer_t pShape = m_aObjectAttributes.find(NS_ooxml::LN_shape);
5400 : OSL_ASSERT(pShape.get());
5401 4 : if (pShape.get())
5402 2 : pShape->getAny() >>= xShape;
5403 4 : Mapper().startShape(xShape);
5404 4 : Mapper().props(pProperties);
5405 4 : Mapper().endShape();
5406 4 : m_aObjectAttributes.clear();
5407 4 : m_aOLEAttributes.clear();
5408 8 : m_bObject = false;
5409 : }
5410 4 : break;
5411 : case Destination::ANNOTATIONDATE:
5412 : {
5413 6 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5414 0 : break; // not for nested group
5415 12 : OUString aStr(OStringToOUString(lcl_DTTM22OString(m_aStates.top().pDestinationText->makeStringAndClear().toInt32()),
5416 12 : aState.nCurrentEncoding));
5417 12 : auto pValue = std::make_shared<RTFValue>(aStr);
5418 12 : RTFSprms aAnnAttributes;
5419 6 : aAnnAttributes.set(NS_ooxml::LN_CT_TrackChange_date, pValue);
5420 12 : writerfilter::Reference<Properties>::Pointer_t pProperties = std::make_shared<RTFReferenceProperties>(aAnnAttributes);
5421 12 : Mapper().props(pProperties);
5422 : }
5423 6 : break;
5424 : case Destination::ANNOTATIONAUTHOR:
5425 6 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5426 0 : break; // not for nested group
5427 6 : m_aAuthor = m_aStates.top().pDestinationText->makeStringAndClear();
5428 6 : break;
5429 : case Destination::ATNID:
5430 6 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5431 0 : break; // not for nested group
5432 6 : m_aAuthorInitials = m_aStates.top().pDestinationText->makeStringAndClear();
5433 6 : break;
5434 : case Destination::ANNOTATIONREFERENCESTART:
5435 : case Destination::ANNOTATIONREFERENCEEND:
5436 : {
5437 12 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5438 0 : break; // not for nested group
5439 12 : OUString aStr = m_aStates.top().pDestinationText->makeStringAndClear();
5440 24 : auto pValue = std::make_shared<RTFValue>(aStr.toInt32());
5441 24 : RTFSprms aAttributes;
5442 12 : if (aState.eDestination == Destination::ANNOTATIONREFERENCESTART)
5443 6 : aAttributes.set(NS_ooxml::LN_EG_RangeMarkupElements_commentRangeStart, pValue);
5444 : else
5445 6 : aAttributes.set(NS_ooxml::LN_EG_RangeMarkupElements_commentRangeEnd, pValue);
5446 24 : writerfilter::Reference<Properties>::Pointer_t pProperties = std::make_shared<RTFReferenceProperties>(aAttributes);
5447 24 : Mapper().props(pProperties);
5448 : }
5449 12 : break;
5450 : case Destination::ANNOTATIONREFERENCE:
5451 : {
5452 6 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5453 0 : break; // not for nested group
5454 6 : OUString aStr = m_aStates.top().pDestinationText->makeStringAndClear();
5455 12 : RTFSprms aAnnAttributes;
5456 6 : aAnnAttributes.set(NS_ooxml::LN_CT_Markup_id, std::make_shared<RTFValue>(aStr.toInt32()));
5457 12 : Mapper().props(std::make_shared<RTFReferenceProperties>(aAnnAttributes));
5458 : }
5459 6 : break;
5460 : case Destination::FALT:
5461 : {
5462 481 : if (&m_aStates.top().aDestinationText != m_aStates.top().pDestinationText)
5463 8 : break; // not for nested group
5464 473 : OUString aStr(m_aStates.top().pDestinationText->makeStringAndClear());
5465 946 : auto pValue = std::make_shared<RTFValue>(aStr);
5466 946 : aState.aTableSprms.set(NS_ooxml::LN_CT_Font_altName, pValue);
5467 : }
5468 473 : break;
5469 : case Destination::DRAWINGOBJECT:
5470 26 : if (m_aStates.top().aDrawingObject.xShape.is())
5471 : {
5472 26 : RTFDrawingObject& rDrawing = m_aStates.top().aDrawingObject;
5473 26 : uno::Reference<drawing::XShape> xShape(rDrawing.xShape);
5474 52 : uno::Reference<beans::XPropertySet> xPropertySet(rDrawing.xPropertySet);
5475 :
5476 52 : uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY);
5477 26 : bool bTextFrame = xServiceInfo->supportsService("com.sun.star.text.TextFrame");
5478 :
5479 : // The default is certainly not inline, but then what Word supports is just at-character.
5480 26 : xPropertySet->setPropertyValue("AnchorType", uno::makeAny(text::TextContentAnchorType_AT_CHARACTER));
5481 :
5482 26 : if (bTextFrame)
5483 : {
5484 13 : xPropertySet->setPropertyValue("HoriOrientPosition", uno::makeAny((sal_Int32)rDrawing.nLeft));
5485 13 : xPropertySet->setPropertyValue("VertOrientPosition", uno::makeAny((sal_Int32)rDrawing.nTop));
5486 : }
5487 : else
5488 : {
5489 13 : xShape->setPosition(awt::Point(rDrawing.nLeft, rDrawing.nTop));
5490 : }
5491 26 : xShape->setSize(awt::Size(rDrawing.nRight, rDrawing.nBottom));
5492 :
5493 26 : if (rDrawing.bHasLineColor)
5494 : {
5495 10 : uno::Any aLineColor = uno::makeAny(sal_uInt32((rDrawing.nLineColorR<<16) + (rDrawing.nLineColorG<<8) + rDrawing.nLineColorB));
5496 20 : uno::Any aLineWidth;
5497 20 : RTFSdrImport::resolveLineColorAndWidth(bTextFrame, xPropertySet, aLineColor, aLineWidth);
5498 : }
5499 26 : if (rDrawing.bHasFillColor)
5500 6 : xPropertySet->setPropertyValue("FillColor", uno::makeAny(sal_uInt32((rDrawing.nFillColorR<<16) + (rDrawing.nFillColorG<<8) + rDrawing.nFillColorB)));
5501 20 : else if (!bTextFrame)
5502 : // If there is no fill, the Word default is 100% transparency.
5503 8 : xPropertySet->setPropertyValue("FillTransparence", uno::makeAny(sal_Int32(100)));
5504 :
5505 26 : RTFSdrImport::resolveFLine(xPropertySet, rDrawing.nFLine);
5506 :
5507 26 : if (!m_aStates.top().aDrawingObject.bHadShapeText)
5508 : {
5509 13 : Mapper().startShape(xShape);
5510 : }
5511 52 : Mapper().endShape();
5512 : }
5513 26 : break;
5514 : case Destination::PICT:
5515 : // fdo#79319 ignore picture data if it's really a shape
5516 21 : if (!m_pSdrImport->isFakePict())
5517 : {
5518 19 : resolvePict(true, m_pSdrImport->getCurrentShape());
5519 : }
5520 21 : m_bNeedFinalPar = true;
5521 21 : break;
5522 : case Destination::SHAPE:
5523 102 : m_bNeedFinalPar = true;
5524 102 : m_bNeedCr = m_bNeedCrOrig;
5525 102 : if (aState.aFrame.inFrame())
5526 : {
5527 : // parBreak modify m_aStates.top() so we can't apply resetFrame directly on aState
5528 2 : m_aStates.top().resetFrame();
5529 2 : parBreak();
5530 : // Save this state for later use, so we only reset frame status only for the first shape inside a frame.
5531 2 : aState = m_aStates.top();
5532 2 : m_bNeedPap = true;
5533 : }
5534 102 : break;
5535 : case Destination::MOMATH:
5536 : {
5537 73 : m_aMathBuffer.appendClosingTag(M_TOKEN(oMath));
5538 :
5539 73 : SvGlobalName aGlobalName(SO3_SM_CLASSID);
5540 146 : comphelper::EmbeddedObjectContainer aContainer;
5541 146 : OUString aName;
5542 146 : uno::Reference<embed::XEmbeddedObject> xObject = aContainer.CreateEmbeddedObject(aGlobalName.GetByteSequence(), aName);
5543 146 : uno::Reference<util::XCloseable> xComponent(xObject->getComponent(), uno::UNO_QUERY_THROW);
5544 : // gcc4.4 (and 4.3 and possibly older) have a problem with dynamic_cast directly to the target class,
5545 : // so help it with an intermediate cast. I'm not sure what exactly the problem is, seems to be unrelated
5546 : // to RTLD_GLOBAL, so most probably a gcc bug.
5547 73 : oox::FormulaImportBase& rImport = dynamic_cast<oox::FormulaImportBase&>(dynamic_cast<SfxBaseModel&>(*xComponent.get()));
5548 73 : rImport.readFormulaOoxml(m_aMathBuffer);
5549 146 : auto pValue = std::make_shared<RTFValue>(xObject);
5550 146 : RTFSprms aMathAttributes;
5551 73 : aMathAttributes.set(NS_ooxml::LN_starmath, pValue);
5552 146 : writerfilter::Reference<Properties>::Pointer_t pProperties = std::make_shared<RTFReferenceProperties>(aMathAttributes);
5553 73 : Mapper().props(pProperties);
5554 146 : m_aMathBuffer = oox::formulaimport::XmlStreamBuilder();
5555 : }
5556 73 : break;
5557 : case Destination::MR:
5558 1311 : lcl_DestinationToMath(*m_aStates.top().pDestinationText, m_aMathBuffer, m_bMathNor);
5559 1311 : break;
5560 : case Destination::MF:
5561 35 : m_aMathBuffer.appendClosingTag(M_TOKEN(f));
5562 35 : break;
5563 : case Destination::MFPR:
5564 21 : m_aMathBuffer.appendClosingTag(M_TOKEN(fPr));
5565 21 : break;
5566 : case Destination::MCTRLPR:
5567 150 : m_aMathBuffer.appendClosingTag(M_TOKEN(ctrlPr));
5568 150 : break;
5569 : case Destination::MNUM:
5570 35 : m_aMathBuffer.appendClosingTag(M_TOKEN(num));
5571 35 : break;
5572 : case Destination::MDEN:
5573 35 : m_aMathBuffer.appendClosingTag(M_TOKEN(den));
5574 35 : break;
5575 : case Destination::MACC:
5576 36 : m_aMathBuffer.appendClosingTag(M_TOKEN(acc));
5577 36 : break;
5578 : case Destination::MACCPR:
5579 36 : m_aMathBuffer.appendClosingTag(M_TOKEN(accPr));
5580 36 : break;
5581 : case Destination::MCHR:
5582 : case Destination::MPOS:
5583 : case Destination::MVERTJC:
5584 : case Destination::MSTRIKEH:
5585 : case Destination::MDEGHIDE:
5586 : case Destination::MBEGCHR:
5587 : case Destination::MSEPCHR:
5588 : case Destination::MENDCHR:
5589 : case Destination::MSUBHIDE:
5590 : case Destination::MSUPHIDE:
5591 : case Destination::MTYPE:
5592 : case Destination::MGROW:
5593 : {
5594 169 : sal_Int32 nMathToken = 0;
5595 169 : switch (aState.eDestination)
5596 : {
5597 : case Destination::MCHR:
5598 57 : nMathToken = M_TOKEN(chr);
5599 57 : break;
5600 : case Destination::MPOS:
5601 5 : nMathToken = M_TOKEN(pos);
5602 5 : break;
5603 : case Destination::MVERTJC:
5604 4 : nMathToken = M_TOKEN(vertJc);
5605 4 : break;
5606 : case Destination::MSTRIKEH:
5607 3 : nMathToken = M_TOKEN(strikeH);
5608 3 : break;
5609 : case Destination::MDEGHIDE:
5610 4 : nMathToken = M_TOKEN(degHide);
5611 4 : break;
5612 : case Destination::MBEGCHR:
5613 40 : nMathToken = M_TOKEN(begChr);
5614 40 : break;
5615 : case Destination::MSEPCHR:
5616 4 : nMathToken = M_TOKEN(sepChr);
5617 4 : break;
5618 : case Destination::MENDCHR:
5619 40 : nMathToken = M_TOKEN(endChr);
5620 40 : break;
5621 : case Destination::MSUBHIDE:
5622 2 : nMathToken = M_TOKEN(subHide);
5623 2 : break;
5624 : case Destination::MSUPHIDE:
5625 2 : nMathToken = M_TOKEN(supHide);
5626 2 : break;
5627 : case Destination::MTYPE:
5628 6 : nMathToken = M_TOKEN(type);
5629 6 : break;
5630 : case Destination::MGROW:
5631 2 : nMathToken = M_TOKEN(grow);
5632 2 : break;
5633 : default:
5634 0 : break;
5635 : }
5636 :
5637 169 : oox::formulaimport::XmlStream::AttributeList aAttribs;
5638 169 : aAttribs[M_TOKEN(val)] = m_aStates.top().pDestinationText->makeStringAndClear();
5639 169 : m_aMathBuffer.appendOpeningTag(nMathToken, aAttribs);
5640 169 : m_aMathBuffer.appendClosingTag(nMathToken);
5641 : }
5642 169 : break;
5643 : case Destination::ME:
5644 253 : m_aMathBuffer.appendClosingTag(M_TOKEN(e));
5645 253 : break;
5646 : case Destination::MBAR:
5647 3 : m_aMathBuffer.appendClosingTag(M_TOKEN(bar));
5648 3 : break;
5649 : case Destination::MBARPR:
5650 3 : m_aMathBuffer.appendClosingTag(M_TOKEN(barPr));
5651 3 : break;
5652 : case Destination::MD:
5653 56 : m_aMathBuffer.appendClosingTag(M_TOKEN(d));
5654 56 : break;
5655 : case Destination::MDPR:
5656 56 : m_aMathBuffer.appendClosingTag(M_TOKEN(dPr));
5657 56 : break;
5658 : case Destination::MFUNC:
5659 12 : m_aMathBuffer.appendClosingTag(M_TOKEN(func));
5660 12 : break;
5661 : case Destination::MFUNCPR:
5662 11 : m_aMathBuffer.appendClosingTag(M_TOKEN(funcPr));
5663 11 : break;
5664 : case Destination::MFNAME:
5665 12 : m_aMathBuffer.appendClosingTag(M_TOKEN(fName));
5666 12 : break;
5667 : case Destination::MLIMLOW:
5668 8 : m_aMathBuffer.appendClosingTag(M_TOKEN(limLow));
5669 8 : break;
5670 : case Destination::MLIMLOWPR:
5671 5 : m_aMathBuffer.appendClosingTag(M_TOKEN(limLowPr));
5672 5 : break;
5673 : case Destination::MLIM:
5674 14 : m_aMathBuffer.appendClosingTag(M_TOKEN(lim));
5675 14 : break;
5676 : case Destination::MM:
5677 3 : m_aMathBuffer.appendClosingTag(M_TOKEN(m));
5678 3 : break;
5679 : case Destination::MMPR:
5680 2 : m_aMathBuffer.appendClosingTag(M_TOKEN(mPr));
5681 2 : break;
5682 : case Destination::MMR:
5683 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(mr));
5684 6 : break;
5685 : case Destination::MNARY:
5686 20 : m_aMathBuffer.appendClosingTag(M_TOKEN(nary));
5687 20 : break;
5688 : case Destination::MNARYPR:
5689 20 : m_aMathBuffer.appendClosingTag(M_TOKEN(naryPr));
5690 20 : break;
5691 : case Destination::MSUB:
5692 41 : m_aMathBuffer.appendClosingTag(M_TOKEN(sub));
5693 41 : break;
5694 : case Destination::MSUP:
5695 69 : m_aMathBuffer.appendClosingTag(M_TOKEN(sup));
5696 69 : break;
5697 : case Destination::MLIMUPP:
5698 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(limUpp));
5699 6 : break;
5700 : case Destination::MLIMUPPPR:
5701 4 : m_aMathBuffer.appendClosingTag(M_TOKEN(limUppPr));
5702 4 : break;
5703 : case Destination::MGROUPCHR:
5704 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(groupChr));
5705 6 : break;
5706 : case Destination::MGROUPCHRPR:
5707 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(groupChrPr));
5708 6 : break;
5709 : case Destination::MBORDERBOX:
5710 3 : m_aMathBuffer.appendClosingTag(M_TOKEN(borderBox));
5711 3 : break;
5712 : case Destination::MBORDERBOXPR:
5713 3 : m_aMathBuffer.appendClosingTag(M_TOKEN(borderBoxPr));
5714 3 : break;
5715 : case Destination::MRAD:
5716 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(rad));
5717 6 : break;
5718 : case Destination::MRADPR:
5719 5 : m_aMathBuffer.appendClosingTag(M_TOKEN(radPr));
5720 5 : break;
5721 : case Destination::MDEG:
5722 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(deg));
5723 6 : break;
5724 : case Destination::MSSUB:
5725 9 : m_aMathBuffer.appendClosingTag(M_TOKEN(sSub));
5726 9 : break;
5727 : case Destination::MSSUBPR:
5728 5 : m_aMathBuffer.appendClosingTag(M_TOKEN(sSubPr));
5729 5 : break;
5730 : case Destination::MSSUP:
5731 37 : m_aMathBuffer.appendClosingTag(M_TOKEN(sSup));
5732 37 : break;
5733 : case Destination::MSSUPPR:
5734 20 : m_aMathBuffer.appendClosingTag(M_TOKEN(sSupPr));
5735 20 : break;
5736 : case Destination::MSSUBSUP:
5737 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(sSubSup));
5738 6 : break;
5739 : case Destination::MSSUBSUPPR:
5740 4 : m_aMathBuffer.appendClosingTag(M_TOKEN(sSubSupPr));
5741 4 : break;
5742 : case Destination::MSPRE:
5743 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(sPre));
5744 6 : break;
5745 : case Destination::MSPREPR:
5746 4 : m_aMathBuffer.appendClosingTag(M_TOKEN(sPrePr));
5747 4 : break;
5748 : case Destination::MBOX:
5749 2 : m_aMathBuffer.appendClosingTag(M_TOKEN(box));
5750 2 : break;
5751 : case Destination::MEQARR:
5752 6 : m_aMathBuffer.appendClosingTag(M_TOKEN(eqArr));
5753 6 : break;
5754 : case Destination::SHAPEGROUP:
5755 8 : if (aState.bCreatedShapeGroup)
5756 6 : m_pSdrImport->popParent();
5757 8 : break;
5758 : default:
5759 17344 : break;
5760 : }
5761 :
5762 : // See if we need to end a track change
5763 25454 : if (aState.bStartedTrackchange)
5764 : {
5765 2 : RTFSprms aTCSprms;
5766 4 : auto pValue = std::make_shared<RTFValue>(0);
5767 2 : aTCSprms.set(NS_ooxml::LN_endtrackchange, pValue);
5768 2 : if (!m_aStates.top().pCurrentBuffer)
5769 1 : Mapper().props(std::make_shared<RTFReferenceProperties>(RTFSprms(), aTCSprms));
5770 : else
5771 3 : m_aStates.top().pCurrentBuffer->push_back(Buf_t(BUFFER_PROPS, std::make_shared<RTFValue>(RTFSprms(), aTCSprms)));
5772 : }
5773 :
5774 : // This is the end of the doc, see if we need to close the last section.
5775 25454 : if (m_pTokenizer->getGroup() == 1 && !m_bFirstRun)
5776 : {
5777 : // \par means an empty paragraph at the end of footnotes/endnotes, but
5778 : // not in case of other substreams, like headers.
5779 493 : if (m_bNeedCr && !(m_nStreamType == NS_ooxml::LN_footnote || m_nStreamType == NS_ooxml::LN_endnote) && m_bIsNewDoc)
5780 28 : dispatchSymbol(RTF_PAR);
5781 493 : if (m_bNeedSect) // may be set by dispatchSymbol above!
5782 489 : sectBreak(true);
5783 : }
5784 :
5785 25454 : m_aStates.pop();
5786 :
5787 25454 : m_pTokenizer->popGroup();
5788 :
5789 : // list table
5790 25454 : switch (aState.eDestination)
5791 : {
5792 : case Destination::LISTENTRY:
5793 : {
5794 98 : auto pValue = std::make_shared<RTFValue>(aState.aTableAttributes, aState.aTableSprms);
5795 98 : m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_abstractNum, pValue, RTFOverwrite::NO_APPEND);
5796 : }
5797 98 : break;
5798 : case Destination::PARAGRAPHNUMBERING:
5799 : {
5800 5 : RTFValue::Pointer_t pIdValue = aState.aTableAttributes.find(NS_ooxml::LN_CT_AbstractNum_nsid);
5801 5 : if (pIdValue.get() && !m_aStates.empty())
5802 : {
5803 : // Abstract numbering
5804 5 : RTFSprms aLeveltextAttributes;
5805 10 : OUString aTextValue;
5806 10 : RTFValue::Pointer_t pTextBefore = aState.aTableAttributes.find(NS_ooxml::LN_CT_LevelText_val);
5807 5 : if (pTextBefore.get())
5808 4 : aTextValue += pTextBefore->getString();
5809 5 : aTextValue += "%1";
5810 10 : RTFValue::Pointer_t pTextAfter = aState.aTableAttributes.find(NS_ooxml::LN_CT_LevelSuffix_val);
5811 5 : if (pTextAfter.get())
5812 4 : aTextValue += pTextAfter->getString();
5813 10 : auto pTextValue = std::make_shared<RTFValue>(aTextValue);
5814 5 : aLeveltextAttributes.set(NS_ooxml::LN_CT_LevelText_val, pTextValue);
5815 :
5816 10 : RTFSprms aLevelAttributes;
5817 10 : RTFSprms aLevelSprms;
5818 10 : auto pIlvlValue = std::make_shared<RTFValue>(0);
5819 5 : aLevelAttributes.set(NS_ooxml::LN_CT_Lvl_ilvl, pIlvlValue);
5820 :
5821 10 : RTFValue::Pointer_t pFmtValue = aState.aTableSprms.find(NS_ooxml::LN_CT_Lvl_numFmt);
5822 5 : if (pFmtValue.get())
5823 5 : aLevelSprms.set(NS_ooxml::LN_CT_Lvl_numFmt, pFmtValue);
5824 :
5825 10 : RTFValue::Pointer_t pStartatValue = aState.aTableSprms.find(NS_ooxml::LN_CT_Lvl_start);
5826 5 : if (pStartatValue.get())
5827 5 : aLevelSprms.set(NS_ooxml::LN_CT_Lvl_start, pStartatValue);
5828 :
5829 10 : auto pLeveltextValue = std::make_shared<RTFValue>(aLeveltextAttributes);
5830 5 : aLevelSprms.set(NS_ooxml::LN_CT_Lvl_lvlText, pLeveltextValue);
5831 10 : RTFValue::Pointer_t pRunProps = aState.aTableSprms.find(NS_ooxml::LN_CT_Lvl_rPr);
5832 5 : if (pRunProps.get())
5833 1 : aLevelSprms.set(NS_ooxml::LN_CT_Lvl_rPr, pRunProps);
5834 :
5835 10 : RTFSprms aAbstractAttributes;
5836 10 : RTFSprms aAbstractSprms;
5837 5 : aAbstractAttributes.set(NS_ooxml::LN_CT_AbstractNum_abstractNumId, pIdValue);
5838 10 : auto pLevelValue = std::make_shared<RTFValue>(aLevelAttributes, aLevelSprms);
5839 5 : aAbstractSprms.set(NS_ooxml::LN_CT_AbstractNum_lvl, pLevelValue, RTFOverwrite::NO_APPEND);
5840 :
5841 10 : RTFSprms aListTableSprms;
5842 10 : auto pAbstractValue = std::make_shared<RTFValue>(aAbstractAttributes, aAbstractSprms);
5843 : // It's important that Numbering_abstractNum and Numbering_num never overwrites previous values.
5844 5 : aListTableSprms.set(NS_ooxml::LN_CT_Numbering_abstractNum, pAbstractValue, RTFOverwrite::NO_APPEND);
5845 :
5846 : // Numbering
5847 10 : RTFSprms aNumberingAttributes;
5848 10 : RTFSprms aNumberingSprms;
5849 5 : aNumberingAttributes.set(NS_ooxml::LN_CT_AbstractNum_nsid, pIdValue);
5850 5 : aNumberingSprms.set(NS_ooxml::LN_CT_Num_abstractNumId, pIdValue);
5851 10 : auto pNumberingValue = std::make_shared<RTFValue>(aNumberingAttributes, aNumberingSprms);
5852 5 : aListTableSprms.set(NS_ooxml::LN_CT_Numbering_num, pNumberingValue, RTFOverwrite::NO_APPEND);
5853 :
5854 : // Table
5855 10 : RTFSprms aListTableAttributes;
5856 10 : writerfilter::Reference<Properties>::Pointer_t pProp = std::make_shared<RTFReferenceProperties>(aListTableAttributes, aListTableSprms);
5857 :
5858 10 : RTFReferenceTable::Entries_t aListTableEntries;
5859 5 : aListTableEntries.insert(std::make_pair(0, pProp));
5860 10 : writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(aListTableEntries));
5861 5 : Mapper().table(NS_ooxml::LN_NUMBERING, pTable);
5862 :
5863 : // Use it
5864 5 : lcl_putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_numPr, NS_ooxml::LN_CT_NumPr_ilvl, pIlvlValue);
5865 10 : lcl_putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_tabs, NS_ooxml::LN_CT_NumPr_numId, pIdValue);
5866 5 : }
5867 : }
5868 5 : break;
5869 : case Destination::PARAGRAPHNUMBERING_TEXTAFTER:
5870 4 : if (!m_aStates.empty())
5871 : {
5872 : // FIXME: don't use pDestinationText, points to popped state
5873 4 : auto pValue = std::make_shared<RTFValue>(aState.aDestinationText.makeStringAndClear(), true);
5874 4 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_LevelSuffix_val, pValue);
5875 : }
5876 4 : break;
5877 : case Destination::PARAGRAPHNUMBERING_TEXTBEFORE:
5878 4 : if (!m_aStates.empty())
5879 : {
5880 : // FIXME: don't use pDestinationText, points to popped state
5881 4 : auto pValue = std::make_shared<RTFValue>(aState.aDestinationText.makeStringAndClear(), true);
5882 4 : m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_LevelText_val, pValue);
5883 : }
5884 4 : break;
5885 : case Destination::LISTNAME:
5886 39 : break;
5887 : case Destination::LISTLEVEL:
5888 634 : if (!m_aStates.empty())
5889 : {
5890 634 : auto pInnerValue = std::make_shared<RTFValue>(m_aStates.top().nListLevelNum++);
5891 634 : aState.aTableAttributes.set(NS_ooxml::LN_CT_Lvl_ilvl, pInnerValue);
5892 :
5893 1268 : auto pValue = std::make_shared<RTFValue>(aState.aTableAttributes, aState.aTableSprms);
5894 634 : if (m_aStates.top().eDestination != Destination::LFOLEVEL)
5895 623 : m_aStates.top().aListLevelEntries.set(NS_ooxml::LN_CT_AbstractNum_lvl, pValue, RTFOverwrite::NO_APPEND);
5896 : else
5897 645 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_NumLvl_lvl, pValue);
5898 : }
5899 634 : break;
5900 : case Destination::LFOLEVEL:
5901 73 : if (!m_aStates.empty())
5902 : {
5903 73 : auto pInnerValue = std::make_shared<RTFValue>(m_aStates.top().nListLevelNum++);
5904 73 : aState.aTableAttributes.set(NS_ooxml::LN_CT_NumLvl_ilvl, pInnerValue);
5905 :
5906 146 : auto pValue = std::make_shared<RTFValue>(aState.aTableAttributes, aState.aTableSprms);
5907 146 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Num_lvlOverride, pValue, RTFOverwrite::NO_APPEND);
5908 : }
5909 73 : break;
5910 : // list override table
5911 : case Destination::LISTOVERRIDEENTRY:
5912 126 : if (!m_aStates.empty())
5913 : {
5914 126 : if (m_aStates.top().eDestination == Destination::LISTOVERRIDEENTRY)
5915 : {
5916 : // copy properties upwards so upper popState inserts it
5917 1 : m_aStates.top().aTableAttributes = aState.aTableAttributes;
5918 1 : m_aStates.top().aTableSprms = aState.aTableSprms;
5919 : }
5920 : else
5921 : {
5922 125 : auto pValue = std::make_shared<RTFValue>(aState.aTableAttributes, aState.aTableSprms);
5923 125 : m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_num, pValue, RTFOverwrite::NO_APPEND);
5924 : }
5925 : }
5926 126 : break;
5927 : case Destination::LEVELTEXT:
5928 688 : if (!m_aStates.empty())
5929 : {
5930 688 : auto pValue = std::make_shared<RTFValue>(aState.aTableAttributes);
5931 688 : m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_lvlText, pValue);
5932 : }
5933 688 : break;
5934 : case Destination::LEVELNUMBERS:
5935 636 : if (!m_aStates.empty())
5936 636 : m_aStates.top().aTableSprms = aState.aTableSprms;
5937 636 : break;
5938 : case Destination::FIELDINSTRUCTION:
5939 32 : if (!m_aStates.empty())
5940 32 : m_aStates.top().eFieldStatus = RTFFieldStatus::INSTRUCTION;
5941 32 : break;
5942 : case Destination::FIELDRESULT:
5943 30 : if (!m_aStates.empty())
5944 30 : m_aStates.top().eFieldStatus = RTFFieldStatus::RESULT;
5945 30 : break;
5946 : case Destination::FIELD:
5947 32 : if (aState.eFieldStatus == RTFFieldStatus::INSTRUCTION)
5948 2 : singleChar(cFieldEnd);
5949 32 : break;
5950 : case Destination::SHAPEPROPERTYVALUEPICT:
5951 23 : if (!m_aStates.empty())
5952 : {
5953 23 : m_aStates.top().aPicture = aState.aPicture;
5954 : // both \sp and \sv are destinations, copy the text up-ward for later
5955 23 : m_aStates.top().aDestinationText = aState.aDestinationText;
5956 : }
5957 23 : break;
5958 : case Destination::FALT:
5959 481 : if (!m_aStates.empty())
5960 481 : m_aStates.top().aTableSprms = aState.aTableSprms;
5961 481 : break;
5962 : case Destination::SHAPEPROPERTYNAME:
5963 : case Destination::SHAPEPROPERTYVALUE:
5964 : case Destination::SHAPEPROPERTY:
5965 2920 : if (!m_aStates.empty())
5966 : {
5967 2919 : m_aStates.top().aShape = aState.aShape;
5968 2919 : m_aStates.top().aPicture = aState.aPicture;
5969 2919 : m_aStates.top().aCharacterAttributes = aState.aCharacterAttributes;
5970 : }
5971 2920 : break;
5972 : case Destination::FLYMAINCONTENT:
5973 : case Destination::SHPPICT:
5974 : case Destination::SHAPE:
5975 124 : if (!m_aStates.empty())
5976 : {
5977 123 : m_aStates.top().aFrame = aState.aFrame;
5978 123 : if (aState.eDestination == Destination::SHPPICT && m_aStates.top().eDestination == Destination::LISTPICTURE)
5979 : {
5980 3 : RTFSprms aAttributes;
5981 3 : aAttributes.set(NS_ooxml::LN_CT_NumPicBullet_numPicBulletId, std::make_shared<RTFValue>(m_nListPictureId++));
5982 6 : RTFSprms aSprms;
5983 : // Dummy value, real picture is already sent to dmapper.
5984 3 : aSprms.set(NS_ooxml::LN_CT_NumPicBullet_pict, std::make_shared<RTFValue>(0));
5985 6 : auto pValue = std::make_shared<RTFValue>(aAttributes, aSprms);
5986 6 : m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_numPicBullet, pValue, RTFOverwrite::NO_APPEND);
5987 : }
5988 : }
5989 124 : break;
5990 : case Destination::SHAPETEXT:
5991 56 : if (!m_aStates.empty())
5992 : {
5993 : // If we're leaving the shapetext group (it may have nested ones) and this is a shape, not an old drawingobject.
5994 56 : if (m_aStates.top().eDestination != Destination::SHAPETEXT && !m_aStates.top().aDrawingObject.bHadShapeText)
5995 : {
5996 44 : m_aStates.top().bHadShapeText = true;
5997 44 : if (!m_aStates.top().pCurrentBuffer)
5998 43 : m_pSdrImport->close();
5999 : else
6000 1 : m_aStates.top().pCurrentBuffer->push_back(
6001 2 : Buf_t(BUFFER_ENDSHAPE));
6002 : }
6003 :
6004 : // It's allowed to declare these inside the shape text, and they
6005 : // are expected to have an effect for the whole shape.
6006 56 : if (aState.aDrawingObject.nLeft)
6007 1 : m_aStates.top().aDrawingObject.nLeft = aState.aDrawingObject.nLeft;
6008 56 : if (aState.aDrawingObject.nTop)
6009 1 : m_aStates.top().aDrawingObject.nTop = aState.aDrawingObject.nTop;
6010 56 : if (aState.aDrawingObject.nRight)
6011 1 : m_aStates.top().aDrawingObject.nRight = aState.aDrawingObject.nRight;
6012 56 : if (aState.aDrawingObject.nBottom)
6013 1 : m_aStates.top().aDrawingObject.nBottom = aState.aDrawingObject.nBottom;
6014 : }
6015 56 : break;
6016 : default:
6017 : {
6018 19449 : if (!m_aStates.empty() && m_aStates.top().eDestination == Destination::PICT)
6019 23 : m_aStates.top().aPicture = aState.aPicture;
6020 : }
6021 19449 : break;
6022 : }
6023 :
6024 25454 : if (aState.pCurrentBuffer == &m_aSuperBuffer)
6025 : {
6026 : OSL_ASSERT(!m_aStates.empty() && m_aStates.top().pCurrentBuffer == nullptr);
6027 :
6028 22 : if (!m_bHasFootnote)
6029 22 : replayBuffer(m_aSuperBuffer, nullptr, nullptr);
6030 :
6031 22 : m_bHasFootnote = false;
6032 : }
6033 :
6034 25454 : return RTFError::OK;
6035 : }
6036 :
6037 4 : RTFError RTFDocumentImpl::handleEmbeddedObject()
6038 : {
6039 4 : SvMemoryStream aStream;
6040 4 : int b = 0, count = 2;
6041 :
6042 : // Feed the destination text to a stream.
6043 8 : OString aStr = OUStringToOString(m_aStates.top().pDestinationText->makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
6044 4 : const char* str = aStr.getStr();
6045 46140 : for (int i = 0; i < aStr.getLength(); ++i)
6046 : {
6047 46136 : char ch = str[i];
6048 46136 : if (ch != 0x0d && ch != 0x0a)
6049 : {
6050 46136 : b = b << 4;
6051 46136 : sal_Int8 parsed = RTFTokenizer::asHex(ch);
6052 46136 : if (parsed == -1)
6053 0 : return RTFError::HEX_INVALID;
6054 46136 : b += parsed;
6055 46136 : count--;
6056 46136 : if (!count)
6057 : {
6058 23068 : aStream.WriteChar(b);
6059 23068 : count = 2;
6060 23068 : b = 0;
6061 : }
6062 : }
6063 : }
6064 :
6065 8 : std::unique_ptr<SvStream> pStream(new SvMemoryStream());
6066 :
6067 : // Skip ObjectHeader, see [MS-OLEDS] 2.2.4.
6068 4 : if (aStream.Tell())
6069 : {
6070 4 : aStream.Seek(0);
6071 : sal_uInt32 nData;
6072 4 : aStream.ReadUInt32(nData); // OLEVersion
6073 4 : aStream.ReadUInt32(nData); // FormatID
6074 4 : aStream.ReadUInt32(nData); // ClassName
6075 4 : aStream.SeekRel(nData);
6076 4 : aStream.ReadUInt32(nData); // TopicName
6077 4 : aStream.SeekRel(nData);
6078 4 : aStream.ReadUInt32(nData); // ItemName
6079 4 : aStream.SeekRel(nData);
6080 4 : aStream.ReadUInt32(nData); // NativeDataSize
6081 :
6082 4 : if (nData)
6083 : {
6084 4 : pStream->WriteStream(aStream);
6085 4 : pStream->Seek(0);
6086 : }
6087 : }
6088 :
6089 8 : uno::Reference<io::XInputStream> xInputStream(new utl::OSeekableInputStreamWrapper(pStream.release(), /*_bOwner=*/true));
6090 8 : auto pStreamValue = std::make_shared<RTFValue>(xInputStream);
6091 4 : m_aOLEAttributes.set(NS_ooxml::LN_inputstream, pStreamValue);
6092 :
6093 8 : return RTFError::OK;
6094 : }
6095 :
6096 82 : bool RTFDocumentImpl::isInBackground()
6097 : {
6098 82 : return m_aStates.top().bInBackground;
6099 : }
6100 :
6101 471548 : RTFInternalState RTFDocumentImpl::getInternalState()
6102 : {
6103 471548 : return m_aStates.top().nInternalState;
6104 : }
6105 :
6106 27313 : void RTFDocumentImpl::setInternalState(RTFInternalState nInternalState)
6107 : {
6108 27313 : m_aStates.top().nInternalState = nInternalState;
6109 27313 : }
6110 :
6111 222000 : Destination RTFDocumentImpl::getDestination()
6112 : {
6113 222000 : return m_aStates.top().eDestination;
6114 : }
6115 :
6116 1568 : void RTFDocumentImpl::setDestination(Destination eDestination)
6117 : {
6118 1568 : m_aStates.top().eDestination = eDestination;
6119 1568 : }
6120 :
6121 : // this is a questionably named method that is used only in a very special
6122 : // situation where it looks like the "current" buffer is needed?
6123 22 : void RTFDocumentImpl::setDestinationText(OUString& rString)
6124 : {
6125 22 : m_aStates.top().aDestinationText.setLength(0);
6126 22 : m_aStates.top().aDestinationText.append(rString);
6127 22 : }
6128 :
6129 170960 : bool RTFDocumentImpl::getSkipUnknown()
6130 : {
6131 170960 : return m_bSkipUnknown;
6132 : }
6133 :
6134 3133 : void RTFDocumentImpl::setSkipUnknown(bool bSkipUnknown)
6135 : {
6136 3133 : m_bSkipUnknown = bSkipUnknown;
6137 3133 : }
6138 :
6139 297279 : void RTFDocumentImpl::checkUnicode(bool bUnicode, bool bHex)
6140 : {
6141 297279 : if (bUnicode && !m_aUnicodeBuffer.isEmpty())
6142 : {
6143 527 : OUString aString = m_aUnicodeBuffer.makeStringAndClear();
6144 527 : text(aString);
6145 : }
6146 297279 : if (bHex && !m_aHexBuffer.isEmpty())
6147 : {
6148 14134 : OUString aString = OStringToOUString(m_aHexBuffer.makeStringAndClear(), m_aStates.top().nCurrentEncoding);
6149 14134 : text(aString);
6150 : }
6151 297279 : }
6152 :
6153 504 : RTFParserState::RTFParserState(RTFDocumentImpl* pDocumentImpl)
6154 : : m_pDocumentImpl(pDocumentImpl),
6155 : nInternalState(RTFInternalState::NORMAL),
6156 : eDestination(Destination::NORMAL),
6157 : eFieldStatus(RTFFieldStatus::NONE),
6158 : nBorderState(RTFBorderState::NONE),
6159 : aTableSprms(),
6160 : aTableAttributes(),
6161 : aCharacterSprms(),
6162 : aCharacterAttributes(),
6163 : aParagraphSprms(),
6164 : aParagraphAttributes(),
6165 : aSectionSprms(),
6166 : aSectionAttributes(),
6167 : aTableRowSprms(),
6168 : aTableRowAttributes(),
6169 : aTableCellSprms(),
6170 : aTableCellAttributes(),
6171 : aTabAttributes(),
6172 : aCurrentColor(),
6173 504 : nCurrentEncoding(rtl_getTextEncodingFromWindowsCharset(0)),
6174 : nUc(1),
6175 : nCharsToSkip(0),
6176 : nBinaryToRead(0),
6177 : nListLevelNum(0),
6178 : aListLevelEntries(),
6179 : aLevelNumbers(),
6180 : aPicture(),
6181 : aShape(),
6182 : aDrawingObject(),
6183 : aFrame(this),
6184 : eRunType(LOCH),
6185 : isRightToLeft(false),
6186 : nYear(0),
6187 : nMonth(0),
6188 : nDay(0),
6189 : nHour(0),
6190 : nMinute(0),
6191 : pDestinationText(nullptr),
6192 : nCurrentStyleIndex(-1),
6193 : nCurrentCharacterStyleIndex(-1),
6194 : pCurrentBuffer(nullptr),
6195 : bInListpicture(false),
6196 : bInBackground(false),
6197 : bHadShapeText(false),
6198 : bInShapeGroup(false),
6199 : bInShape(false),
6200 : bCreatedShapeGroup(false),
6201 1008 : bStartedTrackchange(false)
6202 : {
6203 504 : }
6204 :
6205 1274 : void RTFParserState::resetFrame()
6206 : {
6207 1274 : aFrame = RTFFrame(this);
6208 1274 : }
6209 :
6210 2853 : RTFColorTableEntry::RTFColorTableEntry()
6211 : : nRed(0),
6212 : nGreen(0),
6213 2853 : nBlue(0)
6214 : {
6215 2853 : }
6216 :
6217 504 : RTFPicture::RTFPicture()
6218 : : nWidth(0),
6219 : nHeight(0),
6220 : nGoalWidth(0),
6221 : nGoalHeight(0),
6222 : nScaleX(100),
6223 : nScaleY(100),
6224 : nCropT(0),
6225 : nCropB(0),
6226 : nCropL(0),
6227 : nCropR(0),
6228 : eWMetafile(0),
6229 504 : eStyle(RTFBmpStyle::NONE)
6230 : {
6231 504 : }
6232 :
6233 158488 : RTFShape::RTFShape()
6234 : : nLeft(0),
6235 : nTop(0),
6236 : nRight(0),
6237 : nBottom(0),
6238 : nHoriOrientRelation(0),
6239 : nVertOrientRelation(0),
6240 : nHoriOrientRelationToken(0),
6241 : nVertOrientRelationToken(0),
6242 : nWrap(-1),
6243 158488 : bInBackground(false)
6244 : {
6245 158488 : }
6246 :
6247 504 : RTFDrawingObject::RTFDrawingObject()
6248 : : nLineColorR(0),
6249 : nLineColorG(0),
6250 : nLineColorB(0),
6251 : bHasLineColor(false),
6252 : nFillColorR(0),
6253 : nFillColorG(0),
6254 : nFillColorB(0),
6255 : bHasFillColor(false),
6256 : nDhgt(0),
6257 : nFLine(-1),
6258 : nPolyLineCount(0),
6259 504 : bHadShapeText(false)
6260 : {
6261 504 : }
6262 :
6263 1778 : RTFFrame::RTFFrame(RTFParserState* pParserState)
6264 : : m_pParserState(pParserState),
6265 : nX(0),
6266 : nY(0),
6267 : nW(0),
6268 : nH(0),
6269 : nHoriPadding(0),
6270 : nVertPadding(0),
6271 : nHoriAlign(0),
6272 : nHoriAnchor(0),
6273 : nVertAlign(0),
6274 : nVertAnchor(0),
6275 : nHRule(NS_ooxml::LN_Value_doc_ST_HeightRule_auto),
6276 1778 : nAnchorType(0)
6277 : {
6278 1778 : }
6279 :
6280 179 : void RTFFrame::setSprm(Id nId, Id nValue)
6281 : {
6282 179 : if (m_pParserState->m_pDocumentImpl->getFirstRun())
6283 : {
6284 12 : m_pParserState->m_pDocumentImpl->checkFirstRun();
6285 12 : m_pParserState->m_pDocumentImpl->setNeedPar(false);
6286 : }
6287 179 : switch (nId)
6288 : {
6289 : case NS_ooxml::LN_CT_FramePr_w:
6290 19 : nW = nValue;
6291 19 : break;
6292 : case NS_ooxml::LN_CT_FramePr_h:
6293 19 : nH = nValue;
6294 19 : break;
6295 : case NS_ooxml::LN_CT_FramePr_x:
6296 19 : nX = nValue;
6297 19 : break;
6298 : case NS_ooxml::LN_CT_FramePr_y:
6299 19 : nY = nValue;
6300 19 : break;
6301 : case NS_ooxml::LN_CT_FramePr_hSpace:
6302 10 : nHoriPadding = nValue;
6303 10 : break;
6304 : case NS_ooxml::LN_CT_FramePr_vSpace:
6305 10 : nVertPadding = nValue;
6306 10 : break;
6307 : case NS_ooxml::LN_CT_FramePr_xAlign:
6308 21 : nHoriAlign = nValue;
6309 21 : break;
6310 : case NS_ooxml::LN_CT_FramePr_hAnchor:
6311 19 : nHoriAnchor = nValue;
6312 19 : break;
6313 : case NS_ooxml::LN_CT_FramePr_yAlign:
6314 21 : nVertAlign = nValue;
6315 21 : break;
6316 : case NS_ooxml::LN_CT_FramePr_vAnchor:
6317 20 : nVertAnchor = nValue;
6318 20 : break;
6319 : case NS_ooxml::LN_CT_FramePr_wrap:
6320 2 : oWrap = nValue;
6321 2 : break;
6322 : default:
6323 0 : break;
6324 : }
6325 179 : }
6326 :
6327 30 : RTFSprms RTFFrame::getSprms()
6328 : {
6329 30 : RTFSprms sprms;
6330 :
6331 : static const Id pNames[] =
6332 : {
6333 : NS_ooxml::LN_CT_FramePr_x,
6334 : NS_ooxml::LN_CT_FramePr_y,
6335 : NS_ooxml::LN_CT_FramePr_hRule, // Make sure nHRule is processed before nH
6336 : NS_ooxml::LN_CT_FramePr_h,
6337 : NS_ooxml::LN_CT_FramePr_w,
6338 : NS_ooxml::LN_CT_FramePr_hSpace,
6339 : NS_ooxml::LN_CT_FramePr_vSpace,
6340 : NS_ooxml::LN_CT_FramePr_hAnchor,
6341 : NS_ooxml::LN_CT_FramePr_vAnchor,
6342 : NS_ooxml::LN_CT_FramePr_xAlign,
6343 : NS_ooxml::LN_CT_FramePr_yAlign,
6344 : NS_ooxml::LN_CT_FramePr_wrap,
6345 : NS_ooxml::LN_CT_FramePr_dropCap,
6346 : NS_ooxml::LN_CT_FramePr_lines
6347 : };
6348 :
6349 450 : for (int i = 0, len = SAL_N_ELEMENTS(pNames); i < len; ++i)
6350 : {
6351 420 : Id nId = pNames[i];
6352 420 : RTFValue::Pointer_t pValue;
6353 :
6354 420 : switch (nId)
6355 : {
6356 : case NS_ooxml::LN_CT_FramePr_x:
6357 30 : if (nX != 0)
6358 29 : pValue = std::make_shared<RTFValue>(nX);
6359 30 : break;
6360 : case NS_ooxml::LN_CT_FramePr_y:
6361 30 : if (nY != 0)
6362 29 : pValue = std::make_shared<RTFValue>(nY);
6363 30 : break;
6364 : case NS_ooxml::LN_CT_FramePr_h:
6365 30 : if (nH != 0)
6366 : {
6367 25 : if (nHRule == NS_ooxml::LN_Value_doc_ST_HeightRule_exact)
6368 24 : pValue = std::make_shared<RTFValue>(-nH); // The negative value just sets nHRule
6369 : else
6370 1 : pValue = std::make_shared<RTFValue>(nH);
6371 : }
6372 30 : break;
6373 : case NS_ooxml::LN_CT_FramePr_w:
6374 30 : if (nW != 0)
6375 29 : pValue = std::make_shared<RTFValue>(nW);
6376 30 : break;
6377 : case NS_ooxml::LN_CT_FramePr_hSpace:
6378 30 : if (nHoriPadding != 0)
6379 2 : pValue = std::make_shared<RTFValue>(nHoriPadding);
6380 30 : break;
6381 : case NS_ooxml::LN_CT_FramePr_vSpace:
6382 30 : if (nVertPadding != 0)
6383 2 : pValue = std::make_shared<RTFValue>(nVertPadding);
6384 30 : break;
6385 : case NS_ooxml::LN_CT_FramePr_hAnchor:
6386 : {
6387 30 : if (nHoriAnchor == 0)
6388 3 : nHoriAnchor = NS_ooxml::LN_Value_doc_ST_HAnchor_margin;
6389 30 : pValue = std::make_shared<RTFValue>(nHoriAnchor);
6390 : }
6391 30 : break;
6392 : case NS_ooxml::LN_CT_FramePr_vAnchor:
6393 : {
6394 30 : if (nVertAnchor == 0)
6395 2 : nVertAnchor = NS_ooxml::LN_Value_doc_ST_VAnchor_margin;
6396 30 : pValue = std::make_shared<RTFValue>(nVertAnchor);
6397 : }
6398 30 : break;
6399 : case NS_ooxml::LN_CT_FramePr_xAlign:
6400 30 : pValue = std::make_shared<RTFValue>(nHoriAlign);
6401 30 : break;
6402 : case NS_ooxml::LN_CT_FramePr_yAlign:
6403 30 : pValue = std::make_shared<RTFValue>(nVertAlign);
6404 30 : break;
6405 : case NS_ooxml::LN_CT_FramePr_hRule:
6406 : {
6407 30 : if (nH < 0)
6408 24 : nHRule = NS_ooxml::LN_Value_doc_ST_HeightRule_exact;
6409 6 : else if (nH > 0)
6410 1 : nHRule = NS_ooxml::LN_Value_doc_ST_HeightRule_atLeast;
6411 30 : pValue = std::make_shared<RTFValue>(nHRule);
6412 : }
6413 30 : break;
6414 : case NS_ooxml::LN_CT_FramePr_wrap:
6415 30 : if (oWrap)
6416 2 : pValue = std::make_shared<RTFValue>(*oWrap);
6417 30 : break;
6418 : default:
6419 60 : break;
6420 : }
6421 :
6422 420 : if (pValue.get())
6423 268 : sprms.set(nId, pValue);
6424 420 : }
6425 :
6426 30 : RTFSprms frameprSprms;
6427 30 : frameprSprms.set(NS_ooxml::LN_CT_PPrBase_framePr, std::make_shared<RTFValue>(sprms));
6428 30 : return frameprSprms;
6429 : }
6430 :
6431 3560 : bool RTFFrame::hasProperties()
6432 : {
6433 10564 : return nX != 0 || nY != 0 || nW != 0 || nH != 0 ||
6434 10506 : nHoriPadding != 0 || nVertPadding != 0 ||
6435 14066 : nHoriAlign != 0 || nHoriAnchor != 0 || nVertAlign != 0 || nVertAnchor != 0 ||
6436 7062 : nAnchorType != 0;
6437 : }
6438 :
6439 : } // namespace rtftok
6440 72 : } // namespace writerfilter
6441 :
6442 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|