summaryrefslogtreecommitdiffstats
path: root/starmath/source/rtfexport.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /starmath/source/rtfexport.cxx
parentInitial commit. (diff)
downloadlibreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz
libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'starmath/source/rtfexport.cxx')
-rw-r--r--starmath/source/rtfexport.cxx505
1 files changed, 505 insertions, 0 deletions
diff --git a/starmath/source/rtfexport.cxx b/starmath/source/rtfexport.cxx
new file mode 100644
index 000000000..87e51a3b9
--- /dev/null
+++ b/starmath/source/rtfexport.cxx
@@ -0,0 +1,505 @@
+/* -*- 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 "rtfexport.hxx"
+#include <node.hxx>
+
+#include <svtools/rtfkeywd.hxx>
+#include <filter/msfilter/rtfutil.hxx>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+
+SmRtfExport::SmRtfExport(const SmNode* pIn)
+ : SmWordExportBase(pIn)
+ , m_pBuffer(nullptr)
+ , m_nEncoding(RTL_TEXTENCODING_DONTKNOW)
+{
+}
+
+void SmRtfExport::ConvertFromStarMath(OStringBuffer& rBuffer, rtl_TextEncoding nEncoding)
+{
+ if (!m_pTree)
+ return;
+ m_pBuffer = &rBuffer;
+ m_nEncoding = nEncoding;
+ m_pBuffer->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE LO_STRING_SVTOOLS_RTF_MOMATH " ");
+ HandleNode(m_pTree, 0);
+ m_pBuffer->append("}"); // moMath
+}
+
+// NOTE: This is still work in progress and unfinished, but it already covers a good
+// part of the rtf math stuff.
+
+void SmRtfExport::HandleVerticalStack(const SmNode* pNode, int nLevel)
+{
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MEQARR " ");
+ int size = pNode->GetNumSubNodes();
+ for (int i = 0; i < size; ++i)
+ {
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ HandleNode(pNode->GetSubNode(i), nLevel + 1);
+ m_pBuffer->append("}"); // me
+ }
+ m_pBuffer->append("}"); // meqArr
+}
+
+void SmRtfExport::HandleText(const SmNode* pNode, int /*nLevel*/)
+{
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MR " ");
+
+ if (pNode->GetToken().eType == TTEXT) // literal text
+ m_pBuffer->append(LO_STRING_SVTOOLS_RTF_MNOR " ");
+
+ auto pTemp = static_cast<const SmTextNode*>(pNode);
+ SAL_INFO("starmath.rtf", "Text: " << pTemp->GetText());
+ for (sal_Int32 i = 0; i < pTemp->GetText().getLength(); i++)
+ {
+ sal_uInt16 nChar = pTemp->GetText()[i];
+ OUString aValue(SmTextNode::ConvertSymbolToUnicode(nChar));
+ m_pBuffer->append(msfilter::rtfutil::OutString(aValue, m_nEncoding));
+ }
+
+ m_pBuffer->append("}"); // mr
+}
+
+void SmRtfExport::HandleFractions(const SmNode* pNode, int nLevel, const char* type)
+{
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MF " ");
+ if (type)
+ {
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MFPR " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MTYPE " ");
+ m_pBuffer->append(type);
+ m_pBuffer->append("}"); // mtype
+ m_pBuffer->append("}"); // mfPr
+ }
+ assert(pNode->GetNumSubNodes() == 3);
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MNUM " ");
+ HandleNode(pNode->GetSubNode(0), nLevel + 1);
+ m_pBuffer->append("}"); // mnum
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MDEN " ");
+ HandleNode(pNode->GetSubNode(2), nLevel + 1);
+ m_pBuffer->append("}"); // mden
+ m_pBuffer->append("}"); // mf
+}
+
+void SmRtfExport::HandleAttribute(const SmAttributNode* pNode, int nLevel)
+{
+ switch (pNode->Attribute()->GetToken().eType)
+ {
+ case TCHECK:
+ case TACUTE:
+ case TGRAVE:
+ case TBREVE:
+ case TCIRCLE:
+ case TVEC:
+ case TTILDE:
+ case THAT:
+ case TDOT:
+ case TDDOT:
+ case TDDDOT:
+ case TWIDETILDE:
+ case TWIDEHAT:
+ case TWIDEHARPOON:
+ case TWIDEVEC:
+ case TBAR:
+ {
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MACC " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MACCPR " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MCHR " ");
+ OUString aValue(pNode->Attribute()->GetToken().cMathChar);
+ m_pBuffer->append(msfilter::rtfutil::OutString(aValue, m_nEncoding));
+ m_pBuffer->append("}"); // mchr
+ m_pBuffer->append("}"); // maccPr
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ HandleNode(pNode->Body(), nLevel + 1);
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("}"); // macc
+ break;
+ }
+ case TOVERLINE:
+ case TUNDERLINE:
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MBAR " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MBARPR " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MPOS " ");
+ m_pBuffer->append((pNode->Attribute()->GetToken().eType == TUNDERLINE) ? "bot" : "top");
+ m_pBuffer->append("}"); // mpos
+ m_pBuffer->append("}"); // mbarPr
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ HandleNode(pNode->Body(), nLevel + 1);
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("}"); // mbar
+ break;
+ case TOVERSTRIKE:
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MBORDERBOX " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MBORDERBOXPR " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MHIDETOP " 1}");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MHIDEBOT " 1}");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MHIDELEFT " 1}");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MHIDERIGHT " 1}");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSTRIKEH " 1}");
+ m_pBuffer->append("}"); // mborderBoxPr
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ HandleNode(pNode->Body(), nLevel + 1);
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("}"); // mborderBox
+ break;
+ default:
+ HandleAllSubNodes(pNode, nLevel);
+ break;
+ }
+}
+
+void SmRtfExport::HandleRoot(const SmRootNode* pNode, int nLevel)
+{
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MRAD " ");
+ if (const SmNode* argument = pNode->Argument())
+ {
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MDEG " ");
+ HandleNode(argument, nLevel + 1);
+ m_pBuffer->append("}"); // mdeg
+ }
+ else
+ {
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MRADPR " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MDEGHIDE " 1}");
+ m_pBuffer->append("}"); // mradPr
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MDEG " }"); // empty but present
+ }
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ HandleNode(pNode->Body(), nLevel + 1);
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("}"); // mrad
+}
+
+namespace
+{
+OString mathSymbolToString(const SmNode* node, rtl_TextEncoding nEncoding)
+{
+ assert(node->GetType() == SmNodeType::Math || node->GetType() == SmNodeType::MathIdent);
+ auto txtnode = static_cast<const SmTextNode*>(node);
+ if (txtnode->GetText().isEmpty())
+ return OString();
+ assert(txtnode->GetText().getLength() == 1);
+ sal_Unicode chr = SmTextNode::ConvertSymbolToUnicode(txtnode->GetText()[0]);
+ OUString aValue(chr);
+ return msfilter::rtfutil::OutString(aValue, nEncoding);
+}
+}
+
+void SmRtfExport::HandleOperator(const SmOperNode* pNode, int nLevel)
+{
+ SAL_INFO("starmath.rtf", "Operator: " << int(pNode->GetToken().eType));
+ switch (pNode->GetToken().eType)
+ {
+ case TINT:
+ case TINTD:
+ case TIINT:
+ case TIIINT:
+ case TLINT:
+ case TLLINT:
+ case TLLLINT:
+ case TPROD:
+ case TCOPROD:
+ case TSUM:
+ {
+ const SmSubSupNode* subsup
+ = pNode->GetSubNode(0)->GetType() == SmNodeType::SubSup
+ ? static_cast<const SmSubSupNode*>(pNode->GetSubNode(0))
+ : nullptr;
+ const SmNode* operation = subsup ? subsup->GetBody() : pNode->GetSubNode(0);
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MNARY " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MNARYPR " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MCHR " ");
+ m_pBuffer->append(mathSymbolToString(operation, m_nEncoding));
+ m_pBuffer->append("}"); // mchr
+ if (!subsup || !subsup->GetSubSup(CSUB))
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUBHIDE " 1}");
+ if (!subsup || !subsup->GetSubSup(CSUP))
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUPHIDE " 1}");
+ m_pBuffer->append("}"); // mnaryPr
+ if (!subsup || !subsup->GetSubSup(CSUB))
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUB " }");
+ else
+ {
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUB " ");
+ HandleNode(subsup->GetSubSup(CSUB), nLevel + 1);
+ m_pBuffer->append("}"); // msub
+ }
+ if (!subsup || !subsup->GetSubSup(CSUP))
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUP " }");
+ else
+ {
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUP " ");
+ HandleNode(subsup->GetSubSup(CSUP), nLevel + 1);
+ m_pBuffer->append("}"); // msup
+ }
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ HandleNode(pNode->GetSubNode(1), nLevel + 1); // body
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("}"); // mnary
+ break;
+ }
+ case TLIM:
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MFUNC " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MFNAME " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIMLOW " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ HandleNode(pNode->GetSymbol(), nLevel + 1);
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIM " ");
+ if (const SmSubSupNode* subsup
+ = pNode->GetSubNode(0)->GetType() == SmNodeType::SubSup
+ ? static_cast<const SmSubSupNode*>(pNode->GetSubNode(0))
+ : nullptr)
+ if (subsup->GetSubSup(CSUB))
+ HandleNode(subsup->GetSubSup(CSUB), nLevel + 1);
+ m_pBuffer->append("}"); // mlim
+ m_pBuffer->append("}"); // mlimLow
+ m_pBuffer->append("}"); // mfName
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ HandleNode(pNode->GetSubNode(1), nLevel + 1); // body
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("}"); // mfunc
+ break;
+ default:
+ SAL_INFO("starmath.rtf", "TODO: " << OSL_THIS_FUNC << " unhandled oper type");
+ break;
+ }
+}
+
+void SmRtfExport::HandleSubSupScriptInternal(const SmSubSupNode* pNode, int nLevel, int flags)
+{
+ // rtf supports only a certain combination of sub/super scripts, but LO can have any,
+ // so try to merge it using several tags if necessary
+ if (flags == 0) // none
+ return;
+ if ((flags & (1 << RSUP | 1 << RSUB)) == (1 << RSUP | 1 << RSUB))
+ {
+ // m:sSubSup
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSSUBSUP " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ flags &= ~(1 << RSUP | 1 << RSUB);
+ if (flags == 0)
+ HandleNode(pNode->GetBody(), nLevel + 1);
+ else
+ HandleSubSupScriptInternal(pNode, nLevel, flags);
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUB " ");
+ HandleNode(pNode->GetSubSup(RSUB), nLevel + 1);
+ m_pBuffer->append("}"); // msub
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUP " ");
+ HandleNode(pNode->GetSubSup(RSUP), nLevel + 1);
+ m_pBuffer->append("}"); // msup
+ m_pBuffer->append("}"); // msubSup
+ }
+ else if ((flags & (1 << RSUB)) == 1 << RSUB)
+ {
+ // m:sSub
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSSUB " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ flags &= ~(1 << RSUB);
+ if (flags == 0)
+ HandleNode(pNode->GetBody(), nLevel + 1);
+ else
+ HandleSubSupScriptInternal(pNode, nLevel, flags);
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUB " ");
+ HandleNode(pNode->GetSubSup(RSUB), nLevel + 1);
+ m_pBuffer->append("}"); // msub
+ m_pBuffer->append("}"); // msSub
+ }
+ else if ((flags & (1 << RSUP)) == 1 << RSUP)
+ {
+ // m:sSup
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSSUP " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ flags &= ~(1 << RSUP);
+ if (flags == 0)
+ HandleNode(pNode->GetBody(), nLevel + 1);
+ else
+ HandleSubSupScriptInternal(pNode, nLevel, flags);
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUP " ");
+ HandleNode(pNode->GetSubSup(RSUP), nLevel + 1);
+ m_pBuffer->append("}"); // msup
+ m_pBuffer->append("}"); // msSup
+ }
+ else if ((flags & (1 << LSUP | 1 << LSUB)) == (1 << LSUP | 1 << LSUB))
+ {
+ // m:sPre
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSPRE " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUB " ");
+ HandleNode(pNode->GetSubSup(LSUB), nLevel + 1);
+ m_pBuffer->append("}"); // msub
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSUP " ");
+ HandleNode(pNode->GetSubSup(LSUP), nLevel + 1);
+ m_pBuffer->append("}"); // msup
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ flags &= ~(1 << LSUP | 1 << LSUB);
+ if (flags == 0)
+ HandleNode(pNode->GetBody(), nLevel + 1);
+ else
+ HandleSubSupScriptInternal(pNode, nLevel, flags);
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("}"); // msPre
+ }
+ else if ((flags & (1 << CSUB)) == (1 << CSUB))
+ {
+ // m:limLow looks like a good element for central superscript
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIMLOW " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ flags &= ~(1 << CSUB);
+ if (flags == 0)
+ HandleNode(pNode->GetBody(), nLevel + 1);
+ else
+ HandleSubSupScriptInternal(pNode, nLevel, flags);
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIM " ");
+ HandleNode(pNode->GetSubSup(CSUB), nLevel + 1);
+ m_pBuffer->append("}"); // mlim
+ m_pBuffer->append("}"); // mlimLow
+ }
+ else if ((flags & (1 << CSUP)) == (1 << CSUP))
+ {
+ // m:limUpp looks like a good element for central superscript
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIMUPP " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ flags &= ~(1 << CSUP);
+ if (flags == 0)
+ HandleNode(pNode->GetBody(), nLevel + 1);
+ else
+ HandleSubSupScriptInternal(pNode, nLevel, flags);
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIM " ");
+ HandleNode(pNode->GetSubSup(CSUP), nLevel + 1);
+ m_pBuffer->append("}"); // mlim
+ m_pBuffer->append("}"); // mlimUpp
+ }
+ else
+ SAL_INFO("starmath.rtf", "TODO: " << OSL_THIS_FUNC << " unhandled subsup type");
+}
+
+void SmRtfExport::HandleMatrix(const SmMatrixNode* pNode, int nLevel)
+{
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MM " ");
+ for (size_t row = 0; row < pNode->GetNumRows(); ++row)
+ {
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MMR " ");
+ for (size_t col = 0; col < pNode->GetNumCols(); ++col)
+ {
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ if (const SmNode* node = pNode->GetSubNode(row * pNode->GetNumCols() + col))
+ HandleNode(node, nLevel + 1);
+ m_pBuffer->append("}"); // me
+ }
+ m_pBuffer->append("}"); // mmr
+ }
+ m_pBuffer->append("}"); // mm
+}
+
+void SmRtfExport::HandleBrace(const SmBraceNode* pNode, int nLevel)
+{
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MD " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MDPR " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MBEGCHR " ");
+ m_pBuffer->append(mathSymbolToString(pNode->OpeningBrace(), m_nEncoding));
+ m_pBuffer->append("}"); // mbegChr
+ std::vector<const SmNode*> subnodes;
+ if (pNode->Body()->GetType() == SmNodeType::Bracebody)
+ {
+ auto body = static_cast<const SmBracebodyNode*>(pNode->Body());
+ bool separatorWritten = false; // assume all separators are the same
+ for (size_t i = 0; i < body->GetNumSubNodes(); ++i)
+ {
+ const SmNode* subnode = body->GetSubNode(i);
+ if (subnode->GetType() == SmNodeType::Math
+ || subnode->GetType() == SmNodeType::MathIdent)
+ {
+ // do not write, but write what separator it is
+ auto math = static_cast<const SmMathSymbolNode*>(subnode);
+ if (!separatorWritten)
+ {
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MSEPCHR " ");
+ m_pBuffer->append(mathSymbolToString(math, m_nEncoding));
+ m_pBuffer->append("}"); // msepChr
+ separatorWritten = true;
+ }
+ }
+ else
+ subnodes.push_back(subnode);
+ }
+ }
+ else
+ subnodes.push_back(pNode->Body());
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MENDCHR " ");
+ m_pBuffer->append(mathSymbolToString(pNode->ClosingBrace(), m_nEncoding));
+ m_pBuffer->append("}"); // mendChr
+ m_pBuffer->append("}"); // mdPr
+ for (const SmNode* subnode : subnodes)
+ {
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ HandleNode(subnode, nLevel + 1);
+ m_pBuffer->append("}"); // me
+ }
+ m_pBuffer->append("}"); // md
+}
+
+void SmRtfExport::HandleVerticalBrace(const SmVerticalBraceNode* pNode, int nLevel)
+{
+ SAL_INFO("starmath.rtf", "Vertical: " << int(pNode->GetToken().eType));
+ switch (pNode->GetToken().eType)
+ {
+ case TOVERBRACE:
+ case TUNDERBRACE:
+ {
+ bool top = (pNode->GetToken().eType == TOVERBRACE);
+ if (top)
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIMUPP " ");
+ else
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIMLOW " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MGROUPCHR " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MGROUPCHRPR " ");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MCHR " ");
+ m_pBuffer->append(mathSymbolToString(pNode->Brace(), m_nEncoding));
+ m_pBuffer->append("}"); // mchr
+ // TODO not sure if pos and vertJc are correct
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MPOS " ")
+ .append(top ? "top" : "bot")
+ .append("}");
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MVERTJC " ")
+ .append(top ? "bot" : "top")
+ .append("}");
+ m_pBuffer->append("}"); // mgroupChrPr
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_ME " ");
+ HandleNode(pNode->Body(), nLevel + 1);
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("}"); // mgroupChr
+ m_pBuffer->append("}"); // me
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MLIM " ");
+ HandleNode(pNode->Script(), nLevel + 1);
+ m_pBuffer->append("}"); // mlim
+ m_pBuffer->append("}"); // mlimUpp or mlimLow
+ break;
+ }
+ default:
+ SAL_INFO("starmath.rtf", "TODO: " << OSL_THIS_FUNC << " unhandled vertical brace type");
+ break;
+ }
+}
+
+void SmRtfExport::HandleBlank()
+{
+ m_pBuffer->append("{" LO_STRING_SVTOOLS_RTF_MR " ");
+ m_pBuffer->append(" ");
+ m_pBuffer->append("}"); // mr
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */