summaryrefslogtreecommitdiffstats
path: root/writerfilter/source/rtftok/rtfdocumentimpl.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'writerfilter/source/rtftok/rtfdocumentimpl.hxx')
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.hxx994
1 files changed, 994 insertions, 0 deletions
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
new file mode 100644
index 000000000..e859c01c9
--- /dev/null
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -0,0 +1,994 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <memory>
+#include <queue>
+#include <tuple>
+#include <vector>
+#include <optional>
+
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/io/WrongFormatException.hpp>
+#include <oox/mathml/importutils.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <tools/color.hxx>
+#include <tools/long.hxx>
+
+#include <rtftok/RTFDocument.hxx>
+#include "rtfreferencetable.hxx"
+#include "rtfsprm.hxx"
+#include "rtflistener.hxx"
+
+class SvStream;
+namespace oox
+{
+class GraphicHelper;
+}
+namespace com::sun::star
+{
+namespace beans
+{
+class XPropertySet;
+}
+namespace document
+{
+class XDocumentProperties;
+}
+namespace lang
+{
+class XMultiServiceFactory;
+}
+}
+
+namespace writerfilter::rtftok
+{
+class RTFParserState;
+class RTFDocumentImpl;
+class RTFTokenizer;
+class RTFSdrImport;
+class TableRowBuffer;
+
+enum class RTFBorderState
+{
+ NONE,
+ PARAGRAPH,
+ PARAGRAPH_BOX,
+ CELL,
+ PAGE,
+ CHARACTER
+};
+
+/// Different kind of buffers for table cell contents.
+enum RTFBufferTypes
+{
+ BUFFER_SETSTYLE,
+ /// Stores properties, should be created only in bufferProperties().
+ BUFFER_PROPS,
+ BUFFER_NESTROW,
+ BUFFER_CELLEND,
+ BUFFER_STARTRUN,
+ BUFFER_TEXT,
+ BUFFER_UTEXT,
+ BUFFER_ENDRUN,
+ BUFFER_PAR,
+ BUFFER_STARTSHAPE,
+ /// Imports a shape.
+ BUFFER_RESOLVESHAPE,
+ BUFFER_ENDSHAPE,
+ BUFFER_RESOLVESUBSTREAM,
+ /// Restores RTFParserState::aPicture.
+ BUFFER_PICTURE
+};
+
+/// Form field types
+enum class RTFFormFieldType
+{
+ NONE,
+ TEXT,
+ CHECKBOX,
+ LIST
+};
+
+enum class RTFBmpStyle
+{
+ NONE,
+ PNG,
+ JPEG,
+ DIBITMAP
+};
+
+enum class RTFFieldStatus
+{
+ NONE,
+ INSTRUCTION,
+ RESULT
+};
+
+/// A buffer storing dmapper calls.
+using Buf_t = std::tuple<RTFBufferTypes, RTFValue::Pointer_t, tools::SvRef<TableRowBuffer>>;
+using RTFBuffer_t = std::deque<Buf_t>;
+
+/// holds one nested table row
+class TableRowBuffer : public virtual SvRefBase
+{
+ RTFBuffer_t m_aBuffer;
+ ::std::deque<RTFSprms> m_aCellsSprms;
+ ::std::deque<RTFSprms> m_aCellsAttributes;
+ int m_nCells;
+ writerfilter::Reference<Properties>::Pointer_t m_pParaProperties;
+ writerfilter::Reference<Properties>::Pointer_t m_pFrameProperties;
+ writerfilter::Reference<Properties>::Pointer_t m_pRowProperties;
+
+public:
+ TableRowBuffer(RTFBuffer_t aBuffer, std::deque<RTFSprms> aSprms,
+ std::deque<RTFSprms> aAttributes, int const nCells)
+ : m_aBuffer(std::move(aBuffer))
+ , m_aCellsSprms(std::move(aSprms))
+ , m_aCellsAttributes(std::move(aAttributes))
+ , m_nCells(nCells)
+ {
+ }
+
+ RTFBuffer_t& GetBuffer() { return m_aBuffer; }
+ std::deque<RTFSprms>& GetCellsSprms() { return m_aCellsSprms; }
+ std::deque<RTFSprms>& GetCellsAttributes() { return m_aCellsAttributes; }
+ int GetCells() const { return m_nCells; }
+ writerfilter::Reference<Properties>::Pointer_t& GetParaProperties()
+ {
+ return m_pParaProperties;
+ }
+ writerfilter::Reference<Properties>::Pointer_t& GetFrameProperties()
+ {
+ return m_pFrameProperties;
+ }
+ writerfilter::Reference<Properties>::Pointer_t& GetRowProperties() { return m_pRowProperties; }
+};
+
+/// An entry in the color table.
+class RTFColorTableEntry
+{
+public:
+ void SetRed(sal_uInt8 nRed)
+ {
+ m_bAuto = false;
+ m_nR = nRed;
+ }
+ void SetGreen(sal_uInt8 nGreen)
+ {
+ m_bAuto = false;
+ m_nG = nGreen;
+ }
+ void SetBlue(sal_uInt8 nBlue)
+ {
+ m_bAuto = false;
+ m_nB = nBlue;
+ }
+ Color GetColor() const { return m_bAuto ? COL_AUTO : Color(m_nR, m_nG, m_nB); }
+
+private:
+ bool m_bAuto = true;
+ sal_uInt8 m_nR = 0;
+ sal_uInt8 m_nG = 0;
+ sal_uInt8 m_nB = 0;
+};
+
+/// Stores the properties of a shape.
+class RTFShape : public virtual SvRefBase
+{
+public:
+ RTFShape();
+
+ std::vector<std::pair<OUString, OUString>>& getProperties() { return m_aProperties; }
+
+ const std::vector<std::pair<OUString, OUString>>& getProperties() const
+ {
+ return m_aProperties;
+ }
+
+ std::vector<std::pair<OUString, OUString>>& getGroupProperties() { return m_aGroupProperties; }
+
+ void setLeft(sal_Int32 nLeft) { m_nLeft = nLeft; }
+
+ sal_Int32 getLeft() const { return m_nLeft; }
+
+ void setTop(sal_Int32 nTop) { m_nTop = nTop; }
+
+ sal_Int32 getTop() const { return m_nTop; }
+
+ void setRight(sal_Int32 nRight) { m_nRight = nRight; }
+
+ sal_Int32 getRight() const { return m_nRight; }
+
+ void setBottom(sal_Int32 nBottom) { m_nBottom = nBottom; }
+
+ sal_Int32 getBottom() const { return m_nBottom; }
+
+ void setZ(sal_Int32 nZ) { m_oZ = nZ; }
+
+ bool hasZ() const { return bool(m_oZ); }
+
+ sal_Int32 getZ() const { return *m_oZ; }
+
+ void setHoriOrientRelation(sal_Int16 nHoriOrientRelation)
+ {
+ m_nHoriOrientRelation = nHoriOrientRelation;
+ }
+
+ sal_Int16 getHoriOrientRelation() const { return m_nHoriOrientRelation; }
+
+ void setVertOrientRelation(sal_Int16 nVertOrientRelation)
+ {
+ m_nVertOrientRelation = nVertOrientRelation;
+ }
+
+ sal_Int16 getVertOrientRelation() const { return m_nVertOrientRelation; }
+
+ void setHoriOrientRelationToken(sal_uInt32 nHoriOrientRelationToken)
+ {
+ m_nHoriOrientRelationToken = nHoriOrientRelationToken;
+ }
+
+ sal_uInt32 getHoriOrientRelationToken() const { return m_nHoriOrientRelationToken; }
+
+ void setVertOrientRelationToken(sal_uInt32 nVertOrientRelationToken)
+ {
+ m_nVertOrientRelationToken = nVertOrientRelationToken;
+ }
+
+ sal_uInt32 getVertOrientRelationToken() const { return m_nVertOrientRelationToken; }
+
+ void setWrap(css::text::WrapTextMode nWrap) { m_nWrap = nWrap; }
+
+ css::text::WrapTextMode getWrap() const { return m_nWrap; }
+
+ void setInBackground(bool bInBackground) { m_bInBackground = bInBackground; }
+
+ bool getInBackground() const { return m_bInBackground; }
+
+ RTFSprms& getWrapPolygonSprms() { return m_aWrapPolygonSprms; }
+
+ RTFSprms& getAnchorAttributes() { return m_aAnchorAttributes; }
+
+ std::pair<Id, RTFValue::Pointer_t>& getWrapSprm() { return m_aWrapSprm; }
+
+private:
+ std::vector<std::pair<OUString, OUString>> m_aProperties; ///< Properties of a single shape.
+ std::vector<std::pair<OUString, OUString>>
+ m_aGroupProperties; ///< Properties applied on the groupshape.
+ sal_Int32 m_nLeft = 0;
+ sal_Int32 m_nTop = 0;
+ sal_Int32 m_nRight = 0;
+ sal_Int32 m_nBottom = 0;
+ std::optional<sal_Int32> m_oZ; ///< Z-Order of the shape.
+ sal_Int16 m_nHoriOrientRelation
+ = 0; ///< Horizontal text::RelOrientation for drawinglayer shapes.
+ sal_Int16 m_nVertOrientRelation = 0; ///< Vertical text::RelOrientation for drawinglayer shapes.
+ sal_uInt32 m_nHoriOrientRelationToken = 0; ///< Horizontal dmapper token for Writer pictures.
+ sal_uInt32 m_nVertOrientRelationToken = 0; ///< Vertical dmapper token for Writer pictures.
+ css::text::WrapTextMode m_nWrap = css::text::WrapTextMode::WrapTextMode_MAKE_FIXED_SIZE;
+ /// If shape is below text (true) or text is below shape (false).
+ bool m_bInBackground = false;
+ /// Wrap polygon, written by RTFSdrImport::resolve(), read by RTFDocumentImpl::resolvePict().
+ RTFSprms m_aWrapPolygonSprms;
+ /// Anchor attributes like wrap distance, written by RTFSdrImport::resolve(), read by RTFDocumentImpl::resolvePict().
+ RTFSprms m_aAnchorAttributes;
+ /// Wrap type, written by RTFDocumentImpl::popState(), read by RTFDocumentImpl::resolvePict().
+ std::pair<Id, RTFValue::Pointer_t> m_aWrapSprm{ 0, nullptr };
+};
+
+/// Stores the properties of a drawing object.
+class RTFDrawingObject : public RTFShape
+{
+public:
+ RTFDrawingObject();
+
+ void setShape(const css::uno::Reference<css::drawing::XShape>& xShape) { m_xShape = xShape; }
+ const css::uno::Reference<css::drawing::XShape>& getShape() const { return m_xShape; }
+ void setPropertySet(const css::uno::Reference<css::beans::XPropertySet>& xPropertySet)
+ {
+ m_xPropertySet = xPropertySet;
+ }
+ const css::uno::Reference<css::beans::XPropertySet>& getPropertySet() const
+ {
+ return m_xPropertySet;
+ }
+ std::vector<css::beans::PropertyValue>& getPendingProperties() { return m_aPendingProperties; }
+ void setLineColorR(sal_uInt8 nLineColorR) { m_nLineColorR = nLineColorR; }
+ sal_uInt8 getLineColorR() const { return m_nLineColorR; }
+ void setLineColorG(sal_uInt8 nLineColorG) { m_nLineColorG = nLineColorG; }
+ sal_uInt8 getLineColorG() const { return m_nLineColorG; }
+ void setLineColorB(sal_uInt8 nLineColorB) { m_nLineColorB = nLineColorB; }
+ sal_uInt8 getLineColorB() const { return m_nLineColorB; }
+ void setHasLineColor(bool bHasLineColor) { m_bHasLineColor = bHasLineColor; }
+ bool getHasLineColor() const { return m_bHasLineColor; }
+ void setFillColorR(sal_uInt8 nFillColorR) { m_nFillColorR = nFillColorR; }
+ sal_uInt8 getFillColorR() const { return m_nFillColorR; }
+ void setFillColorG(sal_uInt8 nFillColorG) { m_nFillColorG = nFillColorG; }
+ sal_uInt8 getFillColorG() const { return m_nFillColorG; }
+ void setFillColorB(sal_uInt8 nFillColorB) { m_nFillColorB = nFillColorB; }
+ sal_uInt8 getFillColorB() const { return m_nFillColorB; }
+ void setHasFillColor(bool bHasFillColor) { m_bHasFillColor = bHasFillColor; }
+ bool getHasFillColor() const { return m_bHasFillColor; }
+ void setDhgt(sal_Int32 nDhgt) { m_nDhgt = nDhgt; }
+ sal_Int32 getDhgt() const { return m_nDhgt; }
+ void setFLine(sal_Int32 nFLine) { m_nFLine = nFLine; }
+ sal_Int32 getFLine() const { return m_nFLine; }
+ void setPolyLineCount(sal_Int32 nPolyLineCount) { m_nPolyLineCount = nPolyLineCount; }
+ sal_Int32 getPolyLineCount() const { return m_nPolyLineCount; }
+ std::vector<css::awt::Point>& getPolyLinePoints() { return m_aPolyLinePoints; }
+ void setHadShapeText(bool bHadShapeText) { m_bHadShapeText = bHadShapeText; }
+ bool getHadShapeText() const { return m_bHadShapeText; }
+
+private:
+ css::uno::Reference<css::drawing::XShape> m_xShape;
+ css::uno::Reference<css::beans::XPropertySet> m_xPropertySet;
+ std::vector<css::beans::PropertyValue> m_aPendingProperties;
+ sal_uInt8 m_nLineColorR = 0;
+ sal_uInt8 m_nLineColorG = 0;
+ sal_uInt8 m_nLineColorB = 0;
+ bool m_bHasLineColor = false;
+ sal_uInt8 m_nFillColorR = 0;
+ sal_uInt8 m_nFillColorG = 0;
+ sal_uInt8 m_nFillColorB = 0;
+ bool m_bHasFillColor = false;
+ sal_Int32 m_nDhgt = 0;
+ sal_Int32 m_nFLine = -1;
+ sal_Int32 m_nPolyLineCount = 0;
+ std::vector<css::awt::Point> m_aPolyLinePoints;
+ bool m_bHadShapeText = false;
+};
+
+/// Stores the properties of a picture.
+class RTFPicture : public virtual SvRefBase
+{
+public:
+ sal_Int32 nWidth = 0;
+ sal_Int32 nHeight = 0;
+ sal_Int32 nGoalWidth = 0;
+ sal_Int32 nGoalHeight = 0;
+ sal_uInt16 nScaleX = 100;
+ sal_uInt16 nScaleY = 100;
+ short nCropT = 0;
+ short nCropB = 0;
+ short nCropL = 0;
+ short nCropR = 0;
+ sal_uInt16 eWMetafile = 0;
+ RTFBmpStyle eStyle = RTFBmpStyle::NONE;
+};
+
+/// Stores the properties of a frame
+class RTFFrame
+{
+private:
+ RTFDocumentImpl* m_pDocumentImpl;
+ sal_Int32 m_nX, m_nY, m_nW, m_nH;
+ sal_Int32 m_nHoriPadding, m_nVertPadding;
+ sal_Int32 m_nHoriAlign, m_nHoriAnchor, m_nVertAlign, m_nVertAnchor;
+ Id m_nHRule;
+ std::optional<Id> m_oWrap;
+
+public:
+ explicit RTFFrame(RTFParserState* pParserState);
+
+ /// Convert the stored properties to Sprms
+ RTFSprms getSprms();
+ /// Store a property
+ void setSprm(Id nId, Id nValue);
+ bool hasProperties() const;
+ /// If we got tokens indicating we're in a frame.
+ bool inFrame() const;
+};
+
+/// State of the parser, which gets saved / restored when changing groups.
+class RTFParserState
+{
+public:
+ /// Maps to OOXML's ascii, cs or eastAsia.
+ enum class RunType
+ {
+ NONE,
+ LOCH,
+ HICH,
+ DBCH,
+ LTRCH_RTLCH_1,
+ LTRCH_RTLCH_2,
+ RTLCH_LTRCH_1,
+ RTLCH_LTRCH_2
+ };
+
+ explicit RTFParserState(RTFDocumentImpl* pDocumentImpl);
+
+ void appendDestinationText(std::u16string_view rString)
+ {
+ if (m_pCurrentDestinationText)
+ m_pCurrentDestinationText->append(rString);
+ }
+
+ void setPropName(const OUString& rPropName) { m_aPropName = rPropName; }
+ OUString const& getPropName() const { return m_aPropName; }
+ void setPropType(const css::uno::Type& rPropType) { m_aPropType = rPropType; }
+ css::uno::Type const& getPropType() const { return m_aPropType; }
+ void setTableRowWidthAfter(int nTableRowWidthAfter)
+ {
+ m_nTableRowWidthAfter = nTableRowWidthAfter;
+ }
+ int getTableRowWidthAfter() const { return m_nTableRowWidthAfter; }
+ void setStartedTrackchange(bool bStartedTrackchange)
+ {
+ m_bStartedTrackchange = bStartedTrackchange;
+ }
+ bool getStartedTrackchange() const { return m_bStartedTrackchange; }
+ void setCreatedShapeGroup(bool bCreatedShapeGroup)
+ {
+ m_bCreatedShapeGroup = bCreatedShapeGroup;
+ }
+ bool getCreatedShapeGroup() const { return m_bCreatedShapeGroup; }
+ void setInShape(bool bInShape) { m_bInShape = bInShape; }
+ bool getInShape() const { return m_bInShape; }
+ void setInShapeGroup(bool bInShapeGroup) { m_bInShapeGroup = bInShapeGroup; }
+ bool getInShapeGroup() const { return m_bInShapeGroup; }
+ void setHadShapeText(bool bHadShapeText) { m_bHadShapeText = bHadShapeText; }
+ bool getHadShapeText() const { return m_bHadShapeText; }
+ void setInBackground(bool bInBackground) { m_bInBackground = bInBackground; }
+ bool getInBackground() const { return m_bInBackground; }
+ void setInListpicture(bool bInListpicture) { m_bInListpicture = bInListpicture; }
+ bool getInListpicture() const { return m_bInListpicture; }
+ void setCurrentBuffer(RTFBuffer_t* pCurrentBuffer) { m_pCurrentBuffer = pCurrentBuffer; }
+ RTFBuffer_t* getCurrentBuffer() const { return m_pCurrentBuffer; }
+ void setCurrentListOverrideIndex(int nCurrentListOverrideIndex)
+ {
+ m_nCurrentListOverrideIndex = nCurrentListOverrideIndex;
+ }
+ int getCurrentListOverrideIndex() const { return m_nCurrentListOverrideIndex; }
+ void setCurrentListIndex(int nCurrentListIndex) { m_nCurrentListIndex = nCurrentListIndex; }
+ int getCurrentListIndex() const { return m_nCurrentListIndex; }
+ void setCurrentCharacterStyleIndex(int nCurrentCharacterStyleIndex)
+ {
+ m_nCurrentCharacterStyleIndex = nCurrentCharacterStyleIndex;
+ }
+ int getCurrentCharacterStyleIndex() const { return m_nCurrentCharacterStyleIndex; }
+ void setCurrentStyleIndex(int nCurrentStyleIndex) { m_nCurrentStyleIndex = nCurrentStyleIndex; }
+ int getCurrentStyleIndex() const { return m_nCurrentStyleIndex; }
+ void setCurrentDestinationText(OUStringBuffer* pDestinationText)
+ {
+ m_pCurrentDestinationText = pDestinationText;
+ }
+ OUStringBuffer* getCurrentDestinationText() const { return m_pCurrentDestinationText; }
+ OUStringBuffer& getDestinationText() { return m_aDestinationText; }
+ void setMinute(sal_uInt16 nMinute) { m_nMinute = nMinute; }
+ sal_uInt16 getMinute() const { return m_nMinute; }
+ void setHour(sal_uInt16 nHour) { m_nHour = nHour; }
+ sal_uInt16 getHour() const { return m_nHour; }
+ void setDay(sal_uInt16 nDay) { m_nDay = nDay; }
+ sal_uInt16 getDay() const { return m_nDay; }
+ void setMonth(sal_uInt16 nMonth) { m_nMonth = nMonth; }
+ sal_uInt16 getMonth() const { return m_nMonth; }
+ void setYear(sal_uInt16 nYear) { m_nYear = nYear; }
+ sal_uInt16 getYear() const { return m_nYear; }
+ void setRunType(RunType eRunType) { m_eRunType = eRunType; }
+ RunType getRunType() const { return m_eRunType; }
+ RTFFrame& getFrame() { return m_aFrame; }
+ RTFDrawingObject& getDrawingObject() { return m_aDrawingObject; }
+ RTFShape& getShape() { return m_aShape; }
+ RTFPicture& getPicture() { return m_aPicture; }
+ void setLevelNumbersValid(bool bLevelNumbersValid)
+ {
+ m_bLevelNumbersValid = bLevelNumbersValid;
+ }
+ bool getLevelNumbersValid() const { return m_bLevelNumbersValid; }
+ std::vector<sal_Int32>& getLevelNumbers() { return m_aLevelNumbers; }
+ RTFSprms& getListLevelEntries() { return m_aListLevelEntries; }
+ int& getListLevelNum() { return m_nListLevelNum; }
+ void setBinaryToRead(int nBinaryToRead) { m_nBinaryToRead = nBinaryToRead; }
+ int getBinaryToRead() const { return m_nBinaryToRead; }
+ int& getCharsToSkip() { return m_nCharsToSkip; }
+ void setUc(int nUc) { m_nUc = nUc; }
+ int getUc() const { return m_nUc; }
+ void setCurrentEncoding(rtl_TextEncoding nCurrentEncoding)
+ {
+ m_nCurrentEncoding = nCurrentEncoding;
+ }
+ rtl_TextEncoding getCurrentEncoding() const { return m_nCurrentEncoding; }
+ RTFColorTableEntry& getCurrentColor() { return m_aCurrentColor; }
+ RTFSprms& getTabAttributes() { return m_aTabAttributes; }
+ RTFSprms& getTableCellAttributes() { return m_aTableCellAttributes; }
+ RTFSprms& getTableCellSprms() { return m_aTableCellSprms; }
+ RTFSprms& getTableRowAttributes() { return m_aTableRowAttributes; }
+ RTFSprms& getTableRowSprms() { return m_aTableRowSprms; }
+ RTFSprms& getSectionAttributes() { return m_aSectionAttributes; }
+ RTFSprms& getSectionSprms() { return m_aSectionSprms; }
+ RTFSprms& getParagraphAttributes() { return m_aParagraphAttributes; }
+ RTFSprms& getParagraphSprms() { return m_aParagraphSprms; }
+ RTFSprms& getCharacterAttributes() { return m_aCharacterAttributes; }
+ RTFSprms& getCharacterSprms() { return m_aCharacterSprms; }
+ RTFSprms& getTableAttributes() { return m_aTableAttributes; }
+ RTFSprms& getTableSprms() { return m_aTableSprms; }
+ void setBorderState(RTFBorderState nBorderState) { m_nBorderState = nBorderState; }
+ RTFBorderState getBorderState() const { return m_nBorderState; }
+ void setFieldStatus(RTFFieldStatus eFieldStatus) { m_eFieldStatus = eFieldStatus; }
+ RTFFieldStatus getFieldStatus() const { return m_eFieldStatus; }
+ void setFieldLocked(bool bSet) { m_bFieldLocked = bSet; }
+ bool isFieldLocked() const { return m_bFieldLocked; }
+ void setDestination(Destination eDestination) { m_eDestination = eDestination; }
+ Destination getDestination() const { return m_eDestination; }
+ void setInternalState(RTFInternalState nInternalState) { m_nInternalState = nInternalState; }
+ RTFInternalState getInternalState() const { return m_nInternalState; }
+ RTFDocumentImpl* getDocumentImpl() { return m_pDocumentImpl; }
+ OUString getDocVar() { return m_aDocVar; }
+ void appendDocVar(OUString& aDocVar) { m_aDocVar += aDocVar; };
+ OUString getDocVarName() { return m_aDocVarName; }
+ void setDocVarName(OUString& aDocVarName) { m_aDocVarName = aDocVarName; }
+ void clearDocVarName() { m_aDocVarName = ""; }
+
+private:
+ RTFDocumentImpl* m_pDocumentImpl;
+ RTFInternalState m_nInternalState;
+ Destination m_eDestination;
+ RTFFieldStatus m_eFieldStatus;
+ bool m_bFieldLocked;
+ RTFBorderState m_nBorderState;
+ // font table, stylesheet table
+ RTFSprms m_aTableSprms;
+ RTFSprms m_aTableAttributes;
+ // reset by plain
+ RTFSprms m_aCharacterSprms;
+ RTFSprms m_aCharacterAttributes;
+ // reset by pard
+ RTFSprms m_aParagraphSprms;
+ RTFSprms m_aParagraphAttributes;
+ // reset by sectd
+ RTFSprms m_aSectionSprms;
+ RTFSprms m_aSectionAttributes;
+ // reset by trowd
+ RTFSprms m_aTableRowSprms;
+ RTFSprms m_aTableRowAttributes;
+ // reset by cellx
+ RTFSprms m_aTableCellSprms;
+ RTFSprms m_aTableCellAttributes;
+ // reset by tx
+ RTFSprms m_aTabAttributes;
+
+ RTFColorTableEntry m_aCurrentColor;
+
+ rtl_TextEncoding m_nCurrentEncoding;
+
+ /// Current \uc value.
+ int m_nUc;
+ /// Characters to skip, set to nUc by \u.
+ int m_nCharsToSkip;
+ /// Characters to read, once in binary mode.
+ int m_nBinaryToRead;
+
+ /// Next list level index to use when parsing list table.
+ int m_nListLevelNum;
+ /// List level entries, which will form a list entry later.
+ RTFSprms m_aListLevelEntries;
+ /// List of character positions in leveltext to replace.
+ std::vector<sal_Int32> m_aLevelNumbers;
+ /// If aLevelNumbers should be read at all.
+ bool m_bLevelNumbersValid;
+
+ RTFPicture m_aPicture;
+ RTFShape m_aShape;
+ RTFDrawingObject m_aDrawingObject;
+ RTFFrame m_aFrame;
+
+ RunType m_eRunType;
+
+ // Info group.
+ sal_Int16 m_nYear;
+ sal_uInt16 m_nMonth;
+ sal_uInt16 m_nDay;
+ sal_uInt16 m_nHour;
+ sal_uInt16 m_nMinute;
+
+ /// Text from special destinations.
+ OUStringBuffer m_aDestinationText{ 512 };
+ /// point to the buffer of the current destination
+ OUStringBuffer* m_pCurrentDestinationText;
+
+ /// Index of the current style.
+ int m_nCurrentStyleIndex;
+ /// Index of the current character style.
+ int m_nCurrentCharacterStyleIndex;
+ /// Current listid, points to a listtable entry.
+ int m_nCurrentListIndex = -1;
+ /// Current ls, points to a listoverridetable entry.
+ int m_nCurrentListOverrideIndex = -1;
+
+ /// Points to the active buffer, if there is one.
+ RTFBuffer_t* m_pCurrentBuffer;
+
+ /// If we're inside a \listpicture group.
+ bool m_bInListpicture;
+
+ /// If we're inside a \background group.
+ bool m_bInBackground;
+
+ bool m_bHadShapeText;
+ bool m_bInShapeGroup; ///< If we're inside a \shpgrp group.
+ bool m_bInShape; ///< If we're inside a \shp group.
+ bool m_bCreatedShapeGroup; ///< A GroupShape was created and pushed to the parent stack.
+ bool m_bStartedTrackchange; ///< Track change is started, need to end it before popping.
+
+ /// User-defined property: key name.
+ OUString m_aPropName;
+ /// User-defined property: value type.
+ css::uno::Type m_aPropType;
+
+ /// Width of invisible cell at the end of the row.
+ int m_nTableRowWidthAfter;
+
+ /// For importing document variables which are not referenced in the document
+ OUString m_aDocVar;
+ OUString m_aDocVarName;
+};
+
+/// An RTF stack is similar to std::stack, except that it has an operator[].
+struct RTFStack
+{
+private:
+ std::deque<RTFParserState> m_Impl;
+
+public:
+ RTFParserState& top()
+ {
+ if (m_Impl.empty())
+ throw css::io::WrongFormatException(
+ "Parser state is empty! Invalid usage of destination braces in RTF?", nullptr);
+ return m_Impl.back();
+ }
+ void pop()
+ {
+ if (m_Impl.empty())
+ throw css::io::WrongFormatException(
+ "Parser state is empty! Invalid usage of destination braces in RTF?", nullptr);
+ return m_Impl.pop_back();
+ }
+ void push(RTFParserState const& rState) { return m_Impl.push_back(rState); }
+ bool empty() const { return m_Impl.empty(); }
+ size_t size() const { return m_Impl.size(); }
+ const RTFParserState& operator[](size_t nIndex) const { return m_Impl[nIndex]; }
+ RTFParserState& operator[](size_t nIndex) { return m_Impl[nIndex]; }
+};
+
+void putBorderProperty(RTFStack& aStates, Id nId, const RTFValue::Pointer_t& pValue);
+void putNestedSprm(RTFSprms& rSprms, Id nParent, Id nId, const RTFValue::Pointer_t& pValue,
+ RTFOverwrite eOverwrite = RTFOverwrite::NO_APPEND);
+Id getParagraphBorder(sal_uInt32 nIndex);
+void putNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId, const RTFValue::Pointer_t& pValue,
+ RTFOverwrite eOverwrite = RTFOverwrite::YES, bool bAttribute = true);
+bool eraseNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId);
+
+/// Looks up the nParent then the nested nId attribute in rSprms.
+RTFValue::Pointer_t getNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId);
+
+/// Looks up the nParent then the nested nId sprm in rSprms.
+RTFValue::Pointer_t getNestedSprm(RTFSprms& rSprms, Id nParent, Id nId);
+
+/// Checks if rName is contained at least once in rProperties as a key.
+bool findPropertyName(const std::vector<css::beans::PropertyValue>& rProperties,
+ const OUString& rName);
+RTFSprms& getLastAttributes(RTFSprms& rSprms, Id nId);
+OString DTTM22OString(tools::Long nDTTM);
+
+/// Implementation of the RTFDocument interface.
+class RTFDocumentImpl : public RTFDocument, public RTFListener
+{
+public:
+ using Pointer_t = tools::SvRef<RTFDocumentImpl>;
+ RTFDocumentImpl(css::uno::Reference<css::uno::XComponentContext> const& xContext,
+ css::uno::Reference<css::io::XInputStream> const& xInputStream,
+ css::uno::Reference<css::lang::XComponent> const& xDstDoc,
+ css::uno::Reference<css::frame::XFrame> const& xFrame,
+ css::uno::Reference<css::task::XStatusIndicator> const& xStatusIndicator,
+ const utl::MediaDescriptor& rMediaDescriptor);
+ ~RTFDocumentImpl() override;
+
+ // RTFDocument
+ void resolve(Stream& rMapper) override;
+
+ // RTFListener
+ RTFError dispatchDestination(RTFKeyword nKeyword) override;
+ RTFError dispatchFlag(RTFKeyword nKeyword) override;
+ RTFError dispatchSymbol(RTFKeyword nKeyword) override;
+ RTFError dispatchToggle(RTFKeyword nKeyword, bool bParam, int nParam) override;
+ RTFError dispatchValue(RTFKeyword nKeyword, int nParam) override;
+ bool dispatchTableSprmValue(RTFKeyword nKeyword, int nParam);
+ bool dispatchCharacterSprmValue(RTFKeyword nKeyword, int nParam);
+ bool dispatchCharacterAttributeValue(RTFKeyword nKeyword, int nParam);
+ bool dispatchParagraphSprmValue(RTFKeyword nKeyword, int nParam);
+ bool dispatchInfoValue(RTFKeyword nKeyword, int nParam);
+ bool dispatchFrameValue(RTFKeyword nKeyword, int nParam);
+ bool dispatchTableValue(RTFKeyword nKeyword, int nParam);
+ RTFError resolveChars(char ch) override;
+ RTFError pushState() override;
+ RTFError beforePopState(RTFParserState& rState);
+ RTFError popState() override;
+ void afterPopState(RTFParserState& rState);
+ Destination getDestination() override;
+ void setDestination(Destination eDestination) override;
+ RTFInternalState getInternalState() override;
+ void setInternalState(RTFInternalState nInternalState) override;
+ bool getSkipUnknown() override;
+ void setSkipUnknown(bool bSkipUnknown) override;
+ void finishSubstream() override;
+ bool isSubstream() const override;
+
+ Stream& Mapper() { return *m_pMapperStream; }
+ void setSuperstream(RTFDocumentImpl* pSuperstream);
+ const css::uno::Reference<css::lang::XMultiServiceFactory>& getModelFactory() const
+ {
+ return m_xModelFactory;
+ }
+ bool isInBackground();
+ void setDestinationText(std::u16string_view rString);
+ /// Resolve a picture: If not inline, then anchored.
+ void resolvePict(bool bInline, css::uno::Reference<css::drawing::XShape> const& rShape);
+
+ /// If this is the first run of the document, starts the initial paragraph.
+ void checkFirstRun();
+ /// Send NS_ooxml::LN_settings_settings to dmapper.
+ void outputSettingsTable();
+ /// If the initial paragraph is started.
+ bool getFirstRun() const { return m_bFirstRun; }
+ /// If we need to add a dummy paragraph before a section break.
+ void setNeedPar(bool bNeedPar);
+ /// Return the dmapper index of an RTF index for fonts.
+ int getFontIndex(int nIndex);
+ /// Return the name of the font, based on a dmapper index.
+ OUString getFontName(int nIndex);
+ /// Return the style name of an RTF style index.
+ OUString getStyleName(int nIndex);
+ /// Return the style type of an RTF style index.
+ Id getStyleType(int nIndex);
+ /// Return the encoding associated with a font index.
+ rtl_TextEncoding getEncoding(int nFontIndex);
+ /// Get the default parser state.
+ RTFParserState& getDefaultState();
+ oox::GraphicHelper& getGraphicHelper();
+ /// Are we inside the stylesheet table?
+ bool isStyleSheetImport();
+ /// Resets m_aStates.top().aFrame.
+ void resetFrame();
+ /// Buffers properties to be sent later.
+ void bufferProperties(RTFBuffer_t& rBuffer, const RTFValue::Pointer_t& pValue,
+ const tools::SvRef<TableRowBuffer>& pTableProperties);
+ /// implement non-obvious RTF specific style inheritance
+ RTFReferenceTable::Entries_t deduplicateStyleTable();
+
+private:
+ SvStream& Strm();
+ Color getColorTable(sal_uInt32 nIndex);
+ writerfilter::Reference<Properties>::Pointer_t createStyleProperties();
+ void resetSprms();
+ void resetAttributes();
+ void resolveSubstream(std::size_t nPos, Id nId);
+ void resolveSubstream(std::size_t nPos, Id nId, OUString const& rIgnoreFirst);
+
+ void text(OUString& rString);
+ // Sends a single character to dmapper, taking care of buffering.
+ void singleChar(sal_uInt8 nValue, bool bRunProps = false);
+ // Sends run properties to dmapper, taking care of buffering.
+ void runProps();
+ void runBreak();
+ void parBreak();
+ void tableBreak();
+ writerfilter::Reference<Properties>::Pointer_t
+ getProperties(const RTFSprms& rAttributes, RTFSprms const& rSprms, Id nStyleType);
+ void checkNeedPap();
+ void handleFontTableEntry();
+ void sectBreak(bool bFinal = false);
+ void prepareProperties(RTFParserState& rState,
+ writerfilter::Reference<Properties>::Pointer_t& o_rpParagraphProperties,
+ writerfilter::Reference<Properties>::Pointer_t& o_rpFrameProperties,
+ writerfilter::Reference<Properties>::Pointer_t& o_rpTableRowProperties,
+ int nCells, int nCurrentCellX);
+ /// Send the passed properties to dmapper.
+ void sendProperties(writerfilter::Reference<Properties>::Pointer_t const& pParagraphProperties,
+ writerfilter::Reference<Properties>::Pointer_t const& pFrameProperties,
+ writerfilter::Reference<Properties>::Pointer_t const& pTableRowProperties);
+ void replayRowBuffer(RTFBuffer_t& rBuffer, ::std::deque<RTFSprms>& rCellsSrpms,
+ ::std::deque<RTFSprms>& rCellsAttributes, int nCells);
+ void replayBuffer(RTFBuffer_t& rBuffer, RTFSprms* pSprms, RTFSprms const* pAttributes);
+ /// If we have some unicode or hex characters to send.
+ void checkUnicode(bool bUnicode, bool bHex);
+ /// If we need a final section break at the end of the document.
+ void setNeedSect(bool bNeedSect);
+ void resetTableRowProperties();
+ void backupTableRowProperties();
+ void restoreTableRowProperties();
+ /// Turns the destination text into an input stream of the current OLE attributes.
+ RTFError handleEmbeddedObject();
+
+ css::uno::Reference<css::uno::XComponentContext> const& m_xContext;
+ css::uno::Reference<css::io::XInputStream> const& m_xInputStream;
+ css::uno::Reference<css::lang::XComponent> const& m_xDstDoc;
+ css::uno::Reference<css::frame::XFrame> const& m_xFrame;
+ css::uno::Reference<css::task::XStatusIndicator> const& m_xStatusIndicator;
+ css::uno::Reference<css::lang::XMultiServiceFactory> m_xModelFactory;
+ css::uno::Reference<css::document::XDocumentProperties> m_xDocumentProperties;
+ std::unique_ptr<SvStream> m_pInStream;
+ Stream* m_pMapperStream;
+ tools::SvRef<RTFSdrImport> m_pSdrImport;
+ tools::SvRef<RTFTokenizer> m_pTokenizer;
+ RTFStack m_aStates;
+ /// Read by RTF_PARD.
+ RTFParserState m_aDefaultState;
+ bool m_bSkipUnknown;
+ /// Font index <-> encoding map, *not* part of the parser state
+ std::map<int, rtl_TextEncoding> m_aFontEncodings;
+ /// Font index <-> name map.
+ std::map<int, OUString> m_aFontNames;
+ /// Maps the non-continuous font indexes to the continuous dmapper indexes.
+ std::vector<int> m_aFontIndexes;
+ /// Maps style indexes to style names.
+ std::map<int, OUString> m_aStyleNames;
+ /// Maps style indexes to style types.
+ std::map<int, Id> m_aStyleTypes;
+ /// Color index <-> RGB color value map
+ std::vector<Color> m_aColorTable;
+ /// to start initial paragraph / section after font/style tables
+ bool m_bFirstRun;
+ /// except in the case of tables in initial multicolumn section (global for assertion)
+ bool m_bFirstRunException;
+ /// If paragraph properties should be emitted on next run.
+ bool m_bNeedPap;
+ /// If we need to emit a CR at the end of substream.
+ bool m_bNeedCr;
+ /// Original value of m_bNeedCr -- saved/restored before/after textframes.
+ bool m_bNeedCrOrig;
+ bool m_bNeedPar;
+ /// If set, an empty paragraph will be added at the end of the document.
+ bool m_bNeedFinalPar;
+ /// The list table and list override table combined.
+ RTFSprms m_aListTableSprms;
+ /// Maps between listoverridetable and listtable indexes.
+ std::map<int, int> m_aListOverrideTable;
+ /// Maps listtable indexes to listtable entries.
+ std::map<int, RTFValue::Pointer_t> m_aListTable;
+ /// Index of the current list level in a list table entry.
+ int m_nListLevel = -1;
+ /// Maps List level indexes to removed values in the current list entry.
+ std::map<int, int> m_aInvalidListLevelFirstIndents;
+ /// Maps list table indexes to levels (and their removed values).
+ std::map<int, std::map<int, int>> m_aInvalidListTableFirstIndents;
+ /// The settings table attributes.
+ RTFSprms m_aSettingsTableAttributes;
+ /// The settings table sprms.
+ RTFSprms m_aSettingsTableSprms;
+
+ std::shared_ptr<oox::GraphicHelper> m_pGraphicHelper;
+
+ /// cell props buffer for nested tables, reset by \nestrow
+ /// the \nesttableprops is a destination and must follow the
+ /// nested cells, so it should be sufficient to store the
+ /// currently active one, no need for a stack of them
+ int m_nNestedCells;
+ std::deque<RTFSprms> m_aNestedTableCellsSprms;
+ std::deque<RTFSprms> m_aNestedTableCellsAttributes;
+ /// cell props buffer for top-level table, reset by \row
+ int m_nTopLevelCells;
+ std::deque<RTFSprms> m_aTopLevelTableCellsSprms;
+ std::deque<RTFSprms> m_aTopLevelTableCellsAttributes;
+ /// backup of top-level props, to support inheriting cell props
+ int m_nInheritingCells;
+ std::deque<RTFSprms> m_aTableInheritingCellsSprms;
+ std::deque<RTFSprms> m_aTableInheritingCellsAttributes;
+
+ // Left row margin (for nested and top-level rows)
+ int m_nNestedTRLeft;
+ int m_nTopLevelTRLeft;
+
+ /// Current cellx value (nested table)
+ int m_nNestedCurrentCellX;
+ /// Current cellx value (top-level table)
+ int m_nTopLevelCurrentCellX;
+
+ // Backup of what \trowd clears, to work around invalid input.
+ RTFSprms m_aBackupTableRowSprms;
+ RTFSprms m_aBackupTableRowAttributes;
+ int m_nBackupTopLevelCurrentCellX;
+
+ /// Buffered table cells, till cell definitions are not reached.
+ /// for nested table, one buffer per table level
+ std::deque<RTFBuffer_t> m_aTableBufferStack;
+ /// Buffered superscript, till footnote is reached (or not).
+ RTFBuffer_t m_aSuperBuffer;
+
+ /// Superstream of this substream.
+ RTFDocumentImpl* m_pSuperstream;
+ /// Type of the stream: header, footer, footnote, etc.
+ Id m_nStreamType;
+ std::queue<std::pair<Id, std::size_t>> m_nHeaderFooterPositions;
+ std::size_t m_nGroupStartPos;
+ /// Ignore the first occurrence of this text.
+ OUString m_aIgnoreFirst;
+ /// Bookmark name <-> index map.
+ std::map<OUString, int> m_aBookmarks;
+ /// Revision index <-> author map.
+ std::map<int, OUString> m_aAuthors;
+ /// Annotation author of the next annotation.
+ OUString m_aAuthor;
+ /// Initials of author of the next annotation.
+ OUString m_aAuthorInitials;
+
+ RTFSprms m_aFormfieldSprms;
+ RTFSprms m_aFormfieldAttributes;
+ RTFFormFieldType m_nFormFieldType;
+
+ /// OLE attributes are attributes of the ooxml:OLEObject_OLEObject sprm.
+ RTFSprms m_aOLEAttributes;
+ RTFSprms m_aObjectAttributes;
+ /** If we are in an object group and if the we use its
+ * \objdata element.
+ * (if we don't use the \objdata we use the \result element)*/
+ bool m_bObject;
+ /// If the data for a picture is a binary one, it's stored here.
+ std::shared_ptr<SvStream> m_pBinaryData;
+
+ RTFReferenceTable::Entries_t m_aFontTableEntries;
+ int m_nCurrentFontIndex;
+ /// Used only during font table parsing till we don't know the font name.
+ int m_nCurrentEncoding;
+ /// Raw default font index, use getFont() on it to get a real one.
+ int m_nDefaultFontIndex;
+
+ /// To avoid copying entries between DomainMapper instances it is stored as pointer
+ std::shared_ptr<RTFReferenceTable::Entries_t> m_pStyleTableEntries;
+ int m_nCurrentStyleIndex;
+ bool m_bFormField;
+ /// For the INCLUDEPICTURE field's argument.
+ OUString m_aPicturePath;
+ // Unicode characters are collected here so we don't have to send them one by one.
+ OUStringBuffer m_aUnicodeBuffer{ 512 };
+ /// Same for hex characters.
+ OStringBuffer m_aHexBuffer{ 512 };
+ /// Formula import.
+ oox::formulaimport::XmlStreamBuilder m_aMathBuffer;
+ /// Normal text property, that is math italic and math spacing are not applied to the current run.
+ bool m_bMathNor;
+ /// If the next continuous section break should be ignored.
+ bool m_bIgnoreNextContSectBreak;
+ /// clean up a synthetic page break, see RTF_PAGE
+ /// if inactive value is -1, otherwise the RTF_SKB* to restore
+ RTFKeyword m_nResetBreakOnSectBreak;
+ /// If a section break is needed before the end of the doc (false right after a section break).
+ bool m_bNeedSect;
+ /// If aFrame.inFrame() was true in the previous state.
+ bool m_bWasInFrame;
+ /// A picture was seen in the current paragraph.
+ bool m_bHadPicture;
+ /// The document has multiple sections.
+ bool m_bHadSect;
+ /// Max width of the rows in the current table.
+ int m_nCellxMax;
+ /// ID of the next \listlevel picture.
+ int m_nListPictureId;
+
+ /// New document means not pasting into an existing one.
+ bool m_bIsNewDoc;
+ /// The media descriptor contains e.g. the base URL of the document.
+ const utl::MediaDescriptor& m_rMediaDescriptor;
+
+ /// Flags for ensuring that only one header and footer is added per section
+ bool m_hasRHeader;
+ bool m_hasFHeader;
+ bool m_hasRFooter;
+ bool m_hasFFooter;
+
+ /// Are we after a \cell, but before a \row?
+ bool m_bAfterCellBeforeRow;
+};
+} // namespace writerfilter::rtftok
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */