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