[Libreoffice-commits] core.git: writerfilter/Library_writerfilter.mk writerfilter/source
Miklos Vajna
vmiklos at collabora.co.uk
Mon May 9 15:29:33 UTC 2016
writerfilter/Library_writerfilter.mk | 4
writerfilter/source/rtftok/rtfcontrolwords.hxx | 1
writerfilter/source/rtftok/rtfdispatchdestination.cxx | 623 +++
writerfilter/source/rtftok/rtfdispatchflag.cxx | 1083 +++++
writerfilter/source/rtftok/rtfdispatchsymbol.cxx | 409 ++
writerfilter/source/rtftok/rtfdispatchvalue.cxx | 1347 +++++++
writerfilter/source/rtftok/rtfdocumentimpl.cxx | 3411 ------------------
writerfilter/source/rtftok/rtfdocumentimpl.hxx | 12
writerfilter/source/rtftok/rtffly.hxx | 4
9 files changed, 3522 insertions(+), 3372 deletions(-)
New commits:
commit a3615d5517ee84ddf9a9b2c28ff6a3a37fcb70db
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Mon May 9 09:13:25 2016 +0200
writerfilter: extract dispatch{destination,flag,symbol,value} from rtfdocimpl
These were half of the lines of rtfdocumentimpl.
Change-Id: I3f24cd5d23c91bf0d53b898266c187699ae6ee56
Reviewed-on: https://gerrit.libreoffice.org/24790
Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
Tested-by: Jenkins <ci at libreoffice.org>
diff --git a/writerfilter/Library_writerfilter.mk b/writerfilter/Library_writerfilter.mk
index 27eb752..b23256e 100644
--- a/writerfilter/Library_writerfilter.mk
+++ b/writerfilter/Library_writerfilter.mk
@@ -64,6 +64,10 @@ $(eval $(call gb_Library_use_externals,writerfilter,\
$(eval $(call gb_Library_add_exception_objects,writerfilter,\
writerfilter/source/rtftok/rtfcharsets \
writerfilter/source/rtftok/rtfcontrolwords \
+ writerfilter/source/rtftok/rtfdispatchdestination \
+ writerfilter/source/rtftok/rtfdispatchflag \
+ writerfilter/source/rtftok/rtfdispatchsymbol \
+ writerfilter/source/rtftok/rtfdispatchvalue \
writerfilter/source/rtftok/rtfdocumentfactory \
writerfilter/source/rtftok/rtfdocumentimpl \
writerfilter/source/rtftok/rtflookahead \
diff --git a/writerfilter/source/rtftok/rtfcontrolwords.hxx b/writerfilter/source/rtftok/rtfcontrolwords.hxx
index 80a2d1e..2a7d596 100644
--- a/writerfilter/source/rtftok/rtfcontrolwords.hxx
+++ b/writerfilter/source/rtftok/rtfcontrolwords.hxx
@@ -1980,6 +1980,7 @@ enum RTFKeyword
RTF_FLYHORZ,
RTF_FLYANCHOR
};
+const char* keywordToString(RTFKeyword nKeyword);
/// Types of an RTF Control Word
enum RTFControlTypes
diff --git a/writerfilter/source/rtftok/rtfdispatchdestination.cxx b/writerfilter/source/rtftok/rtfdispatchdestination.cxx
new file mode 100644
index 0000000..af8a3f1
--- /dev/null
+++ b/writerfilter/source/rtftok/rtfdispatchdestination.cxx
@@ -0,0 +1,623 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <rtfdocumentimpl.hxx>
+
+#include <com/sun/star/document/DocumentProperties.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+
+#include <filter/msfilter/escherex.hxx>
+#include <tools/stream.hxx>
+
+#include <dmapper/DomainMapperFactory.hxx>
+#include <ooxml/resourceids.hxx>
+
+#include <rtflookahead.hxx>
+#include <rtfreferenceproperties.hxx>
+#include <rtfsdrimport.hxx>
+#include <rtfskipdestination.hxx>
+
+using namespace com::sun::star;
+
+namespace writerfilter
+{
+namespace rtftok
+{
+
+RTFError RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword)
+{
+ setNeedSect(true);
+ checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
+ RTFSkipDestination aSkip(*this);
+ // special case \upr: ignore everything except nested \ud
+ if (Destination::UPR == m_aStates.top().eDestination && RTF_UD != nKeyword)
+ {
+ m_aStates.top().eDestination = Destination::SKIP;
+ aSkip.setParsed(false);
+ }
+ else
+ switch (nKeyword)
+ {
+ case RTF_RTF:
+ break;
+ case RTF_FONTTBL:
+ m_aStates.top().eDestination = Destination::FONTTABLE;
+ break;
+ case RTF_COLORTBL:
+ m_aStates.top().eDestination = Destination::COLORTABLE;
+ break;
+ case RTF_STYLESHEET:
+ m_aStates.top().eDestination = Destination::STYLESHEET;
+ break;
+ case RTF_FIELD:
+ m_aStates.top().eDestination = Destination::FIELD;
+ break;
+ case RTF_FLDINST:
+ {
+ // Look for the field type
+ sal_Size nPos = Strm().Tell();
+ OStringBuffer aBuf;
+ char ch = 0;
+ bool bFoundCode = false;
+ bool bInKeyword = false;
+ while (!bFoundCode && ch != '}')
+ {
+ Strm().ReadChar(ch);
+ if ('\\' == ch)
+ bInKeyword = true;
+ if (!bInKeyword && isalnum(ch))
+ aBuf.append(ch);
+ else if (bInKeyword && isspace(ch))
+ bInKeyword = false;
+ if (!aBuf.isEmpty() && !isalnum(ch))
+ bFoundCode = true;
+ }
+
+ if (aBuf.toString() == "INCLUDEPICTURE")
+ {
+ // Extract the field argument of INCLUDEPICTURE: we handle that
+ // at a tokenizer level, as DOCX has no such field.
+ aBuf.append(ch);
+ while (true)
+ {
+ Strm().ReadChar(ch);
+ if (ch == '}')
+ break;
+ aBuf.append(ch);
+ }
+ OUString aFieldCommand = OStringToOUString(aBuf.toString(), RTL_TEXTENCODING_UTF8);
+ std::tuple<OUString, std::vector<OUString>, std::vector<OUString> > aResult = writerfilter::dmapper::splitFieldCommand(aFieldCommand);
+ m_aPicturePath = std::get<1>(aResult).empty() ? OUString() : std::get<1>(aResult).front();
+ }
+
+ Strm().Seek(nPos);
+
+ // Form data should be handled only for form fields if any
+ if (aBuf.toString().indexOf(OString("FORM")) != -1)
+ m_bFormField = true;
+
+ singleChar(cFieldStart);
+ m_aStates.top().eDestination = Destination::FIELDINSTRUCTION;
+ }
+ break;
+ case RTF_FLDRSLT:
+ m_aStates.top().eDestination = Destination::FIELDRESULT;
+ break;
+ case RTF_LISTTABLE:
+ m_aStates.top().eDestination = Destination::LISTTABLE;
+ break;
+ case RTF_LISTPICTURE:
+ m_aStates.top().eDestination = Destination::LISTPICTURE;
+ m_aStates.top().bInListpicture = true;
+ break;
+ case RTF_LIST:
+ m_aStates.top().eDestination = Destination::LISTENTRY;
+ break;
+ case RTF_LISTNAME:
+ m_aStates.top().eDestination = Destination::LISTNAME;
+ break;
+ case RTF_LFOLEVEL:
+ m_aStates.top().eDestination = Destination::LFOLEVEL;
+ m_aStates.top().aTableSprms.clear();
+ break;
+ case RTF_LISTOVERRIDETABLE:
+ m_aStates.top().eDestination = Destination::LISTOVERRIDETABLE;
+ break;
+ case RTF_LISTOVERRIDE:
+ m_aStates.top().eDestination = Destination::LISTOVERRIDEENTRY;
+ break;
+ case RTF_LISTLEVEL:
+ m_aStates.top().eDestination = Destination::LISTLEVEL;
+ break;
+ case RTF_LEVELTEXT:
+ m_aStates.top().eDestination = Destination::LEVELTEXT;
+ break;
+ case RTF_LEVELNUMBERS:
+ m_aStates.top().eDestination = Destination::LEVELNUMBERS;
+ break;
+ case RTF_SHPPICT:
+ resetFrame();
+ m_aStates.top().eDestination = Destination::SHPPICT;
+ break;
+ case RTF_PICT:
+ if (m_aStates.top().eDestination != Destination::SHAPEPROPERTYVALUE)
+ m_aStates.top().eDestination = Destination::PICT; // as character
+ else
+ m_aStates.top().eDestination = Destination::SHAPEPROPERTYVALUEPICT; // anchored inside a shape
+ break;
+ case RTF_PICPROP:
+ m_aStates.top().eDestination = Destination::PICPROP;
+ break;
+ case RTF_SP:
+ m_aStates.top().eDestination = Destination::SHAPEPROPERTY;
+ break;
+ case RTF_SN:
+ m_aStates.top().eDestination = Destination::SHAPEPROPERTYNAME;
+ break;
+ case RTF_SV:
+ m_aStates.top().eDestination = Destination::SHAPEPROPERTYVALUE;
+ break;
+ case RTF_SHP:
+ m_bNeedCrOrig = m_bNeedCr;
+ m_aStates.top().eDestination = Destination::SHAPE;
+ m_aStates.top().bInShape = true;
+ break;
+ case RTF_SHPINST:
+ m_aStates.top().eDestination = Destination::SHAPEINSTRUCTION;
+ break;
+ case RTF_NESTTABLEPROPS:
+ // do not set any properties of outer table at nested table!
+ m_aStates.top().aTableCellSprms = m_aDefaultState.aTableCellSprms;
+ m_aStates.top().aTableCellAttributes =
+ m_aDefaultState.aTableCellAttributes;
+ m_aNestedTableCellsSprms.clear();
+ m_aNestedTableCellsAttributes.clear();
+ m_nNestedCells = 0;
+ m_aStates.top().eDestination = Destination::NESTEDTABLEPROPERTIES;
+ break;
+ case RTF_HEADER:
+ case RTF_FOOTER:
+ case RTF_HEADERL:
+ case RTF_HEADERR:
+ case RTF_HEADERF:
+ case RTF_FOOTERL:
+ case RTF_FOOTERR:
+ case RTF_FOOTERF:
+ if (!m_pSuperstream)
+ {
+ Id nId = 0;
+ sal_Size nPos = m_nGroupStartPos - 1;
+ switch (nKeyword)
+ {
+ case RTF_HEADER:
+ nId = NS_ooxml::LN_headerr;
+ break;
+ case RTF_FOOTER:
+ nId = NS_ooxml::LN_footerr;
+ break;
+ case RTF_HEADERL:
+ nId = NS_ooxml::LN_headerl;
+ break;
+ case RTF_HEADERR:
+ nId = NS_ooxml::LN_headerr;
+ break;
+ case RTF_HEADERF:
+ nId = NS_ooxml::LN_headerf;
+ break;
+ case RTF_FOOTERL:
+ nId = NS_ooxml::LN_footerl;
+ break;
+ case RTF_FOOTERR:
+ nId = NS_ooxml::LN_footerr;
+ break;
+ case RTF_FOOTERF:
+ nId = NS_ooxml::LN_footerf;
+ break;
+ default:
+ break;
+ }
+ m_nHeaderFooterPositions.push(std::make_pair(nId, nPos));
+ m_aStates.top().eDestination = Destination::SKIP;
+ }
+ break;
+ case RTF_FOOTNOTE:
+ checkFirstRun();
+ if (!m_pSuperstream)
+ {
+ Id nId = NS_ooxml::LN_footnote;
+
+ // Check if this is an endnote.
+ OStringBuffer aBuf;
+ char ch;
+ sal_Size nCurrent = Strm().Tell();
+ for (int i = 0; i < 7; ++i)
+ {
+ Strm().ReadChar(ch);
+ aBuf.append(ch);
+ }
+ Strm().Seek(nCurrent);
+ OString aKeyword = aBuf.makeStringAndClear();
+ if (aKeyword.equals("\\ftnalt"))
+ nId = NS_ooxml::LN_endnote;
+
+ if (m_aStates.top().pCurrentBuffer == &m_aSuperBuffer)
+ m_aStates.top().pCurrentBuffer = nullptr;
+ bool bCustomMark = false;
+ OUString aCustomMark;
+ while (m_aSuperBuffer.size())
+ {
+ Buf_t aTuple = m_aSuperBuffer.front();
+ m_aSuperBuffer.pop_front();
+ if (std::get<0>(aTuple) == BUFFER_UTEXT)
+ {
+ aCustomMark = std::get<1>(aTuple)->getString();
+ bCustomMark = true;
+ }
+ }
+ m_aStates.top().eDestination = Destination::FOOTNOTE;
+ if (bCustomMark)
+ Mapper().startCharacterGroup();
+ if (!m_aStates.top().pCurrentBuffer)
+ resolveSubstream(m_nGroupStartPos - 1, nId, aCustomMark);
+ else
+ {
+ RTFSprms aAttributes;
+ aAttributes.set(Id(0), std::make_shared<RTFValue>(m_nGroupStartPos - 1));
+ aAttributes.set(Id(1), std::make_shared<RTFValue>(nId));
+ aAttributes.set(Id(2), std::make_shared<RTFValue>(aCustomMark));
+ m_aStates.top().pCurrentBuffer->push_back(Buf_t(BUFFER_RESOLVESUBSTREAM, std::make_shared<RTFValue>(aAttributes), nullptr));
+ }
+ if (bCustomMark)
+ {
+ m_aStates.top().aCharacterAttributes.clear();
+ m_aStates.top().aCharacterSprms.clear();
+ auto pValue = std::make_shared<RTFValue>(1);
+ m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_FtnEdnRef_customMarkFollows, pValue);
+ text(aCustomMark);
+ Mapper().endCharacterGroup();
+ }
+ m_aStates.top().eDestination = Destination::SKIP;
+ }
+ break;
+ case RTF_BKMKSTART:
+ m_aStates.top().eDestination = Destination::BOOKMARKSTART;
+ break;
+ case RTF_BKMKEND:
+ m_aStates.top().eDestination = Destination::BOOKMARKEND;
+ break;
+ case RTF_XE:
+ m_aStates.top().eDestination = Destination::INDEXENTRY;
+ break;
+ case RTF_TC:
+ case RTF_TCN:
+ m_aStates.top().eDestination = Destination::TOCENTRY;
+ break;
+ case RTF_REVTBL:
+ m_aStates.top().eDestination = Destination::REVISIONTABLE;
+ break;
+ case RTF_ANNOTATION:
+ if (!m_pSuperstream)
+ {
+ resolveSubstream(m_nGroupStartPos - 1, NS_ooxml::LN_annotation);
+ m_aStates.top().eDestination = Destination::SKIP;
+ }
+ else
+ {
+ // If there is an author set, emit it now.
+ if (!m_aAuthor.isEmpty() || !m_aAuthorInitials.isEmpty())
+ {
+ RTFSprms aAttributes;
+ if (!m_aAuthor.isEmpty())
+ {
+ auto pValue = std::make_shared<RTFValue>(m_aAuthor);
+ aAttributes.set(NS_ooxml::LN_CT_TrackChange_author, pValue);
+ }
+ if (!m_aAuthorInitials.isEmpty())
+ {
+ auto pValue = std::make_shared<RTFValue>(m_aAuthorInitials);
+ aAttributes.set(NS_ooxml::LN_CT_Comment_initials, pValue);
+ }
+ writerfilter::Reference<Properties>::Pointer_t pProperties = std::make_shared<RTFReferenceProperties>(aAttributes);
+ Mapper().props(pProperties);
+ }
+ }
+ break;
+ case RTF_SHPTXT:
+ case RTF_DPTXBXTEXT:
+ {
+ bool bPictureFrame = false;
+ for (std::size_t i = 0; i < m_aStates.top().aShape.aProperties.size(); ++i)
+ {
+ std::pair<OUString, OUString>& rProperty = m_aStates.top().aShape.aProperties[i];
+ if (rProperty.first == "shapeType" && rProperty.second == OUString::number(ESCHER_ShpInst_PictureFrame))
+ {
+ bPictureFrame = true;
+ break;
+ }
+ }
+ if (bPictureFrame)
+ // Skip text on picture frames.
+ m_aStates.top().eDestination = Destination::SKIP;
+ else
+ {
+ m_aStates.top().eDestination = Destination::SHAPETEXT;
+ checkFirstRun();
+ dispatchFlag(RTF_PARD);
+ m_bNeedPap = true;
+ if (nKeyword == RTF_SHPTXT)
+ {
+ if (!m_aStates.top().pCurrentBuffer)
+ m_pSdrImport->resolve(m_aStates.top().aShape, false, RTFSdrImport::SHAPE);
+ else
+ {
+ auto pValue = std::make_shared<RTFValue>(m_aStates.top().aShape);
+ m_aStates.top().pCurrentBuffer->push_back(Buf_t(BUFFER_STARTSHAPE, pValue, nullptr));
+ }
+ }
+ }
+ }
+ break;
+ case RTF_FORMFIELD:
+ if (m_aStates.top().eDestination == Destination::FIELDINSTRUCTION)
+ m_aStates.top().eDestination = Destination::FORMFIELD;
+ break;
+ case RTF_FFNAME:
+ m_aStates.top().eDestination = Destination::FORMFIELDNAME;
+ break;
+ case RTF_FFL:
+ m_aStates.top().eDestination = Destination::FORMFIELDLIST;
+ break;
+ case RTF_DATAFIELD:
+ m_aStates.top().eDestination = Destination::DATAFIELD;
+ break;
+ case RTF_INFO:
+ m_aStates.top().eDestination = Destination::INFO;
+ break;
+ case RTF_CREATIM:
+ m_aStates.top().eDestination = Destination::CREATIONTIME;
+ break;
+ case RTF_REVTIM:
+ m_aStates.top().eDestination = Destination::REVISIONTIME;
+ break;
+ case RTF_PRINTIM:
+ m_aStates.top().eDestination = Destination::PRINTTIME;
+ break;
+ case RTF_AUTHOR:
+ m_aStates.top().eDestination = Destination::AUTHOR;
+ break;
+ case RTF_KEYWORDS:
+ m_aStates.top().eDestination = Destination::KEYWORDS;
+ break;
+ case RTF_OPERATOR:
+ m_aStates.top().eDestination = Destination::OPERATOR;
+ break;
+ case RTF_COMPANY:
+ m_aStates.top().eDestination = Destination::COMPANY;
+ break;
+ case RTF_COMMENT:
+ m_aStates.top().eDestination = Destination::COMMENT;
+ break;
+ case RTF_OBJECT:
+ {
+ // beginning of an OLE Object
+ m_aStates.top().eDestination = Destination::OBJECT;
+
+ // check if the object is in a special container (e.g. a table)
+ if (!m_aStates.top().pCurrentBuffer)
+ {
+ // the object is in a table or another container.
+ // Don't try to treat it as an OLE object (fdo#53594).
+ // Use the \result (RTF_RESULT) element of the object instead,
+ // the result element contain picture representing the OLE Object.
+ m_bObject = true;
+ }
+ }
+ break;
+ case RTF_OBJDATA:
+ // check if the object is in a special container (e.g. a table)
+ if (m_aStates.top().pCurrentBuffer)
+ {
+ // the object is in a table or another container.
+ // Use the \result (RTF_RESULT) element of the object instead,
+ // of the \objdata.
+ m_aStates.top().eDestination = Destination::SKIP;
+ }
+ else
+ {
+ m_aStates.top().eDestination = Destination::OBJDATA;
+ }
+ break;
+ case RTF_OBJCLASS:
+ m_aStates.top().eDestination = Destination::OBJCLASS;
+ break;
+ case RTF_RESULT:
+ m_aStates.top().eDestination = Destination::RESULT;
+ break;
+ case RTF_ATNDATE:
+ m_aStates.top().eDestination = Destination::ANNOTATIONDATE;
+ break;
+ case RTF_ATNAUTHOR:
+ m_aStates.top().eDestination = Destination::ANNOTATIONAUTHOR;
+ break;
+ case RTF_ATNREF:
+ m_aStates.top().eDestination = Destination::ANNOTATIONREFERENCE;
+ break;
+ case RTF_FALT:
+ m_aStates.top().eDestination = Destination::FALT;
+ break;
+ case RTF_FLYMAINCNT:
+ m_aStates.top().eDestination = Destination::FLYMAINCONTENT;
+ break;
+ case RTF_LISTTEXT:
+ // Should be ignored by any reader that understands Word 97 through Word 2007 numbering.
+ case RTF_NONESTTABLES:
+ // This destination should be ignored by readers that support nested tables.
+ m_aStates.top().eDestination = Destination::SKIP;
+ break;
+ case RTF_DO:
+ m_aStates.top().eDestination = Destination::DRAWINGOBJECT;
+ break;
+ case RTF_PN:
+ m_aStates.top().eDestination = Destination::PARAGRAPHNUMBERING;
+ break;
+ case RTF_PNTEXT:
+ // This destination should be ignored by readers that support paragraph numbering.
+ m_aStates.top().eDestination = Destination::SKIP;
+ break;
+ case RTF_PNTXTA:
+ m_aStates.top().eDestination = Destination::PARAGRAPHNUMBERING_TEXTAFTER;
+ break;
+ case RTF_PNTXTB:
+ m_aStates.top().eDestination = Destination::PARAGRAPHNUMBERING_TEXTBEFORE;
+ break;
+ case RTF_TITLE:
+ m_aStates.top().eDestination = Destination::TITLE;
+ break;
+ case RTF_SUBJECT:
+ m_aStates.top().eDestination = Destination::SUBJECT;
+ break;
+ case RTF_DOCCOMM:
+ m_aStates.top().eDestination = Destination::DOCCOMM;
+ break;
+ case RTF_ATRFSTART:
+ m_aStates.top().eDestination = Destination::ANNOTATIONREFERENCESTART;
+ break;
+ case RTF_ATRFEND:
+ m_aStates.top().eDestination = Destination::ANNOTATIONREFERENCEEND;
+ break;
+ case RTF_ATNID:
+ m_aStates.top().eDestination = Destination::ATNID;
+ break;
+ case RTF_MMATH:
+ case RTF_MOMATHPARA:
+ // Nothing to do here (just enter the destination) till RTF_MMATHPR is implemented.
+ break;
+ case RTF_MR:
+ m_aStates.top().eDestination = Destination::MR;
+ break;
+ case RTF_MCHR:
+ m_aStates.top().eDestination = Destination::MCHR;
+ break;
+ case RTF_MPOS:
+ m_aStates.top().eDestination = Destination::MPOS;
+ break;
+ case RTF_MVERTJC:
+ m_aStates.top().eDestination = Destination::MVERTJC;
+ break;
+ case RTF_MSTRIKEH:
+ m_aStates.top().eDestination = Destination::MSTRIKEH;
+ break;
+ case RTF_MDEGHIDE:
+ m_aStates.top().eDestination = Destination::MDEGHIDE;
+ break;
+ case RTF_MTYPE:
+ m_aStates.top().eDestination = Destination::MTYPE;
+ break;
+ case RTF_MGROW:
+ m_aStates.top().eDestination = Destination::MGROW;
+ break;
+ case RTF_MHIDETOP:
+ case RTF_MHIDEBOT:
+ case RTF_MHIDELEFT:
+ case RTF_MHIDERIGHT:
+ // SmOoxmlImport::handleBorderBox will ignore these anyway, so silently ignore for now.
+ m_aStates.top().eDestination = Destination::SKIP;
+ break;
+ case RTF_MSUBHIDE:
+ m_aStates.top().eDestination = Destination::MSUBHIDE;
+ break;
+ case RTF_MSUPHIDE:
+ m_aStates.top().eDestination = Destination::MSUPHIDE;
+ break;
+ case RTF_MBEGCHR:
+ m_aStates.top().eDestination = Destination::MBEGCHR;
+ break;
+ case RTF_MSEPCHR:
+ m_aStates.top().eDestination = Destination::MSEPCHR;
+ break;
+ case RTF_MENDCHR:
+ m_aStates.top().eDestination = Destination::MENDCHR;
+ break;
+ case RTF_UPR:
+ m_aStates.top().eDestination = Destination::UPR;
+ break;
+ case RTF_UD:
+ // Anything inside \ud is just normal Unicode content.
+ m_aStates.top().eDestination = Destination::NORMAL;
+ break;
+ case RTF_BACKGROUND:
+ m_aStates.top().eDestination = Destination::BACKGROUND;
+ m_aStates.top().bInBackground = true;
+ break;
+ case RTF_SHPGRP:
+ {
+ RTFLookahead aLookahead(Strm(), m_pTokenizer->getGroupStart());
+ if (!aLookahead.hasTable())
+ {
+ uno::Reference<drawing::XShapes> xGroupShape(m_xModelFactory->createInstance("com.sun.star.drawing.GroupShape"), uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPageSupplier> xDrawSupplier(m_xDstDoc, uno::UNO_QUERY);
+ if (xDrawSupplier.is())
+ {
+ uno::Reference<drawing::XShape> xShape(xGroupShape, uno::UNO_QUERY);
+ xDrawSupplier->getDrawPage()->add(xShape);
+ }
+ m_pSdrImport->pushParent(xGroupShape);
+ m_aStates.top().bCreatedShapeGroup = true;
+ }
+ m_aStates.top().eDestination = Destination::SHAPEGROUP;
+ m_aStates.top().bInShapeGroup = true;
+ }
+ break;
+ case RTF_FTNSEP:
+ m_aStates.top().eDestination = Destination::FOOTNOTESEPARATOR;
+ m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_FtnEdn_type, std::make_shared<RTFValue>(NS_ooxml::LN_Value_doc_ST_FtnEdn_separator));
+ break;
+ case RTF_USERPROPS:
+ // Container of all user-defined properties.
+ m_aStates.top().eDestination = Destination::USERPROPS;
+ if (m_xDocumentProperties.is())
+ // Create a custom document properties to be able to process them later all at once.
+ m_xDocumentProperties = document::DocumentProperties::create(m_xContext);
+ break;
+ case RTF_PROPNAME:
+ m_aStates.top().eDestination = Destination::PROPNAME;
+ break;
+ case RTF_STATICVAL:
+ m_aStates.top().eDestination = Destination::STATICVAL;
+ break;
+ default:
+ {
+ // Check if it's a math token.
+ RTFMathSymbol aSymbol;
+ aSymbol.eKeyword = nKeyword;
+ if (RTFTokenizer::lookupMathKeyword(aSymbol))
+ {
+ m_aMathBuffer.appendOpeningTag(aSymbol.nToken);
+ m_aStates.top().eDestination = aSymbol.eDestination;
+ return RTFError::OK;
+ }
+
+ SAL_INFO("writerfilter", "TODO handle destination '" << keywordToString(nKeyword) << "'");
+ // Make sure we skip destinations (even without \*) till we don't handle them
+ m_aStates.top().eDestination = Destination::SKIP;
+ aSkip.setParsed(false);
+ }
+ break;
+ }
+
+ // new destination => use new destination text
+ m_aStates.top().pDestinationText = &m_aStates.top().aDestinationText;
+
+ return RTFError::OK;
+}
+
+} // namespace rtftok
+} // namespace writerfilter
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/rtftok/rtfdispatchflag.cxx b/writerfilter/source/rtftok/rtfdispatchflag.cxx
new file mode 100644
index 0000000..d3bc517
--- /dev/null
+++ b/writerfilter/source/rtftok/rtfdispatchflag.cxx
@@ -0,0 +1,1083 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <rtfdocumentimpl.hxx>
+
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
+#include <com/sun/star/text/RelOrientation.hpp>
+
+#include <filter/msfilter/escherex.hxx>
+
+#include <ooxml/resourceids.hxx>
+
+#include <rtfsdrimport.hxx>
+#include <rtfskipdestination.hxx>
+
+using namespace com::sun::star;
+
+namespace writerfilter
+{
+namespace rtftok
+{
+
+RTFError RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
+{
+ setNeedSect(true);
+ checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
+ RTFSkipDestination aSkip(*this);
+ int nParam = -1;
+ int nSprm = -1;
+
+ // Underline flags.
+ switch (nKeyword)
+ {
+ case RTF_ULD:
+ nSprm = NS_ooxml::LN_Value_ST_Underline_dotted;
+ break;
+ case RTF_ULW:
+ nSprm = NS_ooxml::LN_Value_ST_Underline_words;
+ break;
+ default:
+ break;
+ }
+ if (nSprm >= 0)
+ {
+ auto pValue = std::make_shared<RTFValue>(nSprm);
+ m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_Underline_val, pValue);
+ return RTFError::OK;
+ }
+
+ // Indentation
+ switch (nKeyword)
+ {
+ case RTF_QC:
+ nParam = NS_ooxml::LN_Value_ST_Jc_center;
+ break;
+ case RTF_QJ:
+ nParam = NS_ooxml::LN_Value_ST_Jc_both;
+ break;
+ case RTF_QL:
+ nParam = NS_ooxml::LN_Value_ST_Jc_left;
+ break;
+ case RTF_QR:
+ nParam = NS_ooxml::LN_Value_ST_Jc_right;
+ break;
+ case RTF_QD:
+ nParam = NS_ooxml::LN_Value_ST_Jc_both;
+ break;
+ default:
+ break;
+ }
+ if (nParam >= 0)
+ {
+ auto pValue = std::make_shared<RTFValue>(nParam);
+ m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_jc, pValue);
+ m_bNeedPap = true;
+ return RTFError::OK;
+ }
+
+ // Font Alignment
+ switch (nKeyword)
+ {
+ case RTF_FAFIXED:
+ case RTF_FAAUTO:
+ nParam = NS_ooxml::LN_Value_doc_ST_TextAlignment_auto;
+ break;
+ case RTF_FAHANG:
+ nParam = NS_ooxml::LN_Value_doc_ST_TextAlignment_top;
+ break;
+ case RTF_FACENTER:
+ nParam = NS_ooxml::LN_Value_doc_ST_TextAlignment_center;
+ break;
+ case RTF_FAROMAN:
+ nParam = NS_ooxml::LN_Value_doc_ST_TextAlignment_baseline;
+ break;
+ case RTF_FAVAR:
+ nParam = NS_ooxml::LN_Value_doc_ST_TextAlignment_bottom;
+ break;
+ default:
+ break;
+ }
+ if (nParam >= 0)
+ {
+ auto pValue = std::make_shared<RTFValue>(nParam);
+ m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_textAlignment, pValue);
+ return RTFError::OK;
+ }
+
+ // Tab kind.
+ switch (nKeyword)
+ {
+ case RTF_TQR:
+ nParam = NS_ooxml::LN_Value_ST_TabJc_right;
+ break;
+ case RTF_TQC:
+ nParam = NS_ooxml::LN_Value_ST_TabJc_center;
+ break;
+ case RTF_TQDEC:
+ nParam = NS_ooxml::LN_Value_ST_TabJc_decimal;
+ break;
+ default:
+ break;
+ }
+ if (nParam >= 0)
+ {
+ auto pValue = std::make_shared<RTFValue>(nParam);
+ m_aStates.top().aTabAttributes.set(NS_ooxml::LN_CT_TabStop_val, pValue);
+ return RTFError::OK;
+ }
+
+ // Tab lead.
+ switch (nKeyword)
+ {
+ case RTF_TLDOT:
+ nParam = NS_ooxml::LN_Value_ST_TabTlc_dot;
+ break;
+ case RTF_TLMDOT:
+ nParam = NS_ooxml::LN_Value_ST_TabTlc_middleDot;
+ break;
+ case RTF_TLHYPH:
+ nParam = NS_ooxml::LN_Value_ST_TabTlc_hyphen;
+ break;
+ case RTF_TLUL:
+ nParam = NS_ooxml::LN_Value_ST_TabTlc_underscore;
+ break;
+ case RTF_TLTH:
+ nParam = NS_ooxml::LN_Value_ST_TabTlc_hyphen;
+ break; // thick line is not supported by dmapper, this is just a hack
+ case RTF_TLEQ:
+ nParam = NS_ooxml::LN_Value_ST_TabTlc_none;
+ break; // equal sign isn't, either
+ default:
+ break;
+ }
+ if (nParam >= 0)
+ {
+ auto pValue = std::make_shared<RTFValue>(nParam);
+ m_aStates.top().aTabAttributes.set(NS_ooxml::LN_CT_TabStop_leader, pValue);
+ return RTFError::OK;
+ }
+
+ // Border types
+ {
+ switch (nKeyword)
+ {
+ // brdrhair and brdrs are the same, brdrw will make a difference
+ // map to values in ooxml/model.xml resource ST_Border
+ case RTF_BRDRHAIR:
+ case RTF_BRDRS:
+ nParam = NS_ooxml::LN_Value_ST_Border_single;
+ break;
+ case RTF_BRDRDOT:
+ nParam = NS_ooxml::LN_Value_ST_Border_dotted;
+ break;
+ case RTF_BRDRDASH:
+ nParam = NS_ooxml::LN_Value_ST_Border_dashed;
+ break;
+ case RTF_BRDRDB:
+ nParam = NS_ooxml::LN_Value_ST_Border_double;
+ break;
+ case RTF_BRDRTNTHSG:
+ nParam = NS_ooxml::LN_Value_ST_Border_thinThickSmallGap;
+ break;
+ case RTF_BRDRTNTHMG:
+ nParam = NS_ooxml::LN_Value_ST_Border_thinThickMediumGap;
+ break;
+ case RTF_BRDRTNTHLG:
+ nParam = NS_ooxml::LN_Value_ST_Border_thinThickLargeGap;
+ break;
+ case RTF_BRDRTHTNSG:
+ nParam = NS_ooxml::LN_Value_ST_Border_thickThinSmallGap;
+ break;
+ case RTF_BRDRTHTNMG:
+ nParam = NS_ooxml::LN_Value_ST_Border_thickThinMediumGap;
+ break;
+ case RTF_BRDRTHTNLG:
+ nParam = NS_ooxml::LN_Value_ST_Border_thickThinLargeGap;
+ break;
+ case RTF_BRDREMBOSS:
+ nParam = NS_ooxml::LN_Value_ST_Border_threeDEmboss;
+ break;
+ case RTF_BRDRENGRAVE:
+ nParam = NS_ooxml::LN_Value_ST_Border_threeDEngrave;
+ break;
+ case RTF_BRDROUTSET:
+ nParam = NS_ooxml::LN_Value_ST_Border_outset;
+ break;
+ case RTF_BRDRINSET:
+ nParam = NS_ooxml::LN_Value_ST_Border_inset;
+ break;
+ case RTF_BRDRNONE:
+ nParam = NS_ooxml::LN_Value_ST_Border_none;
+ break;
+ default:
+ break;
+ }
+ if (nParam >= 0)
+ {
+ auto pValue = std::make_shared<RTFValue>(nParam);
+ putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_val, pValue);
+ return RTFError::OK;
+ }
+ }
+
+ // Section breaks
+ switch (nKeyword)
+ {
+ case RTF_SBKNONE:
+ nParam = NS_ooxml::LN_Value_ST_SectionMark_continuous;
+ break;
+ case RTF_SBKCOL:
+ nParam = NS_ooxml::LN_Value_ST_SectionMark_nextColumn;
+ break;
+ case RTF_SBKPAGE:
+ nParam = NS_ooxml::LN_Value_ST_SectionMark_nextPage;
+ break;
+ case RTF_SBKEVEN:
+ nParam = NS_ooxml::LN_Value_ST_SectionMark_evenPage;
+ break;
+ case RTF_SBKODD:
+ nParam = NS_ooxml::LN_Value_ST_SectionMark_oddPage;
+ break;
+ default:
+ break;
+ }
+ if (nParam >= 0)
+ {
+ if (m_nResetBreakOnSectBreak != RTF_invalid)
+ {
+ m_nResetBreakOnSectBreak = nKeyword;
+ }
+ auto pValue = std::make_shared<RTFValue>(nParam);
+ m_aStates.top().aSectionSprms.set(NS_ooxml::LN_EG_SectPrContents_type, pValue);
+ return RTFError::OK;
+ }
+
+ // Footnote numbering
+ switch (nKeyword)
+ {
+ case RTF_FTNNAR:
+ nParam = NS_ooxml::LN_Value_ST_NumberFormat_decimal;
+ break;
+ case RTF_FTNNALC:
+ nParam = NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter;
+ break;
+ case RTF_FTNNAUC:
+ nParam = NS_ooxml::LN_Value_ST_NumberFormat_upperLetter;
+ break;
+ case RTF_FTNNRLC:
+ nParam = NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman;
+ break;
+ case RTF_FTNNRUC:
+ nParam = NS_ooxml::LN_Value_ST_NumberFormat_upperRoman;
+ break;
+ case RTF_FTNNCHI:
+ nParam = NS_ooxml::LN_Value_ST_NumberFormat_chicago;
+ break;
+ default:
+ break;
+ }
+ if (nParam >= 0)
+ {
+ auto pValue = std::make_shared<RTFValue>(nParam);
+ putNestedSprm(m_aDefaultState.aParagraphSprms, NS_ooxml::LN_EG_SectPrContents_footnotePr, NS_ooxml::LN_CT_FtnProps_numFmt, pValue);
+ return RTFError::OK;
+ }
+
+ // Footnote restart type
+ switch (nKeyword)
+ {
+ case RTF_FTNRSTPG:
+ nParam = NS_ooxml::LN_Value_ST_RestartNumber_eachPage;
+ break;
+ case RTF_FTNRESTART:
+ nParam = NS_ooxml::LN_Value_ST_RestartNumber_eachSect;
+ break;
+ case RTF_FTNRSTCONT:
+ nParam = NS_ooxml::LN_Value_ST_RestartNumber_continuous;
+ break;
+ default:
+ break;
+ }
+ if (nParam >= 0)
+ {
+ auto pValue = std::make_shared<RTFValue>(nParam);
+ putNestedSprm(m_aDefaultState.aParagraphSprms, NS_ooxml::LN_EG_SectPrContents_footnotePr, NS_ooxml::LN_EG_FtnEdnNumProps_numRestart, pValue);
+ return RTFError::OK;
+ }
+
+ // Endnote numbering
+ switch (nKeyword)
+ {
+ case RTF_AFTNNAR:
+ nParam = NS_ooxml::LN_Value_ST_NumberFormat_decimal;
+ break;
+ case RTF_AFTNNALC:
+ nParam = NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter;
+ break;
+ case RTF_AFTNNAUC:
+ nParam = NS_ooxml::LN_Value_ST_NumberFormat_upperLetter;
+ break;
+ case RTF_AFTNNRLC:
+ nParam = NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman;
+ break;
+ case RTF_AFTNNRUC:
+ nParam = NS_ooxml::LN_Value_ST_NumberFormat_upperRoman;
+ break;
+ case RTF_AFTNNCHI:
+ nParam = NS_ooxml::LN_Value_ST_NumberFormat_chicago;
+ break;
+ default:
+ break;
+ }
+ if (nParam >= 0)
+ {
+ auto pValue = std::make_shared<RTFValue>(nParam);
+ putNestedSprm(m_aDefaultState.aParagraphSprms, NS_ooxml::LN_EG_SectPrContents_endnotePr, NS_ooxml::LN_CT_EdnProps_numFmt, pValue);
+ return RTFError::OK;
+ }
+
+ switch (nKeyword)
+ {
+ case RTF_TRQL:
+ nParam = NS_ooxml::LN_Value_ST_Jc_left;
+ break;
+ case RTF_TRQC:
+ nParam = NS_ooxml::LN_Value_ST_Jc_center;
+ break;
+ case RTF_TRQR:
+ nParam = NS_ooxml::LN_Value_ST_Jc_right;
+ break;
+ default:
+ break;
+ }
+ if (nParam >= 0)
+ {
+ auto pValue = std::make_shared<RTFValue>(nParam);
+ m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TrPrBase_jc, pValue);
+ return RTFError::OK;
+ }
+
+ // Cell Text Flow
+ switch (nKeyword)
+ {
+ case RTF_CLTXLRTB:
+ nParam = NS_ooxml::LN_Value_ST_TextDirection_lrTb;
+ break;
+ case RTF_CLTXTBRL:
+ nParam = NS_ooxml::LN_Value_ST_TextDirection_tbRl;
+ break;
+ case RTF_CLTXBTLR:
+ nParam = NS_ooxml::LN_Value_ST_TextDirection_btLr;
+ break;
+ case RTF_CLTXLRTBV:
+ nParam = NS_ooxml::LN_Value_ST_TextDirection_lrTbV;
+ break;
+ case RTF_CLTXTBRLV:
+ nParam = NS_ooxml::LN_Value_ST_TextDirection_tbRlV;
+ break;
+ default:
+ break;
+ }
+ if (nParam >= 0)
+ {
+ auto pValue = std::make_shared<RTFValue>(nParam);
+ m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_textDirection, pValue);
+ }
+
+ // Trivial paragraph flags
+ switch (nKeyword)
+ {
+ case RTF_KEEP:
+ if (m_aStates.top().pCurrentBuffer != &m_aTableBufferStack.back())
+ nParam = NS_ooxml::LN_CT_PPrBase_keepLines;
+ break;
+ case RTF_KEEPN:
+ if (m_aStates.top().pCurrentBuffer != &m_aTableBufferStack.back())
+ nParam = NS_ooxml::LN_CT_PPrBase_keepNext;
+ break;
+ case RTF_INTBL:
+ {
+ m_aStates.top().pCurrentBuffer = &m_aTableBufferStack.back();
+ nParam = NS_ooxml::LN_inTbl;
+ }
+ break;
+ case RTF_PAGEBB:
+ nParam = NS_ooxml::LN_CT_PPrBase_pageBreakBefore;
+ break;
+ default:
+ break;
+ }
+ if (nParam >= 0)
+ {
+ auto pValue = std::make_shared<RTFValue>(1);
+ m_aStates.top().aParagraphSprms.erase(NS_ooxml::LN_inTbl);
+ m_aStates.top().aParagraphSprms.set(nParam, pValue);
+ return RTFError::OK;
+ }
+
+ switch (nKeyword)
+ {
+ case RTF_FNIL:
+ case RTF_FROMAN:
+ case RTF_FSWISS:
+ case RTF_FMODERN:
+ case RTF_FSCRIPT:
+ case RTF_FDECOR:
+ case RTF_FTECH:
+ case RTF_FBIDI:
+ // TODO ooxml:CT_Font_family seems to be ignored by the domain mapper
+ break;
+ case RTF_ANSI:
+ m_aStates.top().nCurrentEncoding = RTL_TEXTENCODING_MS_1252;
+ break;
+ case RTF_MAC:
+ m_aDefaultState.nCurrentEncoding = RTL_TEXTENCODING_APPLE_ROMAN;
+ m_aStates.top().nCurrentEncoding = m_aDefaultState.nCurrentEncoding;
+ break;
+ case RTF_PC:
+ m_aDefaultState.nCurrentEncoding = RTL_TEXTENCODING_IBM_437;
+ m_aStates.top().nCurrentEncoding = m_aDefaultState.nCurrentEncoding;
+ break;
+ case RTF_PCA:
+ m_aDefaultState.nCurrentEncoding = RTL_TEXTENCODING_IBM_850;
+ m_aStates.top().nCurrentEncoding = m_aDefaultState.nCurrentEncoding;
+ break;
+ case RTF_PLAIN:
+ {
+ m_aStates.top().aCharacterSprms = getDefaultState().aCharacterSprms;
+ m_aStates.top().nCurrentEncoding = getEncoding(getFontIndex(m_nDefaultFontIndex));
+ m_aStates.top().aCharacterAttributes = getDefaultState().aCharacterAttributes;
+ m_aStates.top().nCurrentCharacterStyleIndex = -1;
+ m_aStates.top().isRightToLeft = false;
+ m_aStates.top().eRunType = RTFParserState::LOCH;
+ }
+ break;
+ case RTF_PARD:
+ if (m_bHadPicture)
+ dispatchSymbol(RTF_PAR);
+ // \pard is allowed between \cell and \row, but in that case it should not reset the fact that we're inside a table.
+ m_aStates.top().aParagraphSprms = m_aDefaultState.aParagraphSprms;
+ m_aStates.top().aParagraphAttributes = m_aDefaultState.aParagraphAttributes;
+
+ if (m_nTopLevelCells == 0 && m_nNestedCells == 0)
+ {
+ // Reset that we're in a table.
+ m_aStates.top().pCurrentBuffer = nullptr;
+ }
+ else
+ {
+ // We are still in a table.
+ m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_inTbl, std::make_shared<RTFValue>(1));
+ // Ideally getDefaultSPRM() would take care of this, but it would not when we're buffering.
+ m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_tabs, std::make_shared<RTFValue>());
+ }
+ resetFrame();
+
+ // Reset currently selected paragraph style as well.
+ // By default the style with index 0 is applied.
+ {
+ OUString const aName = getStyleName(0);
+ if (!aName.isEmpty())
+ {
+ m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_pStyle, std::make_shared<RTFValue>(aName));
+ m_aStates.top().nCurrentStyleIndex = 0;
+ }
+ else
+ {
+ m_aStates.top().nCurrentStyleIndex = -1;
+ }
+ }
+ // Need to send paragraph properties again, if there will be any.
+ m_bNeedPap = true;
+ break;
+ case RTF_SECTD:
+ {
+ m_aStates.top().aSectionSprms = m_aDefaultState.aSectionSprms;
+ m_aStates.top().aSectionAttributes = m_aDefaultState.aSectionAttributes;
+ }
+ break;
+ case RTF_TROWD:
+ {
+ // Back these up, in case later we still need this info.
+ backupTableRowProperties();
+ resetTableRowProperties();
+ // In case the table definition is in the middle of the row
+ // (invalid), make sure table definition is emitted.
+ m_bNeedPap = true;
+ }
+ break;
+ case RTF_WIDCTLPAR:
+ case RTF_NOWIDCTLPAR:
+ {
+ auto pValue = std::make_shared<RTFValue>(int(nKeyword == RTF_WIDCTLPAR));
+ m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_widowControl, pValue);
+ }
+ break;
+ case RTF_BOX:
+ {
+ RTFSprms aAttributes;
+ auto pValue = std::make_shared<RTFValue>(aAttributes);
+ for (int i = 0; i < 4; i++)
+ m_aStates.top().aParagraphSprms.set(getParagraphBorder(i), pValue);
+ m_aStates.top().nBorderState = RTFBorderState::PARAGRAPH_BOX;
+ }
+ break;
+ case RTF_LTRSECT:
+ case RTF_RTLSECT:
+ {
+ auto pValue = std::make_shared<RTFValue>(nKeyword == RTF_LTRSECT ? 0 : 1);
+ m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_EG_SectPrContents_textDirection, pValue);
+ }
+ break;
+ case RTF_LTRPAR:
+ case RTF_RTLPAR:
+ {
+ auto pValue = std::make_shared<RTFValue>(nKeyword == RTF_LTRPAR ? 0 : 1);
+ m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_bidi, pValue);
+ }
+ break;
+ case RTF_LTRROW:
+ case RTF_RTLROW:
+ m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TblPrBase_bidiVisual, std::make_shared<RTFValue>(int(nKeyword == RTF_RTLROW)));
+ break;
+ case RTF_LTRCH:
+ // dmapper does not support this.
+ m_aStates.top().isRightToLeft = false;
+ break;
+ case RTF_RTLCH:
+ m_aStates.top().isRightToLeft = true;
+ if (m_aDefaultState.nCurrentEncoding == RTL_TEXTENCODING_MS_1255)
+ m_aStates.top().nCurrentEncoding = m_aDefaultState.nCurrentEncoding;
+ break;
+ case RTF_ULNONE:
+ {
+ auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_Underline_none);
+ m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_Underline_val, pValue);
+ }
+ break;
+ case RTF_NONSHPPICT:
+ case RTF_MMATHPICT: // Picture group used by readers not understanding \moMath group
+ m_aStates.top().eDestination = Destination::SKIP;
+ break;
+ case RTF_CLBRDRT:
+ case RTF_CLBRDRL:
+ case RTF_CLBRDRB:
+ case RTF_CLBRDRR:
+ {
+ RTFSprms aAttributes;
+ RTFSprms aSprms;
+ auto pValue = std::make_shared<RTFValue>(aAttributes, aSprms);
+ switch (nKeyword)
+ {
+ case RTF_CLBRDRT:
+ nParam = NS_ooxml::LN_CT_TcBorders_top;
+ break;
+ case RTF_CLBRDRL:
+ nParam = NS_ooxml::LN_CT_TcBorders_left;
+ break;
+ case RTF_CLBRDRB:
+ nParam = NS_ooxml::LN_CT_TcBorders_bottom;
+ break;
+ case RTF_CLBRDRR:
+ nParam = NS_ooxml::LN_CT_TcBorders_right;
+ break;
+ default:
+ break;
+ }
+ putNestedSprm(m_aStates.top().aTableCellSprms, NS_ooxml::LN_CT_TcPrBase_tcBorders, nParam, pValue);
+ m_aStates.top().nBorderState = RTFBorderState::CELL;
+ }
+ break;
+ case RTF_PGBRDRT:
+ case RTF_PGBRDRL:
+ case RTF_PGBRDRB:
+ case RTF_PGBRDRR:
+ {
+ RTFSprms aAttributes;
+ RTFSprms aSprms;
+ auto pValue = std::make_shared<RTFValue>(aAttributes, aSprms);
+ switch (nKeyword)
+ {
+ case RTF_PGBRDRT:
+ nParam = NS_ooxml::LN_CT_PageBorders_top;
+ break;
+ case RTF_PGBRDRL:
+ nParam = NS_ooxml::LN_CT_PageBorders_left;
+ break;
+ case RTF_PGBRDRB:
+ nParam = NS_ooxml::LN_CT_PageBorders_bottom;
+ break;
+ case RTF_PGBRDRR:
+ nParam = NS_ooxml::LN_CT_PageBorders_right;
+ break;
+ default:
+ break;
+ }
+ putNestedSprm(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgBorders, nParam, pValue);
+ m_aStates.top().nBorderState = RTFBorderState::PAGE;
+ }
+ break;
+ case RTF_BRDRT:
+ case RTF_BRDRL:
+ case RTF_BRDRB:
+ case RTF_BRDRR:
+ {
+ RTFSprms aAttributes;
+ RTFSprms aSprms;
+ auto pValue = std::make_shared<RTFValue>(aAttributes, aSprms);
+ switch (nKeyword)
+ {
+ case RTF_BRDRT:
+ nParam = getParagraphBorder(0);
+ break;
+ case RTF_BRDRL:
+ nParam = getParagraphBorder(1);
+ break;
+ case RTF_BRDRB:
+ nParam = getParagraphBorder(2);
+ break;
+ case RTF_BRDRR:
+ nParam = getParagraphBorder(3);
+ break;
+ default:
+ break;
+ }
+ putNestedSprm(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PrBase_pBdr, nParam, pValue);
+ m_aStates.top().nBorderState = RTFBorderState::PARAGRAPH;
+ }
+ break;
+ case RTF_CHBRDR:
+ {
+ RTFSprms aAttributes;
+ auto pValue = std::make_shared<RTFValue>(aAttributes);
+ m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_bdr, pValue);
+ m_aStates.top().nBorderState = RTFBorderState::CHARACTER;
+ }
+ break;
+ case RTF_CLMGF:
+ {
+ auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_Merge_restart);
+ m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_hMerge, pValue);
+ }
+ break;
+ case RTF_CLMRG:
+ {
+ auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_Merge_continue);
+ m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_hMerge, pValue);
+ }
+ break;
+ case RTF_CLVMGF:
+ {
+ auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_Merge_restart);
+ m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_vMerge, pValue);
+ }
+ break;
+ case RTF_CLVMRG:
+ {
+ auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_Merge_continue);
+ m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_vMerge, pValue);
+ }
+ break;
+ case RTF_CLVERTALT:
+ case RTF_CLVERTALC:
+ case RTF_CLVERTALB:
+ {
+ switch (nKeyword)
+ {
+ case RTF_CLVERTALT:
+ nParam = NS_ooxml::LN_Value_ST_VerticalJc_top;
+ break;
+ case RTF_CLVERTALC:
+ nParam = NS_ooxml::LN_Value_ST_VerticalJc_center;
+ break;
+ case RTF_CLVERTALB:
+ nParam = NS_ooxml::LN_Value_ST_VerticalJc_bottom;
+ break;
+ default:
+ break;
+ }
+ auto pValue = std::make_shared<RTFValue>(nParam);
+ m_aStates.top().aTableCellSprms.set(NS_ooxml::LN_CT_TcPrBase_vAlign, pValue);
+ }
+ break;
+ case RTF_TRKEEP:
+ {
+ auto pValue = std::make_shared<RTFValue>(1);
+ m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TrPrBase_cantSplit, pValue);
+ }
+ break;
+ case RTF_SECTUNLOCKED:
+ {
+ auto pValue = std::make_shared<RTFValue>(int(!nParam));
+ m_aStates.top().aSectionSprms.set(NS_ooxml::LN_EG_SectPrContents_formProt, pValue);
+ }
+ break;
+ case RTF_PGNBIDIA:
+ case RTF_PGNBIDIB:
+ // These should be mapped to NS_ooxml::LN_EG_SectPrContents_pgNumType, but dmapper has no API for that at the moment.
+ break;
+ case RTF_LOCH:
+ m_aStates.top().eRunType = RTFParserState::LOCH;
+ break;
+ case RTF_HICH:
+ m_aStates.top().eRunType = RTFParserState::HICH;
+ break;
+ case RTF_DBCH:
+ m_aStates.top().eRunType = RTFParserState::DBCH;
+ break;
+ case RTF_TITLEPG:
+ {
+ auto pValue = std::make_shared<RTFValue>(1);
+ m_aStates.top().aSectionSprms.set(NS_ooxml::LN_EG_SectPrContents_titlePg, pValue);
+ }
+ break;
+ case RTF_SUPER:
+ {
+ if (!m_aStates.top().pCurrentBuffer)
+ m_aStates.top().pCurrentBuffer = &m_aSuperBuffer;
+
+ auto pValue = std::make_shared<RTFValue>("superscript");
+ m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue);
+ }
+ break;
+ case RTF_SUB:
+ {
+ auto pValue = std::make_shared<RTFValue>("subscript");
+ m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_vertAlign, pValue);
+ }
+ break;
+ case RTF_NOSUPERSUB:
+ {
+ if (m_aStates.top().pCurrentBuffer == &m_aSuperBuffer)
+ {
+ replayBuffer(m_aSuperBuffer, nullptr, nullptr);
+ m_aStates.top().pCurrentBuffer = nullptr;
+ }
+ m_aStates.top().aCharacterSprms.erase(NS_ooxml::LN_EG_RPrBase_vertAlign);
+ }
+ break;
+ case RTF_LINEPPAGE:
+ case RTF_LINECONT:
+ {
+ auto pValue = std::make_shared<RTFValue>(nKeyword == RTF_LINEPPAGE ? NS_ooxml::LN_Value_ST_LineNumberRestart_newPage : NS_ooxml::LN_Value_ST_LineNumberRestart_continuous);
+ putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_lnNumType, NS_ooxml::LN_CT_LineNumber_restart, pValue);
+ }
+ break;
+ case RTF_AENDDOC:
+ // Noop, this is the default in Writer.
+ break;
+ case RTF_AENDNOTES:
+ // Noop, Writer does not support having endnotes at the end of section.
+ break;
+ case RTF_AFTNRSTCONT:
+ // Noop, this is the default in Writer.
+ break;
+ case RTF_AFTNRESTART:
+ // Noop, Writer does not support restarting endnotes at each section.
+ break;
+ case RTF_FTNBJ:
+ // Noop, this is the default in Writer.
+ break;
+ case RTF_ENDDOC:
+ {
+ auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_RestartNumber_eachSect);
+ putNestedSprm(m_aDefaultState.aParagraphSprms, NS_ooxml::LN_EG_SectPrContents_footnotePr, NS_ooxml::LN_EG_FtnEdnNumProps_numRestart, pValue);
+ }
+ break;
+ case RTF_NOLINE:
+ eraseNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_lnNumType, NS_ooxml::LN_CT_LineNumber_distance);
+ break;
+ case RTF_FORMSHADE:
+ // Noop, this is the default in Writer.
+ break;
+ case RTF_PNGBLIP:
+ m_aStates.top().aPicture.eStyle = RTFBmpStyle::PNG;
+ break;
+ case RTF_JPEGBLIP:
+ m_aStates.top().aPicture.eStyle = RTFBmpStyle::JPEG;
+ break;
+ case RTF_POSYT:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_doc_ST_YAlign_top);
+ break;
+ case RTF_POSYB:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_doc_ST_YAlign_bottom);
+ break;
+ case RTF_POSYC:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_doc_ST_YAlign_center);
+ break;
+ case RTF_POSYIN:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_doc_ST_YAlign_inside);
+ break;
+ case RTF_POSYOUT:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_doc_ST_YAlign_outside);
+ break;
+ case RTF_POSYIL:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, NS_ooxml::LN_Value_doc_ST_YAlign_inline);
+ break;
+
+ case RTF_PHMRG:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hAnchor, NS_ooxml::LN_Value_doc_ST_HAnchor_margin);
+ break;
+ case RTF_PVMRG:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vAnchor, NS_ooxml::LN_Value_doc_ST_VAnchor_margin);
+ break;
+ case RTF_PHPG:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hAnchor, NS_ooxml::LN_Value_doc_ST_HAnchor_page);
+ break;
+ case RTF_PVPG:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vAnchor, NS_ooxml::LN_Value_doc_ST_VAnchor_page);
+ break;
+ case RTF_PHCOL:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_hAnchor, NS_ooxml::LN_Value_doc_ST_HAnchor_text);
+ break;
+ case RTF_PVPARA:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_vAnchor, NS_ooxml::LN_Value_doc_ST_VAnchor_text);
+ break;
+
+ case RTF_POSXC:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_doc_ST_XAlign_center);
+ break;
+ case RTF_POSXI:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_doc_ST_XAlign_inside);
+ break;
+ case RTF_POSXO:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_doc_ST_XAlign_outside);
+ break;
+ case RTF_POSXL:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_doc_ST_XAlign_left);
+ break;
+ case RTF_POSXR:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, NS_ooxml::LN_Value_doc_ST_XAlign_right);
+ break;
+
+ case RTF_DPLINE:
+ case RTF_DPRECT:
+ case RTF_DPELLIPSE:
+ case RTF_DPTXBX:
+ case RTF_DPPOLYLINE:
+ case RTF_DPPOLYGON:
+ {
+ sal_Int32 nType = 0;
+ switch (nKeyword)
+ {
+ case RTF_DPLINE:
+ m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.drawing.LineShape"), uno::UNO_QUERY);
+ break;
+ case RTF_DPPOLYLINE:
+ // The reason this is not a simple CustomShape is that in the old syntax we have no ViewBox info.
+ m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.drawing.PolyLineShape"), uno::UNO_QUERY);
+ break;
+ case RTF_DPPOLYGON:
+ m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.drawing.PolyPolygonShape"), uno::UNO_QUERY);
+ break;
+ case RTF_DPRECT:
+ m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY);
+ break;
+ case RTF_DPELLIPSE:
+ nType = ESCHER_ShpInst_Ellipse;
+ break;
+ case RTF_DPTXBX:
+ {
+ m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.text.TextFrame"), uno::UNO_QUERY);
+ std::vector<beans::PropertyValue> aDefaults = RTFSdrImport::getTextFrameDefaults(false);
+ for (std::size_t i = 0; i < aDefaults.size(); ++i)
+ {
+ if (!findPropertyName(m_aStates.top().aDrawingObject.aPendingProperties, aDefaults[i].Name))
+ m_aStates.top().aDrawingObject.aPendingProperties.push_back(aDefaults[i]);
+ }
+ checkFirstRun();
+ Mapper().startShape(m_aStates.top().aDrawingObject.xShape);
+ m_aStates.top().aDrawingObject.bHadShapeText = true;
+ }
+ break;
+ default:
+ break;
+ }
+ if (nType)
+ m_aStates.top().aDrawingObject.xShape.set(getModelFactory()->createInstance("com.sun.star.drawing.CustomShape"), uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPageSupplier> xDrawSupplier(m_xDstDoc, uno::UNO_QUERY);
+ if (xDrawSupplier.is())
+ {
+ uno::Reference<drawing::XShapes> xShapes(xDrawSupplier->getDrawPage(), uno::UNO_QUERY);
+ if (xShapes.is() && nKeyword != RTF_DPTXBX)
+ xShapes->add(m_aStates.top().aDrawingObject.xShape);
+ }
+ if (nType)
+ {
+ uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(m_aStates.top().aDrawingObject.xShape, uno::UNO_QUERY);
+ xDefaulter->createCustomShapeDefaults(OUString::number(nType));
+ }
+ m_aStates.top().aDrawingObject.xPropertySet.set(m_aStates.top().aDrawingObject.xShape, uno::UNO_QUERY);
+ std::vector<beans::PropertyValue>& rPendingProperties = m_aStates.top().aDrawingObject.aPendingProperties;
+ for (std::vector<beans::PropertyValue>::iterator i = rPendingProperties.begin(); i != rPendingProperties.end(); ++i)
+ m_aStates.top().aDrawingObject.xPropertySet->setPropertyValue(i->Name, i->Value);
+ m_pSdrImport->resolveDhgt(m_aStates.top().aDrawingObject.xPropertySet, m_aStates.top().aDrawingObject.nDhgt, /*bOldStyle=*/true);
+ }
+ break;
+ case RTF_DOBXMARGIN:
+ case RTF_DOBYMARGIN:
+ {
+ beans::PropertyValue aPropertyValue;
+ aPropertyValue.Name = (nKeyword == RTF_DOBXMARGIN ? OUString("HoriOrientRelation") : OUString("VertOrientRelation"));
+ aPropertyValue.Value <<= text::RelOrientation::PAGE_PRINT_AREA;
+ m_aStates.top().aDrawingObject.aPendingProperties.push_back(aPropertyValue);
+ }
+ break;
+ case RTF_DOBXPAGE:
+ case RTF_DOBYPAGE:
+ {
+ beans::PropertyValue aPropertyValue;
+ aPropertyValue.Name = (nKeyword == RTF_DOBXPAGE ? OUString("HoriOrientRelation") : OUString("VertOrientRelation"));
+ aPropertyValue.Value <<= text::RelOrientation::PAGE_FRAME;
+ m_aStates.top().aDrawingObject.aPendingProperties.push_back(aPropertyValue);
+ }
+ break;
+ case RTF_DOBYPARA:
+ {
+ beans::PropertyValue aPropertyValue;
+ aPropertyValue.Name = "VertOrientRelation";
+ aPropertyValue.Value <<= text::RelOrientation::FRAME;
+ m_aStates.top().aDrawingObject.aPendingProperties.push_back(aPropertyValue);
+ }
+ break;
+ case RTF_CONTEXTUALSPACE:
+ {
+ auto pValue = std::make_shared<RTFValue>(1);
+ m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_contextualSpacing, pValue);
+ }
+ break;
+ case RTF_LINKSTYLES:
+ {
+ auto pValue = std::make_shared<RTFValue>(1);
+ m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_linkStyles, pValue);
+ }
+ break;
+ case RTF_PNLVLBODY:
+ {
+ auto pValue = std::make_shared<RTFValue>(2);
+ m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_AbstractNum_nsid, pValue);
+ }
+ break;
+ case RTF_PNDEC:
+ {
+ auto pValue = std::make_shared<RTFValue>(0); // decimal, same as \levelnfc0
+ m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_numFmt, pValue);
+ }
+ break;
+ case RTF_PNLVLBLT:
+ {
+ m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_AbstractNum_nsid, std::make_shared<RTFValue>(1));
+ m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_numFmt, std::make_shared<RTFValue>(23)); // bullets, same as \levelnfc23
+ }
+ break;
+ case RTF_LANDSCAPE: // fall through: set the default + current value
+ {
+ auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_PageOrientation_landscape);
+ putNestedAttribute(m_aDefaultState.aSectionSprms,
+ NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_orient, pValue);
+ }
+ case RTF_LNDSCPSXN:
+ {
+ auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_PageOrientation_landscape);
+ putNestedAttribute(m_aStates.top().aSectionSprms,
+ NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_orient, pValue);
+ }
+ break;
+ case RTF_SHPBXPAGE:
+ m_aStates.top().aShape.nHoriOrientRelation = text::RelOrientation::PAGE_FRAME;
+ m_aStates.top().aShape.nHoriOrientRelationToken = NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_page;
+ break;
+ case RTF_SHPBYPAGE:
+ m_aStates.top().aShape.nVertOrientRelation = text::RelOrientation::PAGE_FRAME;
+ m_aStates.top().aShape.nVertOrientRelationToken = NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_page;
+ break;
+ case RTF_DPLINEHOLLOW:
+ m_aStates.top().aDrawingObject.nFLine = 0;
+ break;
+ case RTF_DPROUNDR:
+ if (m_aStates.top().aDrawingObject.xPropertySet.is())
+ // Seems this old syntax has no way to specify a custom radius, and this is the default
+ m_aStates.top().aDrawingObject.xPropertySet->setPropertyValue("CornerRadius", uno::makeAny(sal_Int32(83)));
+ break;
+ case RTF_NOWRAP:
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_wrap, NS_ooxml::LN_Value_doc_ST_Wrap_notBeside);
+ break;
+ case RTF_MNOR:
+ m_bMathNor = true;
+ break;
+ case RTF_REVISIONS:
+ m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_trackRevisions, std::make_shared<RTFValue>(1));
+ break;
+ case RTF_BRDRSH:
+ putBorderProperty(m_aStates, NS_ooxml::LN_CT_Border_shadow, std::make_shared<RTFValue>(1));
+ break;
+ case RTF_NOCOLBAL:
+ m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Compat_noColumnBalance, std::make_shared<RTFValue>(1));
+ break;
+ case RTF_MARGMIRROR:
+ m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_mirrorMargins, std::make_shared<RTFValue>(1));
+ break;
+ case RTF_SAUTOUPD:
+ m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Style_autoRedefine, std::make_shared<RTFValue>(1));
+ break;
+ case RTF_WIDOWCTRL:
+ m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_widowControl, std::make_shared<RTFValue>(1));
+ break;
+ case RTF_LINEBETCOL:
+ putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_cols, NS_ooxml::LN_CT_Columns_sep, std::make_shared<RTFValue>(1));
+ break;
+ case RTF_PGNRESTART:
+ putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgNumType, NS_ooxml::LN_CT_PageNumber_start, std::make_shared<RTFValue>(1));
+ break;
+ case RTF_PGNUCLTR:
+ {
+ auto pIntValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_NumberFormat_upperLetter);
+ putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgNumType, NS_ooxml::LN_CT_PageNumber_fmt, pIntValue);
+ }
+ break;
+ case RTF_PGNLCLTR:
+ {
+ auto pIntValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter);
+ putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgNumType, NS_ooxml::LN_CT_PageNumber_fmt, pIntValue);
+ }
+ break;
+ case RTF_PGNUCRM:
+ {
+ auto pIntValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_NumberFormat_upperRoman);
+ putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgNumType, NS_ooxml::LN_CT_PageNumber_fmt, pIntValue);
+ }
+ break;
+ case RTF_PGNLCRM:
+ {
+ auto pIntValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman);
+ putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgNumType, NS_ooxml::LN_CT_PageNumber_fmt, pIntValue);
+ }
+ break;
+ case RTF_PGNDEC:
+ {
+ auto pIntValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_NumberFormat_decimal);
+ putNestedAttribute(m_aStates.top().aSectionSprms, NS_ooxml::LN_EG_SectPrContents_pgNumType, NS_ooxml::LN_CT_PageNumber_fmt, pIntValue);
+ }
+ break;
+ default:
+ {
+ SAL_INFO("writerfilter", "TODO handle flag '" << keywordToString(nKeyword) << "'");
+ aSkip.setParsed(false);
+ }
+ break;
+ }
+ return RTFError::OK;
+}
+
+} // namespace rtftok
+} // namespace writerfilter
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/rtftok/rtfdispatchsymbol.cxx b/writerfilter/source/rtftok/rtfdispatchsymbol.cxx
new file mode 100644
index 0000000..98aa43d
--- /dev/null
+++ b/writerfilter/source/rtftok/rtfdispatchsymbol.cxx
@@ -0,0 +1,409 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <rtfdocumentimpl.hxx>
+
+#include <svl/lngmisc.hxx>
+
+#include <ooxml/resourceids.hxx>
+
+#include <rtfreferenceproperties.hxx>
+#include <rtfskipdestination.hxx>
+
+using namespace com::sun::star;
+
+namespace writerfilter
+{
+namespace rtftok
+{
+
+RTFError RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
+{
+ setNeedSect(true);
+ if (nKeyword != RTF_HEXCHAR)
+ checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
+ else
+ checkUnicode(/*bUnicode =*/ true, /*bHex =*/ false);
+ RTFSkipDestination aSkip(*this);
+
+ if (RTF_LINE == nKeyword)
+ {
+ // very special handling since text() will eat lone '\n'
+ singleChar('\n');
+ return RTFError::OK;
+ }
+ // Trivial symbols
+ sal_uInt8 cCh = 0;
+ switch (nKeyword)
+ {
+ case RTF_TAB:
+ cCh = '\t';
+ break;
+ case RTF_BACKSLASH:
+ cCh = '\\';
+ break;
+ case RTF_LBRACE:
+ cCh = '{';
+ break;
+ case RTF_RBRACE:
+ cCh = '}';
+ break;
+ case RTF_EMDASH:
+ cCh = 151;
+ break;
+ case RTF_ENDASH:
+ cCh = 150;
+ break;
+ case RTF_BULLET:
+ cCh = 149;
+ break;
+ case RTF_LQUOTE:
+ cCh = 145;
+ break;
+ case RTF_RQUOTE:
+ cCh = 146;
+ break;
+ case RTF_LDBLQUOTE:
+ cCh = 147;
+ break;
+ case RTF_RDBLQUOTE:
+ cCh = 148;
+ break;
+ default:
+ break;
+ }
+ if (cCh > 0)
+ {
+ OUString aStr(OStringToOUString(OString(cCh), RTL_TEXTENCODING_MS_1252));
+ text(aStr);
+ return RTFError::OK;
+ }
+
+ switch (nKeyword)
+ {
+ case RTF_IGNORE:
+ {
+ m_bSkipUnknown = true;
+ aSkip.setReset(false);
+ return RTFError::OK;
+ }
+ break;
+ case RTF_PAR:
+ {
+ if (m_aStates.top().eDestination == Destination::FOOTNOTESEPARATOR)
+ break; // just ignore it - only thing we read in here is CHFTNSEP
+ checkFirstRun();
+ bool bNeedPap = m_bNeedPap;
+ checkNeedPap();
+ if (bNeedPap)
+ runProps();
+ if (!m_aStates.top().pCurrentBuffer)
+ {
+ parBreak();
+ // Not in table? Reset max width.
+ if (m_nCellxMax)
+ {
+ // Was in table, but not anymore -> tblEnd.
+ RTFSprms aAttributes;
+ RTFSprms aSprms;
+ aSprms.set(NS_ooxml::LN_tblEnd, std::make_shared<RTFValue>(1));
+ writerfilter::Reference<Properties>::Pointer_t pProperties = std::make_shared<RTFReferenceProperties>(aAttributes, aSprms);
+ Mapper().props(pProperties);
+ }
+ m_nCellxMax = 0;
+ }
+ else if (m_aStates.top().eDestination != Destination::SHAPETEXT)
+ {
+ RTFValue::Pointer_t pValue;
+ m_aStates.top().pCurrentBuffer->push_back(
+ Buf_t(BUFFER_PAR, pValue, nullptr));
+ }
+ // but don't emit properties yet, since they may change till the first text token arrives
+ m_bNeedPap = true;
+ if (!m_aStates.top().aFrame.inFrame())
+ m_bNeedPar = false;
+ m_bNeedFinalPar = false;
+ }
+ break;
+ case RTF_SECT:
+ {
+ m_bHadSect = true;
+ if (m_bIgnoreNextContSectBreak)
+ m_bIgnoreNextContSectBreak = false;
+ else
+ {
+ sectBreak();
+ if (m_nResetBreakOnSectBreak != RTF_invalid)
+ {
+ // this should run on _second_ \sect after \page
+ dispatchSymbol(m_nResetBreakOnSectBreak); // lazy reset
+ m_nResetBreakOnSectBreak = RTF_invalid;
+ m_bNeedSect = false; // dispatchSymbol set it
+ }
+ }
+ }
+ break;
+ case RTF_NOBREAK:
+ {
+ OUString aStr(SVT_HARD_SPACE);
+ text(aStr);
+ }
+ break;
+ case RTF_NOBRKHYPH:
+ {
+ OUString aStr(SVT_HARD_HYPHEN);
+ text(aStr);
+ }
+ break;
+ case RTF_OPTHYPH:
+ {
+ OUString aStr(SVT_SOFT_HYPHEN);
+ text(aStr);
+ }
+ break;
+ case RTF_HEXCHAR:
+ m_aStates.top().nInternalState = RTFInternalState::HEX;
+ break;
+ case RTF_CELL:
+ case RTF_NESTCELL:
+ {
+ checkFirstRun();
+ if (m_bNeedPap)
+ {
+ // There were no runs in the cell, so we need to send paragraph and character properties here.
+ auto pPValue = std::make_shared<RTFValue>(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms);
+ m_aTableBufferStack.back().push_back(Buf_t(BUFFER_PROPS, pPValue, nullptr));
+ auto pCValue = std::make_shared<RTFValue>(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms);
+ m_aTableBufferStack.back().push_back(Buf_t(BUFFER_PROPS, pCValue, nullptr));
+ }
+
+ RTFValue::Pointer_t pValue;
+ m_aTableBufferStack.back().push_back(Buf_t(BUFFER_CELLEND, pValue, nullptr));
+ m_bNeedPap = true;
+ }
+ break;
+ case RTF_NESTROW:
+ {
+ std::shared_ptr<TableRowBuffer> const pBuffer(
+ new TableRowBuffer(
+ m_aTableBufferStack.back(),
+ m_aNestedTableCellsSprms,
+ m_aNestedTableCellsAttributes,
+ m_nNestedCells));
+ prepareProperties(m_aStates.top(),
+ pBuffer->pParaProperties,
+ pBuffer->pFrameProperties,
+ pBuffer->pRowProperties,
+ m_nNestedCells, m_nNestedCurrentCellX);
+
+ assert(m_aStates.top().pCurrentBuffer == &m_aTableBufferStack.back());
+ if (m_aTableBufferStack.size() == 1)
+ {
+ throw io::WrongFormatException(
+ "mismatch between \\itap and number of \\nestrow", nullptr);
+ }
+ // note: there may be several states pointing to table buffer!
+ for (std::size_t i = 0; i < m_aStates.size(); ++i)
+ {
+ if (m_aStates[i].pCurrentBuffer == &m_aTableBufferStack.back())
+ {
+ m_aStates[i].pCurrentBuffer =
+ &m_aTableBufferStack[m_aTableBufferStack.size()-2];
+ }
+ }
+ m_aTableBufferStack.pop_back();
+ m_aTableBufferStack.back().push_back(
+ Buf_t(BUFFER_NESTROW, RTFValue::Pointer_t(), pBuffer));
+
+ m_aNestedTableCellsSprms.clear();
+ m_aNestedTableCellsAttributes.clear();
+ m_nNestedCells = 0;
+ m_bNeedPap = true;
+ }
+ break;
+ case RTF_ROW:
+ {
+ bool bRestored = false;
+ // Ending a row, but no cells defined?
+ // See if there was an invalid table row reset, so we can restore cell infos to help invalid documents.
+ if (!m_nTopLevelCurrentCellX && m_nBackupTopLevelCurrentCellX)
+ {
+ restoreTableRowProperties();
+ bRestored = true;
+ }
+
+ // If the right edge of the last cell (row width) is smaller than the width of some other row, mimic WW8TabDesc::CalcDefaults(): resize the last cell
+ const int MINLAY = 23; // sw/inc/swtypes.hxx, minimal possible size of frames.
+ if ((m_nCellxMax - m_nTopLevelCurrentCellX) >= MINLAY)
+ {
+ auto pXValueLast = m_aStates.top().aTableRowSprms.find(NS_ooxml::LN_CT_TblGridBase_gridCol, false);
+ auto pXValue = std::make_shared<RTFValue>(pXValueLast->getInt() + m_nCellxMax - m_nTopLevelCurrentCellX);
+ m_aStates.top().aTableRowSprms.eraseLast(NS_ooxml::LN_CT_TblGridBase_gridCol);
+ m_aStates.top().aTableRowSprms.set(NS_ooxml::LN_CT_TblGridBase_gridCol, pXValue, RTFOverwrite::NO_APPEND);
+ m_nTopLevelCurrentCellX = m_nCellxMax;
+ }
+
+ if (m_nTopLevelCells)
+ {
+ // Make a backup before we start popping elements
+ m_aTableInheritingCellsSprms = m_aTopLevelTableCellsSprms;
+ m_aTableInheritingCellsAttributes = m_aTopLevelTableCellsAttributes;
+ m_nInheritingCells = m_nTopLevelCells;
+ }
+ else
+ {
+ // No table definition? Then inherit from the previous row
+ m_aTopLevelTableCellsSprms = m_aTableInheritingCellsSprms;
+ m_aTopLevelTableCellsAttributes = m_aTableInheritingCellsAttributes;
+ m_nTopLevelCells = m_nInheritingCells;
+ }
+
+ while (m_aTableBufferStack.size() > 1)
+ {
+ SAL_WARN("writerfilter.rtf", "dropping extra table buffer");
+ // note: there may be several states pointing to table buffer!
+ for (std::size_t i = 0; i < m_aStates.size(); ++i)
+ {
+ if (m_aStates[i].pCurrentBuffer == &m_aTableBufferStack.back())
+ {
+ m_aStates[i].pCurrentBuffer =
+ &m_aTableBufferStack.front();
+ }
+ }
+ m_aTableBufferStack.pop_back();
+ }
+
+ replayRowBuffer(m_aTableBufferStack.back(),
+ m_aTopLevelTableCellsSprms, m_aTopLevelTableCellsAttributes,
+ m_nTopLevelCells);
+
+ m_aStates.top().aTableCellSprms = m_aDefaultState.aTableCellSprms;
+ m_aStates.top().aTableCellAttributes = m_aDefaultState.aTableCellAttributes;
+
+ writerfilter::Reference<Properties>::Pointer_t paraProperties;
+ writerfilter::Reference<Properties>::Pointer_t frameProperties;
+ writerfilter::Reference<Properties>::Pointer_t rowProperties;
+ prepareProperties(m_aStates.top(),
+ paraProperties, frameProperties, rowProperties,
+ m_nTopLevelCells, m_nTopLevelCurrentCellX);
+ sendProperties(paraProperties, frameProperties, rowProperties);
+
+ m_bNeedPap = true;
+ m_bNeedFinalPar = true;
+ m_aTableBufferStack.back().clear();
+ m_nTopLevelCells = 0;
+
+ if (bRestored)
+ // We restored cell definitions, clear these now.
+ // This is necessary, as later cell definitions want to overwrite the restored ones.
+ resetTableRowProperties();
+ }
+ break;
+ case RTF_COLUMN:
+ {
+ bool bColumns = false; // If we have multiple columns
+ RTFValue::Pointer_t pCols = m_aStates.top().aSectionSprms.find(NS_ooxml::LN_EG_SectPrContents_cols);
+ if (pCols.get())
+ {
+ RTFValue::Pointer_t pNum = pCols->getAttributes().find(NS_ooxml::LN_CT_Columns_num);
+ if (pNum.get() && pNum->getInt() > 1)
+ bColumns = true;
+ }
+ checkFirstRun();
+ if (bColumns)
+ {
+ sal_uInt8 sBreak[] = { 0xe };
+ Mapper().startCharacterGroup();
+ Mapper().text(sBreak, 1);
+ Mapper().endCharacterGroup();
+ }
+ else
+ dispatchSymbol(RTF_PAGE);
+ }
+ break;
+ case RTF_CHFTN:
+ {
+ if (m_aStates.top().pCurrentBuffer == &m_aSuperBuffer)
+ // Stop buffering, there will be no custom mark for this footnote or endnote.
+ m_aStates.top().pCurrentBuffer = nullptr;
+ break;
+ }
+ case RTF_PAGE:
+ {
+ // Ignore page breaks inside tables.
+ if (m_aStates.top().pCurrentBuffer == &m_aTableBufferStack.back())
+ break;
+
+ // If we're inside a continuous section, we should send a section break, not a page one.
+ RTFValue::Pointer_t pBreak = m_aStates.top().aSectionSprms.find(NS_ooxml::LN_EG_SectPrContents_type);
+ // Unless we're on a title page.
+ RTFValue::Pointer_t pTitlePg = m_aStates.top().aSectionSprms.find(NS_ooxml::LN_EG_SectPrContents_titlePg);
+ if (((pBreak.get() && pBreak->getInt() == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_continuous))
+ || m_nResetBreakOnSectBreak == RTF_SBKNONE)
+ && !(pTitlePg.get() && pTitlePg->getInt()))
+ {
+ if (m_bWasInFrame)
+ {
+ dispatchSymbol(RTF_PAR);
+ m_bWasInFrame = false;
+ }
+ sectBreak();
+ // note: this will not affect the following section break
+ // but the one just pushed
+ dispatchFlag(RTF_SBKPAGE);
+ if (m_bNeedPar)
+ dispatchSymbol(RTF_PAR);
+ m_bIgnoreNextContSectBreak = true;
+ // arrange to clean up the synthetic RTF_SBKPAGE
+ m_nResetBreakOnSectBreak = RTF_SBKNONE;
+ }
+ else
+ {
+ checkFirstRun();
+ checkNeedPap();
+ sal_uInt8 sBreak[] = { 0xc };
+ Mapper().text(sBreak, 1);
+ if (!m_bNeedPap)
+ {
+ parBreak();
+ m_bNeedPap = true;
+ }
+ m_bNeedCr = true;
+ }
+ }
+ break;
+ case RTF_CHPGN:
+ {
+ OUString aStr("PAGE");
+ singleChar(cFieldStart);
+ text(aStr);
+ singleChar(cFieldSep, true);
+ singleChar(cFieldEnd);
+ }
+ break;
+ case RTF_CHFTNSEP:
+ {
+ static const sal_Unicode uFtnEdnSep = 0x3;
+ Mapper().utext(reinterpret_cast<const sal_uInt8*>(&uFtnEdnSep), 1);
+ }
+ break;
+ default:
+ {
+ SAL_INFO("writerfilter", "TODO handle symbol '" << keywordToString(nKeyword) << "'");
+ aSkip.setParsed(false);
+ }
+ break;
+ }
+ return RTFError::OK;
+}
+
+} // namespace rtftok
+} // namespace writerfilter
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/rtftok/rtfdispatchvalue.cxx b/writerfilter/source/rtftok/rtfdispatchvalue.cxx
new file mode 100644
index 0000000..76e24dd
--- /dev/null
+++ b/writerfilter/source/rtftok/rtfdispatchvalue.cxx
@@ -0,0 +1,1347 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <rtfdocumentimpl.hxx>
+
+#include <com/sun/star/text/WrapTextMode.hpp>
+
+#include <comphelper/sequence.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <rtl/tencinfo.h>
+#include <tools/colordata.hxx>
+#include <tools/mapunit.hxx>
+
+#include <ooxml/resourceids.hxx>
+
+#include <rtfcharsets.hxx>
+#include <rtffly.hxx>
+#include <rtfreferenceproperties.hxx>
+#include <rtfskipdestination.hxx>
+
+using namespace com::sun::star;
+
+namespace writerfilter
+{
+
+int getNumberFormat(int nParam)
+{
+ static const int aMap[] =
+ {
+ NS_ooxml::LN_Value_ST_NumberFormat_decimal,
+ NS_ooxml::LN_Value_ST_NumberFormat_upperRoman,
+ NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman,
+ NS_ooxml::LN_Value_ST_NumberFormat_upperLetter,
+ NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter,
+ NS_ooxml::LN_Value_ST_NumberFormat_ordinal,
+ NS_ooxml::LN_Value_ST_NumberFormat_cardinalText,
+ NS_ooxml::LN_Value_ST_NumberFormat_ordinalText,
+ NS_ooxml::LN_Value_ST_NumberFormat_none, // Undefined in RTF 1.8 spec.
+ NS_ooxml::LN_Value_ST_NumberFormat_none, // Undefined in RTF 1.8 spec.
+ NS_ooxml::LN_Value_ST_NumberFormat_ideographDigital,
+ NS_ooxml::LN_Value_ST_NumberFormat_japaneseCounting,
+ NS_ooxml::LN_Value_ST_NumberFormat_aiueo,
+ NS_ooxml::LN_Value_ST_NumberFormat_iroha,
+ NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth,
+ NS_ooxml::LN_Value_ST_NumberFormat_decimalHalfWidth,
+ NS_ooxml::LN_Value_ST_NumberFormat_japaneseLegal,
+ NS_ooxml::LN_Value_ST_NumberFormat_japaneseDigitalTenThousand ,
+ NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircleChinese,
+ NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth2,
+ NS_ooxml::LN_Value_ST_NumberFormat_aiueoFullWidth,
+ NS_ooxml::LN_Value_ST_NumberFormat_irohaFullWidth,
+ NS_ooxml::LN_Value_ST_NumberFormat_decimalZero,
+ NS_ooxml::LN_Value_ST_NumberFormat_bullet,
+ NS_ooxml::LN_Value_ST_NumberFormat_ganada,
+ NS_ooxml::LN_Value_ST_NumberFormat_chosung,
+ NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedFullstop,
+ NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedParen,
+ NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircleChinese,
+ NS_ooxml::LN_Value_ST_NumberFormat_ideographEnclosedCircle,
+ NS_ooxml::LN_Value_ST_NumberFormat_ideographTraditional,
+ NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiac,
+ NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiacTraditional,
+ NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCounting,
+ NS_ooxml::LN_Value_ST_NumberFormat_ideographLegalTraditional,
+ NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCountingThousand,
+ NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseDigital,
+ NS_ooxml::LN_Value_ST_NumberFormat_chineseCounting,
+ NS_ooxml::LN_Value_ST_NumberFormat_chineseLegalSimplified,
+ NS_ooxml::LN_Value_ST_NumberFormat_chineseCountingThousand,
+ NS_ooxml::LN_Value_ST_NumberFormat_decimal,
+ NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital,
+ NS_ooxml::LN_Value_ST_NumberFormat_koreanCounting,
+ NS_ooxml::LN_Value_ST_NumberFormat_koreanLegal,
+ NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital2,
+ NS_ooxml::LN_Value_ST_NumberFormat_hebrew1,
+ NS_ooxml::LN_Value_ST_NumberFormat_arabicAlpha,
+ NS_ooxml::LN_Value_ST_NumberFormat_hebrew2,
+ NS_ooxml::LN_Value_ST_NumberFormat_arabicAbjad
+ };
+ const int nLen = SAL_N_ELEMENTS(aMap);
+ int nValue = 0;
+ if (nParam >= 0 && nParam < nLen)
+ nValue = aMap[nParam];
+ else // 255 and the other cases.
+ nValue = NS_ooxml::LN_Value_ST_NumberFormat_none;
+ return nValue;
+}
+
+namespace rtftok
+{
+
+RTFError RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
+{
+ setNeedSect(true);
+ checkUnicode(/*bUnicode =*/ nKeyword != RTF_U, /*bHex =*/ true);
+ RTFSkipDestination aSkip(*this);
+ int nSprm = 0;
+ auto pIntValue = std::make_shared<RTFValue>(nParam);
+ // Trivial table sprms.
+ switch (nKeyword)
+ {
+ case RTF_LEVELJC:
+ {
+ nSprm = NS_ooxml::LN_CT_Lvl_lvlJc;
+ int nValue = 0;
+ switch (nParam)
+ {
+ case 0:
+ nValue = NS_ooxml::LN_Value_ST_Jc_left;
+ break;
+ case 1:
+ nValue = NS_ooxml::LN_Value_ST_Jc_center;
+ break;
+ case 2:
+ nValue = NS_ooxml::LN_Value_ST_Jc_right;
+ break;
+ }
+ pIntValue = std::make_shared<RTFValue>(nValue);
+ break;
+ }
+ case RTF_LEVELNFC:
+ nSprm = NS_ooxml::LN_CT_Lvl_numFmt;
+ pIntValue = std::make_shared<RTFValue>(getNumberFormat(nParam));
+ break;
+ case RTF_LEVELSTARTAT:
+ nSprm = NS_ooxml::LN_CT_Lvl_start;
+ break;
+ case RTF_LEVELPICTURE:
+ nSprm = NS_ooxml::LN_CT_Lvl_lvlPicBulletId;
+ break;
+ case RTF_SBASEDON:
+ nSprm = NS_ooxml::LN_CT_Style_basedOn;
+ pIntValue = std::make_shared<RTFValue>(getStyleName(nParam));
+ break;
+ default:
+ break;
+ }
+ if (nSprm > 0)
+ {
+ m_aStates.top().aTableSprms.set(nSprm, pIntValue);
+ return RTFError::OK;
+ }
+ // Trivial character sprms.
+ switch (nKeyword)
+ {
+ case RTF_FS:
+ case RTF_AFS:
+ nSprm = (m_aStates.top().isRightToLeft || m_aStates.top().eRunType == RTFParserState::HICH) ? NS_ooxml::LN_EG_RPrBase_szCs : NS_ooxml::LN_EG_RPrBase_sz;
+ break;
+ case RTF_ANIMTEXT:
+ nSprm = NS_ooxml::LN_EG_RPrBase_effect;
+ break;
+ case RTF_EXPNDTW:
+ nSprm = NS_ooxml::LN_EG_RPrBase_spacing;
+ break;
+ case RTF_KERNING:
+ nSprm = NS_ooxml::LN_EG_RPrBase_kern;
+ break;
+ case RTF_CHARSCALEX:
+ nSprm = NS_ooxml::LN_EG_RPrBase_w;
+ break;
+ default:
+ break;
+ }
+ if (nSprm > 0)
+ {
+ m_aStates.top().aCharacterSprms.set(nSprm, pIntValue);
+ return RTFError::OK;
+ }
+ // Trivial character attributes.
+ switch (nKeyword)
+ {
+ case RTF_LANG:
+ case RTF_ALANG:
+ if (m_aStates.top().isRightToLeft || m_aStates.top().eRunType == RTFParserState::HICH)
+ {
+ nSprm = NS_ooxml::LN_CT_Language_bidi;
+ }
+ else if (m_aStates.top().eRunType == RTFParserState::DBCH)
+ {
+ nSprm = NS_ooxml::LN_CT_Language_eastAsia;
+ }
+ else
+ {
+ assert(m_aStates.top().eRunType == RTFParserState::LOCH);
+ nSprm = NS_ooxml::LN_CT_Language_val;
+ }
+ break;
+ case RTF_LANGFE: // this one is always CJK apparently
+ nSprm = NS_ooxml::LN_CT_Language_eastAsia;
+ break;
+ default:
+ break;
+ }
+ if (nSprm > 0)
+ {
+ LanguageTag aTag((LanguageType)nParam);
+ auto pValue = std::make_shared<RTFValue>(aTag.getBcp47());
+ putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_EG_RPrBase_lang, nSprm, pValue);
+ // Language is a character property, but we should store it at a paragraph level as well for fields.
+ if (nKeyword == RTF_LANG && m_bNeedPap)
+ putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_EG_RPrBase_lang, nSprm, pValue);
+ return RTFError::OK;
+ }
+ // Trivial paragraph sprms.
+ switch (nKeyword)
+ {
+ case RTF_ITAP:
+ nSprm = NS_ooxml::LN_tblDepth;
+ break;
+ default:
+ break;
+ }
+ if (nSprm > 0)
+ {
+ m_aStates.top().aParagraphSprms.set(nSprm, pIntValue);
+ if (nKeyword == RTF_ITAP && nParam > 0)
+ {
+ while (m_aTableBufferStack.size() < sal::static_int_cast<std::size_t>(nParam))
+ {
+ m_aTableBufferStack.push_back(RTFBuffer_t());
+ }
+ // Invalid tables may omit INTBL after ITAP
+ dispatchFlag(RTF_INTBL); // sets newly pushed buffer as current
+ assert(m_aStates.top().pCurrentBuffer == &m_aTableBufferStack.back());
+ }
+ return RTFError::OK;
+ }
+
+ // Info group.
+ switch (nKeyword)
+ {
+ case RTF_YR:
+ {
+ m_aStates.top().nYear = nParam;
+ nSprm = 1;
+ }
+ break;
+ case RTF_MO:
+ {
+ m_aStates.top().nMonth = nParam;
+ nSprm = 1;
+ }
+ break;
+ case RTF_DY:
+ {
+ m_aStates.top().nDay = nParam;
+ nSprm = 1;
+ }
+ break;
+ case RTF_HR:
+ {
+ m_aStates.top().nHour = nParam;
+ nSprm = 1;
+ }
+ break;
+ case RTF_MIN:
+ {
+ m_aStates.top().nMinute = nParam;
+ nSprm = 1;
+ }
+ break;
+ default:
+ break;
+ }
+ if (nSprm > 0)
+ return RTFError::OK;
+
+ // Frame size / position.
+ Id nId = 0;
+ switch (nKeyword)
+ {
+ case RTF_ABSW:
+ nId = NS_ooxml::LN_CT_FramePr_w;
+ break;
+ case RTF_ABSH:
+ nId = NS_ooxml::LN_CT_FramePr_h;
+ break;
+ case RTF_POSX:
+ {
+ nId = NS_ooxml::LN_CT_FramePr_x;
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_xAlign, 0);
+ }
+ break;
+ case RTF_POSY:
+ {
+ nId = NS_ooxml::LN_CT_FramePr_y;
+ m_aStates.top().aFrame.setSprm(NS_ooxml::LN_CT_FramePr_yAlign, 0);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (nId > 0)
+ {
+ m_bNeedPap = true;
+ // Don't try to support text frames inside tables for now.
+ if (m_aStates.top().pCurrentBuffer != &m_aTableBufferStack.back())
+ m_aStates.top().aFrame.setSprm(nId, nParam);
+
+ return RTFError::OK;
+ }
+
+ // Then check for the more complex ones.
+ switch (nKeyword)
+ {
+ case RTF_F:
+ case RTF_AF:
+ if (m_aStates.top().isRightToLeft || m_aStates.top().eRunType == RTFParserState::HICH)
+ {
+ nSprm = NS_ooxml::LN_CT_Fonts_cs;
+ }
+ else if (m_aStates.top().eRunType == RTFParserState::DBCH)
+ {
+ nSprm = NS_ooxml::LN_CT_Fonts_eastAsia;
+ }
+ else
+ {
+ assert(m_aStates.top().eRunType == RTFParserState::LOCH);
+ nSprm = NS_ooxml::LN_CT_Fonts_ascii;
+ }
+ if (m_aStates.top().eDestination == Destination::FONTTABLE || m_aStates.top().eDestination == Destination::FONTENTRY)
+ {
+ m_aFontIndexes.push_back(nParam);
+ m_nCurrentFontIndex = getFontIndex(nParam);
+ }
+ else if (m_aStates.top().eDestination == Destination::LISTLEVEL)
+ {
+ RTFSprms aFontAttributes;
+ aFontAttributes.set(nSprm, std::make_shared<RTFValue>(m_aFontNames[getFontIndex(nParam)]));
+ RTFSprms aRunPropsSprms;
+ aRunPropsSprms.set(NS_ooxml::LN_EG_RPrBase_rFonts, std::make_shared<RTFValue>(aFontAttributes));
+ m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_rPr, std::make_shared<RTFValue>(RTFSprms(), aRunPropsSprms), RTFOverwrite::NO_APPEND);
+ }
+ else
+ {
+ m_nCurrentFontIndex = getFontIndex(nParam);
+ auto pValue = std::make_shared<RTFValue>(getFontName(m_nCurrentFontIndex));
+ putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_EG_RPrBase_rFonts, nSprm, pValue);
+ if (nKeyword == RTF_F)
+ m_aStates.top().nCurrentEncoding = getEncoding(m_nCurrentFontIndex);
+ }
+ break;
+ case RTF_RED:
+ m_aStates.top().aCurrentColor.nRed = nParam;
+ break;
+ case RTF_GREEN:
+ m_aStates.top().aCurrentColor.nGreen = nParam;
+ break;
+ case RTF_BLUE:
+ m_aStates.top().aCurrentColor.nBlue = nParam;
+ break;
+ case RTF_FCHARSET:
+ {
+ // we always send text to the domain mapper in OUString, so no
+ // need to send encoding info
+ int i;
+ for (i = 0; i < nRTFEncodings; i++)
+ {
+ if (aRTFEncodings[i].charset == nParam)
+ break;
+ }
+ if (i == nRTFEncodings)
+ // not found
+ return RTFError::OK;
+
+ m_nCurrentEncoding = rtl_getTextEncodingFromWindowsCodePage(aRTFEncodings[i].codepage);
+ m_aStates.top().nCurrentEncoding = m_nCurrentEncoding;
+ }
+ break;
+ case RTF_ANSICPG:
+ {
+ m_aDefaultState.nCurrentEncoding = rtl_getTextEncodingFromWindowsCodePage(nParam);
+ m_aStates.top().nCurrentEncoding = rtl_getTextEncodingFromWindowsCodePage(nParam);
+ }
+ break;
+ case RTF_CPG:
+ m_nCurrentEncoding = rtl_getTextEncodingFromWindowsCodePage(nParam);
+ m_aStates.top().nCurrentEncoding = m_nCurrentEncoding;
+ break;
+ case RTF_CF:
+ {
+ RTFSprms aAttributes;
+ auto pValue = std::make_shared<RTFValue>(getColorTable(nParam));
+ aAttributes.set(NS_ooxml::LN_CT_Color_val, pValue);
+ m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_color, std::make_shared<RTFValue>(aAttributes));
+ }
+ break;
+ case RTF_S:
+ {
+ m_aStates.top().nCurrentStyleIndex = nParam;
+
+ if (m_aStates.top().eDestination == Destination::STYLESHEET || m_aStates.top().eDestination == Destination::STYLEENTRY)
+ {
+ m_nCurrentStyleIndex = nParam;
+ auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_StyleType_paragraph);
+ m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Style_type, pValue); // paragraph style
+ }
+ else
+ {
+ OUString aName = getStyleName(nParam);
+ if (!aName.isEmpty())
+ {
+ if (m_aStates.top().eDestination == Destination::LISTLEVEL)
+ m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Lvl_pStyle, std::make_shared<RTFValue>(aName));
+ else
+ m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_pStyle, std::make_shared<RTFValue>(aName));
+
+ }
+ }
+ }
+ break;
+ case RTF_CS:
+ m_aStates.top().nCurrentCharacterStyleIndex = nParam;
+ if (m_aStates.top().eDestination == Destination::STYLESHEET || m_aStates.top().eDestination == Destination::STYLEENTRY)
+ {
+ m_nCurrentStyleIndex = nParam;
+ auto pValue = std::make_shared<RTFValue>(NS_ooxml::LN_Value_ST_StyleType_character);
+ m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Style_type, pValue); // character style
+ }
+ else
+ {
+ OUString aName = getStyleName(nParam);
+ if (!aName.isEmpty())
+ m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_rStyle, std::make_shared<RTFValue>(aName));
+ }
+ break;
+ case RTF_DS:
+ if (m_aStates.top().eDestination == Destination::STYLESHEET || m_aStates.top().eDestination == Destination::STYLEENTRY)
+ {
+ m_nCurrentStyleIndex = nParam;
+ auto pValue = std::make_shared<RTFValue>(0); // TODO no value in enum StyleType?
+ m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Style_type, pValue); // section style
+ }
+ break;
+ case RTF_TS:
+ if (m_aStates.top().eDestination == Destination::STYLESHEET || m_aStates.top().eDestination == Destination::STYLEENTRY)
+ {
+ m_nCurrentStyleIndex = nParam;
+ // 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
+ auto pValue = std::make_shared<RTFValue>(0);
+ m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_Style_type, pValue); // table style
+ }
+ break;
+ case RTF_DEFF:
+ m_nDefaultFontIndex = nParam;
+ break;
+ case RTF_DEFLANG:
+ case RTF_ADEFLANG:
+ {
+ LanguageTag aTag((LanguageType)nParam);
+ auto pValue = std::make_shared<RTFValue>(aTag.getBcp47());
+ putNestedAttribute(m_aStates.top().aCharacterSprms, (nKeyword == RTF_DEFLANG ? NS_ooxml::LN_EG_RPrBase_lang : NS_ooxml::LN_CT_Language_bidi), nSprm, pValue);
+ }
+ break;
+ case RTF_CHCBPAT:
+ {
+ auto pValue = std::make_shared<RTFValue>(nParam ? getColorTable(nParam) : COL_AUTO);
+ putNestedAttribute(m_aStates.top().aCharacterSprms, NS_ooxml::LN_EG_RPrBase_shd, NS_ooxml::LN_CT_Shd_fill, pValue);
+ }
+ break;
+ case RTF_CLCBPAT:
+ {
+ auto pValue = std::make_shared<RTFValue>(getColorTable(nParam));
+ putNestedAttribute(m_aStates.top().aTableCellSprms, NS_ooxml::LN_CT_TcPrBase_shd, NS_ooxml::LN_CT_Shd_fill, pValue);
+ }
+ break;
+ case RTF_CBPAT:
+ if (nParam)
+ {
+ auto pValue = std::make_shared<RTFValue>(getColorTable(nParam));
+ putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PrBase_shd, NS_ooxml::LN_CT_Shd_fill, pValue);
+ }
+ break;
+ case RTF_ULC:
+ {
+ auto pValue = std::make_shared<RTFValue>(getColorTable(nParam));
+ m_aStates.top().aCharacterSprms.set(0x6877, pValue);
+ }
+ break;
+ case RTF_HIGHLIGHT:
+ {
+ auto pValue = std::make_shared<RTFValue>(nParam ? getColorTable(nParam) : COL_AUTO);
+ m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_highlight, pValue);
+ }
+ break;
+ case RTF_UP:
+ case RTF_DN:
+ {
+ auto pValue = std::make_shared<RTFValue>(nParam * (nKeyword == RTF_UP ? 1 : -1));
+ m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_position, pValue);
+ }
+ break;
+ case RTF_HORZVERT:
+ {
+ auto pValue = std::make_shared<RTFValue>(int(true));
+ m_aStates.top().aCharacterAttributes.set(NS_ooxml::LN_CT_EastAsianLayout_vert, pValue);
+ if (nParam)
+ // rotate fits to a single line
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list