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

Generated by: LCOV version 1.10