LCOV - code coverage report
Current view: top level - writerfilter/source/rtftok - rtfdocumentimpl.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 3182 3514 90.6 %
Date: 2015-06-13 12:38:46 Functions: 89 91 97.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11