summaryrefslogtreecommitdiffstats
path: root/starmath/source/mathml
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--starmath/source/mathml/attribute.cxx475
-rw-r--r--starmath/source/mathml/def.cxx124
-rw-r--r--starmath/source/mathml/element.cxx136
-rw-r--r--starmath/source/mathml/export.cxx1110
-rw-r--r--starmath/source/mathml/import.cxx1430
-rw-r--r--starmath/source/mathml/iterator.cxx77
-rw-r--r--starmath/source/mathml/mathmlMo.cxx1127
-rw-r--r--starmath/source/mathml/mathmlattr.cxx165
-rw-r--r--starmath/source/mathml/mathmlexport.cxx1457
-rw-r--r--starmath/source/mathml/mathmlimport.cxx2696
-rw-r--r--starmath/source/mathml/starmathdatabase.cxx794
-rw-r--r--starmath/source/mathml/xparsmlbase.cxx2166
12 files changed, 11757 insertions, 0 deletions
diff --git a/starmath/source/mathml/attribute.cxx b/starmath/source/mathml/attribute.cxx
new file mode 100644
index 000000000..a1be708ae
--- /dev/null
+++ b/starmath/source/mathml/attribute.cxx
@@ -0,0 +1,475 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 <mathml/attribute.hxx>
+
+void SmMlAttribute::clearPreviousAttributeValue()
+{
+ switch (m_aSmMlAttributeValueType)
+ {
+ case SmMlAttributeValueType::NMlEmpty:
+ break;
+ case SmMlAttributeValueType::MlHref:
+ if (m_aAttributeValue.m_aHref.m_aLnk)
+ delete m_aAttributeValue.m_aHref.m_aLnk;
+ break;
+ case SmMlAttributeValueType::MlLspace:
+ if (m_aAttributeValue.m_aLspace.m_aLengthValue.m_aOriginalText)
+ delete m_aAttributeValue.m_aLspace.m_aLengthValue.m_aOriginalText;
+ break;
+ case SmMlAttributeValueType::MlMathsize:
+ if (m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aOriginalText)
+ delete m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aOriginalText;
+ break;
+ case SmMlAttributeValueType::MlMaxsize:
+ if (m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aOriginalText)
+ delete m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aOriginalText;
+ break;
+ case SmMlAttributeValueType::MlMinsize:
+ if (m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aOriginalText)
+ delete m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aOriginalText;
+ break;
+ case SmMlAttributeValueType::MlRspace:
+ if (m_aAttributeValue.m_aRspace.m_aLengthValue.m_aOriginalText)
+ delete m_aAttributeValue.m_aRspace.m_aLengthValue.m_aOriginalText;
+ break;
+ default:
+ break;
+ }
+}
+
+void SmMlAttribute::setDefaultAttributeValue()
+{
+ switch (m_aSmMlAttributeValueType)
+ {
+ case SmMlAttributeValueType::NMlEmpty:
+ break;
+ case SmMlAttributeValueType::MlAccent:
+ m_aAttributeValue.m_aAccent.m_aAccent = SmMlAttributeValueAccent::MlFalse;
+ break;
+ case SmMlAttributeValueType::MlDir:
+ m_aAttributeValue.m_aDir.m_aDir = SmMlAttributeValueDir::MlLtr;
+ break;
+ case SmMlAttributeValueType::MlDisplaystyle:
+ m_aAttributeValue.m_aDisplaystyle.m_aDisplaystyle
+ = SmMlAttributeValueDisplaystyle::MlFalse;
+ break;
+ case SmMlAttributeValueType::MlFence:
+ m_aAttributeValue.m_aFence.m_aFence = SmMlAttributeValueFence::MlFalse;
+ break;
+ case SmMlAttributeValueType::MlForm:
+ m_aAttributeValue.m_aForm.m_aForm = SmMlAttributeValueForm::MlInfix;
+ break;
+ case SmMlAttributeValueType::MlHref:
+ m_aAttributeValue.m_aHref.m_aHref = SmMlAttributeValueHref::NMlEmpty;
+ m_aAttributeValue.m_aHref.m_aLnk = new OUString(u"");
+ break;
+ case SmMlAttributeValueType::MlLspace:
+ m_aAttributeValue.m_aLspace.m_aLengthValue.m_aLengthUnit = SmLengthUnit::MlEm;
+ m_aAttributeValue.m_aLspace.m_aLengthValue.m_aLengthValue = 5.0 / 18;
+ m_aAttributeValue.m_aLspace.m_aLengthValue.m_aOriginalText = new OUString(u"5/18em");
+ break;
+ case SmMlAttributeValueType::MlMathbackground:
+ m_aAttributeValue.m_aMathbackground.m_aMathbackground
+ = SmMlAttributeValueMathbackground::MlTransparent;
+ break;
+ case SmMlAttributeValueType::MlMathcolor:
+ m_aAttributeValue.m_aMathcolor.m_aMathcolor = SmMlAttributeValueMathcolor::MlDefault;
+ break;
+ case SmMlAttributeValueType::MlMathsize:
+ m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aLengthUnit = SmLengthUnit::MlP;
+ m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aLengthValue = 100;
+ m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aOriginalText = new OUString(u"100%");
+ break;
+ case SmMlAttributeValueType::MlMathvariant:
+ m_aAttributeValue.m_aMathvariant.m_aMathvariant = SmMlAttributeValueMathvariant::normal;
+ break;
+ case SmMlAttributeValueType::MlMaxsize:
+ m_aAttributeValue.m_aMaxsize.m_aMaxsize = SmMlAttributeValueMaxsize::MlInfinity;
+ m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aLengthUnit = SmLengthUnit::MlP;
+ m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aLengthValue = 10000;
+ m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aOriginalText = new OUString(u"10000%");
+ break;
+ case SmMlAttributeValueType::MlMinsize:
+ m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aLengthUnit = SmLengthUnit::MlP;
+ m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aLengthValue = 1;
+ m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aOriginalText = new OUString(u"1%");
+ break;
+ case SmMlAttributeValueType::MlMovablelimits:
+ m_aAttributeValue.m_aMovablelimits.m_aMovablelimits
+ = SmMlAttributeValueMovablelimits::MlFalse;
+ break;
+ case SmMlAttributeValueType::MlRspace:
+ m_aAttributeValue.m_aRspace.m_aLengthValue.m_aLengthUnit = SmLengthUnit::MlEm;
+ m_aAttributeValue.m_aRspace.m_aLengthValue.m_aLengthValue = 5.0 / 18;
+ m_aAttributeValue.m_aRspace.m_aLengthValue.m_aOriginalText = new OUString(u"5/18em");
+ break;
+ case SmMlAttributeValueType::MlSeparator:
+ m_aAttributeValue.m_aSeparator.m_aSeparator = SmMlAttributeValueSeparator::MlFalse;
+ break;
+ case SmMlAttributeValueType::MlStretchy:
+ m_aAttributeValue.m_aStretchy.m_aStretchy = SmMlAttributeValueStretchy::MlFalse;
+ break;
+ case SmMlAttributeValueType::MlSymmetric:
+ m_aAttributeValue.m_aSymmetric.m_aSymmetric = SmMlAttributeValueSymmetric::MlFalse;
+ break;
+ }
+}
+
+void SmMlAttribute::setAttributeValue(const SmMlAttribute* aAttribute)
+{
+ switch (aAttribute->getMlAttributeValueType())
+ {
+ case SmMlAttributeValueType::NMlEmpty:
+ clearPreviousAttributeValue();
+ m_aSmMlAttributeValueType = SmMlAttributeValueType::NMlEmpty;
+ break;
+ case SmMlAttributeValueType::MlAccent:
+ setMlAccent(aAttribute->getMlAccent());
+ break;
+ case SmMlAttributeValueType::MlDir:
+ setMlDir(aAttribute->getMlDir());
+ break;
+ case SmMlAttributeValueType::MlDisplaystyle:
+ setMlDisplaystyle(aAttribute->getMlDisplaystyle());
+ break;
+ case SmMlAttributeValueType::MlFence:
+ setMlFence(aAttribute->getMlFence());
+ break;
+ case SmMlAttributeValueType::MlForm:
+ setMlForm(aAttribute->getMlForm());
+ break;
+ case SmMlAttributeValueType::MlHref:
+ setMlHref(aAttribute->getMlHref());
+ break;
+ case SmMlAttributeValueType::MlLspace:
+ setMlLspace(aAttribute->getMlLspace());
+ break;
+ case SmMlAttributeValueType::MlMathbackground:
+ setMlMathbackground(aAttribute->getMlMathbackground());
+ break;
+ case SmMlAttributeValueType::MlMathcolor:
+ setMlMathcolor(aAttribute->getMlMathcolor());
+ break;
+ case SmMlAttributeValueType::MlMathsize:
+ setMlMathsize(aAttribute->getMlMathsize());
+ break;
+ case SmMlAttributeValueType::MlMathvariant:
+ setMlMathvariant(aAttribute->getMlMathvariant());
+ break;
+ case SmMlAttributeValueType::MlMaxsize:
+ setMlMaxsize(aAttribute->getMlMaxsize());
+ break;
+ case SmMlAttributeValueType::MlMinsize:
+ setMlMinsize(aAttribute->getMlMinsize());
+ break;
+ case SmMlAttributeValueType::MlMovablelimits:
+ setMlMovablelimits(aAttribute->getMlMovablelimits());
+ break;
+ case SmMlAttributeValueType::MlRspace:
+ setMlRspace(aAttribute->getMlRspace());
+ break;
+ case SmMlAttributeValueType::MlSeparator:
+ setMlSeparator(aAttribute->getMlSeparator());
+ break;
+ case SmMlAttributeValueType::MlStretchy:
+ setMlStretchy(aAttribute->getMlStretchy());
+ break;
+ case SmMlAttributeValueType::MlSymmetric:
+ setMlSymmetric(aAttribute->getMlSymmetric());
+ break;
+ }
+}
+
+/* get values */
+/*************************************************************************************************/
+
+const struct SmMlAccent* SmMlAttribute::getMlAccent() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlAccent)
+ return &m_aAttributeValue.m_aAccent;
+ return nullptr;
+}
+
+const struct SmMlDir* SmMlAttribute::getMlDir() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlDir)
+ return &m_aAttributeValue.m_aDir;
+ return nullptr;
+}
+
+const struct SmMlDisplaystyle* SmMlAttribute::getMlDisplaystyle() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlDisplaystyle)
+ return &m_aAttributeValue.m_aDisplaystyle;
+ return nullptr;
+}
+
+const struct SmMlFence* SmMlAttribute::getMlFence() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlFence)
+ return &m_aAttributeValue.m_aFence;
+ return nullptr;
+}
+
+const struct SmMlForm* SmMlAttribute::getMlForm() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlForm)
+ return &m_aAttributeValue.m_aForm;
+ return nullptr;
+}
+
+const struct SmMlHref* SmMlAttribute::getMlHref() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlHref)
+ return &m_aAttributeValue.m_aHref;
+ return nullptr;
+}
+
+const struct SmMlLspace* SmMlAttribute::getMlLspace() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlLspace)
+ return &m_aAttributeValue.m_aLspace;
+ return nullptr;
+}
+
+const struct SmMlMathbackground* SmMlAttribute::getMlMathbackground() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlMathbackground)
+ return &m_aAttributeValue.m_aMathbackground;
+ return nullptr;
+}
+
+const struct SmMlMathcolor* SmMlAttribute::getMlMathcolor() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlMathcolor)
+ return &m_aAttributeValue.m_aMathcolor;
+ return nullptr;
+}
+
+const struct SmMlMathsize* SmMlAttribute::getMlMathsize() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlAccent)
+ return &m_aAttributeValue.m_aMathsize;
+ return nullptr;
+}
+
+const struct SmMlMathvariant* SmMlAttribute::getMlMathvariant() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlMathvariant)
+ return &m_aAttributeValue.m_aMathvariant;
+ return nullptr;
+}
+
+const struct SmMlMaxsize* SmMlAttribute::getMlMaxsize() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlMaxsize)
+ return &m_aAttributeValue.m_aMaxsize;
+ return nullptr;
+}
+
+const struct SmMlMinsize* SmMlAttribute::getMlMinsize() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlMinsize)
+ return &m_aAttributeValue.m_aMinsize;
+ return nullptr;
+}
+
+const struct SmMlMovablelimits* SmMlAttribute::getMlMovablelimits() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlMovablelimits)
+ return &m_aAttributeValue.m_aMovablelimits;
+ return nullptr;
+}
+
+const struct SmMlRspace* SmMlAttribute::getMlRspace() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlRspace)
+ return &m_aAttributeValue.m_aRspace;
+ return nullptr;
+}
+
+const struct SmMlSeparator* SmMlAttribute::getMlSeparator() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlSeparator)
+ return &m_aAttributeValue.m_aSeparator;
+ return nullptr;
+}
+
+const struct SmMlStretchy* SmMlAttribute::getMlStretchy() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlStretchy)
+ return &m_aAttributeValue.m_aStretchy;
+ return nullptr;
+}
+
+const struct SmMlSymmetric* SmMlAttribute::getMlSymmetric() const
+{
+ if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlSymmetric)
+ return &m_aAttributeValue.m_aSymmetric;
+ return nullptr;
+}
+
+/* set values */
+/*************************************************************************************************/
+
+void SmMlAttribute::setMlAccent(const SmMlAccent* aAccent)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aAccent.m_aAccent = aAccent->m_aAccent;
+}
+
+void SmMlAttribute::setMlDir(const SmMlDir* aDir)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aDir.m_aDir = aDir->m_aDir;
+}
+
+void SmMlAttribute::setMlDisplaystyle(const SmMlDisplaystyle* aDisplaystyle)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aDisplaystyle.m_aDisplaystyle = aDisplaystyle->m_aDisplaystyle;
+}
+
+void SmMlAttribute::setMlFence(const SmMlFence* aFence)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aFence.m_aFence = aFence->m_aFence;
+}
+
+void SmMlAttribute::setMlForm(const SmMlForm* aForm)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aForm.m_aForm = aForm->m_aForm;
+}
+
+void SmMlAttribute::setMlHref(const SmMlHref* aHref)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aHref.m_aHref = aHref->m_aHref;
+ m_aAttributeValue.m_aHref.m_aLnk = new OUString(*aHref->m_aLnk);
+}
+
+void SmMlAttribute::setMlLspace(const SmMlLspace* aLspace)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aLspace.m_aLengthValue.m_aLengthUnit
+ = aLspace->m_aLengthValue.m_aLengthUnit;
+ m_aAttributeValue.m_aLspace.m_aLengthValue.m_aLengthValue
+ = aLspace->m_aLengthValue.m_aLengthValue;
+ m_aAttributeValue.m_aLspace.m_aLengthValue.m_aOriginalText
+ = new OUString(*aLspace->m_aLengthValue.m_aOriginalText);
+}
+
+void SmMlAttribute::setMlMathbackground(const SmMlMathbackground* aMathbackground)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aMathbackground.m_aMathbackground = aMathbackground->m_aMathbackground;
+}
+
+void SmMlAttribute::setMlMathcolor(const SmMlMathcolor* aMathcolor)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aMathcolor.m_aMathcolor = aMathcolor->m_aMathcolor;
+}
+
+void SmMlAttribute::setMlMathsize(const SmMlMathsize* aMathsize)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aLengthUnit
+ = aMathsize->m_aLengthValue.m_aLengthUnit;
+ m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aLengthValue
+ = aMathsize->m_aLengthValue.m_aLengthValue;
+ m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aOriginalText
+ = new OUString(*aMathsize->m_aLengthValue.m_aOriginalText);
+}
+
+void SmMlAttribute::setMlMathvariant(const SmMlMathvariant* aMathvariant)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aMathvariant.m_aMathvariant = aMathvariant->m_aMathvariant;
+}
+
+void SmMlAttribute::setMlMaxsize(const SmMlMaxsize* aMaxsize)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aMaxsize.m_aMaxsize = aMaxsize->m_aMaxsize;
+ m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aLengthUnit
+ = aMaxsize->m_aLengthValue.m_aLengthUnit;
+ m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aLengthValue
+ = aMaxsize->m_aLengthValue.m_aLengthValue;
+ m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aOriginalText
+ = new OUString(*aMaxsize->m_aLengthValue.m_aOriginalText);
+}
+
+void SmMlAttribute::setMlMinsize(const SmMlMinsize* aMinsize)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aLengthUnit
+ = aMinsize->m_aLengthValue.m_aLengthUnit;
+ m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aLengthValue
+ = aMinsize->m_aLengthValue.m_aLengthValue;
+ m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aOriginalText
+ = new OUString(*aMinsize->m_aLengthValue.m_aOriginalText);
+}
+
+void SmMlAttribute::setMlMovablelimits(const SmMlMovablelimits* aMovablelimits)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aMovablelimits.m_aMovablelimits = aMovablelimits->m_aMovablelimits;
+}
+
+void SmMlAttribute::setMlRspace(const SmMlRspace* aRspace)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aRspace.m_aLengthValue.m_aLengthUnit
+ = aRspace->m_aLengthValue.m_aLengthUnit;
+ m_aAttributeValue.m_aRspace.m_aLengthValue.m_aLengthValue
+ = aRspace->m_aLengthValue.m_aLengthValue;
+ m_aAttributeValue.m_aRspace.m_aLengthValue.m_aOriginalText
+ = new OUString(*aRspace->m_aLengthValue.m_aOriginalText);
+}
+
+void SmMlAttribute::setMlSeparator(const SmMlSeparator* aSeparator)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aSeparator.m_aSeparator = aSeparator->m_aSeparator;
+}
+
+void SmMlAttribute::setMlStretchy(const SmMlStretchy* aStretchy)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aStretchy.m_aStretchy = aStretchy->m_aStretchy;
+}
+
+void SmMlAttribute::setMlSymmetric(const SmMlSymmetric* aSymmetric)
+{
+ m_bSet = true;
+ clearPreviousAttributeValue();
+ m_aAttributeValue.m_aSymmetric.m_aSymmetric = aSymmetric->m_aSymmetric;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/starmath/source/mathml/def.cxx b/starmath/source/mathml/def.cxx
new file mode 100644
index 000000000..484dcd665
--- /dev/null
+++ b/starmath/source/mathml/def.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 <mathml/attribute.hxx>
+
+SmMlAttributePos starmathdatabase::MlAttributeListEmpty[] = {
+ // clang-format off
+ { SmMlAttributeValueType::NMlEmpty, 0 }
+ // clang-format on
+};
+
+SmMlAttributePos starmathdatabase::MlAttributeListMath[] = {
+ // clang-format off
+ { SmMlAttributeValueType::NMlEmpty, 0 }
+ // clang-format on
+};
+
+SmMlAttributePos starmathdatabase::MlAttributeListMi[] = {
+ // clang-format off
+ { SmMlAttributeValueType::MlHref, 0 },
+ { SmMlAttributeValueType::MlDir, 1 },
+ { SmMlAttributeValueType::MlMathbackground, 2 },
+ { SmMlAttributeValueType::MlMathcolor, 3 },
+ { SmMlAttributeValueType::MlDisplaystyle, 4 },
+ { SmMlAttributeValueType::MlMathsize, 5 },
+ { SmMlAttributeValueType::MlMathvariant, 6 }
+ // clang-format on
+};
+
+SmMlAttributePos starmathdatabase::MlAttributeListMerror[] = {
+ // clang-format off
+ { SmMlAttributeValueType::MlHref, 0 },
+ { SmMlAttributeValueType::MlMathbackground, 1 },
+ { SmMlAttributeValueType::MlMathcolor, 2 },
+ { SmMlAttributeValueType::MlDisplaystyle, 3 }
+ // clang-format on
+};
+
+SmMlAttributePos starmathdatabase::MlAttributeListMn[] = {
+ // clang-format off
+ { SmMlAttributeValueType::MlHref, 0 },
+ { SmMlAttributeValueType::MlDir, 1 },
+ { SmMlAttributeValueType::MlMathbackground, 2 },
+ { SmMlAttributeValueType::MlMathcolor, 3 },
+ { SmMlAttributeValueType::MlDisplaystyle, 4 },
+ { SmMlAttributeValueType::MlMathsize, 5 },
+ { SmMlAttributeValueType::MlMathvariant, 6 }
+ // clang-format on
+};
+
+SmMlAttributePos starmathdatabase::MlAttributeListMo[] = {
+ // clang-format off
+ { SmMlAttributeValueType::MlHref, 0 },
+ { SmMlAttributeValueType::MlDir, 1 },
+ { SmMlAttributeValueType::MlMathbackground, 2 },
+ { SmMlAttributeValueType::MlMathcolor, 3 },
+ { SmMlAttributeValueType::MlDisplaystyle, 4 },
+ { SmMlAttributeValueType::MlMathsize, 5 },
+ { SmMlAttributeValueType::MlMathvariant, 6 },
+ { SmMlAttributeValueType::MlFence, 7 },
+ { SmMlAttributeValueType::MlForm, 8 },
+ { SmMlAttributeValueType::MlMaxsize, 9 },
+ { SmMlAttributeValueType::MlMinsize, 10 },
+ { SmMlAttributeValueType::MlMovablelimits, 11 },
+ { SmMlAttributeValueType::MlLspace, 12 },
+ { SmMlAttributeValueType::MlRspace, 13 },
+ { SmMlAttributeValueType::MlAccent, 14 },
+ { SmMlAttributeValueType::MlStretchy, 15 },
+ { SmMlAttributeValueType::MlSeparator, 16 },
+ { SmMlAttributeValueType::MlSymmetric, 17 }
+ // clang-format on
+};
+
+SmMlAttributePos starmathdatabase::MlAttributeListMrow[] = {
+ // clang-format off
+ { SmMlAttributeValueType::MlHref, 0 },
+ { SmMlAttributeValueType::MlDir, 1 },
+ { SmMlAttributeValueType::MlMathbackground, 2 },
+ { SmMlAttributeValueType::MlMathcolor, 3 }
+ // clang-format on
+};
+
+SmMlAttributePos starmathdatabase::MlAttributeListMtext[] = {
+ // clang-format off
+ { SmMlAttributeValueType::MlHref, 0 },
+ { SmMlAttributeValueType::MlDir, 1 },
+ { SmMlAttributeValueType::MlMathbackground, 2 },
+ { SmMlAttributeValueType::MlMathcolor, 3 },
+ { SmMlAttributeValueType::MlDisplaystyle, 4 },
+ { SmMlAttributeValueType::MlMathsize, 5 },
+ { SmMlAttributeValueType::MlMathvariant, 6 }
+ // clang-format on
+};
+
+SmMlAttributePos starmathdatabase::MlAttributeListMstyle[] = {
+ // clang-format off
+ { SmMlAttributeValueType::MlHref, 0 },
+ { SmMlAttributeValueType::MlDir, 1 },
+ { SmMlAttributeValueType::MlMathbackground, 2 },
+ { SmMlAttributeValueType::MlMathcolor, 3 },
+ { SmMlAttributeValueType::MlDisplaystyle, 4 },
+ { SmMlAttributeValueType::MlMathsize, 5 },
+ { SmMlAttributeValueType::MlMathvariant, 6 },
+ { SmMlAttributeValueType::MlFence, 7 },
+ { SmMlAttributeValueType::MlForm, 8 },
+ { SmMlAttributeValueType::MlMaxsize, 9 },
+ { SmMlAttributeValueType::MlMinsize, 10 },
+ { SmMlAttributeValueType::MlMovablelimits, 11 },
+ { SmMlAttributeValueType::MlLspace, 12 },
+ { SmMlAttributeValueType::MlRspace, 13 },
+ { SmMlAttributeValueType::MlAccent, 14 },
+ { SmMlAttributeValueType::MlStretchy, 15 },
+ { SmMlAttributeValueType::MlSeparator, 16 },
+ { SmMlAttributeValueType::MlSymmetric, 17 }
+ // clang-format on
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/starmath/source/mathml/element.cxx b/starmath/source/mathml/element.cxx
new file mode 100644
index 000000000..4f8f2a64f
--- /dev/null
+++ b/starmath/source/mathml/element.cxx
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 <mathml/element.hxx>
+
+void SmMlElement::SmImplAttributeType()
+{
+ switch (m_aElementType)
+ {
+ case SmMlElementType::NMlEmpty:
+ m_aAttributePosList = std::vector<SmMlAttributePos>(0);
+ break;
+ case SmMlElementType::NMlStructural:
+ m_aAttributePosList = std::vector<SmMlAttributePos>(0);
+ break;
+ case SmMlElementType::NMlSmNode:
+ m_aAttributePosList = std::vector<SmMlAttributePos>(0);
+ break;
+ case SmMlElementType::MlMath:
+ m_aAttributePosList = std::vector<SmMlAttributePos>(0);
+ //m_aAttributePosList = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMath), std::end(starmathdatabase::MlAttributeListMath));
+ break;
+ case SmMlElementType::MlMi:
+ m_aAttributePosList
+ = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMi),
+ std::end(starmathdatabase::MlAttributeListMi));
+ break;
+ case SmMlElementType::MlMerror:
+ m_aAttributePosList
+ = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMerror),
+ std::end(starmathdatabase::MlAttributeListMerror));
+ break;
+ case SmMlElementType::MlMn:
+ m_aAttributePosList
+ = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMn),
+ std::end(starmathdatabase::MlAttributeListMn));
+ break;
+ case SmMlElementType::MlMo:
+ m_aAttributePosList
+ = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMo),
+ std::end(starmathdatabase::MlAttributeListMo));
+ break;
+ case SmMlElementType::MlMrow:
+ m_aAttributePosList
+ = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMrow),
+ std::end(starmathdatabase::MlAttributeListMrow));
+ break;
+ case SmMlElementType::MlMtext:
+ m_aAttributePosList
+ = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMtext),
+ std::end(starmathdatabase::MlAttributeListMtext));
+ break;
+ case SmMlElementType::MlMstyle:
+ m_aAttributePosList
+ = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMstyle),
+ std::end(starmathdatabase::MlAttributeListMstyle));
+ break;
+ default:
+ break;
+ }
+ // Create attribute vector with given pattern
+ m_aAttributeList = starmathdatabase::makeMlAttributeList(m_aAttributePosList);
+}
+
+SmMlAttribute SmMlElement::getAttribute(SmMlAttributeValueType aAttributeType) const
+{
+ // Look for the attribute position and return if exists
+ for (size_t i = 0; i < m_aAttributePosList.size(); ++i)
+ {
+ if (m_aAttributePosList[i].m_aAttributeValueType == aAttributeType)
+ return m_aAttributeList[m_aAttributePosList[i].m_nPos];
+ }
+ return SmMlAttribute();
+}
+
+bool SmMlElement::isAttributeSet(SmMlAttributeValueType aAttributeType) const
+{
+ // Look for the attribute position and return if exists
+ for (size_t i = 0; i < m_aAttributePosList.size(); ++i)
+ {
+ if (m_aAttributePosList[i].m_aAttributeValueType == aAttributeType)
+ return m_aAttributeList[m_aAttributePosList[i].m_nPos].isSet();
+ }
+ return false;
+}
+
+void SmMlElement::setAttribute(const SmMlAttribute* aAttribute)
+{
+ // Look for the attribute position and assign if exists
+ for (size_t i = 0; i < m_aAttributePosList.size(); ++i)
+ {
+ if (m_aAttributePosList[i].m_aAttributeValueType == aAttribute->getMlAttributeValueType())
+ {
+ m_aAttributeList[m_aAttributePosList[i].m_nPos].setMlAttributeValue(aAttribute);
+ break;
+ }
+ }
+}
+
+void SmMlElement::setSubElement(size_t nPos, SmMlElement* aElement)
+{
+ // This is the new parent element
+ aElement->setParentElement(this);
+ aElement->setSubElementId(nPos);
+ // Check if the vector is long enough
+ // Careful nOldSize can be 0 and -1 will underflow
+ // We must put something on the empty locations
+ size_t nOldSize = m_aSubElements.size();
+ if (nPos + 1 > nOldSize)
+ {
+ m_aSubElements.resize(nPos + 1);
+ for (; nOldSize < nPos; ++nOldSize)
+ m_aSubElements[nOldSize] = nullptr;
+ }
+ // Assign value
+ m_aSubElements[nPos] = aElement;
+}
+
+std::vector<SmMlAttribute>
+starmathdatabase::makeMlAttributeList(std::vector<SmMlAttributePos> aAttributePosList)
+{
+ std::vector<SmMlAttribute> aAttributeList(aAttributePosList.size());
+ for (size_t i = 0; i < aAttributePosList.size(); ++i)
+ {
+ aAttributeList[i].setMlAttributeValueType(aAttributePosList[i].m_aAttributeValueType);
+ }
+ return aAttributeList;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/starmath/source/mathml/export.cxx b/starmath/source/mathml/export.cxx
new file mode 100644
index 000000000..b55be5092
--- /dev/null
+++ b/starmath/source/mathml/export.cxx
@@ -0,0 +1,1110 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+// Our mathml
+#include <mathml/export.hxx>
+#include <mathml/iterator.hxx>
+
+// LO tools to use
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+#include <com/sun/star/uno/Any.h>
+#include <com/sun/star/util/MeasureUnit.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+
+// Extra LO tools
+#include <comphelper/genericpropertyset.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <sfx2/frame.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <unotools/streamwrap.hxx>
+#include <xmloff/namespacemap.hxx>
+
+// Our starmath tools
+#include <document.hxx>
+#include <smmod.hxx>
+#include <strings.hrc>
+#include <unomodel.hxx>
+#include <xparsmlbase.hxx>
+#include <starmathdatabase.hxx>
+
+// Old parser
+#include <mathmlexport.hxx>
+
+using namespace ::com::sun::star;
+using namespace xmloff::token;
+
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+// SmMLExportWrapper
+/*************************************************************************************************/
+
+bool SmMLExportWrapper::Export(SfxMedium& rMedium)
+{
+ bool bRet = true;
+ uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
+
+ // Check all fine
+ SAL_WARN_IF(m_xModel == nullptr, "starmath", "Missing model");
+ SAL_WARN_IF(xContext == nullptr, "starmath", "Missing context");
+ if (m_xModel == nullptr || xContext == nullptr)
+ return false;
+
+ //Get model
+ uno::Reference<lang::XComponent> xModelComp = m_xModel;
+ SAL_WARN_IF(xModelComp == nullptr, "starmath", "Missing model component");
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(m_xModel);
+ SAL_WARN_IF(pModel == nullptr, "starmath", "Failed to get threw uno tunnel");
+ if (xModelComp == nullptr || pModel == nullptr)
+ return false;
+
+ // Get doc shell
+ SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
+ if (pDocShell == nullptr)
+ {
+ SAL_WARN("starmath", "Failed to fetch sm document");
+ return false;
+ }
+
+ // Check if it is a standalone window or embed object
+ bool bEmbedded = SfxObjectCreateMode::EMBEDDED == pDocShell->GetCreateMode();
+
+ // Medium item set
+ SfxItemSet* pMediumItemSet = rMedium.GetItemSet();
+ if (pDocShell == nullptr)
+ {
+ SAL_WARN("starmath", "Failed to get medium item set");
+ return false;
+ }
+
+ // Progress bar ~
+ uno::Reference<task::XStatusIndicator> xStatusIndicator;
+
+ if (!bEmbedded)
+ {
+ // Extra check to ensure everything is fine
+ if (pDocShell->GetMedium() != &rMedium)
+ {
+ SAL_WARN("starmath", "Input medium and sm document medium do not match");
+ //return false;
+ }
+
+ // Fetch progress bar
+ const SfxUnoAnyItem* pItem = pMediumItemSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL);
+ if (pItem)
+ {
+ // set progress range and start status indicator
+ pItem->GetValue() >>= xStatusIndicator;
+ xStatusIndicator->start(SmResId(STR_STATSTR_WRITING), 3);
+ xStatusIndicator->setValue(0);
+ }
+ }
+
+ // create XPropertySet with three properties for status indicator
+ static const comphelper::PropertyMapEntry aInfoMap[]{
+ { OUString("UsePrettyPrinting"), 0, cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 }
+ };
+ uno::Reference<beans::XPropertySet> xInfoSet(
+ comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));
+
+ // Always print pretty
+ xInfoSet->setPropertyValue("UsePrettyPrinting", Any(true));
+
+ // Set base URI
+ xInfoSet->setPropertyValue(u"BaseURI", Any(rMedium.GetBaseURL(true)));
+
+ if (!m_bFlat) //Storage (Package) of Stream
+ {
+ // Fetch the output storage
+ uno::Reference<embed::XStorage> xStg = rMedium.GetOutputStorage();
+ if (xStg == nullptr)
+ {
+ SAL_WARN("starmath", "Failed to fetch output storage");
+ return false;
+ }
+
+ // TODO/LATER: handle the case of embedded links gracefully
+ if (bEmbedded) //&& !pStg->IsRoot() )
+ {
+ const SfxStringItem* pDocHierarchItem
+ = pMediumItemSet->GetItem(SID_DOC_HIERARCHICALNAME);
+ if (pDocHierarchItem != nullptr)
+ {
+ OUString aName = pDocHierarchItem->GetValue();
+ if (!aName.isEmpty())
+ xInfoSet->setPropertyValue("StreamRelPath", Any(aName));
+ }
+ }
+ else
+ {
+ // Write file metadata ( data, LO version ... )
+ // Note: export through an XML exporter component (storage version)
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(1);
+
+ bRet = WriteThroughComponentS(xStg, xModelComp, u"meta.xml", xContext, xInfoSet,
+ u"com.sun.star.comp.Math.MLOasisMetaExporter", 6);
+ }
+
+ // Write starmath formula
+ // Note: export through an XML exporter component (storage version)
+ if (bRet)
+ {
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(2);
+
+ if (pDocShell->GetSmSyntaxVersion() == 5)
+ bRet = WriteThroughComponentS(xStg, xModelComp, u"content.xml", xContext, xInfoSet,
+ u"com.sun.star.comp.Math.XMLContentExporter", 5);
+ else
+ bRet = WriteThroughComponentS(xStg, xModelComp, u"content.xml", xContext, xInfoSet,
+ u"com.sun.star.comp.Math.MLContentExporter", 6);
+ }
+
+ // Write starmath settings
+ // Note: export through an XML exporter component (storage version)
+ if (bRet)
+ {
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(3);
+
+ bRet = WriteThroughComponentS(xStg, xModelComp, u"settings.xml", xContext, xInfoSet,
+ u"com.sun.star.comp.Math.MLOasisSettingsExporter", 6);
+ }
+ }
+ else
+ {
+ // Fetch the output stream
+ SvStream* pStream = rMedium.GetOutStream();
+ if (pStream == nullptr)
+ {
+ SAL_WARN("starmath", "Missing output stream");
+ return false;
+ }
+ uno::Reference<io::XOutputStream> xOut(new utl::OOutputStreamWrapper(*pStream));
+
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(1);
+
+ // Write everything in the same place
+ // Note: export through an XML exporter component (output stream version)
+ if (pDocShell->GetSmSyntaxVersion() == 5)
+ bRet = WriteThroughComponentOS(xOut, xModelComp, xContext, xInfoSet,
+ u"com.sun.star.comp.Math.XMLContentExporter", 5);
+ else
+ bRet = WriteThroughComponentOS(xOut, xModelComp, xContext, xInfoSet,
+ u"com.sun.star.comp.Math.MLContentExporter", 6);
+ }
+
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ return bRet;
+}
+
+OUString SmMLExportWrapper::Export(SmMlElement* pElementTree)
+{
+ uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
+
+ // Check all fine
+ m_pElementTree = nullptr;
+ SAL_WARN_IF(m_xModel == nullptr, "starmath", "Missing model");
+ SAL_WARN_IF(xContext == nullptr, "starmath", "Missing context");
+ if (m_xModel == nullptr || xContext == nullptr)
+ return u"";
+
+ //Get model
+ uno::Reference<lang::XComponent> xModelComp = m_xModel;
+ SAL_WARN_IF(xModelComp == nullptr, "starmath", "Missing model component");
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(m_xModel);
+ SAL_WARN_IF(pModel == nullptr, "starmath", "Failed to get threw uno tunnel");
+ if (xModelComp == nullptr || pModel == nullptr)
+ return u"";
+
+ // Get doc shell
+ SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
+ if (pDocShell == nullptr)
+ {
+ SAL_WARN("starmath", "Failed to fetch sm document");
+ return u"";
+ }
+
+ // create XPropertySet with three properties for status indicator
+ static const comphelper::PropertyMapEntry aInfoMap[]{
+ { OUString("UsePrettyPrinting"), 0, cppu::UnoType<bool>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 }
+ };
+ uno::Reference<beans::XPropertySet> xInfoSet(
+ comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));
+
+ // Always print pretty
+ xInfoSet->setPropertyValue("UsePrettyPrinting", Any(true));
+
+ // Fetch mathml tree
+ m_pElementTree = pElementTree;
+
+ // Write stuff
+ // Note: export through an XML exporter component (memory stream version)
+ return WriteThroughComponentMS(xModelComp, xContext, xInfoSet);
+}
+
+// export through an XML exporter component (output stream version)
+bool SmMLExportWrapper::WriteThroughComponentOS(const Reference<io::XOutputStream>& xOutputStream,
+ const Reference<XComponent>& xComponent,
+ Reference<uno::XComponentContext> const& rxContext,
+ Reference<beans::XPropertySet> const& rPropSet,
+ const char16_t* pComponentName,
+ int_fast16_t nSyntaxVersion)
+{
+ // We need a output stream but it is already checked by caller
+ // We need a component but it is already checked by caller
+ // We need a context but it is already checked by caller
+ // We need a property set but it is already checked by caller
+ // We need a component name but it is already checked by caller
+
+ // get sax writer
+ Reference<xml::sax::XWriter> xSaxWriter = xml::sax::Writer::create(rxContext);
+
+ // connect XML writer to output stream
+ xSaxWriter->setOutputStream(xOutputStream);
+ if (m_bUseHTMLMLEntities)
+ xSaxWriter->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntitiesExport);
+
+ // prepare arguments (prepend doc handler to given arguments)
+ Sequence<Any> aArgs{ Any(xSaxWriter), Any(rPropSet) };
+
+ // get filter component
+ auto xExporterData = rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ OUString(pComponentName), aArgs, rxContext);
+ Reference<document::XExporter> xExporter(xExporterData, UNO_QUERY);
+
+ // Check everything is fine
+ if (!xExporter.is())
+ {
+ SAL_WARN("starmath", "can't instantiate export filter component");
+ return false;
+ }
+
+ // connect model and filter
+ xExporter->setSourceDocument(xComponent);
+ Reference<XFilter> xFilter(xExporter, UNO_QUERY);
+ uno::Sequence<PropertyValue> aProps(0);
+
+ // filter
+ if (nSyntaxVersion == 5)
+ {
+ SmXMLExport* pFilter = comphelper::getFromUnoTunnel<SmXMLExport>(xFilter);
+ if (pFilter == nullptr)
+ {
+ SAL_WARN("starmath", "Failed to fetch SmMLExport");
+ return false;
+ }
+ xFilter->filter(aProps);
+ return pFilter->GetSuccess();
+ }
+
+ // filter
+ SmMLExport* pFilter = comphelper::getFromUnoTunnel<SmMLExport>(xFilter);
+
+ // Setup filter
+ if (pFilter == nullptr)
+ {
+ SAL_WARN("starmath", "Failed to fetch SmMLExport");
+ return false;
+ }
+ pFilter->setUseExportTag(m_bUseExportTag);
+ pFilter->setElementTree(m_pElementTree);
+
+ // Execute operation
+ xFilter->filter(aProps);
+ return pFilter->getSuccess();
+}
+
+// export through an XML exporter component (storage version)
+bool SmMLExportWrapper::WriteThroughComponentS(const Reference<embed::XStorage>& xStorage,
+ const Reference<XComponent>& xComponent,
+ const char16_t* pStreamName,
+ Reference<uno::XComponentContext> const& rxContext,
+ Reference<beans::XPropertySet> const& rPropSet,
+ const char16_t* pComponentName,
+ int_fast16_t nSyntaxVersion)
+{
+ // We need a storage name but it is already checked by caller
+ // We need a component name but it is already checked by caller
+ // We need a stream name but it is already checked by caller
+ // We need a context but it is already checked by caller
+ // We need a property set but it is already checked by caller
+ // We need a component but it is already checked by caller
+
+ // open stream
+ Reference<io::XStream> xStream;
+ try
+ {
+ xStream = xStorage->openStreamElement(
+ OUString(pStreamName), embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE);
+ }
+ catch (const uno::Exception&)
+ {
+ SAL_WARN("starmath", "Can't create output stream in package");
+ return false;
+ }
+
+ // Set stream as text / xml
+ uno::Reference<beans::XPropertySet> xSet(xStream, uno::UNO_QUERY);
+ xSet->setPropertyValue("MediaType", Any(OUString(u"text/xml")));
+
+ // all streams must be encrypted in encrypted document
+ xSet->setPropertyValue("UseCommonStoragePasswordEncryption", Any(true));
+
+ // set Base URL
+ rPropSet->setPropertyValue("StreamName", Any(OUString(pStreamName)));
+
+ // write the stuff
+ // Note: export through an XML exporter component (output stream version)
+ return WriteThroughComponentOS(xStream->getOutputStream(), xComponent, rxContext, rPropSet,
+ pComponentName, nSyntaxVersion);
+}
+
+// export through an XML exporter component (memory stream version)
+OUString
+SmMLExportWrapper::WriteThroughComponentMS(const Reference<XComponent>& xComponent,
+ Reference<uno::XComponentContext> const& rxContext,
+ Reference<beans::XPropertySet> const& rPropSet)
+{
+ // We need a component but it is already checked by caller
+ // We need a context but it is already checked by caller
+ // We need a property set it is already checked by caller
+
+ // open stream
+ SvMemoryStream aMemoryStream(8192, 1024);
+ uno::Reference<io::XOutputStream> xStream(new utl::OOutputStreamWrapper(aMemoryStream));
+
+ // Set the stream as text
+ uno::Reference<beans::XPropertySet> xSet(xStream, uno::UNO_QUERY);
+ xSet->setPropertyValue("MediaType", Any(OUString("text/xml")));
+
+ // write the stuff
+ // Note: export through an XML exporter component (output stream version)
+ bool bOk = WriteThroughComponentOS(xStream, xComponent, rxContext, rPropSet,
+ u"com.sun.star.comp.Mathml.MLContentExporter", 6);
+
+ // We don't want to read uninitialized data
+ if (!bOk)
+ return u"";
+
+ // Recover data and generate string
+ OString aString(static_cast<const char*>(aMemoryStream.GetData()),
+ aMemoryStream.GetSize() / sizeof(char));
+ return OStringToOUString(aString, RTL_TEXTENCODING_UTF8);
+}
+
+// SmMLExport technical
+/*************************************************************************************************/
+
+sal_Int64 SAL_CALL SmMLExport::getSomething(const uno::Sequence<sal_Int8>& rId)
+{
+ return comphelper::getSomethingImpl(rId, this,
+ comphelper::FallbackToGetSomethingOf<SvXMLExport>{});
+}
+
+const uno::Sequence<sal_Int8>& SmMLExport::getUnoTunnelId() noexcept
+{
+ static const comphelper::UnoIdInit theSmMLExportUnoTunnelId;
+ return theSmMLExportUnoTunnelId.getSeq();
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+Math_MLExporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new SmMLExport(context, "com.sun.star.comp.Math.XMLExporter",
+ SvXMLExportFlags::OASIS | SvXMLExportFlags::ALL));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+Math_MLOasisMetaExporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new SmMLExport(context, "com.sun.star.comp.Math.XMLOasisMetaExporter",
+ SvXMLExportFlags::OASIS | SvXMLExportFlags::META));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+Math_MLOasisSettingsExporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new SmMLExport(context, "com.sun.star.comp.Math.XMLOasisSettingsExporter",
+ SvXMLExportFlags::OASIS | SvXMLExportFlags::SETTINGS));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+Math_MLContentExporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new SmMLExport(context, "com.sun.star.comp.Math.XMLContentExporter",
+ SvXMLExportFlags::OASIS | SvXMLExportFlags::CONTENT));
+}
+
+SmDocShell* SmMLExport::getSmDocShell()
+{
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(GetModel());
+ if (pModel != nullptr)
+ return static_cast<SmDocShell*>(pModel->GetObjectShell());
+ return nullptr;
+}
+
+ErrCode SmMLExport::exportDoc(enum XMLTokenEnum eClass)
+{
+ if (!(getExportFlags() & SvXMLExportFlags::CONTENT))
+ {
+ // Everything that isn't the formula itself get's default export
+ SvXMLExport::exportDoc(eClass);
+ return ERRCODE_NONE;
+ }
+
+ // Checks if it has to export a particular tree
+ if (m_pElementTree == nullptr)
+ {
+ // Set element tree
+ SmDocShell* pDocShell = getSmDocShell();
+ if (pDocShell != nullptr)
+ m_pElementTree = pDocShell->GetMlElementTree();
+ else
+ {
+ m_bSuccess = false;
+ return SVSTREAM_INVALID_PARAMETER;
+ }
+ }
+
+ // Start document and encrypt if necessary
+ GetDocHandler()->startDocument();
+ addChaffWhenEncryptedStorage();
+
+ // make use of a default namespace
+ // Math doesn't need namespaces from xmloff, since it now uses default namespaces
+ // Because that is common with current MathML usage in the web -> ResetNamespaceMap();
+ GetNamespaceMap_().Add(OUString(u""), GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH);
+
+ // Add xmlns line
+ if (m_bUseExportTag)
+ {
+ GetAttrList().AddAttribute(GetNamespaceMap().GetAttrNameByKey(XML_NAMESPACE_MATH),
+ GetNamespaceMap().GetNameByKey(XML_NAMESPACE_MATH));
+ }
+
+ // Export and close document
+ ExportContent_();
+ GetDocHandler()->endDocument();
+
+ return ERRCODE_NONE;
+}
+
+void SmMLExport::GetViewSettings(Sequence<PropertyValue>& aProps)
+{
+ // Get the document shell
+ SmDocShell* pDocShell = getSmDocShell();
+ if (pDocShell == nullptr)
+ {
+ SAL_WARN("starmath", "Missing document shell so no view settings");
+ return;
+ }
+
+ // Allocate enough memory
+ aProps.realloc(4);
+ PropertyValue* pValue = aProps.getArray();
+
+ // The view settings are the formula display settings
+ tools::Rectangle aRect(pDocShell->GetVisArea());
+
+ pValue[0].Name = "ViewAreaTop";
+ pValue[0].Value <<= aRect.Top();
+
+ pValue[1].Name = "ViewAreaLeft";
+ pValue[1].Value <<= aRect.Left();
+
+ pValue[2].Name = "ViewAreaWidth";
+ pValue[2].Value <<= aRect.GetWidth();
+
+ pValue[3].Name = "ViewAreaHeight";
+ pValue[3].Value <<= aRect.GetHeight();
+}
+
+void SmMLExport::GetConfigurationSettings(Sequence<PropertyValue>& rProps)
+{
+ // Get model property set (settings)
+ Reference<XPropertySet> xProps(GetModel(), UNO_QUERY);
+ if (!xProps.is())
+ {
+ SAL_WARN("starmath", "Missing model properties so no configuration settings");
+ return;
+ }
+
+ // Get model property set info (settings values)
+ Reference<XPropertySetInfo> xPropertySetInfo = xProps->getPropertySetInfo();
+ if (!xPropertySetInfo.is())
+ {
+ SAL_WARN("starmath", "Missing model properties info so no configuration settings");
+ return;
+ }
+
+ // Allocate to store the properties
+ Sequence<Property> aProps = xPropertySetInfo->getProperties();
+ const sal_Int32 nCount = aProps.getLength();
+ rProps.realloc(nCount);
+ auto pProps = rProps.getArray();
+
+ // Copy properties
+ // This needs further revision
+ // Based in code mathmlexport.cxx::GetConfigurationSettings
+ for (sal_Int32 i = 0; i < nCount; ++i)
+ {
+ if (aProps[i].Name != "Formula" && aProps[i].Name != "BasicLibraries"
+ && aProps[i].Name != "DialogLibraries" && aProps[i].Name != "RuntimeUID")
+ {
+ pProps[i].Name = aProps[i].Name;
+ pProps[i].Value = xProps->getPropertyValue(aProps[i].Name);
+ }
+ }
+}
+
+SmMLExport::SmMLExport(const css::uno::Reference<css::uno::XComponentContext>& rContext,
+ OUString const& implementationName, SvXMLExportFlags nExportFlags)
+ : SvXMLExport(rContext, implementationName, util::MeasureUnit::INCH, XML_MATH, nExportFlags)
+ , m_pElementTree(nullptr)
+ , m_bSuccess(true)
+ , m_bUseExportTag(true)
+{
+}
+
+// SmMLExport
+/*************************************************************************************************/
+
+void SmMLExport::declareMlError()
+{
+ SAL_WARN("starmath", "Invalid use of mathml.");
+ m_bSuccess = false;
+}
+
+void SmMLExport::exportMlAttributeLength(xmloff::token::XMLTokenEnum pAttribute,
+ const SmLengthValue& aLengthValue)
+{
+ if (!aLengthValue.m_aOriginalText->isEmpty())
+ {
+ addAttribute(pAttribute, *aLengthValue.m_aOriginalText);
+ }
+ else
+ {
+ OUStringBuffer aSizeBuffer(64);
+ aSizeBuffer.append(aLengthValue.m_aLengthValue);
+ switch (aLengthValue.m_aLengthUnit)
+ {
+ case SmLengthUnit::MlEm:
+ aSizeBuffer.append(u"em");
+ break;
+ case SmLengthUnit::MlEx:
+ aSizeBuffer.append(u"ex");
+ break;
+ case SmLengthUnit::MlPx:
+ aSizeBuffer.append(u"px");
+ break;
+ case SmLengthUnit::MlIn:
+ aSizeBuffer.append(u"in");
+ break;
+ case SmLengthUnit::MlCm:
+ aSizeBuffer.append(u"cm");
+ break;
+ case SmLengthUnit::MlMm:
+ aSizeBuffer.append(u"mm");
+ break;
+ case SmLengthUnit::MlPt:
+ aSizeBuffer.append(u"pt");
+ break;
+ case SmLengthUnit::MlPc:
+ aSizeBuffer.append(u"pc");
+ break;
+ case SmLengthUnit::MlP:
+ aSizeBuffer.append(u"%");
+ break;
+ case SmLengthUnit::MlM:
+ break;
+ default:
+ declareMlError();
+ break;
+ }
+ addAttribute(pAttribute, aSizeBuffer.makeStringAndClear());
+ }
+}
+
+void SmMLExport::exportMlAttributes(const SmMlElement* pMlElement)
+{
+ size_t nAttributeCount = pMlElement->getAttributeCount();
+ for (size_t i = 0; i < nAttributeCount; ++i)
+ {
+ SmMlAttribute aAttribute = pMlElement->getAttribute(i);
+ if (!aAttribute.isSet())
+ continue;
+
+ switch (aAttribute.getMlAttributeValueType())
+ {
+ case SmMlAttributeValueType::MlAccent:
+ {
+ auto aAttributeValue = aAttribute.getMlAccent();
+ switch (aAttributeValue->m_aAccent)
+ {
+ case SmMlAttributeValueAccent::MlFalse:
+ addAttribute(XML_ACCENT, XML_FALSE);
+ break;
+ case SmMlAttributeValueAccent::MlTrue:
+ addAttribute(XML_ACCENT, XML_TRUE);
+ break;
+ default:
+ declareMlError();
+ break;
+ }
+ break;
+ }
+ case SmMlAttributeValueType::MlDir:
+ {
+ auto aAttributeValue = aAttribute.getMlDir();
+ switch (aAttributeValue->m_aDir)
+ {
+ case SmMlAttributeValueDir::MlLtr:
+ addAttribute(XML_DIR, XML_LTR);
+ break;
+ case SmMlAttributeValueDir::MlRtl:
+ addAttribute(XML_DIR, XML_RTL);
+ break;
+ default:
+ declareMlError();
+ break;
+ }
+ break;
+ }
+ case SmMlAttributeValueType::MlDisplaystyle:
+ {
+ auto aAttributeValue = aAttribute.getMlDisplaystyle();
+ switch (aAttributeValue->m_aDisplaystyle)
+ {
+ case SmMlAttributeValueDisplaystyle::MlTrue:
+ addAttribute(XML_DISPLAYSTYLE, XML_FALSE);
+ break;
+ case SmMlAttributeValueDisplaystyle::MlFalse:
+ addAttribute(XML_DISPLAYSTYLE, XML_TRUE);
+ break;
+ default:
+ declareMlError();
+ break;
+ }
+ break;
+ }
+ case SmMlAttributeValueType::MlFence:
+ {
+ auto aAttributeValue = aAttribute.getMlFence();
+ switch (aAttributeValue->m_aFence)
+ {
+ case SmMlAttributeValueFence::MlTrue:
+ addAttribute(XML_FENCE, XML_FALSE);
+ break;
+ case SmMlAttributeValueFence::MlFalse:
+ addAttribute(XML_FENCE, XML_TRUE);
+ break;
+ default:
+ declareMlError();
+ break;
+ }
+ break;
+ }
+ case SmMlAttributeValueType::MlHref:
+ {
+ auto aAttributeValue = aAttribute.getMlHref();
+ switch (aAttributeValue->m_aHref)
+ {
+ case SmMlAttributeValueHref::NMlEmpty:
+ break;
+ case SmMlAttributeValueHref::NMlValid:
+ addAttribute(XML_HREF, *aAttributeValue->m_aLnk);
+ break;
+ default:
+ declareMlError();
+ break;
+ }
+ break;
+ }
+ case SmMlAttributeValueType::MlLspace:
+ {
+ auto aSizeData = aAttribute.getMlLspace();
+ auto aLengthData = aSizeData->m_aLengthValue;
+ exportMlAttributeLength(XML_LSPACE, aLengthData);
+ break;
+ }
+ case SmMlAttributeValueType::MlMathbackground:
+ {
+ auto aAttributeValue = aAttribute.getMlMathbackground();
+ switch (aAttributeValue->m_aMathbackground)
+ {
+ case SmMlAttributeValueMathbackground::MlTransparent:
+ addAttribute(XML_MATHBACKGROUND, "transparent");
+ break;
+ case SmMlAttributeValueMathbackground::MlRgb:
+ {
+ const OUString& rTextColor = starmathdatabase::Identify_Color_MATHML(
+ sal_uInt32(aAttributeValue->m_aCol))
+ .aIdent;
+ addAttribute(XML_MATHBACKGROUND, rTextColor);
+ break;
+ }
+ default:
+ declareMlError();
+ break;
+ }
+ break;
+ }
+ case SmMlAttributeValueType::MlMathcolor:
+ {
+ auto aAttributeValue = aAttribute.getMlMathcolor();
+ switch (aAttributeValue->m_aMathcolor)
+ {
+ case SmMlAttributeValueMathcolor::MlDefault:
+ break;
+ case SmMlAttributeValueMathcolor::MlRgb:
+ {
+ const OUString& rTextColor = starmathdatabase::Identify_Color_MATHML(
+ sal_uInt32(aAttributeValue->m_aCol))
+ .aIdent;
+ addAttribute(XML_MATHCOLOR, rTextColor);
+ break;
+ }
+ default:
+ declareMlError();
+ break;
+ }
+ break;
+ }
+ case SmMlAttributeValueType::MlMathsize:
+ {
+ auto aSizeData = aAttribute.getMlMathsize();
+ auto aLengthData = aSizeData->m_aLengthValue;
+ exportMlAttributeLength(XML_MATHSIZE, aLengthData);
+ break;
+ }
+ case SmMlAttributeValueType::MlMathvariant:
+ {
+ auto aAttributeValue = aAttribute.getMlMathvariant();
+ switch (aAttributeValue->m_aMathvariant)
+ {
+ case SmMlAttributeValueMathvariant::normal:
+ addAttribute(XML_MATHVARIANT, "normal");
+ break;
+ case SmMlAttributeValueMathvariant::bold:
+ addAttribute(XML_MATHVARIANT, "bold");
+ break;
+ case SmMlAttributeValueMathvariant::italic:
+ addAttribute(XML_MATHVARIANT, "italic");
+ break;
+ case SmMlAttributeValueMathvariant::double_struck:
+ addAttribute(XML_MATHVARIANT, "double-struck");
+ break;
+ case SmMlAttributeValueMathvariant::script:
+ addAttribute(XML_MATHVARIANT, "script");
+ break;
+ case SmMlAttributeValueMathvariant::fraktur:
+ addAttribute(XML_MATHVARIANT, "fraktur");
+ break;
+ case SmMlAttributeValueMathvariant::sans_serif:
+ addAttribute(XML_MATHVARIANT, "sans-serif");
+ break;
+ case SmMlAttributeValueMathvariant::monospace:
+ addAttribute(XML_MATHVARIANT, "monospace");
+ break;
+ case SmMlAttributeValueMathvariant::bold_italic:
+ addAttribute(XML_MATHVARIANT, "bold-italic");
+ break;
+ case SmMlAttributeValueMathvariant::bold_fraktur:
+ addAttribute(XML_MATHVARIANT, "bold-fracktur");
+ break;
+ case SmMlAttributeValueMathvariant::bold_script:
+ addAttribute(XML_MATHVARIANT, "bold-script");
+ break;
+ case SmMlAttributeValueMathvariant::bold_sans_serif:
+ addAttribute(XML_MATHVARIANT, "bold-sans-serif");
+ break;
+ case SmMlAttributeValueMathvariant::sans_serif_italic:
+ addAttribute(XML_MATHVARIANT, "sans-serif-italic");
+ break;
+ case SmMlAttributeValueMathvariant::sans_serif_bold_italic:
+ addAttribute(XML_MATHVARIANT, "sans-serif-bold-italic");
+ break;
+ case SmMlAttributeValueMathvariant::initial:
+ addAttribute(XML_MATHVARIANT, "initial");
+ break;
+ case SmMlAttributeValueMathvariant::tailed:
+ addAttribute(XML_MATHVARIANT, "tailed");
+ break;
+ case SmMlAttributeValueMathvariant::looped:
+ addAttribute(XML_MATHVARIANT, "looped");
+ break;
+ case SmMlAttributeValueMathvariant::stretched:
+ addAttribute(XML_MATHVARIANT, "stretched");
+ break;
+ default:
+ declareMlError();
+ break;
+ }
+ break;
+ }
+ case SmMlAttributeValueType::MlMaxsize:
+ {
+ auto aSizeData = aAttribute.getMlMaxsize();
+ auto aLengthData = aSizeData->m_aLengthValue;
+ switch (aSizeData->m_aMaxsize)
+ {
+ case SmMlAttributeValueMaxsize::MlInfinity:
+ {
+ addAttribute(XML_MAXSIZE, XML_INFINITY);
+ break;
+ }
+ case SmMlAttributeValueMaxsize::MlFinite:
+ {
+ exportMlAttributeLength(XML_MAXSIZE, aLengthData);
+ break;
+ }
+ }
+ break;
+ }
+ case SmMlAttributeValueType::MlMinsize:
+ {
+ auto aSizeData = aAttribute.getMlMinsize();
+ auto aLengthData = aSizeData->m_aLengthValue;
+ exportMlAttributeLength(XML_MINSIZE, aLengthData);
+ break;
+ }
+ case SmMlAttributeValueType::MlMovablelimits:
+ {
+ auto aAttributeValue = aAttribute.getMlMovablelimits();
+ switch (aAttributeValue->m_aMovablelimits)
+ {
+ case SmMlAttributeValueMovablelimits::MlFalse:
+ addAttribute(XML_MOVABLELIMITS, XML_FALSE);
+ break;
+ case SmMlAttributeValueMovablelimits::MlTrue:
+ addAttribute(XML_MOVABLELIMITS, XML_TRUE);
+ break;
+ default:
+ declareMlError();
+ break;
+ }
+ break;
+ }
+ case SmMlAttributeValueType::MlRspace:
+ {
+ auto aSizeData = aAttribute.getMlRspace();
+ auto aLengthData = aSizeData->m_aLengthValue;
+ exportMlAttributeLength(XML_RSPACE, aLengthData);
+ break;
+ }
+ case SmMlAttributeValueType::MlSeparator:
+ {
+ auto aAttributeValue = aAttribute.getMlSeparator();
+ switch (aAttributeValue->m_aSeparator)
+ {
+ case SmMlAttributeValueSeparator::MlFalse:
+ addAttribute(XML_SEPARATOR, XML_FALSE);
+ break;
+ case SmMlAttributeValueSeparator::MlTrue:
+ addAttribute(XML_SEPARATOR, XML_TRUE);
+ break;
+ default:
+ declareMlError();
+ break;
+ }
+ break;
+ }
+ case SmMlAttributeValueType::MlStretchy:
+ {
+ auto aAttributeValue = aAttribute.getMlStretchy();
+ switch (aAttributeValue->m_aStretchy)
+ {
+ case SmMlAttributeValueStretchy::MlFalse:
+ addAttribute(XML_STRETCHY, XML_FALSE);
+ break;
+ case SmMlAttributeValueStretchy::MlTrue:
+ addAttribute(XML_STRETCHY, XML_TRUE);
+ break;
+ default:
+ declareMlError();
+ break;
+ }
+ break;
+ }
+ case SmMlAttributeValueType::MlSymmetric:
+ {
+ auto aAttributeValue = aAttribute.getMlSymmetric();
+ switch (aAttributeValue->m_aSymmetric)
+ {
+ case SmMlAttributeValueSymmetric::MlFalse:
+ addAttribute(XML_SYMMETRIC, XML_FALSE);
+ break;
+ case SmMlAttributeValueSymmetric::MlTrue:
+ addAttribute(XML_SYMMETRIC, XML_TRUE);
+ break;
+ default:
+ declareMlError();
+ break;
+ }
+ break;
+ }
+ default:
+ declareMlError();
+ break;
+ }
+ }
+}
+
+SvXMLElementExport* SmMLExport::exportMlElement(const SmMlElement* pMlElement)
+{
+ SvXMLElementExport* pElementExport;
+ switch (pMlElement->getMlElementType())
+ {
+ case SmMlElementType::MlMath:
+ pElementExport = createElementExport(XML_MATH);
+ break;
+ case SmMlElementType::MlMi:
+ pElementExport = createElementExport(XML_MI);
+ break;
+ case SmMlElementType::MlMerror:
+ pElementExport = createElementExport(XML_MERROR);
+ break;
+ case SmMlElementType::MlMn:
+ pElementExport = createElementExport(XML_MN);
+ break;
+ case SmMlElementType::MlMo:
+ pElementExport = createElementExport(XML_MO);
+ break;
+ case SmMlElementType::MlMrow:
+ pElementExport = createElementExport(XML_MROW);
+ break;
+ case SmMlElementType::MlMtext:
+ pElementExport = createElementExport(XML_MTEXT);
+ break;
+ case SmMlElementType::MlMstyle:
+ pElementExport = createElementExport(XML_MSTYLE);
+ break;
+ default:
+ pElementExport = nullptr;
+ }
+ const OUString& aElementText = pMlElement->getText();
+ exportMlAttributes(pMlElement);
+ if (aElementText.isEmpty())
+ GetDocHandler()->characters(aElementText);
+ return pElementExport;
+}
+
+namespace
+{
+struct exportMlElementTreeExecData
+{
+private:
+ SmMLExport* m_pSmMLExport;
+ std::vector<SvXMLElementExport*> m_aSvXMLElementExportList;
+ size_t m_nDepth;
+
+public:
+ inline exportMlElementTreeExecData(SmMLExport* pSmMLExport)
+ : m_pSmMLExport(pSmMLExport)
+ , m_aSvXMLElementExportList(1024)
+ , m_nDepth(0)
+ {
+ }
+
+ inline void deleteDepthData()
+ {
+ delete m_aSvXMLElementExportList[m_nDepth];
+ --m_nDepth;
+ }
+
+ inline void setDepthData(SvXMLElementExport* aSvXMLElementExportList)
+ {
+ if (m_nDepth == m_aSvXMLElementExportList.size())
+ m_aSvXMLElementExportList.resize(m_aSvXMLElementExportList.size() + 1024);
+ m_aSvXMLElementExportList[m_nDepth] = aSvXMLElementExportList;
+ }
+
+ inline void incrementDepth() { ++m_nDepth; }
+
+ inline SmMLExport* getSmMLExport() { return m_pSmMLExport; };
+};
+
+} // end unnamed namespace
+
+static inline void exportMlElementTreeExec(SmMlElement* aSmMlElement, void* aData)
+{
+ // Prepare data
+ exportMlElementTreeExecData* pData = static_cast<exportMlElementTreeExecData*>(aData);
+ pData->setDepthData(pData->getSmMLExport()->exportMlElement(aSmMlElement));
+
+ // Prepare for following
+ // If it has sub elements, then it will be the next
+ if (aSmMlElement->getSubElementsCount() != 0)
+ pData->incrementDepth();
+ else // Otherwise remounts up to where it should be
+ {
+ while (aSmMlElement->getParentElement() != nullptr)
+ {
+ // get parent
+ SmMlElement* pParent = aSmMlElement->getParentElement();
+ pData->deleteDepthData();
+ // was this the last branch ?
+ if (aSmMlElement->getSubElementId() + 1 != pParent->getSubElementsCount()) // yes -> up
+ break; // no -> stop going up
+ // Prepare for next round
+ aSmMlElement = pParent;
+ }
+ }
+}
+
+void SmMLExport::exportMlElementTree()
+{
+ exportMlElementTreeExecData* aData = new exportMlElementTreeExecData(this);
+ mathml::SmMlIteratorTopToBottom(m_pElementTree, exportMlElementTreeExec, aData);
+ delete aData;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/starmath/source/mathml/import.cxx b/starmath/source/mathml/import.cxx
new file mode 100644
index 000000000..52d47028e
--- /dev/null
+++ b/starmath/source/mathml/import.cxx
@@ -0,0 +1,1430 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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/.
+ */
+
+// Our mathml
+#include <mathml/import.hxx>
+
+// LO tools to use
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/packages/WrongPasswordException.hpp>
+#include <com/sun/star/packages/zip/ZipIOException.hpp>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+#include <com/sun/star/xml/sax/FastParser.hpp>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+
+// Extra LO tools
+#include <comphelper/fileformat.h>
+#include <comphelper/genericpropertyset.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <rtl/character.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/frame.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <sot/storage.hxx>
+#include <svtools/sfxecode.hxx>
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/strings.hrc>
+#include <unotools/streamwrap.hxx>
+#include <xmloff/DocumentSettingsContext.hxx>
+#include <xmloff/xmlmetai.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <o3tl/string_view.hxx>
+
+// Our starmath tools
+#include <cfgitem.hxx>
+#include <document.hxx>
+#include <xparsmlbase.hxx>
+#include <smmod.hxx>
+#include <starmathdatabase.hxx>
+#include <unomodel.hxx>
+
+// Old parser
+#include <mathmlimport.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace com::sun::star::xml::sax;
+using namespace ::xmloff::token;
+
+// SmMLImportContext
+/*************************************************************************************************/
+
+SmMlElement* SmMLImportWrapper::getElementTree()
+{
+ return m_pMlImport == nullptr ? nullptr : m_pMlImport->getElementTree();
+}
+
+ErrCode SmMLImportWrapper::Import(SfxMedium& rMedium)
+{
+ // Fetch context
+ uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
+ if (!xContext.is())
+ {
+ SAL_WARN("starmath", "Failed to fetch model while file input");
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+
+ // Check model
+ if (!m_xModel.is())
+ {
+ SAL_WARN("starmath", "Failed to fetch model while file input");
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+
+ // Make a model component from our SmModel
+ uno::Reference<lang::XComponent> xModelComp = m_xModel;
+ if (!xModelComp.is())
+ {
+ SAL_WARN("starmath", "Failed to make model while file input");
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+
+ // Try to get an XStatusIndicator from the Medium
+ uno::Reference<task::XStatusIndicator> xStatusIndicator;
+
+ // Get model via uno
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(m_xModel);
+ if (pModel == nullptr)
+ {
+ SAL_WARN("starmath", "Failed to fetch sm model while file input");
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+
+ // Get doc shell
+ m_pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
+ if (m_pDocShell == nullptr)
+ {
+ SAL_WARN("starmath", "Failed to fetch smdoc shell while file input");
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+
+ // Check if it is an embed object
+ bool bEmbedded = m_pDocShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED;
+
+ if (!bEmbedded)
+ {
+ // Extra check to ensure everything is fine
+ if (m_pDocShell->GetMedium() != &rMedium)
+ {
+ SAL_WARN("starmath", "Given medium and doc shell medium differ while file input");
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+
+ // Fetch the item set
+ SfxItemSet* pSet = rMedium.GetItemSet();
+ if (pSet)
+ {
+ const SfxUnoAnyItem* pItem = pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL);
+ if (pItem != nullptr)
+ pItem->GetValue() >>= xStatusIndicator;
+ }
+ }
+
+ // Create property list
+ static const comphelper::PropertyMapEntry aInfoMap[]
+ = { { u"PrivateData", 0, cppu::UnoType<XInterface>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { u"BaseURI", 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID,
+ 0 },
+ { u"StreamRelPath", 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { u"StreamName", 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 } };
+ uno::Reference<beans::XPropertySet> xInfoSet(
+ comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));
+
+ // Set base URI
+ // needed for relative URLs; but it's OK to import e.g. MathML from the clipboard without one
+ SAL_INFO_IF(rMedium.GetBaseURL().isEmpty(), "starmath", "SmMLImportWrapper: no base URL");
+ xInfoSet->setPropertyValue("BaseURI", Any(rMedium.GetBaseURL()));
+
+ // Fetch progress range
+ sal_Int32 nProgressRange(rMedium.IsStorage() ? 3 : 1);
+ if (xStatusIndicator.is())
+ {
+ xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange);
+ xStatusIndicator->setValue(0);
+ }
+
+ // Get storage
+ if (rMedium.IsStorage())
+ {
+ // TODO/LATER: handle the case of embedded links gracefully
+ if (bEmbedded) // && !rMedium.GetStorage()->IsRoot() )
+ {
+ OUString aName(u"dummyObjName");
+ if (rMedium.GetItemSet())
+ {
+ const SfxStringItem* pDocHierarchItem
+ = rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME);
+ if (pDocHierarchItem != nullptr)
+ aName = pDocHierarchItem->GetValue();
+ }
+
+ if (!aName.isEmpty())
+ xInfoSet->setPropertyValue("StreamRelPath", Any(aName));
+ }
+
+ // Check if use OASIS ( new document format )
+ bool bOASIS = SotStorage::GetVersion(rMedium.GetStorage()) > SOFFICE_FILEFORMAT_60;
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(1);
+
+ // Error code in case of needed
+ ErrCode nWarn = ERRCODE_NONE;
+
+ // Read metadata
+ // read a component from storage
+ if (!bEmbedded)
+ {
+ if (bOASIS)
+ nWarn = ReadThroughComponentS(rMedium.GetStorage(), xModelComp, u"meta.xml",
+ xContext, xInfoSet,
+ u"com.sun.star.comp.Math.MLOasisMetaImporter", 6);
+ else
+ nWarn
+ = ReadThroughComponentS(rMedium.GetStorage(), xModelComp, u"meta.xml", xContext,
+ xInfoSet, u"com.sun.star.comp.Math.XMLMetaImporter", 5);
+ }
+
+ // Check if successful
+ if (nWarn != ERRCODE_NONE)
+ {
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ SAL_WARN("starmath", "Failed to read file");
+ return nWarn;
+ }
+
+ // Increase success indicator
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(2);
+
+ // Read settings
+ // read a component from storage
+ if (bOASIS)
+ nWarn = ReadThroughComponentS(rMedium.GetStorage(), xModelComp, u"settings.xml",
+ xContext, xInfoSet,
+ u"com.sun.star.comp.Math.MLOasisSettingsImporter", 6);
+ else
+ nWarn
+ = ReadThroughComponentS(rMedium.GetStorage(), xModelComp, u"settings.xml", xContext,
+ xInfoSet, u"com.sun.star.comp.Math.XMLSettingsImporter", 5);
+
+ // Check if successful
+ if (nWarn == ERRCODE_IO_BROKENPACKAGE)
+ {
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ SAL_WARN("starmath", "Failed to read file");
+ return nWarn;
+ }
+
+ // Increase success indicator
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(3);
+
+ // Read document
+ // read a component from storage
+ if (m_pDocShell->GetSmSyntaxVersion() == 5)
+ nWarn
+ = ReadThroughComponentS(rMedium.GetStorage(), xModelComp, u"content.xml", xContext,
+ xInfoSet, u"com.sun.star.comp.Math.XMLImporter", 5);
+ else
+ nWarn
+ = ReadThroughComponentS(rMedium.GetStorage(), xModelComp, u"content.xml", xContext,
+ xInfoSet, u"com.sun.star.comp.Math.MLImporter", 6);
+ // Check if successful
+ if (nWarn != ERRCODE_NONE)
+ {
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ SAL_WARN("starmath", "Failed to read file");
+ return nWarn;
+ }
+
+ // Finish
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ return ERRCODE_NONE;
+ }
+ else
+ {
+ // Create input stream
+ Reference<io::XInputStream> xInputStream
+ = new utl::OInputStreamWrapper(rMedium.GetInStream());
+
+ // Increase success indicator
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(1);
+
+ // Read data
+ // read a component from input stream
+ ErrCode nError = ERRCODE_NONE;
+ if (m_pDocShell->GetSmSyntaxVersion() == 5)
+ nError = ReadThroughComponentIS(xInputStream, xModelComp, xContext, xInfoSet,
+ u"com.sun.star.comp.Math.XMLImporter", false, 5);
+ else
+ nError = ReadThroughComponentIS(xInputStream, xModelComp, xContext, xInfoSet,
+ u"com.sun.star.comp.Math.MLImporter", false, 6);
+
+ // Finish
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+
+ // Declare any error
+ if (nError != ERRCODE_NONE)
+ SAL_WARN("starmath", "Failed to read file");
+
+ return nError;
+ }
+}
+
+ErrCode SmMLImportWrapper::Import(std::u16string_view aSource)
+{
+ // Fetch context
+ uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
+ if (!xContext.is())
+ {
+ SAL_WARN("starmath", "Failed to fetch model while file input");
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+
+ // Check model
+ if (!m_xModel.is())
+ {
+ SAL_WARN("starmath", "Failed to fetch model while file input");
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+
+ // Make a model component from our SmModel
+ uno::Reference<lang::XComponent> xModelComp = m_xModel;
+ if (!xModelComp.is())
+ {
+ SAL_WARN("starmath", "Failed to make model while file input");
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+
+ // Get model via uno
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(m_xModel);
+ if (pModel == nullptr)
+ {
+ SAL_WARN("starmath", "Failed to fetch sm model while file input");
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+
+ // Get doc shell
+ m_pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
+ if (m_pDocShell == nullptr)
+ {
+ SAL_WARN("starmath", "Failed to fetch smdoc shell while file input");
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+
+ // Create property list
+ static const comphelper::PropertyMapEntry aInfoMap[]
+ = { { u"PrivateData", 0, cppu::UnoType<XInterface>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { u"BaseURI", 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID,
+ 0 },
+ { u"StreamRelPath", 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { u"StreamName", 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 } };
+ uno::Reference<beans::XPropertySet> xInfoSet(
+ comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));
+
+ // Read data
+ // read a component from text
+ ErrCode nError = ReadThroughComponentMS(aSource, xModelComp, xContext, xInfoSet);
+
+ // Declare any error
+ if (nError != ERRCODE_NONE)
+ {
+ SAL_WARN("starmath", "Failed to read file");
+ return nError;
+ }
+
+ return ERRCODE_NONE;
+}
+
+// read a component from input stream
+ErrCode SmMLImportWrapper::ReadThroughComponentIS(
+ const Reference<io::XInputStream>& xInputStream, const Reference<XComponent>& xModelComponent,
+ Reference<uno::XComponentContext> const& rxContext,
+ Reference<beans::XPropertySet> const& rPropSet, const char16_t* pFilterName, bool bEncrypted,
+ int_fast16_t nSyntaxVersion)
+{
+ // Needs an input stream but checked by caller
+ // Needs a context but checked by caller
+ // Needs property set but checked by caller
+ // Needs a filter name but checked by caller
+
+ // Prepare ParserInputSource
+ xml::sax::InputSource aParserInput;
+ aParserInput.aInputStream = xInputStream;
+
+ // Prepare property list
+ Sequence<Any> aArgs{ Any(rPropSet) };
+
+ // Get filter
+ Reference<XInterface> xFilter
+ = rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ OUString(pFilterName), aArgs, rxContext);
+ if (!xFilter.is())
+ {
+ SAL_WARN("starmath", "Can't instantiate filter component " << OUString(pFilterName));
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+
+ // Connect model and filter
+ Reference<XImporter> xImporter(xFilter, UNO_QUERY);
+ xImporter->setTargetDocument(xModelComponent);
+
+ // Finally, parser the stream
+ try
+ {
+ Reference<css::xml::sax::XFastParser> xFastParser(xFilter, UNO_QUERY);
+ Reference<css::xml::sax::XFastDocumentHandler> xFastDocHandler(xFilter, UNO_QUERY);
+ if (xFastParser)
+ {
+ xFastParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities);
+ xFastParser->parseStream(aParserInput);
+ }
+ else if (xFastDocHandler)
+ {
+ Reference<css::xml::sax::XFastParser> xParser
+ = css::xml::sax::FastParser::create(rxContext);
+ xParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities);
+ xParser->setFastDocumentHandler(xFastDocHandler);
+ xParser->parseStream(aParserInput);
+ }
+ else
+ {
+ Reference<css::xml::sax::XDocumentHandler> xDocHandler(xFilter, UNO_QUERY);
+ assert(xDocHandler);
+ Reference<css::xml::sax::XParser> xParser = css::xml::sax::Parser::create(rxContext);
+ xParser->setDocumentHandler(xDocHandler);
+ xParser->parseStream(aParserInput);
+ }
+
+ if (nSyntaxVersion == 5)
+ {
+ SmXMLImport* pXMlImport = comphelper::getFromUnoTunnel<SmXMLImport>(xFilter);
+ if (pXMlImport != nullptr && pXMlImport->GetSuccess())
+ return ERRCODE_NONE;
+ else
+ {
+ SAL_WARN("starmath", "Filter failed on file input");
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+ }
+
+ m_pMlImport = comphelper::getFromUnoTunnel<SmMLImport>(xFilter);
+ if (m_pMlImport != nullptr && m_pMlImport->getSuccess())
+ return ERRCODE_NONE;
+ else
+ {
+ SAL_WARN("starmath", "Filter failed on file input");
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+ }
+ catch (const xml::sax::SAXParseException& r)
+ {
+ // Sax parser sends wrapped exceptions, try to find the original one
+ xml::sax::SAXException aTmp;
+ xml::sax::SAXException aSaxEx = *static_cast<const xml::sax::SAXException*>(&r);
+ while (aSaxEx.WrappedException >>= aTmp)
+ aSaxEx = aTmp;
+
+ packages::zip::ZipIOException aBrokenPackage;
+ if (aSaxEx.WrappedException >>= aBrokenPackage)
+ {
+ SAL_WARN("starmath", "Failed to read file SAXParseException");
+ return ERRCODE_IO_BROKENPACKAGE;
+ }
+
+ if (bEncrypted)
+ {
+ SAL_WARN("starmath", "Wrong file password SAXParseException");
+ return ERRCODE_SFX_WRONGPASSWORD;
+ }
+ }
+ catch (const xml::sax::SAXException& r)
+ {
+ packages::zip::ZipIOException aBrokenPackage;
+ if (r.WrappedException >>= aBrokenPackage)
+ {
+ SAL_WARN("starmath", "Failed to read file SAXException");
+ return ERRCODE_IO_BROKENPACKAGE;
+ }
+
+ if (bEncrypted)
+ {
+ SAL_WARN("starmath", "Wrong file password SAXException");
+ return ERRCODE_SFX_WRONGPASSWORD;
+ }
+ }
+ catch (const packages::zip::ZipIOException&)
+ {
+ SAL_WARN("starmath", "Failed to unzip file ZipIOException");
+ return ERRCODE_IO_BROKENPACKAGE;
+ }
+ catch (const io::IOException&)
+ {
+ SAL_WARN("starmath", "Failed to read file ZipIOException");
+ return ERRCODE_IO_UNKNOWN;
+ }
+ catch (const std::range_error&)
+ {
+ SAL_WARN("starmath", "Failed to read file");
+ return ERRCODE_ABORT;
+ }
+
+ return ERRCODE_ABORT;
+}
+
+// read a component from storage
+ErrCode SmMLImportWrapper::ReadThroughComponentS(const uno::Reference<embed::XStorage>& xStorage,
+ const Reference<XComponent>& xModelComponent,
+ const char16_t* pStreamName,
+ Reference<uno::XComponentContext> const& rxContext,
+ Reference<beans::XPropertySet> const& rPropSet,
+ const char16_t* pFilterName,
+ int_fast16_t nSyntaxVersion)
+{
+ // Needs a storage but checked by caller
+ // Needs a model but checked by caller
+ // Needs a stream name but checked by caller
+ // Needs a context but checked by caller
+ // Needs a property set but checked by caller
+ // Needs a filter name but checked by caller
+
+ // Get the input stream
+ try
+ {
+ // Create the stream for the event read
+ uno::Reference<io::XStream> xEventsStream
+ = xStorage->openStreamElement(OUString(pStreamName), embed::ElementModes::READ);
+
+ // Determine if stream is encrypted or not
+ uno::Reference<beans::XPropertySet> xProps(xEventsStream, uno::UNO_QUERY);
+ Any aAny = xProps->getPropertyValue("Encrypted");
+ bool bEncrypted = false;
+ aAny >>= bEncrypted;
+
+ // Set base URL and open stream
+ rPropSet->setPropertyValue("StreamName", Any(OUString(pStreamName)));
+ Reference<io::XInputStream> xStream = xEventsStream->getInputStream();
+
+ // Execute read
+ return ReadThroughComponentIS(xStream, xModelComponent, rxContext, rPropSet, pFilterName,
+ bEncrypted, nSyntaxVersion);
+ }
+ catch (packages::WrongPasswordException&)
+ {
+ SAL_WARN("starmath", "Wrong file password");
+ return ERRCODE_SFX_WRONGPASSWORD;
+ }
+ catch (packages::zip::ZipIOException&)
+ {
+ SAL_WARN("starmath", "Failed to unzip file");
+ return ERRCODE_IO_BROKENPACKAGE;
+ }
+ catch (uno::Exception&)
+ {
+ }
+
+ return ERRCODE_SFX_DOLOADFAILED;
+}
+
+// read a component from text
+ErrCode SmMLImportWrapper::ReadThroughComponentMS(
+ std::u16string_view aText, const css::uno::Reference<css::lang::XComponent>& xModelComponent,
+ css::uno::Reference<css::uno::XComponentContext> const& rxContext,
+ css::uno::Reference<css::beans::XPropertySet> const& rPropSet)
+{
+ // Needs a storage but checked by caller
+ // Needs a model but checked by caller
+ // Needs a stream name but checked by caller
+ // Needs a context but checked by caller
+ // Needs a property set but checked by caller
+ // Needs a filter name but checked by caller
+
+ // Get the input stream
+ try
+ {
+ // Generate input memory stream
+ SvMemoryStream aMemoryStream;
+ aMemoryStream.WriteOString(OUStringToOString(aText, RTL_TEXTENCODING_UTF8));
+ uno::Reference<io::XInputStream> xStream(new utl::OInputStreamWrapper(aMemoryStream));
+
+ // Execute read
+ return ReadThroughComponentIS(xStream, xModelComponent, rxContext, rPropSet,
+ u"com.sun.star.comp.Math.MLImporter", false, 6);
+ }
+ catch (packages::WrongPasswordException&)
+ {
+ SAL_WARN("starmath", "Wrong file password");
+ return ERRCODE_SFX_WRONGPASSWORD;
+ }
+ catch (packages::zip::ZipIOException&)
+ {
+ SAL_WARN("starmath", "Failed to unzip file");
+ return ERRCODE_IO_BROKENPACKAGE;
+ }
+ catch (uno::Exception&)
+ {
+ }
+
+ return ERRCODE_SFX_DOLOADFAILED;
+}
+
+// SmMLImport technical
+/*************************************************************************************************/
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+Math_MLImporter_get_implementation(uno::XComponentContext* pCtx,
+ uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(
+ new SmMLImport(pCtx, "com.sun.star.comp.Math.XMLImporter", SvXMLImportFlags::ALL));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+Math_MLOasisMetaImporter_get_implementation(uno::XComponentContext* pCtx,
+ uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new SmMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisMetaImporter",
+ SvXMLImportFlags::META));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+Math_MLOasisSettingsImporter_get_implementation(uno::XComponentContext* pCtx,
+ uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new SmMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisSettingsImporter",
+ SvXMLImportFlags::SETTINGS));
+}
+
+// SmMLImportContext
+/*************************************************************************************************/
+
+namespace
+{
+class SmMLImportContext : public SvXMLImportContext
+{
+private:
+ SmMlElement** m_pParent;
+ SmMlElement* m_pElement;
+ SmMlElement* m_pStyle;
+
+public:
+ SmMLImportContext(SmMLImport& rImport, SmMlElement** pParent)
+ : SvXMLImportContext(rImport)
+ , m_pParent(pParent)
+ , m_pElement(nullptr)
+ , m_pStyle(nullptr)
+ {
+ }
+
+private:
+ void declareMlError();
+
+public:
+ /** Handles characters (text)
+ */
+ virtual void SAL_CALL characters(const OUString& aChars) override;
+
+ /** Starts the mathml element
+ */
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement, const Reference<XFastAttributeList>& aAttributeList) override;
+
+ /** Ends the mathml element
+ */
+ virtual void SAL_CALL endFastElement(sal_Int32 Element) override;
+
+ /** Creates child element
+ */
+ virtual uno::Reference<XFastContextHandler>
+ SAL_CALL createFastChildContext(sal_Int32 nElement,
+ const uno::Reference<XFastAttributeList>& Attribs) override;
+
+ /** Inherits the style from it's parents
+ */
+ void inheritStyle();
+
+ /** Inherits the style from it's parents on end
+ */
+ void inheritStyleEnd();
+
+ /** Handle mathml attributes
+ */
+ void handleAttributes(const Reference<XFastAttributeList>& aAttributeList);
+
+ /** Handle mathml length attributes
+ */
+ SmLengthValue handleLengthAttribute(const OUString& aAttribute);
+};
+
+uno::Reference<XFastContextHandler> SAL_CALL
+SmMLImportContext::createFastChildContext(sal_Int32, const uno::Reference<XFastAttributeList>&)
+{
+ uno::Reference<xml::sax::XFastContextHandler> xContext;
+ xContext = new SmMLImportContext(static_cast<SmMLImport&>(GetImport()), &m_pElement);
+ return xContext;
+}
+
+void SmMLImportContext::declareMlError()
+{
+ SmMLImport& aSmMLImport = static_cast<SmMLImport&>(GetImport());
+ aSmMLImport.declareMlError();
+}
+
+void SmMLImportContext::inheritStyle()
+{
+ while ((m_pStyle = m_pStyle->getParentElement()) != nullptr)
+ {
+ if (m_pStyle->getParentElement()->getMlElementType() == SmMlElementType::MlMstyle
+ || m_pStyle->getParentElement()->getMlElementType() == SmMlElementType::MlMath)
+ break;
+ }
+
+ // Parent inheritation
+ // Mathcolor, mathsize, dir and displaystyle are inherited from parent
+ SmMlElement* pParent = *m_pParent;
+ m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlMathcolor));
+ m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlMathsize));
+ m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlDir));
+ m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlDisplaystyle));
+
+ // Inherit operator dictionary overwrites
+ if (m_pStyle != nullptr
+ && (m_pElement->getMlElementType() == SmMlElementType::MlMo
+ || m_pElement->getMlElementType() == SmMlElementType::MlMstyle
+ || m_pElement->getMlElementType() == SmMlElementType::MlMath))
+ {
+ // TODO fetch operator dictionary first and then overwrite
+ if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlAccent))
+ m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlAccent));
+ if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlFence))
+ m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlFence));
+ if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlLspace))
+ m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlLspace));
+ if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMaxsize))
+ m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlMaxsize));
+ if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMinsize))
+ m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlMinsize));
+ if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMovablelimits))
+ m_pElement->setAttribute(
+ m_pStyle->getAttribute(SmMlAttributeValueType::MlMovablelimits));
+ if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlRspace))
+ m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlRspace));
+ if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlSeparator))
+ m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlSeparator));
+ if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlStretchy))
+ m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlStretchy));
+ if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlSymmetric))
+ m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlSymmetric));
+
+ if (m_pElement->getMlElementType() == SmMlElementType::MlMo)
+ {
+ // Set form based in position
+ SmMlAttribute aAttribute(SmMlAttributeValueType::MlForm);
+ SmMlForm aForm;
+ if (m_pElement->getSubElementId() == 0)
+ aForm = { SmMlAttributeValueForm::MlPrefix };
+ else
+ aForm = { SmMlAttributeValueForm::MlInfix };
+ aAttribute.setMlForm(&aForm);
+ m_pElement->setAttribute(aAttribute);
+ }
+ }
+
+ // Inherit mathvariant
+ if (m_pStyle && m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMathvariant))
+ m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlMathvariant));
+}
+
+void SmMLImportContext::inheritStyleEnd()
+{
+ // Mo: check it is the end: postfix
+ if (m_pElement->getMlElementType() == SmMlElementType::MlMo)
+ {
+ if ((*m_pParent)->getSubElementsCount() == m_pElement->getSubElementId())
+ {
+ // Set form based in position
+ SmMlAttribute aAttribute(SmMlAttributeValueType::MlForm);
+ SmMlForm aForm = { SmMlAttributeValueForm::MlPosfix };
+ aAttribute.setMlForm(&aForm);
+ m_pElement->setAttribute(aAttribute);
+ }
+ }
+
+ // Mi: 1 char -> italic
+ if (m_pElement->getMlElementType() != SmMlElementType::MlMi)
+ return;
+
+ // Inherit mathvariant
+ if (!m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMathvariant))
+ {
+ sal_Int32 nIndexUtf16 = 0;
+ // Check if there is only one code point
+ m_pElement->getText().iterateCodePoints(&nIndexUtf16, 1);
+ // Mathml says that 1 code point -> italic
+ if (nIndexUtf16 == m_pElement->getText().getLength())
+ {
+ SmMlAttribute aAttribute(SmMlAttributeValueType::MlMathvariant);
+ SmMlMathvariant aMathvariant = { SmMlAttributeValueMathvariant::italic };
+ aAttribute.setMlMathvariant(&aMathvariant);
+ aAttribute.setSet(false);
+ m_pElement->setAttribute(aAttribute);
+ }
+ }
+}
+
+SmLengthValue SmMLImportContext::handleLengthAttribute(const OUString& aAttribute)
+{
+ // Locate unit indication
+ int32_t nUnitPos;
+ for (nUnitPos = 0;
+ nUnitPos < aAttribute.getLength()
+ && (rtl::isAsciiHexDigit(aAttribute[nUnitPos]) || aAttribute[nUnitPos] == '.');
+ ++nUnitPos)
+ ;
+
+ // Find unit
+ SmLengthUnit nUnit = SmLengthUnit::MlM;
+ if (nUnitPos != aAttribute.getLength())
+ {
+ OUString aUnit = aAttribute.copy(nUnitPos);
+ if (aUnit.compareToIgnoreAsciiCaseAscii("ex"))
+ nUnit = SmLengthUnit::MlEx;
+ if (aUnit.compareToIgnoreAsciiCaseAscii("px"))
+ nUnit = SmLengthUnit::MlPx;
+ if (aUnit.compareToIgnoreAsciiCaseAscii("in"))
+ nUnit = SmLengthUnit::MlIn;
+ if (aUnit.compareToIgnoreAsciiCaseAscii("cm"))
+ nUnit = SmLengthUnit::MlCm;
+ if (aUnit.compareToIgnoreAsciiCaseAscii("mm"))
+ nUnit = SmLengthUnit::MlMm;
+ if (aUnit.compareToIgnoreAsciiCaseAscii("pt"))
+ nUnit = SmLengthUnit::MlPt;
+ if (aUnit.compareToIgnoreAsciiCaseAscii("pc"))
+ nUnit = SmLengthUnit::MlPc;
+ if (aUnit.compareToIgnoreAsciiCaseAscii("%"))
+ nUnit = SmLengthUnit::MlP;
+ else
+ declareMlError();
+ }
+
+ // Get value
+ std::u16string_view aValue = aAttribute.subView(0, nUnitPos);
+ double nValue = o3tl::toDouble(aValue);
+ if (nValue == 0)
+ {
+ nUnit = SmLengthUnit::MlM;
+ nValue = 1.0;
+ declareMlError();
+ }
+
+ // Return
+ SmLengthValue aLengthValue = { nUnit, nValue, new OUString(aAttribute) };
+ return aLengthValue;
+}
+
+void SmMLImportContext::handleAttributes(const Reference<XFastAttributeList>& aAttributeList)
+{
+ for (auto& aIter : sax_fastparser::castToFastAttributeList(aAttributeList))
+ {
+ SmMlAttribute aAttribute(SmMlAttributeValueType::NMlEmpty);
+ switch (aIter.getToken() & TOKEN_MASK)
+ {
+ case XML_ACCENT:
+ {
+ if (IsXMLToken(aIter, XML_TRUE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlAccent);
+ SmMlAccent aAccent = { SmMlAttributeValueAccent::MlTrue };
+ aAttribute.setMlAccent(&aAccent);
+ }
+ else if (IsXMLToken(aIter, XML_FALSE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlAccent);
+ SmMlAccent aAccent = { SmMlAttributeValueAccent::MlFalse };
+ aAttribute.setMlAccent(&aAccent);
+ }
+ else
+ {
+ declareMlError();
+ }
+ break;
+ }
+ case XML_DIR:
+ {
+ if (IsXMLToken(aIter, XML_RTL))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDir);
+ SmMlDir aDir = { SmMlAttributeValueDir::MlRtl };
+ aAttribute.setMlDir(&aDir);
+ }
+ else if (IsXMLToken(aIter, XML_LTR))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDir);
+ SmMlDir aDir = { SmMlAttributeValueDir::MlLtr };
+ aAttribute.setMlDir(&aDir);
+ }
+ else
+ {
+ declareMlError();
+ }
+ break;
+ }
+ case XML_DISPLAYSTYLE:
+ if (IsXMLToken(aIter, XML_TRUE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDisplaystyle);
+ SmMlDisplaystyle aDisplaystyle = { SmMlAttributeValueDisplaystyle::MlTrue };
+ aAttribute.setMlDisplaystyle(&aDisplaystyle);
+ }
+ else if (IsXMLToken(aIter, XML_FALSE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDisplaystyle);
+ SmMlDisplaystyle aDisplaystyle = { SmMlAttributeValueDisplaystyle::MlFalse };
+ aAttribute.setMlDisplaystyle(&aDisplaystyle);
+ }
+ else
+ {
+ declareMlError();
+ }
+ break;
+ case XML_FENCE:
+ if (IsXMLToken(aIter, XML_TRUE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlFence);
+ SmMlFence aFence = { SmMlAttributeValueFence::MlTrue };
+ aAttribute.setMlFence(&aFence);
+ }
+ else if (IsXMLToken(aIter, XML_FALSE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlFence);
+ SmMlFence aFence = { SmMlAttributeValueFence::MlFalse };
+ aAttribute.setMlFence(&aFence);
+ }
+ else
+ {
+ declareMlError();
+ }
+ break;
+ case XML_HREF:
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlHref);
+ OUString* aRef = new OUString(aIter.toString());
+ SmMlHref aHref = { SmMlAttributeValueHref::NMlValid, aRef };
+ aAttribute.setMlHref(&aHref);
+ break;
+ }
+ case XML_LSPACE:
+ {
+ SmMlLspace aLspace;
+ aLspace.m_aLengthValue = handleLengthAttribute(aIter.toString());
+ aAttribute.setMlLspace(&aLspace);
+ break;
+ }
+ case XML_MATHBACKGROUND:
+ {
+ if (IsXMLToken(aIter, XML_TRANSPARENT))
+ {
+ SmMlMathbackground aMathbackground
+ = { SmMlAttributeValueMathbackground::MlTransparent, COL_TRANSPARENT };
+ aAttribute.setMlMathbackground(&aMathbackground);
+ }
+ else
+ {
+ Color aColor
+ = starmathdatabase::Identify_ColorName_HTML(aIter.toString()).cColor;
+ SmMlMathbackground aMathbackground
+ = { SmMlAttributeValueMathbackground::MlRgb, aColor };
+ aAttribute.setMlMathbackground(&aMathbackground);
+ }
+ break;
+ }
+ case XML_MATHCOLOR:
+ {
+ if (IsXMLToken(aIter, XML_DEFAULT))
+ {
+ SmMlMathcolor aMathcolor
+ = { SmMlAttributeValueMathcolor::MlDefault, COL_BLACK };
+ aAttribute.setMlMathcolor(&aMathcolor);
+ }
+ else
+ {
+ Color aColor
+ = starmathdatabase::Identify_ColorName_HTML(aIter.toString()).cColor;
+ SmMlMathcolor aMathcolor = { SmMlAttributeValueMathcolor::MlRgb, aColor };
+ aAttribute.setMlMathcolor(&aMathcolor);
+ }
+ break;
+ }
+ case XML_MATHSIZE:
+ {
+ SmMlMathsize aMathsize;
+ aMathsize.m_aLengthValue = handleLengthAttribute(aIter.toString());
+ aAttribute.setMlMathsize(&aMathsize);
+ break;
+ }
+ case XML_MATHVARIANT:
+ {
+ OUString aVariant = aIter.toString();
+ SmMlAttributeValueMathvariant nVariant = SmMlAttributeValueMathvariant::normal;
+ if (aVariant.compareTo(u"normal"))
+ nVariant = SmMlAttributeValueMathvariant::normal;
+ else if (aVariant.compareTo(u"bold"))
+ nVariant = SmMlAttributeValueMathvariant::bold;
+ else if (aVariant.compareTo(u"italic"))
+ nVariant = SmMlAttributeValueMathvariant::italic;
+ else if (aVariant.compareTo(u"double-struck"))
+ nVariant = SmMlAttributeValueMathvariant::double_struck;
+ else if (aVariant.compareTo(u"script"))
+ nVariant = SmMlAttributeValueMathvariant::script;
+ else if (aVariant.compareTo(u"fraktur"))
+ nVariant = SmMlAttributeValueMathvariant::fraktur;
+ else if (aVariant.compareTo(u"sans-serif"))
+ nVariant = SmMlAttributeValueMathvariant::sans_serif;
+ else if (aVariant.compareTo(u"monospace"))
+ nVariant = SmMlAttributeValueMathvariant::monospace;
+ else if (aVariant.compareTo(u"bold-italic"))
+ nVariant = SmMlAttributeValueMathvariant::bold_italic;
+ else if (aVariant.compareTo(u"bold-fracktur"))
+ nVariant = SmMlAttributeValueMathvariant::bold_fraktur;
+ else if (aVariant.compareTo(u"bold-script"))
+ nVariant = SmMlAttributeValueMathvariant::bold_script;
+ else if (aVariant.compareTo(u"bold-sans-serif"))
+ nVariant = SmMlAttributeValueMathvariant::bold_sans_serif;
+ else if (aVariant.compareTo(u"sans-serif-italic"))
+ nVariant = SmMlAttributeValueMathvariant::sans_serif_italic;
+ else if (aVariant.compareTo(u"sans-serif-bold-italic"))
+ nVariant = SmMlAttributeValueMathvariant::sans_serif_bold_italic;
+ else if (aVariant.compareTo(u"initial"))
+ nVariant = SmMlAttributeValueMathvariant::initial;
+ else if (aVariant.compareTo(u"tailed"))
+ nVariant = SmMlAttributeValueMathvariant::tailed;
+ else if (aVariant.compareTo(u"looped"))
+ nVariant = SmMlAttributeValueMathvariant::looped;
+ else if (aVariant.compareTo(u"stretched"))
+ nVariant = SmMlAttributeValueMathvariant::stretched;
+ else
+ declareMlError();
+ SmMlMathvariant aMathvariant = { nVariant };
+ aAttribute.setMlMathvariant(&aMathvariant);
+ break;
+ }
+ case XML_MAXSIZE:
+ {
+ SmMlMaxsize aMaxsize;
+ if (IsXMLToken(aIter, XML_INFINITY))
+ {
+ aMaxsize.m_aMaxsize = SmMlAttributeValueMaxsize::MlInfinity;
+ aMaxsize.m_aLengthValue = { SmLengthUnit::MlP, 10000, new OUString(u"10000%") };
+ }
+ else
+ {
+ aMaxsize.m_aMaxsize = SmMlAttributeValueMaxsize::MlFinite;
+ aMaxsize.m_aLengthValue = handleLengthAttribute(aIter.toString());
+ }
+ aAttribute.setMlMaxsize(&aMaxsize);
+ break;
+ }
+ case XML_MINSIZE:
+ {
+ SmMlMinsize aMinsize;
+ aMinsize.m_aLengthValue = handleLengthAttribute(aIter.toString());
+ aAttribute.setMlMinsize(&aMinsize);
+ break;
+ }
+ case XML_MOVABLELIMITS:
+ if (IsXMLToken(aIter, XML_TRUE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlMovablelimits);
+ SmMlMovablelimits aMovablelimits = { SmMlAttributeValueMovablelimits::MlTrue };
+ aAttribute.setMlMovablelimits(&aMovablelimits);
+ }
+ else if (IsXMLToken(aIter, XML_FALSE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlMovablelimits);
+ SmMlMovablelimits aMovablelimits = { SmMlAttributeValueMovablelimits::MlFalse };
+ aAttribute.setMlMovablelimits(&aMovablelimits);
+ }
+ else
+ {
+ declareMlError();
+ }
+ break;
+ case XML_RSPACE:
+ {
+ SmMlRspace aRspace;
+ aRspace.m_aLengthValue = handleLengthAttribute(aIter.toString());
+ aAttribute.setMlRspace(&aRspace);
+ break;
+ }
+ case XML_SEPARATOR:
+ if (IsXMLToken(aIter, XML_TRUE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSeparator);
+ SmMlSeparator aSeparator = { SmMlAttributeValueSeparator::MlTrue };
+ aAttribute.setMlSeparator(&aSeparator);
+ }
+ else if (IsXMLToken(aIter, XML_FALSE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSeparator);
+ SmMlSeparator aSeparator = { SmMlAttributeValueSeparator::MlFalse };
+ aAttribute.setMlSeparator(&aSeparator);
+ }
+ else
+ {
+ declareMlError();
+ }
+ break;
+ case XML_STRETCHY:
+ if (IsXMLToken(aIter, XML_TRUE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlStretchy);
+ SmMlStretchy aStretchy = { SmMlAttributeValueStretchy::MlTrue };
+ aAttribute.setMlStretchy(&aStretchy);
+ }
+ else if (IsXMLToken(aIter, XML_FALSE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlStretchy);
+ SmMlStretchy aStretchy = { SmMlAttributeValueStretchy::MlFalse };
+ aAttribute.setMlStretchy(&aStretchy);
+ }
+ else
+ {
+ declareMlError();
+ }
+ break;
+ case XML_SYMMETRIC:
+ if (IsXMLToken(aIter, XML_TRUE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSymmetric);
+ SmMlSymmetric aSymmetric = { SmMlAttributeValueSymmetric::MlTrue };
+ aAttribute.setMlSymmetric(&aSymmetric);
+ }
+ else if (IsXMLToken(aIter, XML_FALSE))
+ {
+ aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSymmetric);
+ SmMlSymmetric aSymmetric = { SmMlAttributeValueSymmetric::MlFalse };
+ aAttribute.setMlSymmetric(&aSymmetric);
+ }
+ else
+ {
+ declareMlError();
+ }
+ break;
+ default:
+ declareMlError();
+ break;
+ }
+ if (aAttribute.isNullAttribute())
+ declareMlError();
+ else
+ m_pElement->setAttribute(aAttribute);
+ }
+}
+
+void SmMLImportContext::characters(const OUString& aChars) { m_pElement->setText(aChars); }
+
+void SmMLImportContext::startFastElement(sal_Int32 nElement,
+ const Reference<XFastAttributeList>& aAttributeList)
+{
+ switch (nElement)
+ {
+ case XML_ELEMENT(MATH, XML_MATH):
+ m_pElement = new SmMlElement(SmMlElementType::MlMath);
+ break;
+ case XML_ELEMENT(MATH, XML_MI):
+ m_pElement = new SmMlElement(SmMlElementType::MlMi);
+ break;
+ case XML_ELEMENT(MATH, XML_MERROR):
+ m_pElement = new SmMlElement(SmMlElementType::MlMerror);
+ break;
+ case XML_ELEMENT(MATH, XML_MN):
+ m_pElement = new SmMlElement(SmMlElementType::MlMn);
+ break;
+ case XML_ELEMENT(MATH, XML_MO):
+ m_pElement = new SmMlElement(SmMlElementType::MlMo);
+ break;
+ case XML_ELEMENT(MATH, XML_MROW):
+ m_pElement = new SmMlElement(SmMlElementType::MlMrow);
+ break;
+ case XML_ELEMENT(MATH, XML_MTEXT):
+ m_pElement = new SmMlElement(SmMlElementType::MlMtext);
+ break;
+ case XML_ELEMENT(MATH, XML_MSTYLE):
+ m_pElement = new SmMlElement(SmMlElementType::MlMstyle);
+ break;
+ default:
+ m_pElement = new SmMlElement(SmMlElementType::NMlEmpty);
+ declareMlError();
+ break;
+ }
+ SmMlElement* pParent = *m_pParent;
+ pParent->setSubElement(pParent->getSubElementsCount(), m_pElement);
+ inheritStyle();
+ handleAttributes(aAttributeList);
+}
+
+void SmMLImportContext::endFastElement(sal_Int32) { inheritStyleEnd(); }
+}
+
+// SmMLImport
+/*************************************************************************************************/
+
+const uno::Sequence<sal_Int8>& SmMLImport::getUnoTunnelId() noexcept
+{
+ static const comphelper::UnoIdInit theSmMLImportUnoTunnelId;
+ return theSmMLImportUnoTunnelId.getSeq();
+}
+
+sal_Int64 SAL_CALL SmMLImport::getSomething(const uno::Sequence<sal_Int8>& rId)
+{
+ return comphelper::getSomethingImpl(rId, this,
+ comphelper::FallbackToGetSomethingOf<SvXMLImport>{});
+}
+
+SvXMLImportContext*
+SmMLImport::CreateFastContext(sal_Int32 nElement,
+ const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
+{
+ SvXMLImportContext* pContext = nullptr;
+
+ switch (nElement)
+ {
+ case XML_ELEMENT(OFFICE, XML_DOCUMENT):
+ {
+ if (m_pElementTree == nullptr)
+ m_pElementTree = new SmMlElement(SmMlElementType::NMlEmpty);
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(),
+ uno::UNO_QUERY_THROW);
+ pContext = new SmMLImportContext(*this, &m_pElementTree);
+ break;
+ }
+ case XML_ELEMENT(OFFICE, XML_DOCUMENT_META):
+ {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(),
+ uno::UNO_QUERY_THROW);
+ pContext = new SvXMLMetaDocumentContext(*this, xDPS->getDocumentProperties());
+ break;
+ }
+ case XML_ELEMENT(OFFICE, XML_DOCUMENT_SETTINGS):
+ {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(),
+ uno::UNO_QUERY_THROW);
+ pContext = new XMLDocumentSettingsContext(*this);
+ break;
+ }
+ default:
+ declareMlError();
+ break;
+ }
+ return pContext;
+}
+
+void SmMLImport::endDocument()
+{
+ uno::Reference<frame::XModel> xModel = GetModel();
+ if (!xModel.is())
+ {
+ SAL_WARN("starmath", "Failed to set view settings because missing model");
+ SvXMLImport::endDocument();
+ return;
+ }
+
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel);
+ if (!pModel)
+ {
+ SAL_WARN("starmath", "Failed to set view settings because missing sm model");
+ SvXMLImport::endDocument();
+ return;
+ }
+
+ SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
+ if (!pDocShell)
+ {
+ SAL_WARN("starmath", "Failed to set view settings because missing sm doc shell");
+ SvXMLImport::endDocument();
+ return;
+ }
+
+ // Check if there is element tree
+ if (m_pElementTree == nullptr)
+ {
+ m_bSuccess = true;
+ SvXMLImport::endDocument();
+ return;
+ }
+
+ // Get element tree and setup
+
+ if (m_pElementTree->getSubElementsCount() == 0)
+ {
+ delete m_pElementTree;
+ m_pElementTree = nullptr;
+ }
+ else
+ {
+ SmMlElement* pTmpElememt = m_pElementTree->getSubElement(0);
+ delete m_pElementTree;
+ m_pElementTree = pTmpElememt;
+ }
+ pDocShell->SetMlElementTree(m_pElementTree);
+
+ m_bSuccess = true;
+ SvXMLImport::endDocument();
+}
+
+void SmMLImport::SetViewSettings(const Sequence<PropertyValue>& aViewProps)
+{
+ uno::Reference<frame::XModel> xModel = GetModel();
+ if (!xModel.is())
+ {
+ SAL_WARN("starmath", "Failed to set view settings because missing model");
+ return;
+ }
+
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel);
+ if (!pModel)
+ {
+ SAL_WARN("starmath", "Failed to set view settings because missing sm model");
+ return;
+ }
+
+ SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
+ if (!pDocShell)
+ {
+ SAL_WARN("starmath", "Failed to set view settings because missing sm doc shell");
+ return;
+ }
+
+ tools::Rectangle aRect(pDocShell->GetVisArea());
+
+ tools::Long nTmp = 0;
+
+ for (const PropertyValue& rValue : aViewProps)
+ {
+ if (rValue.Name == "ViewAreaTop")
+ {
+ rValue.Value >>= nTmp;
+ aRect.SaturatingSetPosY(nTmp);
+ }
+ else if (rValue.Name == "ViewAreaLeft")
+ {
+ rValue.Value >>= nTmp;
+ aRect.SaturatingSetPosX(nTmp);
+ }
+ else if (rValue.Name == "ViewAreaWidth")
+ {
+ rValue.Value >>= nTmp;
+ Size aSize(aRect.GetSize());
+ aSize.setWidth(nTmp);
+ aRect.SaturatingSetSize(aSize);
+ }
+ else if (rValue.Name == "ViewAreaHeight")
+ {
+ rValue.Value >>= nTmp;
+ Size aSize(aRect.GetSize());
+ aSize.setHeight(nTmp);
+ aRect.SaturatingSetSize(aSize);
+ }
+ }
+
+ pDocShell->SetVisArea(aRect);
+}
+
+void SmMLImport::SetConfigurationSettings(const Sequence<PropertyValue>& aConfProps)
+{
+ uno::Reference<frame::XModel> xModel = GetModel();
+ if (!xModel.is())
+ {
+ SAL_WARN("starmath", "Failed to set view settings because missing model");
+ return;
+ }
+
+ uno::Reference<XPropertySet> xProps(xModel, UNO_QUERY);
+ if (!xProps.is())
+ {
+ SAL_WARN("starmath", "Failed to set view settings because missing model properties");
+ return;
+ }
+
+ Reference<XPropertySetInfo> xInfo(xProps->getPropertySetInfo());
+ if (!xInfo.is())
+ {
+ SAL_WARN("starmath",
+ "Failed to set view settings because missing model properties information");
+ return;
+ }
+
+ static const OUStringLiteral sFormula(u"Formula");
+ static const OUStringLiteral sBasicLibraries(u"BasicLibraries");
+ static const OUStringLiteral sDialogLibraries(u"DialogLibraries");
+ for (const PropertyValue& rValue : aConfProps)
+ {
+ if (rValue.Name != sFormula && rValue.Name != sBasicLibraries
+ && rValue.Name != sDialogLibraries)
+ {
+ try
+ {
+ if (xInfo->hasPropertyByName(rValue.Name))
+ xProps->setPropertyValue(rValue.Name, rValue.Value);
+ }
+ catch (const beans::PropertyVetoException&)
+ {
+ // dealing with read-only properties here. Nothing to do...
+ }
+ catch (const Exception&)
+ {
+ SAL_WARN("starmath", "Unexpected issue while loading document properties");
+ }
+ }
+ }
+}
+
+SmMLImport::SmMLImport(const css::uno::Reference<css::uno::XComponentContext>& rContext,
+ OUString const& implementationName, SvXMLImportFlags nImportFlags)
+ : SvXMLImport(rContext, implementationName, nImportFlags)
+ , m_pElementTree(nullptr)
+ , m_bSuccess(false)
+ , m_nSmSyntaxVersion(SM_MOD()->GetConfig()->GetDefaultSmSyntaxVersion())
+{
+}
+
+/** Handles an error on the mathml structure
+ */
+void SmMLImport::declareMlError()
+{
+ m_bSuccess = false;
+ SAL_WARN("starmath", "MathML error");
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/starmath/source/mathml/iterator.cxx b/starmath/source/mathml/iterator.cxx
new file mode 100644
index 000000000..24de35c18
--- /dev/null
+++ b/starmath/source/mathml/iterator.cxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 <mathml/iterator.hxx>
+
+/** The purpose of this iterator is to be able to iterate threw an infinite element tree
+ * infinite -> as much as your memory can hold
+ * No call-backs that will end up in out of stack
+ */
+
+namespace mathml
+{
+static inline void deleteElement(SmMlElement* aSmMlElement, void*) { delete aSmMlElement; }
+
+static inline void cloneElement(SmMlElement* aSmMlElement, void* aData)
+{
+ // Prepare data
+ SmMlElement* aNewSmMlElement = new SmMlElement(*aSmMlElement);
+ SmMlElement* aCopyTree = *static_cast<SmMlElement**>(aData);
+
+ // Append data
+ aCopyTree->setSubElement(aCopyTree->getSubElementsCount(), aNewSmMlElement);
+
+ // Prepare for following
+ // If it has sub elements, then it will be the next
+ if (aSmMlElement->getSubElementsCount() != 0)
+ aCopyTree = aNewSmMlElement;
+ else // Otherwise remounts up to where it should be
+ {
+ while (aSmMlElement->getParentElement() != nullptr)
+ {
+ // get parent
+ SmMlElement* pParent = aSmMlElement->getParentElement();
+ aCopyTree = aCopyTree->getParentElement();
+ // was this the last branch ?
+ if (aSmMlElement->getSubElementId() + 1 != pParent->getSubElementsCount())
+ break; // no -> stop going up
+ // Prepare for next round
+ aSmMlElement = pParent;
+ }
+ }
+
+ // Closing extras
+ *static_cast<SmMlElement**>(aData) = aCopyTree;
+}
+
+void SmMlIteratorFree(SmMlElement* pMlElementTree)
+{
+ if (pMlElementTree == nullptr)
+ return;
+ for (size_t i = 0; i < pMlElementTree->getSubElementsCount(); ++i)
+ {
+ SmMlIteratorFree(pMlElementTree->getSubElement(i));
+ }
+ deleteElement(pMlElementTree, nullptr);
+}
+
+SmMlElement* SmMlIteratorCopy(SmMlElement* pMlElementTree)
+{
+ if (pMlElementTree == nullptr)
+ return nullptr;
+ SmMlElement* aDummyElement = new SmMlElement();
+ SmMlIteratorTopToBottom(pMlElementTree, cloneElement, &aDummyElement);
+ SmMlElement* aResultElement = aDummyElement->getSubElement(0);
+ delete aDummyElement;
+ return aResultElement;
+}
+
+} // end namespace mathml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/starmath/source/mathml/mathmlMo.cxx b/starmath/source/mathml/mathmlMo.cxx
new file mode 100644
index 000000000..fb76b070e
--- /dev/null
+++ b/starmath/source/mathml/mathmlMo.cxx
@@ -0,0 +1,1127 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <mathmlMo.hxx>
+
+static moOperatorData moOperatorDataDictionaryData[starmathdatabase::MATHML_MO_COUNT]
+ = { { u"\u2018", moOpDF::prefix, 10, 0, 0, moOpDP::fence | moOpDP::nonedp },
+ { u"\u2019", moOpDF::postfix, 10, 0, 0, moOpDP::fence | moOpDP::nonedp },
+ { u"\u201C", moOpDF::prefix, 10, 0, 0, moOpDP::fence | moOpDP::nonedp },
+ { u"\u201D", moOpDF::postfix, 10, 0, 0, moOpDP::fence | moOpDP::nonedp },
+ { u"(", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u")", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"[", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"]", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"{", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"|", moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"||", moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"|||", moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"}", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2016", moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence },
+ { u"\u2308", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2309", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u230A", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u230B", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2329", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u232A", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2772", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2773", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27E6", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27E7", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27E8", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27E9", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27EA", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27EB", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27EC", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27ED", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27EE", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27EF", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2980", moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence },
+ { u"\u2983", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2984", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2985", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2986", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2987", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2988", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2989", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u298A", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u298B", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u298C", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u298D", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u298E", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u298F", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2990", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2991", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2992", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2993", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2994", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2995", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2996", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2997", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2998", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u29FC", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u29FD", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u";", moOpDF::infix, 30, 0, 3, moOpDP::separator | moOpDP::linebreakstyleAfter },
+ { u",", moOpDF::infix, 40, 0, 3, moOpDP::separator | moOpDP::linebreakstyleAfter },
+ { u"\u2063", moOpDF::infix, 40, 0, 0, moOpDP::separator | moOpDP::linebreakstyleAfter },
+ { u"\u2234", moOpDF::infix, 70, 5, 5, moOpDP::nonedp },
+ { u"\u2235", moOpDF::infix, 70, 5, 5, moOpDP::nonedp },
+ { u"->", moOpDF::infix, 90, 5, 5, moOpDP::nonedp },
+ { u"..", moOpDF::postfix, 100, 0, 0, moOpDP::nonedp },
+ { u"...", moOpDF::postfix, 100, 0, 0, moOpDP::nonedp },
+ { u":", moOpDF::infix, 100, 1, 2, moOpDP::nonedp },
+ { u"\u03F6", moOpDF::infix, 110, 5, 5, moOpDP::nonedp },
+ { u"\u2026", moOpDF::infix, 150, 0, 0, moOpDP::nonedp },
+ { u"\u22EE", moOpDF::infix, 150, 5, 5, moOpDP::nonedp },
+ { u"\u22EF", moOpDF::infix, 150, 0, 0, moOpDP::nonedp },
+ { u"\u22F1", moOpDF::infix, 150, 5, 5, moOpDP::nonedp },
+ { u"\u220B", moOpDF::infix, 160, 5, 5, moOpDP::nonedp },
+ { u"\u22A2", moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22A3", moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22A4", moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22A8", moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22A9", moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22AC", moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22AD", moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22AE", moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22AF", moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u2228", moOpDF::infix, 190, 4, 4, moOpDP::nonedp },
+ { u"&&", moOpDF::infix, 200, 4, 4, moOpDP::nonedp },
+ { u"\u2227", moOpDF::infix, 200, 4, 4, moOpDP::nonedp },
+ { u"\u2200", moOpDF::prefix, 230, 2, 1, moOpDP::nonedp },
+ { u"\u2203", moOpDF::prefix, 230, 2, 1, moOpDP::nonedp },
+ { u"\u2204", moOpDF::prefix, 230, 2, 1, moOpDP::nonedp },
+ { u"\u2201", moOpDF::infix, 240, 1, 2, moOpDP::nonedp },
+ { u"\u2208", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2209", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u220C", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2282", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2282\u20D2", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2283", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2283\u20D2", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2284", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2285", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2286", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2287", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2288", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2289", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u228A", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u228B", moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"<=", moOpDF::infix, 241, 5, 5, moOpDP::nonedp },
+ { u"\u2264", moOpDF::infix, 241, 5, 5, moOpDP::nonedp },
+ { u"\u2265", moOpDF::infix, 242, 5, 5, moOpDP::nonedp },
+ { u">", moOpDF::infix, 243, 5, 5, moOpDP::nonedp },
+ { u">=", moOpDF::infix, 243, 5, 5, moOpDP::nonedp },
+ { u"\u226F", moOpDF::infix, 244, 5, 5, moOpDP::nonedp },
+ { u"&lt", moOpDF::infix, 245, 5, 5, moOpDP::nonedp },
+ { u"\u226E", moOpDF::infix, 246, 5, 5, moOpDP::nonedp },
+ { u"\u2248", moOpDF::infix, 247, 5, 5, moOpDP::nonedp },
+ { u"\u223C", moOpDF::infix, 250, 5, 5, moOpDP::nonedp },
+ { u"\u2249", moOpDF::infix, 250, 5, 5, moOpDP::nonedp },
+ { u"\u2262", moOpDF::infix, 252, 5, 5, moOpDP::nonedp },
+ { u"\u2260", moOpDF::infix, 255, 5, 5, moOpDP::nonedp },
+ { u"!=", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"*=", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"+=", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"-=", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"/=", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u":=", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"=", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"==", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u221D", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2224", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2225", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2226", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2241", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2243", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2244", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2245", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2246", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2247", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u224D", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2254", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2257", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2259", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u225A", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u225B", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u225C", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u225F", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2261", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2268", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2269", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u226A", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u226A\u0338", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u226B", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u226B\u0338", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u226D", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2270", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2271", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u227A", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u227B", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u227C", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u227D", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2280", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2281", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22A5", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22B4", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22B5", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22C9", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u22CA", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u22CB", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u22CC", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u22D4", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22D6", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22D7", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22D8", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22D9", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22EA", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22EB", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22EC", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22ED", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u25A0", moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25A1", moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25AA", moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25AB", moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25AD", moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25AE", moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25AF", moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25B0", moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25B1", moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25B3", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25B4", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25B5", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25B6", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25B7", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25B8", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25B9", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25BC", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25BD", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25BE", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25BF", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C0", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C1", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C2", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C3", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C4", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C5", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C6", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C7", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C8", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C9", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25CC", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25CD", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25CE", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25CF", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25D6", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25D7", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25E6", moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u29C0", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u29C1", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u29E3", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u29E4", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u29E5", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u29E6", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u29F3", moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u2A87", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2A88", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2AAF", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2AAF\u0338", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2AB0", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2AB0\u0338", moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2044", moOpDF::infix, 265, 4, 4, moOpDP::stretchy },
+ { u"\u2206", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u220A", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u220D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u220E", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2215", moOpDF::infix, 265, 4, 4, moOpDP::stretchy },
+ { u"\u2217", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2218", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2219", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u221F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2223", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2236", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2237", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2238", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2239", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u223A", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u223B", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u223D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u223D\u0331", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u223E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u223F", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2242", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2242\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224A", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224B", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224C", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224E\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224F\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2250", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2251", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2252", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2253", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2255", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2256", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2258", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u225D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u225E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2263", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2266", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2266\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2267", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u226C", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2272", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2273", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2274", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2275", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2276", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2277", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2278", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2279", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u227E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u227F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u227F\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u228C", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u228D", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u228E", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u228F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u228F\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2290", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2290\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2291", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2292", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2293", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2294", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u229A", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u229B", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u229C", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u229D", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22A6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22A7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22AA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22AB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22BA", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22BB", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22BC", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22BD", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22BE", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u22BF", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u22C4", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22C6", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22C7", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22C8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22CD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22CE", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22CF", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22D0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22D1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22D2", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22D3", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22D5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22DA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22DB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22DC", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22DD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22DE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22DF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22FA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22FB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22FC", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22FD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22FE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22FF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u25B2", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2758", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2981", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2982", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A0", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A1", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A2", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A3", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A4", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A5", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A6", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A7", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A8", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A9", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29AA", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29AB", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29AC", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29AD", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29AE", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29AF", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B0", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B1", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B2", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B3", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B4", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B5", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B6", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29B7", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29B8", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29B9", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29BA", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29BB", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29BC", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29BD", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29BE", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29BF", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29C2", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29C3", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29C4", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29C5", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29C6", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29C7", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29C8", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29C9", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29CA", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29CB", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29CC", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29CD", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29CE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29CF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29CF\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D0\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D6", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29D7", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29D8", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29D9", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29DB", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29DC", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29DD", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29DE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29E0", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29E1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29E2", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29E7", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29E8", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29E9", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29EA", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29EB", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29EC", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29ED", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29EE", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29F0", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29F1", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29F2", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29F5", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29F6", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29F7", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29F8", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29F9", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29FA", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29FB", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29FE", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29FF", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A1D", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2A1E", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2A1F", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2A20", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2A21", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2A22", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A23", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A24", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A25", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A26", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A27", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A28", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A29", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A2A", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A2B", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A2C", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A2D", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A2E", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A30", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A31", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A32", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A33", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A34", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A35", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A36", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A37", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A38", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A39", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A3A", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A3B", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A3C", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A3D", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A3E", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A40", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A41", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A42", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A43", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A44", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A45", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A46", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A47", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A48", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A49", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A4A", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A4B", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A4C", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A4D", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A4E", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A4F", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A50", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A51", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A52", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A53", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A54", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A55", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A56", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A57", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A58", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A59", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A5A", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A5B", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A5C", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A5D", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A5E", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A5F", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A60", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A61", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A62", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A63", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A64", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A65", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A66", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A67", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A68", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A69", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A6A", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A6B", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A6C", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A6D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A6E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A6F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A70", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A71", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A72", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A73", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A74", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A75", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A76", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A77", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A78", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A79", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7A", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7B", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7C", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7D\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7E\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A80", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A81", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A82", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A83", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A84", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A85", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A86", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A89", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A8A", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A8B", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A8C", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A8D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A8E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A8F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A90", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A91", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A92", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A93", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A94", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A95", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A96", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A97", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A98", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A99", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A9A", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A9B", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A9C", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A9D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A9E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A9F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA1\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA2\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AAA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AAB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AAC", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AAD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AAE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ABA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ABB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ABC", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ABD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ABE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ABF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ACA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ACB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ACC", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ACD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ACE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ACF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ADA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ADB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ADD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ADD\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ADE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ADF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AEA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AEB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AEC", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AED", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AEE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AEF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF4", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2AF5", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2AF6", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2AF7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AFA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AFB", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2AFD", moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2AFE", moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"|", moOpDF::infix, 270, 2, 2, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"||", moOpDF::infix, 270, 2, 2, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"|||", moOpDF::infix, 270, 2, 2, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2190", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2191", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2192", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2193", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2194", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2195", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2196", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2197", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2198", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2199", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u219A", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u219B", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u219C", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u219D", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u219E", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u219F", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21A0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21A1", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21A2", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21A3", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21A4", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21A5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21A6", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21A7", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21A8", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21A9", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21AA", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21AB", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21AC", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21AD", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21AE", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21AF", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B1", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B2", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B3", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B4", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B6", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21B7", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21B8", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21B9", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21BA", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21BB", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21BC", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21BD", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21BE", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21BF", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21C0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21C1", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21C2", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21C3", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21C4", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21C5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21C6", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21C7", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21C8", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21C9", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21CA", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21CB", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21CC", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21CD", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21CE", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21CF", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21D0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21D1", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21D2", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21D3", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21D4", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21D5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21D6", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21D7", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21D8", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21D9", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21DA", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21DB", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21DC", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21DD", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21DE", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21DF", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21E0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21E1", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21E2", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21E3", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21E4", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21E5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21E6", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21E7", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21E8", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21E9", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21EA", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21EB", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21EC", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21ED", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21EE", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21EF", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21F0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21F1", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21F2", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21F3", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21F4", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21F5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21F6", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21F7", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21F8", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21F9", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21FA", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21FB", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21FC", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21FD", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21FE", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21FF", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u22B8", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u27F0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u27F1", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u27F5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27F6", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27F7", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27F8", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27F9", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27FA", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27FB", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27FC", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27FD", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27FE", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27FF", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2900", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2901", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2902", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2903", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2904", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2905", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2906", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2907", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2908", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2909", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u290A", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u290B", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u290C", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u290D", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u290E", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u290F", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2910", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2911", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2912", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2913", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2914", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2915", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2916", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2917", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2918", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2919", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u291A", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u291B", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u291C", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u291D", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u291E", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u291F", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2920", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2921", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2922", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2923", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2924", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2925", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2926", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2927", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2928", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2929", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u292A", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u292B", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u292C", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u292D", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u292E", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u292F", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2930", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2931", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2932", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2933", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2934", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2935", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2936", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2937", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2938", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2939", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u293A", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u293B", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u293C", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u293D", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u293E", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u293F", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2940", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2941", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2942", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2943", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2944", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2945", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2946", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2947", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2948", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2949", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u294A", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u294B", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u294C", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u294D", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u294E", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u294F", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2950", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2951", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2952", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2953", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2954", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2955", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2956", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2957", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2958", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2959", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u295A", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u295B", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u295C", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u295D", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u295E", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u295F", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2960", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2961", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2962", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2963", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2964", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2965", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2966", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2967", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2968", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2969", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u296A", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u296B", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u296C", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u296D", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u296E", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u296F", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2970", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2971", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2972", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2973", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2974", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2975", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2976", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2977", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2978", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2979", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u297A", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u297B", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u297C", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u297D", moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u297E", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u297F", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2999", moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u299A", moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u299B", moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u299C", moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u299D", moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u299E", moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u299F", moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u29DF", moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u29EF", moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u29F4", moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2B45", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2B46", moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"+", moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"+", moOpDF::prefix, 275, 0, 1, moOpDP::nonedp },
+ { u"-", moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"-", moOpDF::prefix, 275, 0, 1, moOpDP::nonedp },
+ { u"\u00B1", moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"\u00B1", moOpDF::prefix, 275, 0, 1, moOpDP::nonedp },
+ { u"\u2212", moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"\u2212", moOpDF::prefix, 275, 0, 1, moOpDP::nonedp },
+ { u"\u2213", moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"\u2213", moOpDF::prefix, 275, 0, 1, moOpDP::nonedp },
+ { u"\u2214", moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"\u229E", moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"\u229F", moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"\u2211", moOpDF::prefix, 290, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A0A", moOpDF::prefix, 290, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A0B", moOpDF::prefix, 290, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u222C", moOpDF::prefix, 300, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u222D", moOpDF::prefix, 300, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2295", moOpDF::infix, 300, 4, 4, moOpDP::nonedp },
+ { u"\u2296", moOpDF::infix, 300, 4, 4, moOpDP::nonedp },
+ { u"\u2298", moOpDF::infix, 300, 4, 4, moOpDP::nonedp },
+ { u"\u2A01", moOpDF::prefix, 300, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u222B", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u222E", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u222F", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2230", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2231", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2232", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2233", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A0C", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A0D", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A0E", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A0F", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A10", moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A11", moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A12", moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A13", moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A14", moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A15", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A16", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A17", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A18", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A19", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A1A", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A1B", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A1C", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u22C3", moOpDF::prefix, 320, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A03", moOpDF::prefix, 320, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A04", moOpDF::prefix, 320, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u22C0", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u22C1", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u22C2", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A00", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A02", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A05", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A06", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A07", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A08", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A09", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2AFC", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2AFF", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2240", moOpDF::infix, 340, 4, 4, moOpDP::nonedp },
+ { u"\u220F", moOpDF::prefix, 350, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2210", moOpDF::prefix, 350, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2229", moOpDF::infix, 350, 4, 4, moOpDP::nonedp },
+ { u"\u222A", moOpDF::infix, 350, 4, 4, moOpDP::nonedp },
+ { u"*", moOpDF::infix, 390, 3, 3, moOpDP::nonedp },
+ { u".", moOpDF::infix, 390, 3, 3, moOpDP::nonedp },
+ { u"\u00D7", moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u2022", moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u2043", moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u2062", moOpDF::infix, 390, 0, 0, moOpDP::nonedp },
+ { u"\u22A0", moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u22A1", moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u22C5", moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u2A2F", moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u2A3F", moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u00B7", moOpDF::infix, 400, 4, 4, moOpDP::nonedp },
+ { u"\u2297", moOpDF::infix, 410, 4, 4, moOpDP::nonedp },
+ { u"%", moOpDF::infix, 640, 3, 3, moOpDP::nonedp },
+ { u"\\", moOpDF::infix, 650, 0, 0, moOpDP::nonedp },
+ { u"\u2216", moOpDF::infix, 650, 4, 4, moOpDP::nonedp },
+ { u"/", moOpDF::infix, 660, 1, 1, moOpDP::nonedp },
+ { u"\u00F7", moOpDF::infix, 660, 4, 4, moOpDP::nonedp },
+ { u"\u2220", moOpDF::prefix, 670, 0, 0, moOpDP::nonedp },
+ { u"\u2221", moOpDF::prefix, 670, 0, 0, moOpDP::nonedp },
+ { u"\u2222", moOpDF::prefix, 670, 0, 0, moOpDP::nonedp },
+ { u"\u00AC", moOpDF::prefix, 680, 2, 1, moOpDP::nonedp },
+ { u"\u2299", moOpDF::infix, 710, 4, 4, moOpDP::nonedp },
+ { u"\u2202", moOpDF::prefix, 740, 2, 1, moOpDP::nonedp },
+ { u"\u2207", moOpDF::prefix, 740, 2, 1, moOpDP::nonedp },
+ { u"**", moOpDF::infix, 780, 1, 1, moOpDP::nonedp },
+ { u"<>", moOpDF::infix, 780, 1, 1, moOpDP::nonedp },
+ { u"^", moOpDF::infix, 780, 1, 1, moOpDP::nonedp },
+ { u"\u2032", moOpDF::postfix, 800, 0, 0, moOpDP::nonedp },
+ { u"\u266D", moOpDF::postfix, 800, 0, 2, moOpDP::nonedp },
+ { u"\u266E", moOpDF::postfix, 800, 0, 2, moOpDP::nonedp },
+ { u"\u266F", moOpDF::postfix, 800, 0, 2, moOpDP::nonedp },
+ { u"!", moOpDF::postfix, 810, 1, 0, moOpDP::nonedp },
+ { u"!!", moOpDF::postfix, 810, 1, 0, moOpDP::nonedp },
+ { u"//", moOpDF::infix, 820, 1, 1, moOpDP::nonedp },
+ { u"@", moOpDF::infix, 825, 1, 1, moOpDP::nonedp },
+ { u"?", moOpDF::infix, 835, 1, 1, moOpDP::nonedp },
+ { u"\u2145", moOpDF::prefix, 845, 2, 1, moOpDP::nonedp },
+ { u"\u2146", moOpDF::prefix, 845, 2, 0, moOpDP::nonedp },
+ { u"\u221A", moOpDF::prefix, 845, 1, 1, moOpDP::stretchy },
+ { u"\u221B", moOpDF::prefix, 845, 1, 1, moOpDP::nonedp },
+ { u"\u221C", moOpDF::prefix, 845, 1, 1, moOpDP::nonedp },
+ { u"\u2061", moOpDF::infix, 850, 0, 0, moOpDP::nonedp },
+ { u"\"", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"&", moOpDF::postfix, 880, 0, 0, moOpDP::nonedp },
+ { u"\'", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"++", moOpDF::postfix, 880, 0, 0, moOpDP::nonedp },
+ { u"--", moOpDF::postfix, 880, 0, 0, moOpDP::nonedp },
+ { u"^", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"_", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"`", moOpDF::postfix, 880, 0, 00, moOpDP::accent },
+ { u"~", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u00A8", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00AA", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00AF", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u00B0", moOpDF::postfix, 880, 0, 0, moOpDP::nonedp },
+ { u"\u00B2", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00B3", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00B4", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00B8", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00B9", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00BA", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02C6", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u02C7", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u02C9", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u02CA", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02CB", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02CD", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u02D8", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02D9", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02DA", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02DC", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u02DD", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02F7", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u0302", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u0311", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u201A", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u201B", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u201E", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u201F", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u2033", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u2034", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u2035", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u2036", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u2037", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u203E", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2057", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u2064", moOpDF::infix, 880, 0, 0, moOpDP::nonedp },
+ { u"\u20DB", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u20DC", moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u23B4", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23B5", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23DC", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23DD", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23DE", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23DF", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23E0", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23E1", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"_", moOpDF::infix, 900, 1, 1, moOpDP::nonedp } };
+
+std::vector<moOperatorData> starmathdatabase::moOperatorDataDictionary(
+ moOperatorDataDictionaryData, moOperatorDataDictionaryData + starmathdatabase::MATHML_MO_COUNT);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/starmath/source/mathml/mathmlattr.cxx b/starmath/source/mathml/mathmlattr.cxx
new file mode 100644
index 000000000..5e54f0d92
--- /dev/null
+++ b/starmath/source/mathml/mathmlattr.cxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 <mathmlattr.hxx>
+
+#include <o3tl/safeint.hxx>
+#include <o3tl/string_view.hxx>
+#include <rtl/math.h>
+
+#include <cstddef>
+#include <string_view>
+#include <unordered_map>
+
+static std::size_t ParseMathMLUnsignedNumber(std::u16string_view rStr, Fraction& rUN)
+{
+ auto nLen = rStr.length();
+ std::size_t nDecimalPoint = std::u16string_view::npos;
+ std::size_t nIdx;
+ sal_Int64 nom = 0;
+ sal_Int64 den = 1;
+ bool validNomDen = true;
+ for (nIdx = 0; nIdx < nLen; nIdx++)
+ {
+ auto cD = rStr[nIdx];
+ if (cD == u'.')
+ {
+ if (nDecimalPoint != std::u16string_view::npos)
+ return std::u16string_view::npos;
+ nDecimalPoint = nIdx;
+ continue;
+ }
+ if (cD < u'0' || u'9' < cD)
+ break;
+ if (validNomDen
+ && (o3tl::checked_multiply(nom, sal_Int64(10), nom)
+ || o3tl::checked_add(nom, sal_Int64(cD - u'0'), nom)
+ || nom >= std::numeric_limits<sal_Int32>::max()
+ || (nDecimalPoint != std::u16string_view::npos
+ && o3tl::checked_multiply(den, sal_Int64(10), den))))
+ {
+ validNomDen = false;
+ }
+ }
+ if (nIdx == 0 || (nIdx == 1 && nDecimalPoint == 0))
+ return std::u16string_view::npos;
+
+ // If the input "xx.yyy" can be represented with nom = xx*10^n + yyy and den = 10^n in sal_Int64
+ // (where n is the length of "yyy"), then use that to create an accurate Fraction (and TODO: we
+ // could even ignore trailing "0" characters in "yyy", for a smaller n and thus a greater chance
+ // of validNomDen); if not, use the less accurate approach of creating a Fraction from double:
+ if (validNomDen)
+ {
+ rUN = Fraction(nom, den);
+ }
+ else
+ {
+ rUN = Fraction(
+ rtl_math_uStringToDouble(rStr.data(), rStr.data() + nIdx, '.', 0, nullptr, nullptr));
+ }
+
+ return nIdx;
+}
+
+static std::size_t ParseMathMLNumber(std::u16string_view rStr, Fraction& rN)
+{
+ if (rStr.empty())
+ return std::u16string_view::npos;
+ bool bNegative = (rStr[0] == '-');
+ std::size_t nOffset = bNegative ? 1 : 0;
+ auto nIdx = ParseMathMLUnsignedNumber(rStr.substr(nOffset), rN);
+ if (nIdx == std::u16string_view::npos || !rN.IsValid())
+ return std::u16string_view::npos;
+ if (bNegative)
+ rN *= -1;
+ return nOffset + nIdx;
+}
+
+bool ParseMathMLAttributeLengthValue(std::u16string_view rStr, MathMLAttributeLengthValue& rV)
+{
+ auto nIdx = ParseMathMLNumber(rStr, rV.aNumber);
+ if (nIdx == std::u16string_view::npos)
+ return false;
+ std::u16string_view sRest = rStr.substr(nIdx);
+ if (sRest.empty())
+ {
+ rV.eUnit = MathMLLengthUnit::None;
+ }
+ if (o3tl::starts_with(sRest, u"em"))
+ {
+ rV.eUnit = MathMLLengthUnit::Em;
+ }
+ if (o3tl::starts_with(sRest, u"ex"))
+ {
+ rV.eUnit = MathMLLengthUnit::Ex;
+ }
+ if (o3tl::starts_with(sRest, u"px"))
+ {
+ rV.eUnit = MathMLLengthUnit::Px;
+ }
+ if (o3tl::starts_with(sRest, u"in"))
+ {
+ rV.eUnit = MathMLLengthUnit::In;
+ }
+ if (o3tl::starts_with(sRest, u"cm"))
+ {
+ rV.eUnit = MathMLLengthUnit::Cm;
+ }
+ if (o3tl::starts_with(sRest, u"mm"))
+ {
+ rV.eUnit = MathMLLengthUnit::Mm;
+ }
+ if (o3tl::starts_with(sRest, u"pt"))
+ {
+ rV.eUnit = MathMLLengthUnit::Pt;
+ }
+ if (o3tl::starts_with(sRest, u"pc"))
+ {
+ rV.eUnit = MathMLLengthUnit::Pc;
+ }
+ if (sRest[0] == u'%')
+ {
+ rV.eUnit = MathMLLengthUnit::Percent;
+ }
+ return true;
+}
+
+bool GetMathMLMathvariantValue(const OUString& rStr, MathMLMathvariantValue& rV)
+{
+ static const std::unordered_map<OUString, MathMLMathvariantValue> aMap{
+ { "normal", MathMLMathvariantValue::Normal },
+ { "bold", MathMLMathvariantValue::Bold },
+ { "italic", MathMLMathvariantValue::Italic },
+ { "bold-italic", MathMLMathvariantValue::BoldItalic },
+ { "double-struck", MathMLMathvariantValue::DoubleStruck },
+ { "bold-fraktur", MathMLMathvariantValue::BoldFraktur },
+ { "script", MathMLMathvariantValue::Script },
+ { "bold-script", MathMLMathvariantValue::BoldScript },
+ { "fraktur", MathMLMathvariantValue::Fraktur },
+ { "sans-serif", MathMLMathvariantValue::SansSerif },
+ { "bold-sans-serif", MathMLMathvariantValue::BoldSansSerif },
+ { "sans-serif-italic", MathMLMathvariantValue::SansSerifItalic },
+ { "sans-serif-bold-italic", MathMLMathvariantValue::SansSerifBoldItalic },
+ { "monospace", MathMLMathvariantValue::Monospace },
+ { "initial", MathMLMathvariantValue::Initial },
+ { "tailed", MathMLMathvariantValue::Tailed },
+ { "looped", MathMLMathvariantValue::Looped },
+ { "stretched", MathMLMathvariantValue::Stretched }
+ };
+
+ auto it = aMap.find(rStr);
+ if (it != aMap.end())
+ {
+ rV = it->second;
+ return true;
+ }
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/starmath/source/mathml/mathmlexport.cxx b/starmath/source/mathml/mathmlexport.cxx
new file mode 100644
index 000000000..187dd1953
--- /dev/null
+++ b/starmath/source/mathml/mathmlexport.cxx
@@ -0,0 +1,1457 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+/*
+ Warning: The SvXMLElementExport helper class creates the beginning and
+ closing tags of xml elements in its constructor and destructor, so there's
+ hidden stuff going on, on occasion the ordering of these classes declarations
+ may be significant
+*/
+
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/util/MeasureUnit.hpp>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+#include <com/sun/star/uno/Any.h>
+
+#include <officecfg/Office/Common.hxx>
+#include <rtl/math.hxx>
+#include <sfx2/frame.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <osl/diagnose.h>
+#include <sot/storage.hxx>
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <comphelper/fileformat.h>
+#include <comphelper/processfactory.hxx>
+#include <unotools/streamwrap.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/attrlist.hxx>
+#include <comphelper/genericpropertyset.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <tools/diagnose_ex.h>
+#include <sal/log.hxx>
+
+#include <stack>
+
+#include <mathmlexport.hxx>
+#include <xparsmlbase.hxx>
+#include <strings.hrc>
+#include <smmod.hxx>
+#include <unomodel.hxx>
+#include <document.hxx>
+#include <utility.hxx>
+#include <cfgitem.hxx>
+#include <starmathdatabase.hxx>
+
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+namespace
+{
+bool IsInPrivateUseArea(sal_Unicode cChar) { return 0xE000 <= cChar && cChar <= 0xF8FF; }
+
+sal_Unicode ConvertMathToMathML(sal_Unicode cChar)
+{
+ sal_Unicode cRes = cChar;
+ if (IsInPrivateUseArea(cChar))
+ {
+ SAL_WARN("starmath", "Error: private use area characters should no longer be in use!");
+ cRes = u'@'; // just some character that should easily be notice as odd in the context
+ }
+ return cRes;
+}
+}
+
+bool SmXMLExportWrapper::Export(SfxMedium& rMedium)
+{
+ bool bRet = true;
+ uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
+
+ //Get model
+ uno::Reference<lang::XComponent> xModelComp = xModel;
+
+ bool bEmbedded = false;
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel);
+
+ SmDocShell* pDocShell = pModel ? static_cast<SmDocShell*>(pModel->GetObjectShell()) : nullptr;
+ if (pDocShell && SfxObjectCreateMode::EMBEDDED == pDocShell->GetCreateMode())
+ bEmbedded = true;
+
+ uno::Reference<task::XStatusIndicator> xStatusIndicator;
+ if (!bEmbedded)
+ {
+ if (pDocShell /*&& pDocShell->GetMedium()*/)
+ {
+ OSL_ENSURE(pDocShell->GetMedium() == &rMedium, "different SfxMedium found");
+
+ SfxItemSet* pSet = rMedium.GetItemSet();
+ if (pSet)
+ {
+ const SfxUnoAnyItem* pItem = pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL);
+ if (pItem)
+ pItem->GetValue() >>= xStatusIndicator;
+ }
+ }
+
+ // set progress range and start status indicator
+ if (xStatusIndicator.is())
+ {
+ sal_Int32 nProgressRange = bFlat ? 1 : 3;
+ xStatusIndicator->start(SmResId(STR_STATSTR_WRITING), nProgressRange);
+ }
+ }
+
+ static constexpr OUStringLiteral sUsePrettyPrinting(u"UsePrettyPrinting");
+ static constexpr OUStringLiteral sBaseURI(u"BaseURI");
+ static constexpr OUStringLiteral sStreamRelPath(u"StreamRelPath");
+ static constexpr OUStringLiteral sStreamName(u"StreamName");
+
+ // create XPropertySet with three properties for status indicator
+ static const comphelper::PropertyMapEntry aInfoMap[] = {
+ { sUsePrettyPrinting, 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::MAYBEVOID,
+ 0 },
+ { sBaseURI, 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 },
+ { sStreamRelPath, 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID,
+ 0 },
+ { sStreamName, 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 }
+ };
+ uno::Reference<beans::XPropertySet> xInfoSet(
+ comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));
+
+ bool bUsePrettyPrinting
+ = bFlat || officecfg::Office::Common::Save::Document::PrettyPrinting::get();
+ xInfoSet->setPropertyValue(sUsePrettyPrinting, Any(bUsePrettyPrinting));
+
+ // Set base URI
+ xInfoSet->setPropertyValue(sBaseURI, Any(rMedium.GetBaseURL(true)));
+
+ sal_Int32 nSteps = 0;
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+ if (!bFlat) //Storage (Package) of Stream
+ {
+ uno::Reference<embed::XStorage> xStg = rMedium.GetOutputStorage();
+ bool bOASIS = (SotStorage::GetVersion(xStg) > SOFFICE_FILEFORMAT_60);
+
+ // TODO/LATER: handle the case of embedded links gracefully
+ if (bEmbedded) //&& !pStg->IsRoot() )
+ {
+ OUString aName;
+ if (rMedium.GetItemSet())
+ {
+ const SfxStringItem* pDocHierarchItem
+ = rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME);
+ if (pDocHierarchItem)
+ aName = pDocHierarchItem->GetValue();
+ }
+
+ if (!aName.isEmpty())
+ {
+ xInfoSet->setPropertyValue(sStreamRelPath, Any(aName));
+ }
+ }
+
+ if (!bEmbedded)
+ {
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+
+ bRet = WriteThroughComponent(xStg, xModelComp, "meta.xml", xContext, xInfoSet,
+ (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaExporter"
+ : "com.sun.star.comp.Math.XMLMetaExporter"));
+ }
+ if (bRet)
+ {
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+
+ bRet = WriteThroughComponent(xStg, xModelComp, "content.xml", xContext, xInfoSet,
+ "com.sun.star.comp.Math.XMLContentExporter");
+ }
+
+ if (bRet)
+ {
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+
+ bRet = WriteThroughComponent(xStg, xModelComp, "settings.xml", xContext, xInfoSet,
+ (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsExporter"
+ : "com.sun.star.comp.Math.XMLSettingsExporter"));
+ }
+ }
+ else
+ {
+ SvStream* pStream = rMedium.GetOutStream();
+ uno::Reference<io::XOutputStream> xOut(new utl::OOutputStreamWrapper(*pStream));
+
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+
+ bRet = WriteThroughComponent(xOut, xModelComp, xContext, xInfoSet,
+ "com.sun.star.comp.Math.XMLContentExporter");
+ }
+
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+
+ return bRet;
+}
+
+/// export through an XML exporter component (output stream version)
+bool SmXMLExportWrapper::WriteThroughComponent(const Reference<io::XOutputStream>& xOutputStream,
+ const Reference<XComponent>& xComponent,
+ Reference<uno::XComponentContext> const& rxContext,
+ Reference<beans::XPropertySet> const& rPropSet,
+ const char* pComponentName)
+{
+ OSL_ENSURE(xOutputStream.is(), "I really need an output stream!");
+ OSL_ENSURE(xComponent.is(), "Need component!");
+ OSL_ENSURE(nullptr != pComponentName, "Need component name!");
+
+ // get component
+ Reference<xml::sax::XWriter> xSaxWriter = xml::sax::Writer::create(rxContext);
+
+ // connect XML writer to output stream
+ xSaxWriter->setOutputStream(xOutputStream);
+ if (m_bUseHTMLMLEntities)
+ xSaxWriter->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntitiesExport);
+
+ // prepare arguments (prepend doc handler to given arguments)
+ Sequence<Any> aArgs{ Any(xSaxWriter), Any(rPropSet) };
+
+ // get filter component
+ Reference<document::XExporter> xExporter(
+ rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ OUString::createFromAscii(pComponentName), aArgs, rxContext),
+ UNO_QUERY);
+ OSL_ENSURE(xExporter.is(), "can't instantiate export filter component");
+ if (!xExporter.is())
+ return false;
+
+ // connect model and filter
+ xExporter->setSourceDocument(xComponent);
+
+ // filter!
+ Reference<XFilter> xFilter(xExporter, UNO_QUERY);
+ uno::Sequence<PropertyValue> aProps(0);
+ xFilter->filter(aProps);
+
+ auto pFilter = comphelper::getFromUnoTunnel<SmXMLExport>(xFilter);
+ return pFilter == nullptr || pFilter->GetSuccess();
+}
+
+/// export through an XML exporter component (storage version)
+bool SmXMLExportWrapper::WriteThroughComponent(const Reference<embed::XStorage>& xStorage,
+ const Reference<XComponent>& xComponent,
+ const char* pStreamName,
+ Reference<uno::XComponentContext> const& rxContext,
+ Reference<beans::XPropertySet> const& rPropSet,
+ const char* pComponentName)
+{
+ OSL_ENSURE(xStorage.is(), "Need storage!");
+ OSL_ENSURE(nullptr != pStreamName, "Need stream name!");
+
+ // open stream
+ Reference<io::XStream> xStream;
+ OUString sStreamName = OUString::createFromAscii(pStreamName);
+ try
+ {
+ xStream = xStorage->openStreamElement(sStreamName, embed::ElementModes::READWRITE
+ | embed::ElementModes::TRUNCATE);
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("starmath", "Can't create output stream in package");
+ return false;
+ }
+
+ uno::Reference<beans::XPropertySet> xSet(xStream, uno::UNO_QUERY);
+ static const OUStringLiteral sMediaType = u"MediaType";
+ static const OUStringLiteral sTextXml = u"text/xml";
+ xSet->setPropertyValue(sMediaType, Any(OUString(sTextXml)));
+
+ // all streams must be encrypted in encrypted document
+ static const OUStringLiteral sUseCommonStoragePasswordEncryption
+ = u"UseCommonStoragePasswordEncryption";
+ xSet->setPropertyValue(sUseCommonStoragePasswordEncryption, Any(true));
+
+ // set Base URL
+ if (rPropSet.is())
+ {
+ rPropSet->setPropertyValue("StreamName", Any(sStreamName));
+ }
+
+ // write the stuff
+ bool bRet = WriteThroughComponent(xStream->getOutputStream(), xComponent, rxContext, rPropSet,
+ pComponentName);
+
+ return bRet;
+}
+
+SmXMLExport::SmXMLExport(const css::uno::Reference<css::uno::XComponentContext>& rContext,
+ OUString const& implementationName, SvXMLExportFlags nExportFlags)
+ : SvXMLExport(rContext, implementationName, util::MeasureUnit::INCH, XML_MATH, nExportFlags)
+ , pTree(nullptr)
+ , bSuccess(false)
+{
+}
+
+sal_Int64 SAL_CALL SmXMLExport::getSomething(const uno::Sequence<sal_Int8>& rId)
+{
+ return comphelper::getSomethingImpl(rId, this,
+ comphelper::FallbackToGetSomethingOf<SvXMLExport>{});
+}
+
+const uno::Sequence<sal_Int8>& SmXMLExport::getUnoTunnelId() noexcept
+{
+ static const comphelper::UnoIdInit theSmXMLExportUnoTunnelId;
+ return theSmXMLExportUnoTunnelId.getSeq();
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+Math_XMLExporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new SmXMLExport(context, "com.sun.star.comp.Math.XMLExporter",
+ SvXMLExportFlags::OASIS | SvXMLExportFlags::ALL));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+Math_XMLMetaExporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(
+ new SmXMLExport(context, "com.sun.star.comp.Math.XMLMetaExporter", SvXMLExportFlags::META));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+Math_XMLOasisMetaExporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new SmXMLExport(context, "com.sun.star.comp.Math.XMLOasisMetaExporter",
+ SvXMLExportFlags::OASIS | SvXMLExportFlags::META));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+Math_XMLSettingsExporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new SmXMLExport(context, "com.sun.star.comp.Math.XMLSettingsExporter",
+ SvXMLExportFlags::SETTINGS));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+Math_XMLOasisSettingsExporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new SmXMLExport(context, "com.sun.star.comp.Math.XMLOasisSettingsExporter",
+ SvXMLExportFlags::OASIS | SvXMLExportFlags::SETTINGS));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+Math_XMLContentExporter_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new SmXMLExport(context, "com.sun.star.comp.Math.XMLContentExporter",
+ SvXMLExportFlags::OASIS | SvXMLExportFlags::CONTENT));
+}
+
+ErrCode SmXMLExport::exportDoc(enum XMLTokenEnum eClass)
+{
+ if (!(getExportFlags() & SvXMLExportFlags::CONTENT))
+ {
+ SvXMLExport::exportDoc(eClass);
+ }
+ else
+ {
+ uno::Reference<frame::XModel> xModel = GetModel();
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel);
+
+ if (pModel)
+ {
+ SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
+ pTree = pDocShell->GetFormulaTree();
+ aText = pDocShell->GetText();
+ }
+
+ GetDocHandler()->startDocument();
+
+ addChaffWhenEncryptedStorage();
+
+ /*Add xmlns line*/
+ SvXMLAttributeList& rList = GetAttrList();
+
+ // make use of a default namespace
+ ResetNamespaceMap(); // Math doesn't need namespaces from xmloff, since it now uses default namespaces (because that is common with current MathML usage in the web)
+ GetNamespaceMap_().Add(OUString(), GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH);
+
+ rList.AddAttribute(GetNamespaceMap().GetAttrNameByKey(XML_NAMESPACE_MATH),
+ GetNamespaceMap().GetNameByKey(XML_NAMESPACE_MATH));
+
+ //I think we need something like ImplExportEntities();
+ ExportContent_();
+ GetDocHandler()->endDocument();
+ }
+
+ bSuccess = true;
+ return ERRCODE_NONE;
+}
+
+void SmXMLExport::ExportContent_()
+{
+ uno::Reference<frame::XModel> xModel = GetModel();
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel);
+ SmDocShell* pDocShell = pModel ? static_cast<SmDocShell*>(pModel->GetObjectShell()) : nullptr;
+ OSL_ENSURE(pDocShell, "doc shell missing");
+
+ if (pDocShell && !pDocShell->GetFormat().IsTextmode())
+ {
+ // If the Math equation is not in text mode, we attach a display="block"
+ // attribute on the <math> root. We don't do anything if it is in
+ // text mode, the default display="inline" value will be used.
+ AddAttribute(XML_NAMESPACE_MATH, XML_DISPLAY, XML_BLOCK);
+ }
+ SvXMLElementExport aEquation(*this, XML_NAMESPACE_MATH, XML_MATH, true, true);
+ std::unique_ptr<SvXMLElementExport> pSemantics;
+
+ if (!aText.isEmpty())
+ {
+ pSemantics.reset(
+ new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_SEMANTICS, true, true));
+ }
+
+ ExportNodes(pTree, 0);
+
+ if (aText.isEmpty())
+ return;
+
+ SmModule* pMod = SM_MOD();
+ sal_uInt16 nSmSyntaxVersion = pMod->GetConfig()->GetDefaultSmSyntaxVersion();
+
+ // Convert symbol names
+ if (pDocShell)
+ {
+ nSmSyntaxVersion = pDocShell->GetSmSyntaxVersion();
+ AbstractSmParser* rParser = pDocShell->GetParser();
+ bool bVal = rParser->IsExportSymbolNames();
+ rParser->SetExportSymbolNames(true);
+ auto pTmpTree = rParser->Parse(aText);
+ aText = rParser->GetText();
+ pTmpTree.reset();
+ rParser->SetExportSymbolNames(bVal);
+ }
+
+ OUStringBuffer sStrBuf(12);
+ sStrBuf.append(u"StarMath ");
+ if (nSmSyntaxVersion == 5)
+ sStrBuf.append(u"5.0");
+ else
+ sStrBuf.append(static_cast<sal_Int32>(nSmSyntaxVersion));
+
+ AddAttribute(XML_NAMESPACE_MATH, XML_ENCODING, sStrBuf.makeStringAndClear());
+ SvXMLElementExport aAnnotation(*this, XML_NAMESPACE_MATH, XML_ANNOTATION, true, false);
+ GetDocHandler()->characters(aText);
+}
+
+void SmXMLExport::GetViewSettings(Sequence<PropertyValue>& aProps)
+{
+ uno::Reference<frame::XModel> xModel = GetModel();
+ if (!xModel.is())
+ return;
+
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel);
+
+ if (!pModel)
+ return;
+
+ SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
+ if (!pDocShell)
+ return;
+
+ aProps.realloc(4);
+ PropertyValue* pValue = aProps.getArray();
+ sal_Int32 nIndex = 0;
+
+ tools::Rectangle aRect(pDocShell->GetVisArea());
+
+ pValue[nIndex].Name = "ViewAreaTop";
+ pValue[nIndex++].Value <<= aRect.Top();
+
+ pValue[nIndex].Name = "ViewAreaLeft";
+ pValue[nIndex++].Value <<= aRect.Left();
+
+ pValue[nIndex].Name = "ViewAreaWidth";
+ pValue[nIndex++].Value <<= aRect.GetWidth();
+
+ pValue[nIndex].Name = "ViewAreaHeight";
+ pValue[nIndex++].Value <<= aRect.GetHeight();
+}
+
+void SmXMLExport::GetConfigurationSettings(Sequence<PropertyValue>& rProps)
+{
+ Reference<XPropertySet> xProps(GetModel(), UNO_QUERY);
+ if (!xProps.is())
+ return;
+
+ Reference<XPropertySetInfo> xPropertySetInfo = xProps->getPropertySetInfo();
+ if (!xPropertySetInfo.is())
+ return;
+
+ const Sequence<Property> aProps = xPropertySetInfo->getProperties();
+ const sal_Int32 nCount = aProps.getLength();
+ if (!nCount)
+ return;
+
+ rProps.realloc(nCount);
+ SmMathConfig* pConfig = SM_MOD()->GetConfig();
+ const bool bUsedSymbolsOnly = pConfig && pConfig->IsSaveOnlyUsedSymbols();
+
+ std::transform(aProps.begin(), aProps.end(), rProps.getArray(),
+ [bUsedSymbolsOnly, &xProps](const Property& prop) {
+ PropertyValue aRet;
+ if (prop.Name != "Formula" && prop.Name != "BasicLibraries"
+ && prop.Name != "DialogLibraries" && prop.Name != "RuntimeUID")
+ {
+ aRet.Name = prop.Name;
+ OUString aActualName(prop.Name);
+ // handle 'save used symbols only'
+ static constexpr OUStringLiteral sUserDefinedSymbolsInUse
+ = u"UserDefinedSymbolsInUse";
+ if (bUsedSymbolsOnly && prop.Name == "Symbols")
+ aActualName = sUserDefinedSymbolsInUse;
+ aRet.Value = xProps->getPropertyValue(aActualName);
+ }
+ return aRet;
+ });
+}
+
+void SmXMLExport::ExportLine(const SmNode* pNode, int nLevel) { ExportExpression(pNode, nLevel); }
+
+void SmXMLExport::ExportBinaryHorizontal(const SmNode* pNode, int nLevel)
+{
+ TG nGroup = pNode->GetToken().nGroup;
+
+ SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MROW, true, true);
+
+ // Unfold the binary tree structure as long as the nodes are SmBinHorNode
+ // with the same nGroup. This will reduce the number of nested <mrow>
+ // elements e.g. we only need three <mrow> levels to export
+
+ // "a*b*c*d+e*f*g*h+i*j*k*l = a*b*c*d+e*f*g*h+i*j*k*l =
+ // a*b*c*d+e*f*g*h+i*j*k*l = a*b*c*d+e*f*g*h+i*j*k*l"
+
+ // See https://www.libreoffice.org/bugzilla/show_bug.cgi?id=66081
+ ::std::stack<const SmNode*> s;
+ s.push(pNode);
+ while (!s.empty())
+ {
+ const SmNode* node = s.top();
+ s.pop();
+ if (node->GetType() != SmNodeType::BinHor || node->GetToken().nGroup != nGroup)
+ {
+ ExportNodes(node, nLevel + 1);
+ continue;
+ }
+ const SmBinHorNode* binNode = static_cast<const SmBinHorNode*>(node);
+ s.push(binNode->RightOperand());
+ s.push(binNode->Symbol());
+ s.push(binNode->LeftOperand());
+ }
+}
+
+void SmXMLExport::ExportUnaryHorizontal(const SmNode* pNode, int nLevel)
+{
+ ExportExpression(pNode, nLevel);
+}
+
+void SmXMLExport::ExportExpression(const SmNode* pNode, int nLevel,
+ bool bNoMrowContainer /*=false*/)
+{
+ std::unique_ptr<SvXMLElementExport> pRow;
+ size_t nSize = pNode->GetNumSubNodes();
+
+ // #i115443: nodes of type expression always need to be grouped with mrow statement
+ if (!bNoMrowContainer && (nSize > 1 || pNode->GetType() == SmNodeType::Expression))
+ pRow.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW, true, true));
+
+ for (size_t i = 0; i < nSize; ++i)
+ {
+ if (const SmNode* pTemp = pNode->GetSubNode(i))
+ ExportNodes(pTemp, nLevel + 1);
+ }
+}
+
+void SmXMLExport::ExportBinaryVertical(const SmNode* pNode, int nLevel)
+{
+ assert(pNode->GetNumSubNodes() == 3);
+ const SmNode* pNum = pNode->GetSubNode(0);
+ const SmNode* pDenom = pNode->GetSubNode(2);
+ if (pNum->GetType() == SmNodeType::Align && pNum->GetToken().eType != TALIGNC)
+ {
+ // A left or right alignment is specified on the numerator:
+ // attach the corresponding numalign attribute.
+ AddAttribute(XML_NAMESPACE_MATH, XML_NUMALIGN,
+ pNum->GetToken().eType == TALIGNL ? XML_LEFT : XML_RIGHT);
+ }
+ if (pDenom->GetType() == SmNodeType::Align && pDenom->GetToken().eType != TALIGNC)
+ {
+ // A left or right alignment is specified on the denominator:
+ // attach the corresponding denomalign attribute.
+ AddAttribute(XML_NAMESPACE_MATH, XML_DENOMALIGN,
+ pDenom->GetToken().eType == TALIGNL ? XML_LEFT : XML_RIGHT);
+ }
+ SvXMLElementExport aFraction(*this, XML_NAMESPACE_MATH, XML_MFRAC, true, true);
+ ExportNodes(pNum, nLevel);
+ ExportNodes(pDenom, nLevel);
+}
+
+void SmXMLExport::ExportBinaryDiagonal(const SmNode* pNode, int nLevel)
+{
+ assert(pNode->GetNumSubNodes() == 3);
+
+ if (pNode->GetToken().eType == TWIDESLASH)
+ {
+ // wideslash
+ // export the node as <mfrac bevelled="true">
+ AddAttribute(XML_NAMESPACE_MATH, XML_BEVELLED, XML_TRUE);
+ SvXMLElementExport aFraction(*this, XML_NAMESPACE_MATH, XML_MFRAC, true, true);
+ ExportNodes(pNode->GetSubNode(0), nLevel);
+ ExportNodes(pNode->GetSubNode(1), nLevel);
+ }
+ else
+ {
+ // widebslash
+ // We can not use <mfrac> to a backslash, so just use <mo>\</mo>
+ SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MROW, true, true);
+
+ ExportNodes(pNode->GetSubNode(0), nLevel);
+
+ { // Scoping for <mo> creation
+ SvXMLElementExport aMo(*this, XML_NAMESPACE_MATH, XML_MO, true, true);
+ GetDocHandler()->characters(OUStringChar(MS_BACKSLASH));
+ }
+
+ ExportNodes(pNode->GetSubNode(1), nLevel);
+ }
+}
+
+void SmXMLExport::ExportTable(const SmNode* pNode, int nLevel)
+{
+ std::unique_ptr<SvXMLElementExport> pTable;
+
+ size_t nSize = pNode->GetNumSubNodes();
+
+ //If the list ends in newline then the last entry has
+ //no subnodes, the newline is superfluous so we just drop
+ //the last node, inclusion would create a bad MathML
+ //table
+ if (nSize >= 1)
+ {
+ const SmNode* pLine = pNode->GetSubNode(nSize - 1);
+ if (pLine->GetType() == SmNodeType::Line && pLine->GetNumSubNodes() == 1
+ && pLine->GetSubNode(0) != nullptr
+ && pLine->GetSubNode(0)->GetToken().eType == TNEWLINE)
+ --nSize;
+ }
+
+ // try to avoid creating a mtable element when the formula consists only
+ // of a single output line
+ if (nLevel || (nSize > 1))
+ pTable.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTABLE, true, true));
+
+ for (size_t i = 0; i < nSize; ++i)
+ {
+ if (const SmNode* pTemp = pNode->GetSubNode(i))
+ {
+ std::unique_ptr<SvXMLElementExport> pRow;
+ std::unique_ptr<SvXMLElementExport> pCell;
+ if (pTable)
+ {
+ pRow.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTR, true, true));
+ SmTokenType eAlign = TALIGNC;
+ if (pTemp->GetType() == SmNodeType::Align)
+ {
+ // For Binom() and Stack() constructions, the SmNodeType::Align nodes
+ // are direct children.
+ // binom{alignl ...}{alignr ...} and
+ // stack{alignl ... ## alignr ... ## ...}
+ eAlign = pTemp->GetToken().eType;
+ }
+ else if (pTemp->GetType() == SmNodeType::Line && pTemp->GetNumSubNodes() == 1
+ && pTemp->GetSubNode(0)
+ && pTemp->GetSubNode(0)->GetType() == SmNodeType::Align)
+ {
+ // For the Table() construction, the SmNodeType::Align node is a child
+ // of an SmNodeType::Line node.
+ // alignl ... newline alignr ... newline ...
+ eAlign = pTemp->GetSubNode(0)->GetToken().eType;
+ }
+ if (eAlign != TALIGNC)
+ {
+ // If a left or right alignment is specified on this line,
+ // attach the corresponding columnalign attribute.
+ AddAttribute(XML_NAMESPACE_MATH, XML_COLUMNALIGN,
+ eAlign == TALIGNL ? XML_LEFT : XML_RIGHT);
+ }
+ pCell.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTD, true, true));
+ }
+ ExportNodes(pTemp, nLevel + 1);
+ }
+ }
+}
+
+void SmXMLExport::ExportMath(const SmNode* pNode)
+{
+ const SmTextNode* pTemp = static_cast<const SmTextNode*>(pNode);
+ std::unique_ptr<SvXMLElementExport> pMath;
+
+ if (pNode->GetType() == SmNodeType::Math || pNode->GetType() == SmNodeType::GlyphSpecial)
+ {
+ // Export SmNodeType::Math and SmNodeType::GlyphSpecial symbols as <mo> elements
+ pMath.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MO, true, false));
+ }
+ else if (pNode->GetType() == SmNodeType::Special)
+ {
+ bool bIsItalic = IsItalic(pNode->GetFont());
+ if (!bIsItalic)
+ AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_NORMAL);
+ pMath.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI, true, false));
+ }
+ else
+ {
+ // Export SmNodeType::MathIdent and SmNodeType::Place symbols as <mi> elements:
+ // - These math symbols should not be drawn slanted. Hence we should
+ // attach a mathvariant="normal" attribute to single-char <mi> elements
+ // that are not mathematical alphanumeric symbol. For simplicity and to
+ // work around browser limitations, we always attach such an attribute.
+ // - The MathML specification suggests to use empty <mi> elements as
+ // placeholders but they won't be visible in most MathML rendering
+ // engines so let's use an empty square for SmNodeType::Place instead.
+ AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_NORMAL);
+ pMath.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI, true, false));
+ }
+ sal_Unicode nArse = pTemp->GetText()[0];
+ sal_Unicode cTmp = ConvertMathToMathML(nArse);
+ if (cTmp != 0)
+ nArse = cTmp;
+ OSL_ENSURE(nArse != 0xffff, "Non existent symbol");
+ GetDocHandler()->characters(OUString(nArse));
+}
+
+void SmXMLExport::ExportText(const SmNode* pNode)
+{
+ std::unique_ptr<SvXMLElementExport> pText;
+ const SmTextNode* pTemp = static_cast<const SmTextNode*>(pNode);
+ switch (pNode->GetToken().eType)
+ {
+ default:
+ case TIDENT:
+ {
+ //Note that we change the fontstyle to italic for strings that
+ //are italic and longer than a single character.
+ bool bIsItalic = IsItalic(pTemp->GetFont());
+ if ((pTemp->GetText().getLength() > 1) && bIsItalic)
+ AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_ITALIC);
+ else if ((pTemp->GetText().getLength() == 1) && !bIsItalic)
+ AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_NORMAL);
+ pText.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI, true, false));
+ break;
+ }
+ case TNUMBER:
+ pText.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MN, true, false));
+ break;
+ case TTEXT:
+ pText.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTEXT, true, false));
+ break;
+ }
+ GetDocHandler()->characters(pTemp->GetText());
+}
+
+void SmXMLExport::ExportBlank(const SmNode* pNode)
+{
+ const SmBlankNode* pTemp = static_cast<const SmBlankNode*>(pNode);
+ //!! exports an <mspace> element. Note that for example "~_~" is allowed in
+ //!! Math (so it has no sense at all) but must not result in an empty
+ //!! <msub> tag in MathML !!
+
+ if (pTemp->GetBlankNum() != 0)
+ {
+ // Attach a width attribute. We choose the (somewhat arbitrary) values
+ // ".5em" for a small gap '`' and "2em" for a large gap '~'.
+ // (see SmBlankNode::IncreaseBy for how pTemp->mnNum is set).
+ OUStringBuffer sStrBuf;
+ ::sax::Converter::convertDouble(sStrBuf, pTemp->GetBlankNum() * .5);
+ sStrBuf.append("em");
+ AddAttribute(XML_NAMESPACE_MATH, XML_WIDTH, sStrBuf.makeStringAndClear());
+ }
+
+ SvXMLElementExport aTextExport(*this, XML_NAMESPACE_MATH, XML_MSPACE, true, false);
+
+ GetDocHandler()->characters(OUString());
+}
+
+void SmXMLExport::ExportSubSupScript(const SmNode* pNode, int nLevel)
+{
+ const SmNode* pSub = nullptr;
+ const SmNode* pSup = nullptr;
+ const SmNode* pCSub = nullptr;
+ const SmNode* pCSup = nullptr;
+ const SmNode* pLSub = nullptr;
+ const SmNode* pLSup = nullptr;
+ std::unique_ptr<SvXMLElementExport> pThing2;
+
+ //if we have prescripts at all then we must use the tensor notation
+
+ //This is one of those excellent locations where scope is vital to
+ //arrange the construction and destruction of the element helper
+ //classes correctly
+ pLSub = pNode->GetSubNode(LSUB + 1);
+ pLSup = pNode->GetSubNode(LSUP + 1);
+ if (pLSub || pLSup)
+ {
+ SvXMLElementExport aMultiScripts(*this, XML_NAMESPACE_MATH, XML_MMULTISCRIPTS, true, true);
+
+ if (nullptr != (pCSub = pNode->GetSubNode(CSUB + 1))
+ && nullptr != (pCSup = pNode->GetSubNode(CSUP + 1)))
+ {
+ pThing2.reset(
+ new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDEROVER, true, true));
+ }
+ else if (nullptr != (pCSub = pNode->GetSubNode(CSUB + 1)))
+ {
+ pThing2.reset(
+ new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDER, true, true));
+ }
+ else if (nullptr != (pCSup = pNode->GetSubNode(CSUP + 1)))
+ {
+ pThing2.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MOVER, true, true));
+ }
+
+ ExportNodes(pNode->GetSubNode(0), nLevel + 1); //Main Term
+
+ if (pCSub)
+ ExportNodes(pCSub, nLevel + 1);
+ if (pCSup)
+ ExportNodes(pCSup, nLevel + 1);
+ pThing2.reset();
+
+ pSub = pNode->GetSubNode(RSUB + 1);
+ pSup = pNode->GetSubNode(RSUP + 1);
+ if (pSub || pSup)
+ {
+ if (pSub)
+ ExportNodes(pSub, nLevel + 1);
+ else
+ {
+ SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE, true, true);
+ }
+ if (pSup)
+ ExportNodes(pSup, nLevel + 1);
+ else
+ {
+ SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE, true, true);
+ }
+ }
+
+ //Separator element between suffix and prefix sub/sup pairs
+ {
+ SvXMLElementExport aPrescripts(*this, XML_NAMESPACE_MATH, XML_MPRESCRIPTS, true, true);
+ }
+
+ if (pLSub)
+ ExportNodes(pLSub, nLevel + 1);
+ else
+ {
+ SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE, true, true);
+ }
+ if (pLSup)
+ ExportNodes(pLSup, nLevel + 1);
+ else
+ {
+ SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE, true, true);
+ }
+ }
+ else
+ {
+ std::unique_ptr<SvXMLElementExport> pThing;
+ if (nullptr != (pSub = pNode->GetSubNode(RSUB + 1))
+ && nullptr != (pSup = pNode->GetSubNode(RSUP + 1)))
+ {
+ pThing.reset(
+ new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUBSUP, true, true));
+ }
+ else if (nullptr != (pSub = pNode->GetSubNode(RSUB + 1)))
+ {
+ pThing.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUB, true, true));
+ }
+ else if (nullptr != (pSup = pNode->GetSubNode(RSUP + 1)))
+ {
+ pThing.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUP, true, true));
+ }
+
+ if (nullptr != (pCSub = pNode->GetSubNode(CSUB + 1))
+ && nullptr != (pCSup = pNode->GetSubNode(CSUP + 1)))
+ {
+ pThing2.reset(
+ new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDEROVER, true, true));
+ }
+ else if (nullptr != (pCSub = pNode->GetSubNode(CSUB + 1)))
+ {
+ pThing2.reset(
+ new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDER, true, true));
+ }
+ else if (nullptr != (pCSup = pNode->GetSubNode(CSUP + 1)))
+ {
+ pThing2.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MOVER, true, true));
+ }
+ ExportNodes(pNode->GetSubNode(0), nLevel + 1); //Main Term
+
+ if (pCSub)
+ ExportNodes(pCSub, nLevel + 1);
+ if (pCSup)
+ ExportNodes(pCSup, nLevel + 1);
+ pThing2.reset();
+
+ if (pSub)
+ ExportNodes(pSub, nLevel + 1);
+ if (pSup)
+ ExportNodes(pSup, nLevel + 1);
+ pThing.reset();
+ }
+}
+
+void SmXMLExport::ExportBrace(const SmNode* pNode, int nLevel)
+{
+ const SmNode* pTemp;
+ const SmNode* pLeft = pNode->GetSubNode(0);
+ const SmNode* pRight = pNode->GetSubNode(2);
+
+ // This used to generate <mfenced> or <mrow>+<mo> elements according to
+ // the stretchiness of fences. The MathML recommendation defines an
+ // <mrow>+<mo> construction that is equivalent to the <mfenced> element:
+ // http://www.w3.org/TR/MathML3/chapter3.html#presm.mfenced
+ // To simplify our code and avoid issues with mfenced implementations in
+ // MathML rendering engines, we now always generate <mrow>+<mo> elements.
+ // See #fdo 66282.
+
+ // <mrow>
+ SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MROW, true, true);
+
+ // <mo fence="true"> opening-fence </mo>
+ if (pLeft && (pLeft->GetToken().eType != TNONE))
+ {
+ AddAttribute(XML_NAMESPACE_MATH, XML_FENCE, XML_TRUE);
+ AddAttribute(XML_NAMESPACE_MATH, XML_FORM, XML_PREFIX);
+ if (pNode->GetScaleMode() == SmScaleMode::Height)
+ AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE);
+ else
+ AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE);
+ ExportNodes(pLeft, nLevel + 1);
+ }
+
+ if (nullptr != (pTemp = pNode->GetSubNode(1)))
+ {
+ // <mrow>
+ SvXMLElementExport aRowExport(*this, XML_NAMESPACE_MATH, XML_MROW, true, true);
+ ExportNodes(pTemp, nLevel + 1);
+ // </mrow>
+ }
+
+ // <mo fence="true"> closing-fence </mo>
+ if (pRight && (pRight->GetToken().eType != TNONE))
+ {
+ AddAttribute(XML_NAMESPACE_MATH, XML_FENCE, XML_TRUE);
+ AddAttribute(XML_NAMESPACE_MATH, XML_FORM, XML_POSTFIX);
+ if (pNode->GetScaleMode() == SmScaleMode::Height)
+ AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE);
+ else
+ AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE);
+ ExportNodes(pRight, nLevel + 1);
+ }
+
+ // </mrow>
+}
+
+void SmXMLExport::ExportRoot(const SmNode* pNode, int nLevel)
+{
+ if (pNode->GetSubNode(0))
+ {
+ SvXMLElementExport aRoot(*this, XML_NAMESPACE_MATH, XML_MROOT, true, true);
+ ExportNodes(pNode->GetSubNode(2), nLevel + 1);
+ ExportNodes(pNode->GetSubNode(0), nLevel + 1);
+ }
+ else
+ {
+ SvXMLElementExport aSqrt(*this, XML_NAMESPACE_MATH, XML_MSQRT, true, true);
+ ExportNodes(pNode->GetSubNode(2), nLevel + 1);
+ }
+}
+
+void SmXMLExport::ExportOperator(const SmNode* pNode, int nLevel)
+{
+ /*we need to either use content or font and size attributes
+ *here*/
+ SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MROW, true, true);
+ ExportNodes(pNode->GetSubNode(0), nLevel + 1);
+ ExportNodes(pNode->GetSubNode(1), nLevel + 1);
+}
+
+void SmXMLExport::ExportAttributes(const SmNode* pNode, int nLevel)
+{
+ std::unique_ptr<SvXMLElementExport> pElement;
+
+ if (pNode->GetToken().eType == TUNDERLINE)
+ {
+ AddAttribute(XML_NAMESPACE_MATH, XML_ACCENTUNDER, XML_TRUE);
+ pElement.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDER, true, true));
+ }
+ else if (pNode->GetToken().eType == TOVERSTRIKE)
+ {
+ // export as <menclose notation="horizontalstrike">
+ AddAttribute(XML_NAMESPACE_MATH, XML_NOTATION, XML_HORIZONTALSTRIKE);
+ pElement.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MENCLOSE, true, true));
+ }
+ else
+ {
+ AddAttribute(XML_NAMESPACE_MATH, XML_ACCENT, XML_TRUE);
+ pElement.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MOVER, true, true));
+ }
+
+ ExportNodes(pNode->GetSubNode(1), nLevel + 1);
+ switch (pNode->GetToken().eType)
+ {
+ case TOVERLINE:
+ {
+ //proper entity support required
+ SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO, true, true);
+ static constexpr OUStringLiteral nArse = u"\u00AF";
+ GetDocHandler()->characters(nArse);
+ }
+ break;
+ case TUNDERLINE:
+ {
+ //proper entity support required
+ SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO, true, true);
+ static constexpr OUStringLiteral nArse = u"\u0332";
+ GetDocHandler()->characters(nArse);
+ }
+ break;
+ case TOVERSTRIKE:
+ break;
+ case TWIDETILDE:
+ case TWIDEHAT:
+ case TWIDEVEC:
+ case TWIDEHARPOON:
+ {
+ // make these wide accents stretchy
+ AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE);
+ ExportNodes(pNode->GetSubNode(0), nLevel + 1);
+ }
+ break;
+ default:
+ ExportNodes(pNode->GetSubNode(0), nLevel + 1);
+ break;
+ }
+}
+
+static bool lcl_HasEffectOnMathvariant(const SmTokenType eType)
+{
+ return eType == TBOLD || eType == TNBOLD || eType == TITALIC || eType == TNITALIC
+ || eType == TSANS || eType == TSERIF || eType == TFIXED;
+}
+
+void SmXMLExport::ExportFont(const SmNode* pNode, int nLevel)
+{
+ // gather the mathvariant attribute relevant data from all
+ // successively following SmFontNodes...
+
+ int nBold = -1; // for the following variables: -1 = yet undefined; 0 = false; 1 = true;
+ int nItalic = -1; // for the following variables: -1 = yet undefined; 0 = false; 1 = true;
+ int nSansSerifFixed = -1;
+ SmTokenType eNodeType = TUNKNOWN;
+
+ for (;;)
+ {
+ eNodeType = pNode->GetToken().eType;
+ if (!lcl_HasEffectOnMathvariant(eNodeType))
+ break;
+ switch (eNodeType)
+ {
+ case TBOLD:
+ nBold = 1;
+ break;
+ case TNBOLD:
+ nBold = 0;
+ break;
+ case TITALIC:
+ nItalic = 1;
+ break;
+ case TNITALIC:
+ nItalic = 0;
+ break;
+ case TSANS:
+ nSansSerifFixed = 0;
+ break;
+ case TSERIF:
+ nSansSerifFixed = 1;
+ break;
+ case TFIXED:
+ nSansSerifFixed = 2;
+ break;
+ default:
+ SAL_WARN("starmath", "unexpected case");
+ }
+ // According to the parser every node that is to be evaluated here
+ // has a single non-zero subnode at index 1!! Thus we only need to check
+ // that single node for follow-up nodes that have an effect on the attribute.
+ if (pNode->GetNumSubNodes() > 1 && pNode->GetSubNode(1)
+ && lcl_HasEffectOnMathvariant(pNode->GetSubNode(1)->GetToken().eType))
+ {
+ pNode = pNode->GetSubNode(1);
+ }
+ else
+ break;
+ }
+
+ sal_uInt32 nc;
+ switch (pNode->GetToken().eType)
+ {
+ case TPHANTOM:
+ // No attribute needed. An <mphantom> element will be used below.
+ break;
+ case TMATHMLCOL:
+ {
+ nc = pNode->GetToken().cMathChar.toUInt32(16);
+ const OUString& sssStr = starmathdatabase::Identify_Color_MATHML(nc).aIdent;
+ AddAttribute(XML_NAMESPACE_MATH, XML_MATHCOLOR, sssStr);
+ }
+ break;
+ case TRGB:
+ case TRGBA:
+ case THEX:
+ case THTMLCOL:
+ case TDVIPSNAMESCOL:
+ case TICONICCOL:
+ {
+ nc = pNode->GetToken().cMathChar.toUInt32(16);
+ OUString ssStr("#" + Color(ColorTransparency, nc).AsRGBHEXString());
+ AddAttribute(XML_NAMESPACE_MATH, XML_MATHCOLOR, ssStr);
+ }
+ break;
+ case TSIZE:
+ {
+ const SmFontNode* pFontNode = static_cast<const SmFontNode*>(pNode);
+ const Fraction& aFrac = pFontNode->GetSizeParameter();
+
+ OUStringBuffer sStrBuf;
+ switch (pFontNode->GetSizeType())
+ {
+ case FontSizeType::MULTIPLY:
+ ::sax::Converter::convertDouble(sStrBuf,
+ static_cast<double>(aFrac * Fraction(100.00)));
+ sStrBuf.append('%');
+ break;
+ case FontSizeType::DIVIDE:
+ ::sax::Converter::convertDouble(sStrBuf,
+ static_cast<double>(Fraction(100.00) / aFrac));
+ sStrBuf.append('%');
+ break;
+ case FontSizeType::ABSOLUT:
+ ::sax::Converter::convertDouble(sStrBuf, static_cast<double>(aFrac));
+ sStrBuf.append(GetXMLToken(XML_UNIT_PT));
+ break;
+ default:
+ {
+ //The problem here is that the wheels fall off because
+ //font size is stored in 100th's of a mm not pts, and
+ //rounding errors take their toll on the original
+ //value specified in points.
+
+ //Must fix StarMath to retain the original pt values
+ Fraction aTemp = Sm100th_mmToPts(pFontNode->GetFont().GetFontSize().Height());
+
+ if (pFontNode->GetSizeType() == FontSizeType::MINUS)
+ aTemp -= aFrac;
+ else
+ aTemp += aFrac;
+
+ double mytest = static_cast<double>(aTemp);
+
+ mytest = ::rtl::math::round(mytest, 1);
+ ::sax::Converter::convertDouble(sStrBuf, mytest);
+ sStrBuf.append(GetXMLToken(XML_UNIT_PT));
+ }
+ break;
+ }
+
+ OUString sStr(sStrBuf.makeStringAndClear());
+ AddAttribute(XML_NAMESPACE_MATH, XML_MATHSIZE, sStr);
+ }
+ break;
+ case TBOLD:
+ case TITALIC:
+ case TNBOLD:
+ case TNITALIC:
+ case TFIXED:
+ case TSANS:
+ case TSERIF:
+ {
+ // nBold: -1 = yet undefined; 0 = false; 1 = true;
+ // nItalic: -1 = yet undefined; 0 = false; 1 = true;
+ // nSansSerifFixed: -1 = undefined; 0 = sans; 1 = serif; 2 = fixed;
+ const char* pText = "normal";
+ if (nSansSerifFixed == -1 || nSansSerifFixed == 1)
+ {
+ pText = "normal";
+ if (nBold == 1 && nItalic != 1)
+ pText = "bold";
+ else if (nBold != 1 && nItalic == 1)
+ pText = "italic";
+ else if (nBold == 1 && nItalic == 1)
+ pText = "bold-italic";
+ }
+ else if (nSansSerifFixed == 0)
+ {
+ pText = "sans-serif";
+ if (nBold == 1 && nItalic != 1)
+ pText = "bold-sans-serif";
+ else if (nBold != 1 && nItalic == 1)
+ pText = "sans-serif-italic";
+ else if (nBold == 1 && nItalic == 1)
+ pText = "sans-serif-bold-italic";
+ }
+ else if (nSansSerifFixed == 2)
+ pText = "monospace"; // no modifiers allowed for monospace ...
+ else
+ {
+ SAL_WARN("starmath", "unexpected case");
+ }
+ AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, OUString::createFromAscii(pText));
+ }
+ break;
+ default:
+ break;
+ }
+ {
+ // Wrap everything in an <mphantom> or <mstyle> element. These elements
+ // are mrow-like, so ExportExpression doesn't need to add an explicit
+ // <mrow> element. See #fdo 66283.
+ SvXMLElementExport aElement(*this, XML_NAMESPACE_MATH,
+ pNode->GetToken().eType == TPHANTOM ? XML_MPHANTOM : XML_MSTYLE,
+ true, true);
+ ExportExpression(pNode, nLevel, true);
+ }
+}
+
+void SmXMLExport::ExportVerticalBrace(const SmVerticalBraceNode* pNode, int nLevel)
+{
+ // "[body] overbrace [script]"
+
+ // Position body, overbrace and script vertically. First place the overbrace
+ // OVER the body and then the script OVER this expression.
+
+ // [script]
+ // --[overbrace]--
+ // XXXXXX[body]XXXXXXX
+
+ // Similarly for the underbrace construction.
+
+ XMLTokenEnum which;
+
+ switch (pNode->GetToken().eType)
+ {
+ case TOVERBRACE:
+ default:
+ which = XML_MOVER;
+ break;
+ case TUNDERBRACE:
+ which = XML_MUNDER;
+ break;
+ }
+
+ SvXMLElementExport aOver1(*this, XML_NAMESPACE_MATH, which, true, true);
+ { //Scoping
+ // using accents will draw the over-/underbraces too close to the base
+ // see http://www.w3.org/TR/MathML2/chapter3.html#id.3.4.5.2
+ // also XML_ACCENT is illegal with XML_MUNDER. Thus no XML_ACCENT attribute here!
+ SvXMLElementExport aOver2(*this, XML_NAMESPACE_MATH, which, true, true);
+ ExportNodes(pNode->Body(), nLevel);
+ AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE);
+ ExportNodes(pNode->Brace(), nLevel);
+ }
+ ExportNodes(pNode->Script(), nLevel);
+}
+
+void SmXMLExport::ExportMatrix(const SmNode* pNode, int nLevel)
+{
+ SvXMLElementExport aTable(*this, XML_NAMESPACE_MATH, XML_MTABLE, true, true);
+ const SmMatrixNode* pMatrix = static_cast<const SmMatrixNode*>(pNode);
+ size_t i = 0;
+ for (sal_uInt16 y = 0; y < pMatrix->GetNumRows(); y++)
+ {
+ SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MTR, true, true);
+ for (sal_uInt16 x = 0; x < pMatrix->GetNumCols(); x++)
+ {
+ if (const SmNode* pTemp = pNode->GetSubNode(i++))
+ {
+ if (pTemp->GetType() == SmNodeType::Align && pTemp->GetToken().eType != TALIGNC)
+ {
+ // A left or right alignment is specified on this cell,
+ // attach the corresponding columnalign attribute.
+ AddAttribute(XML_NAMESPACE_MATH, XML_COLUMNALIGN,
+ pTemp->GetToken().eType == TALIGNL ? XML_LEFT : XML_RIGHT);
+ }
+ SvXMLElementExport aCell(*this, XML_NAMESPACE_MATH, XML_MTD, true, true);
+ ExportNodes(pTemp, nLevel + 1);
+ }
+ }
+ }
+}
+
+void SmXMLExport::ExportNodes(const SmNode* pNode, int nLevel)
+{
+ if (!pNode)
+ return;
+ switch (pNode->GetType())
+ {
+ case SmNodeType::Table:
+ ExportTable(pNode, nLevel);
+ break;
+ case SmNodeType::Align:
+ case SmNodeType::Bracebody:
+ case SmNodeType::Expression:
+ ExportExpression(pNode, nLevel);
+ break;
+ case SmNodeType::Line:
+ ExportLine(pNode, nLevel);
+ break;
+ case SmNodeType::Text:
+ ExportText(pNode);
+ break;
+ case SmNodeType::GlyphSpecial:
+ case SmNodeType::Math:
+ {
+ sal_Unicode cTmp = 0;
+ const SmTextNode* pTemp = static_cast<const SmTextNode*>(pNode);
+ if (!pTemp->GetText().isEmpty())
+ cTmp = ConvertMathToMathML(pTemp->GetText()[0]);
+ if (cTmp == 0)
+ {
+ // no conversion to MathML implemented -> export it as text
+ // thus at least it will not vanish into nothing
+ ExportText(pNode);
+ }
+ else
+ {
+ switch (pNode->GetToken().eType)
+ {
+ case TINTD:
+ AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE);
+ break;
+ default:
+ break;
+ }
+ //To fully handle generic MathML we need to implement the full
+ //operator dictionary, we will generate MathML with explicit
+ //stretchiness for now.
+ sal_Int16 nLength = GetAttrList().getLength();
+ bool bAddStretch = true;
+ for (sal_Int16 i = 0; i < nLength; i++)
+ {
+ OUString sLocalName;
+ sal_uInt16 nPrefix = GetNamespaceMap().GetKeyByAttrName(
+ GetAttrList().getNameByIndex(i), &sLocalName);
+
+ if ((XML_NAMESPACE_MATH == nPrefix) && IsXMLToken(sLocalName, XML_STRETCHY))
+ {
+ bAddStretch = false;
+ break;
+ }
+ }
+ if (bAddStretch)
+ {
+ AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE);
+ }
+ ExportMath(pNode);
+ }
+ }
+ break;
+ case SmNodeType::
+ Special: //SmNodeType::Special requires some sort of Entity preservation in the XML engine.
+ case SmNodeType::MathIdent:
+ case SmNodeType::Place:
+ ExportMath(pNode);
+ break;
+ case SmNodeType::BinHor:
+ ExportBinaryHorizontal(pNode, nLevel);
+ break;
+ case SmNodeType::UnHor:
+ ExportUnaryHorizontal(pNode, nLevel);
+ break;
+ case SmNodeType::Brace:
+ ExportBrace(pNode, nLevel);
+ break;
+ case SmNodeType::BinVer:
+ ExportBinaryVertical(pNode, nLevel);
+ break;
+ case SmNodeType::BinDiagonal:
+ ExportBinaryDiagonal(pNode, nLevel);
+ break;
+ case SmNodeType::SubSup:
+ ExportSubSupScript(pNode, nLevel);
+ break;
+ case SmNodeType::Root:
+ ExportRoot(pNode, nLevel);
+ break;
+ case SmNodeType::Oper:
+ ExportOperator(pNode, nLevel);
+ break;
+ case SmNodeType::Attribute:
+ ExportAttributes(pNode, nLevel);
+ break;
+ case SmNodeType::Font:
+ ExportFont(pNode, nLevel);
+ break;
+ case SmNodeType::VerticalBrace:
+ ExportVerticalBrace(static_cast<const SmVerticalBraceNode*>(pNode), nLevel);
+ break;
+ case SmNodeType::Matrix:
+ ExportMatrix(pNode, nLevel);
+ break;
+ case SmNodeType::Blank:
+ ExportBlank(pNode);
+ break;
+ default:
+ SAL_WARN("starmath", "Warning: failed to export a node?");
+ break;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/starmath/source/mathml/mathmlimport.cxx b/starmath/source/mathml/mathmlimport.cxx
new file mode 100644
index 000000000..44d8cc1e3
--- /dev/null
+++ b/starmath/source/mathml/mathmlimport.cxx
@@ -0,0 +1,2696 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+/*todo: Change characters and tcharacters to accumulate the characters together
+into one string, xml parser hands them to us line by line rather than all in
+one go*/
+
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/sax/FastParser.hpp>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/packages/WrongPasswordException.hpp>
+#include <com/sun/star/packages/zip/ZipIOException.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/uno/Any.h>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+
+#include <comphelper/fileformat.h>
+#include <comphelper/genericpropertyset.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <rtl/character.hxx>
+#include <sal/log.hxx>
+#include <sfx2/frame.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <sfx2/sfxmodelfactory.hxx>
+#include <osl/diagnose.h>
+#include <sot/storage.hxx>
+#include <svtools/sfxecode.hxx>
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <unotools/streamwrap.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/DocumentSettingsContext.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlmetai.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/strings.hrc>
+#include <tools/diagnose_ex.h>
+#include <o3tl/string_view.hxx>
+
+#include <mathmlattr.hxx>
+#include <xparsmlbase.hxx>
+#include <mathmlimport.hxx>
+#include <document.hxx>
+#include <smdll.hxx>
+#include <unomodel.hxx>
+#include <utility.hxx>
+#include <visitors.hxx>
+#include <starmathdatabase.hxx>
+#include <smmod.hxx>
+#include <cfgitem.hxx>
+
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+namespace
+{
+std::unique_ptr<SmNode> popOrZero(SmNodeStack& rStack)
+{
+ if (rStack.empty())
+ return nullptr;
+ auto pTmp = std::move(rStack.front());
+ rStack.pop_front();
+ return pTmp;
+}
+}
+
+ErrCode SmXMLImportWrapper::Import(SfxMedium& rMedium)
+{
+ ErrCode nError = ERRCODE_SFX_DOLOADFAILED;
+
+ uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
+
+ //Make a model component from our SmModel
+ uno::Reference<lang::XComponent> xModelComp = xModel;
+ OSL_ENSURE(xModelComp.is(), "XMLReader::Read: got no model");
+
+ // try to get an XStatusIndicator from the Medium
+ uno::Reference<task::XStatusIndicator> xStatusIndicator;
+
+ bool bEmbedded = false;
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel);
+
+ SmDocShell* pDocShell = pModel ? static_cast<SmDocShell*>(pModel->GetObjectShell()) : nullptr;
+ if (pDocShell)
+ {
+ OSL_ENSURE(pDocShell->GetMedium() == &rMedium, "different SfxMedium found");
+
+ SfxItemSet* pSet = rMedium.GetItemSet();
+ if (pSet)
+ {
+ const SfxUnoAnyItem* pItem = pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL);
+ if (pItem)
+ pItem->GetValue() >>= xStatusIndicator;
+ }
+
+ if (SfxObjectCreateMode::EMBEDDED == pDocShell->GetCreateMode())
+ bEmbedded = true;
+ }
+
+ static const comphelper::PropertyMapEntry aInfoMap[]
+ = { { OUString("PrivateData"), 0, cppu::UnoType<XInterface>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 } };
+ uno::Reference<beans::XPropertySet> xInfoSet(
+ comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));
+
+ // Set base URI
+ OUString const baseURI(rMedium.GetBaseURL());
+ // needed for relative URLs; but it's OK to import e.g. MathML from the
+ // clipboard without one
+ SAL_INFO_IF(baseURI.isEmpty(), "starmath", "SmXMLImportWrapper: no base URL");
+ xInfoSet->setPropertyValue("BaseURI", Any(baseURI));
+
+ sal_Int32 nSteps = 3;
+ if (!(rMedium.IsStorage()))
+ nSteps = 1;
+
+ sal_Int32 nProgressRange(nSteps);
+ if (xStatusIndicator.is())
+ {
+ xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange);
+ }
+
+ nSteps = 0;
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+
+ if (rMedium.IsStorage())
+ {
+ // TODO/LATER: handle the case of embedded links gracefully
+ if (bEmbedded) // && !rMedium.GetStorage()->IsRoot() )
+ {
+ OUString aName("dummyObjName");
+ if (rMedium.GetItemSet())
+ {
+ const SfxStringItem* pDocHierarchItem
+ = rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME);
+ if (pDocHierarchItem)
+ aName = pDocHierarchItem->GetValue();
+ }
+
+ if (!aName.isEmpty())
+ {
+ xInfoSet->setPropertyValue("StreamRelPath", Any(aName));
+ }
+ }
+
+ bool bOASIS = (SotStorage::GetVersion(rMedium.GetStorage()) > SOFFICE_FILEFORMAT_60);
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+
+ auto nWarn
+ = ReadThroughComponent(rMedium.GetStorage(), xModelComp, "meta.xml", xContext, xInfoSet,
+ (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaImporter"
+ : "com.sun.star.comp.Math.XMLMetaImporter"),
+ m_bUseHTMLMLEntities);
+
+ if (nWarn != ERRCODE_IO_BROKENPACKAGE)
+ {
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+
+ nWarn = ReadThroughComponent(rMedium.GetStorage(), xModelComp, "settings.xml", xContext,
+ xInfoSet,
+ (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsImporter"
+ : "com.sun.star.comp.Math.XMLSettingsImporter"),
+ m_bUseHTMLMLEntities);
+
+ if (nWarn != ERRCODE_IO_BROKENPACKAGE)
+ {
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+
+ nError = ReadThroughComponent(
+ rMedium.GetStorage(), xModelComp, "content.xml", xContext, xInfoSet,
+ "com.sun.star.comp.Math.XMLImporter", m_bUseHTMLMLEntities);
+ }
+ else
+ nError = ERRCODE_IO_BROKENPACKAGE;
+ }
+ else
+ nError = ERRCODE_IO_BROKENPACKAGE;
+ }
+ else
+ {
+ Reference<io::XInputStream> xInputStream
+ = new utl::OInputStreamWrapper(rMedium.GetInStream());
+
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+
+ nError = ReadThroughComponent(xInputStream, xModelComp, xContext, xInfoSet,
+ "com.sun.star.comp.Math.XMLImporter", false,
+ m_bUseHTMLMLEntities);
+ }
+
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ return nError;
+}
+
+/// read a component (file + filter version)
+ErrCode SmXMLImportWrapper::ReadThroughComponent(const Reference<io::XInputStream>& xInputStream,
+ const Reference<XComponent>& xModelComponent,
+ Reference<uno::XComponentContext> const& rxContext,
+ Reference<beans::XPropertySet> const& rPropSet,
+ const char* pFilterName, bool bEncrypted,
+ bool bUseHTMLMLEntities)
+{
+ ErrCode nError = ERRCODE_SFX_DOLOADFAILED;
+ OSL_ENSURE(xInputStream.is(), "input stream missing");
+ OSL_ENSURE(xModelComponent.is(), "document missing");
+ OSL_ENSURE(rxContext.is(), "factory missing");
+ OSL_ENSURE(nullptr != pFilterName, "I need a service name for the component!");
+
+ // prepare ParserInputSource
+ xml::sax::InputSource aParserInput;
+ aParserInput.aInputStream = xInputStream;
+
+ Sequence<Any> aArgs{ Any(rPropSet) };
+
+ // get filter
+ Reference<XInterface> xFilter
+ = rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ OUString::createFromAscii(pFilterName), aArgs, rxContext);
+ SAL_WARN_IF(!xFilter, "starmath", "Can't instantiate filter component " << pFilterName);
+ if (!xFilter.is())
+ return nError;
+
+ // connect model and filter
+ Reference<XImporter> xImporter(xFilter, UNO_QUERY);
+ xImporter->setTargetDocument(xModelComponent);
+
+ // finally, parser the stream
+ try
+ {
+ Reference<css::xml::sax::XFastParser> xFastParser(xFilter, UNO_QUERY);
+ Reference<css::xml::sax::XFastDocumentHandler> xFastDocHandler(xFilter, UNO_QUERY);
+ if (xFastParser)
+ {
+ if (bUseHTMLMLEntities)
+ xFastParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities);
+ xFastParser->parseStream(aParserInput);
+ }
+ else if (xFastDocHandler)
+ {
+ Reference<css::xml::sax::XFastParser> xParser
+ = css::xml::sax::FastParser::create(rxContext);
+ if (bUseHTMLMLEntities)
+ xParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities);
+ xParser->setFastDocumentHandler(xFastDocHandler);
+ xParser->parseStream(aParserInput);
+ }
+ else
+ {
+ Reference<css::xml::sax::XDocumentHandler> xDocHandler(xFilter, UNO_QUERY);
+ assert(xDocHandler);
+ Reference<css::xml::sax::XParser> xParser = css::xml::sax::Parser::create(rxContext);
+ xParser->setDocumentHandler(xDocHandler);
+ xParser->parseStream(aParserInput);
+ }
+
+ auto pFilter = comphelper::getFromUnoTunnel<SmXMLImport>(xFilter);
+ if (pFilter && pFilter->GetSuccess())
+ nError = ERRCODE_NONE;
+ }
+ catch (const xml::sax::SAXParseException& r)
+ {
+ // sax parser sends wrapped exceptions,
+ // try to find the original one
+ xml::sax::SAXException aSaxEx = *static_cast<const xml::sax::SAXException*>(&r);
+ bool bTryChild = true;
+
+ while (bTryChild)
+ {
+ xml::sax::SAXException aTmp;
+ if (aSaxEx.WrappedException >>= aTmp)
+ aSaxEx = aTmp;
+ else
+ bTryChild = false;
+ }
+
+ packages::zip::ZipIOException aBrokenPackage;
+ if (aSaxEx.WrappedException >>= aBrokenPackage)
+ return ERRCODE_IO_BROKENPACKAGE;
+
+ if (bEncrypted)
+ nError = ERRCODE_SFX_WRONGPASSWORD;
+ }
+ catch (const xml::sax::SAXException& r)
+ {
+ packages::zip::ZipIOException aBrokenPackage;
+ if (r.WrappedException >>= aBrokenPackage)
+ return ERRCODE_IO_BROKENPACKAGE;
+
+ if (bEncrypted)
+ nError = ERRCODE_SFX_WRONGPASSWORD;
+ }
+ catch (const packages::zip::ZipIOException&)
+ {
+ nError = ERRCODE_IO_BROKENPACKAGE;
+ }
+ catch (const io::IOException&)
+ {
+ }
+ catch (const std::range_error&)
+ {
+ }
+
+ return nError;
+}
+
+ErrCode SmXMLImportWrapper::ReadThroughComponent(const uno::Reference<embed::XStorage>& xStorage,
+ const Reference<XComponent>& xModelComponent,
+ const char* pStreamName,
+ Reference<uno::XComponentContext> const& rxContext,
+ Reference<beans::XPropertySet> const& rPropSet,
+ const char* pFilterName, bool bUseHTMLMLEntities)
+{
+ OSL_ENSURE(xStorage.is(), "Need storage!");
+ OSL_ENSURE(nullptr != pStreamName, "Please, please, give me a name!");
+
+ // open stream (and set parser input)
+ OUString sStreamName = OUString::createFromAscii(pStreamName);
+
+ // get input stream
+ try
+ {
+ uno::Reference<io::XStream> xEventsStream
+ = xStorage->openStreamElement(sStreamName, embed::ElementModes::READ);
+
+ // determine if stream is encrypted or not
+ uno::Reference<beans::XPropertySet> xProps(xEventsStream, uno::UNO_QUERY);
+ Any aAny = xProps->getPropertyValue("Encrypted");
+ bool bEncrypted = false;
+ if (aAny.getValueType() == cppu::UnoType<bool>::get())
+ aAny >>= bEncrypted;
+
+ // set Base URL
+ if (rPropSet.is())
+ {
+ rPropSet->setPropertyValue("StreamName", Any(sStreamName));
+ }
+
+ Reference<io::XInputStream> xStream = xEventsStream->getInputStream();
+ return ReadThroughComponent(xStream, xModelComponent, rxContext, rPropSet, pFilterName,
+ bEncrypted, bUseHTMLMLEntities);
+ }
+ catch (packages::WrongPasswordException&)
+ {
+ return ERRCODE_SFX_WRONGPASSWORD;
+ }
+ catch (packages::zip::ZipIOException&)
+ {
+ return ERRCODE_IO_BROKENPACKAGE;
+ }
+ catch (uno::Exception&)
+ {
+ }
+
+ return ERRCODE_SFX_DOLOADFAILED;
+}
+
+SmXMLImport::SmXMLImport(const css::uno::Reference<css::uno::XComponentContext>& rContext,
+ OUString const& implementationName, SvXMLImportFlags nImportFlags)
+ : SvXMLImport(rContext, implementationName, nImportFlags)
+ , bSuccess(false)
+ , nParseDepth(0)
+ , mnSmSyntaxVersion(SM_MOD()->GetConfig()->GetDefaultSmSyntaxVersion())
+{
+}
+
+const uno::Sequence<sal_Int8>& SmXMLImport::getUnoTunnelId() noexcept
+{
+ static const comphelper::UnoIdInit theSmXMLImportUnoTunnelId;
+ return theSmXMLImportUnoTunnelId.getSeq();
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+Math_XMLImporter_get_implementation(uno::XComponentContext* pCtx,
+ uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(
+ new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLImporter", SvXMLImportFlags::ALL));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+Math_XMLOasisMetaImporter_get_implementation(uno::XComponentContext* pCtx,
+ uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisMetaImporter",
+ SvXMLImportFlags::META));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+Math_XMLOasisSettingsImporter_get_implementation(uno::XComponentContext* pCtx,
+ uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisSettingsImporter",
+ SvXMLImportFlags::SETTINGS));
+}
+
+sal_Int64 SAL_CALL SmXMLImport::getSomething(const uno::Sequence<sal_Int8>& rId)
+{
+ return comphelper::getSomethingImpl(rId, this,
+ comphelper::FallbackToGetSomethingOf<SvXMLImport>{});
+}
+
+void SmXMLImport::endDocument()
+{
+ //Set the resulted tree into the SmDocShell where it belongs
+ std::unique_ptr<SmNode> pTree = popOrZero(aNodeStack);
+ if (pTree && pTree->GetType() == SmNodeType::Table)
+ {
+ uno::Reference<frame::XModel> xModel = GetModel();
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel);
+
+ if (pModel)
+ {
+ SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
+ auto pTreeTmp = pTree.get();
+ pDocShell->SetFormulaTree(static_cast<SmTableNode*>(pTree.release()));
+ if (aText.isEmpty()) //If we picked up no annotation text
+ {
+ // Get text from imported formula
+ SmNodeToTextVisitor tmpvisitor(pTreeTmp, aText);
+ }
+
+ // Convert symbol names
+ AbstractSmParser* rParser = pDocShell->GetParser();
+ bool bVal = rParser->IsImportSymbolNames();
+ rParser->SetImportSymbolNames(true);
+ auto pTmpTree = rParser->Parse(aText);
+ aText = rParser->GetText();
+ pTmpTree.reset();
+ rParser->SetImportSymbolNames(bVal);
+
+ pDocShell->SetText(aText);
+ pDocShell->SetSmSyntaxVersion(mnSmSyntaxVersion);
+ }
+ OSL_ENSURE(pModel, "So there *was* a UNO problem after all");
+
+ bSuccess = true;
+ }
+
+ SvXMLImport::endDocument();
+}
+
+namespace
+{
+class SmXMLImportContext : public SvXMLImportContext
+{
+public:
+ SmXMLImportContext(SmXMLImport& rImport)
+ : SvXMLImportContext(rImport)
+ {
+ GetSmImport().IncParseDepth();
+ }
+
+ virtual ~SmXMLImportContext() override { GetSmImport().DecParseDepth(); }
+
+ SmXMLImport& GetSmImport() { return static_cast<SmXMLImport&>(GetImport()); }
+
+ virtual void TCharacters(const OUString& /*rChars*/);
+ virtual void SAL_CALL characters(const OUString& rChars) override;
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& /*rAttrList*/) override
+ {
+ if (GetSmImport().TooDeep())
+ throw std::range_error("too deep");
+ }
+};
+}
+
+void SmXMLImportContext::TCharacters(const OUString& /*rChars*/) {}
+
+void SmXMLImportContext::characters(const OUString& rChars)
+{
+ /*
+ Whitespace occurring within the content of token elements is "trimmed"
+ from the ends (i.e. all whitespace at the beginning and end of the
+ content is removed), and "collapsed" internally (i.e. each sequence of
+ 1 or more whitespace characters is replaced with one blank character).
+ */
+ //collapsing not done yet!
+ const OUString& rChars2 = rChars.trim();
+ if (!rChars2.isEmpty())
+ TCharacters(rChars2 /*.collapse()*/);
+}
+
+namespace
+{
+struct SmXMLContext_Helper
+{
+ sal_Int8 nIsBold;
+ sal_Int8 nIsItalic;
+ double nFontSize;
+ OUString sFontFamily;
+ OUString sColor;
+
+ SmXMLImportContext& rContext;
+
+ explicit SmXMLContext_Helper(SmXMLImportContext& rImport)
+ : nIsBold(-1)
+ , nIsItalic(-1)
+ , nFontSize(0.0)
+ , rContext(rImport)
+ {
+ }
+
+ bool IsFontNodeNeeded() const;
+ void RetrieveAttrs(const uno::Reference<xml::sax::XFastAttributeList>& xAttrList);
+ void ApplyAttrs();
+};
+}
+
+bool SmXMLContext_Helper::IsFontNodeNeeded() const
+{
+ return nIsBold != -1 || nIsItalic != -1 || nFontSize != 0.0 || !sFontFamily.isEmpty()
+ || !sColor.isEmpty();
+}
+
+void SmXMLContext_Helper::RetrieveAttrs(
+ const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ bool bMvFound = false;
+ for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ // sometimes they have namespace, sometimes not?
+ switch (aIter.getToken() & TOKEN_MASK)
+ {
+ case XML_FONTWEIGHT:
+ nIsBold = sal_Int8(IsXMLToken(aIter, XML_BOLD));
+ break;
+ case XML_FONTSTYLE:
+ nIsItalic = sal_Int8(IsXMLToken(aIter, XML_ITALIC));
+ break;
+ case XML_FONTSIZE:
+ case XML_MATHSIZE:
+ {
+ OUString sValue = aIter.toString();
+ ::sax::Converter::convertDouble(nFontSize, sValue);
+ rContext.GetSmImport().GetMM100UnitConverter().SetXMLMeasureUnit(
+ util::MeasureUnit::POINT);
+ if (-1 == sValue.indexOf(GetXMLToken(XML_UNIT_PT)))
+ {
+ if (-1 == sValue.indexOf('%'))
+ nFontSize = 0.0;
+ else
+ {
+ rContext.GetSmImport().GetMM100UnitConverter().SetXMLMeasureUnit(
+ util::MeasureUnit::PERCENT);
+ }
+ }
+ break;
+ }
+ case XML_FONTFAMILY:
+ sFontFamily = aIter.toString();
+ break;
+ case XML_COLOR:
+ sColor = aIter.toString();
+ break;
+ case XML_MATHCOLOR:
+ sColor = aIter.toString();
+ break;
+ case XML_MATHVARIANT:
+ bMvFound = true;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("starmath", aIter);
+ break;
+ }
+ }
+
+ if (bMvFound)
+ {
+ // Ignore deprecated attributes fontfamily, fontweight, and fontstyle
+ // in favor of mathvariant, as specified in
+ // <https://www.w3.org/TR/MathML3/chapter3.html#presm.deprecatt>.
+ sFontFamily.clear();
+ nIsBold = -1;
+ nIsItalic = -1;
+ }
+}
+
+void SmXMLContext_Helper::ApplyAttrs()
+{
+ SmNodeStack& rNodeStack = rContext.GetSmImport().GetNodeStack();
+
+ if (!IsFontNodeNeeded())
+ return;
+
+ SmToken aToken;
+ aToken.cMathChar = u"";
+ aToken.nLevel = 5;
+
+ if (nIsBold != -1)
+ {
+ if (nIsBold)
+ aToken.eType = TBOLD;
+ else
+ aToken.eType = TNBOLD;
+ std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
+ pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
+ rNodeStack.push_front(std::move(pFontNode));
+ }
+ if (nIsItalic != -1)
+ {
+ if (nIsItalic)
+ aToken.eType = TITALIC;
+ else
+ aToken.eType = TNITALIC;
+ std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
+ pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
+ rNodeStack.push_front(std::move(pFontNode));
+ }
+ if (nFontSize != 0.0)
+ {
+ aToken.eType = TSIZE;
+ std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
+
+ if (util::MeasureUnit::PERCENT
+ == rContext.GetSmImport().GetMM100UnitConverter().GetXMLMeasureUnit())
+ {
+ if (nFontSize < 100.00)
+ pFontNode->SetSizeParameter(Fraction(100.00 / nFontSize), FontSizeType::DIVIDE);
+ else
+ pFontNode->SetSizeParameter(Fraction(nFontSize / 100.00), FontSizeType::MULTIPLY);
+ }
+ else
+ pFontNode->SetSizeParameter(Fraction(nFontSize), FontSizeType::ABSOLUT);
+
+ pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
+ rNodeStack.push_front(std::move(pFontNode));
+ }
+ if (!sColor.isEmpty())
+ {
+ SmColorTokenTableEntry aSmColorTokenTableEntry;
+ aSmColorTokenTableEntry = starmathdatabase::Identify_ColorName_HTML(sColor);
+ if (aSmColorTokenTableEntry.eType == TRGB)
+ aSmColorTokenTableEntry = starmathdatabase::Identify_Color_Parser(
+ sal_uInt32(aSmColorTokenTableEntry.cColor));
+ if (aSmColorTokenTableEntry.eType != TERROR)
+ {
+ aToken = aSmColorTokenTableEntry;
+ std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
+ pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
+ rNodeStack.push_front(std::move(pFontNode));
+ }
+ // If not known, not implemented yet. Giving up.
+ }
+ if (sFontFamily.isEmpty())
+ return;
+
+ if (sFontFamily.equalsIgnoreAsciiCase(GetXMLToken(XML_FIXED)))
+ aToken.eType = TFIXED;
+ else if (sFontFamily.equalsIgnoreAsciiCase("sans"))
+ aToken.eType = TSANS;
+ else if (sFontFamily.equalsIgnoreAsciiCase("serif"))
+ aToken.eType = TSERIF;
+ else //Just give up, we need to extend our font mechanism to be
+ //more general
+ return;
+
+ aToken.aText = sFontFamily;
+ std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
+ pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
+ rNodeStack.push_front(std::move(pFontNode));
+}
+
+namespace
+{
+class SmXMLTokenAttrHelper
+{
+ SmXMLImportContext& mrContext;
+ MathMLMathvariantValue meMv;
+ bool mbMvFound;
+
+public:
+ SmXMLTokenAttrHelper(SmXMLImportContext& rContext)
+ : mrContext(rContext)
+ , meMv(MathMLMathvariantValue::Normal)
+ , mbMvFound(false)
+ {
+ }
+
+ void RetrieveAttrs(const uno::Reference<xml::sax::XFastAttributeList>& xAttrList);
+ void ApplyAttrs(MathMLMathvariantValue eDefaultMv);
+};
+}
+
+void SmXMLTokenAttrHelper::RetrieveAttrs(
+ const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ OUString sValue = aIter.toString();
+ switch (aIter.getToken())
+ {
+ case XML_MATHVARIANT:
+ if (!GetMathMLMathvariantValue(sValue, meMv))
+ SAL_WARN("starmath", "failed to recognize mathvariant: " << sValue);
+ mbMvFound = true;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("starmath", aIter);
+ break;
+ }
+ }
+}
+
+void SmXMLTokenAttrHelper::ApplyAttrs(MathMLMathvariantValue eDefaultMv)
+{
+ assert(eDefaultMv == MathMLMathvariantValue::Normal
+ || eDefaultMv == MathMLMathvariantValue::Italic);
+
+ std::vector<SmTokenType> vVariant;
+ MathMLMathvariantValue eMv = mbMvFound ? meMv : eDefaultMv;
+ switch (eMv)
+ {
+ case MathMLMathvariantValue::Normal:
+ vVariant.push_back(TNITALIC);
+ break;
+ case MathMLMathvariantValue::Bold:
+ vVariant.push_back(TBOLD);
+ break;
+ case MathMLMathvariantValue::Italic:
+ // nothing to do
+ break;
+ case MathMLMathvariantValue::BoldItalic:
+ vVariant.push_back(TITALIC);
+ vVariant.push_back(TBOLD);
+ break;
+ case MathMLMathvariantValue::DoubleStruck:
+ // TODO
+ break;
+ case MathMLMathvariantValue::BoldFraktur:
+ // TODO: Fraktur
+ vVariant.push_back(TBOLD);
+ break;
+ case MathMLMathvariantValue::Script:
+ // TODO
+ break;
+ case MathMLMathvariantValue::BoldScript:
+ // TODO: Script
+ vVariant.push_back(TBOLD);
+ break;
+ case MathMLMathvariantValue::Fraktur:
+ // TODO
+ break;
+ case MathMLMathvariantValue::SansSerif:
+ vVariant.push_back(TSANS);
+ break;
+ case MathMLMathvariantValue::BoldSansSerif:
+ vVariant.push_back(TSANS);
+ vVariant.push_back(TBOLD);
+ break;
+ case MathMLMathvariantValue::SansSerifItalic:
+ vVariant.push_back(TITALIC);
+ vVariant.push_back(TSANS);
+ break;
+ case MathMLMathvariantValue::SansSerifBoldItalic:
+ vVariant.push_back(TITALIC);
+ vVariant.push_back(TBOLD);
+ vVariant.push_back(TSANS);
+ break;
+ case MathMLMathvariantValue::Monospace:
+ vVariant.push_back(TFIXED);
+ break;
+ case MathMLMathvariantValue::Initial:
+ case MathMLMathvariantValue::Tailed:
+ case MathMLMathvariantValue::Looped:
+ case MathMLMathvariantValue::Stretched:
+ // TODO
+ break;
+ }
+ if (vVariant.empty())
+ return;
+ SmNodeStack& rNodeStack = mrContext.GetSmImport().GetNodeStack();
+ for (auto eType : vVariant)
+ {
+ SmToken aToken;
+ aToken.eType = eType;
+ aToken.cMathChar = u"";
+ aToken.nLevel = 5;
+ std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
+ pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
+ rNodeStack.push_front(std::move(pFontNode));
+ }
+}
+
+namespace
+{
+class SmXMLDocContext_Impl : public SmXMLImportContext
+{
+public:
+ SmXMLDocContext_Impl(SmXMLImport& rImport)
+ : SmXMLImportContext(rImport)
+ {
+ }
+
+ virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+
+/*avert the gaze from the originator*/
+class SmXMLRowContext_Impl : public SmXMLDocContext_Impl
+{
+protected:
+ size_t nElementCount;
+
+public:
+ SmXMLRowContext_Impl(SmXMLImport& rImport)
+ : SmXMLDocContext_Impl(rImport)
+ , nElementCount(GetSmImport().GetNodeStack().size())
+ {
+ }
+
+ virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
+
+ uno::Reference<xml::sax::XFastContextHandler> StrictCreateChildContext(sal_Int32 nElement);
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+
+class SmXMLEncloseContext_Impl : public SmXMLRowContext_Impl
+{
+public:
+ // TODO/LATER: convert <menclose notation="horizontalstrike"> into
+ // "overstrike{}" and extend the Math syntax to support more notations
+ SmXMLEncloseContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+}
+
+void SmXMLEncloseContext_Impl::endFastElement(sal_Int32 nElement)
+{
+ /*
+ <menclose> accepts any number of arguments; if this number is not 1, its
+ contents are treated as a single "inferred <mrow>" containing its
+ arguments
+ */
+ if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
+ SmXMLRowContext_Impl::endFastElement(nElement);
+}
+
+namespace
+{
+class SmXMLFracContext_Impl : public SmXMLRowContext_Impl
+{
+public:
+ // TODO/LATER: convert <mfrac bevelled="true"> into "wideslash{}{}"
+ SmXMLFracContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+
+class SmXMLSqrtContext_Impl : public SmXMLRowContext_Impl
+{
+public:
+ SmXMLSqrtContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+
+class SmXMLRootContext_Impl : public SmXMLRowContext_Impl
+{
+public:
+ SmXMLRootContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+
+class SmXMLStyleContext_Impl : public SmXMLRowContext_Impl
+{
+protected:
+ SmXMLContext_Helper aStyleHelper;
+
+public:
+ /*Right now the style tag is completely ignored*/
+ SmXMLStyleContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ , aStyleHelper(*this)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+ void SAL_CALL startFastElement(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
+};
+}
+
+void SmXMLStyleContext_Impl::startFastElement(
+ sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ aStyleHelper.RetrieveAttrs(xAttrList);
+}
+
+void SmXMLStyleContext_Impl::endFastElement(sal_Int32 nElement)
+{
+ /*
+ <mstyle> accepts any number of arguments; if this number is not 1, its
+ contents are treated as a single "inferred <mrow>" containing its
+ arguments
+ */
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+ if (rNodeStack.size() - nElementCount != 1)
+ SmXMLRowContext_Impl::endFastElement(nElement);
+ aStyleHelper.ApplyAttrs();
+}
+
+namespace
+{
+class SmXMLPaddedContext_Impl : public SmXMLRowContext_Impl
+{
+public:
+ /*Right now the style tag is completely ignored*/
+ SmXMLPaddedContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+}
+
+void SmXMLPaddedContext_Impl::endFastElement(sal_Int32 nElement)
+{
+ /*
+ <mpadded> accepts any number of arguments; if this number is not 1, its
+ contents are treated as a single "inferred <mrow>" containing its
+ arguments
+ */
+ if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
+ SmXMLRowContext_Impl::endFastElement(nElement);
+}
+
+namespace
+{
+class SmXMLPhantomContext_Impl : public SmXMLRowContext_Impl
+{
+public:
+ /*Right now the style tag is completely ignored*/
+ SmXMLPhantomContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+}
+
+void SmXMLPhantomContext_Impl::endFastElement(sal_Int32 nElement)
+{
+ /*
+ <mphantom> accepts any number of arguments; if this number is not 1, its
+ contents are treated as a single "inferred <mrow>" containing its
+ arguments
+ */
+ if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
+ SmXMLRowContext_Impl::endFastElement(nElement);
+
+ SmToken aToken;
+ aToken.cMathChar = u"";
+ aToken.nLevel = 5;
+ aToken.eType = TPHANTOM;
+
+ std::unique_ptr<SmFontNode> pPhantom(new SmFontNode(aToken));
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+ pPhantom->SetSubNodes(nullptr, popOrZero(rNodeStack));
+ rNodeStack.push_front(std::move(pPhantom));
+}
+
+namespace
+{
+class SmXMLFencedContext_Impl : public SmXMLRowContext_Impl
+{
+protected:
+ sal_Unicode cBegin;
+ sal_Unicode cEnd;
+ bool bIsStretchy;
+
+public:
+ SmXMLFencedContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ , cBegin('(')
+ , cEnd(')')
+ , bIsStretchy(false)
+ {
+ }
+
+ void SAL_CALL startFastElement(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+}
+
+void SmXMLFencedContext_Impl::startFastElement(
+ sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch (aIter.getToken())
+ {
+ //temp, starmath cannot handle multichar brackets (I think)
+ case XML_OPEN:
+ cBegin = aIter.toString()[0];
+ break;
+ case XML_CLOSE:
+ cEnd = aIter.toString()[0];
+ break;
+ case XML_STRETCHY:
+ bIsStretchy = IsXMLToken(aIter, XML_TRUE);
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("starmath", aIter);
+ /*Go to superclass*/
+ break;
+ }
+ }
+}
+
+void SmXMLFencedContext_Impl::endFastElement(sal_Int32 /*nElement*/)
+{
+ SmToken aToken;
+ aToken.cMathChar = u"";
+ aToken.aText = ",";
+ aToken.nLevel = 5;
+
+ std::unique_ptr<SmStructureNode> pSNode(new SmBraceNode(aToken));
+ if (bIsStretchy)
+ aToken = starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl(cBegin);
+ else
+ aToken = starmathdatabase::Identify_Prefix_SmXMLOperatorContext_Impl(cBegin);
+ if (aToken.eType == TERROR)
+ aToken = SmToken(TLPARENT, MS_LPARENT, "(", TG::LBrace, 5);
+ std::unique_ptr<SmNode> pLeft(new SmMathSymbolNode(aToken));
+ if (bIsStretchy)
+ aToken = starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl(cEnd);
+ else
+ aToken = starmathdatabase::Identify_Postfix_SmXMLOperatorContext_Impl(cEnd);
+ if (aToken.eType == TERROR)
+ aToken = SmToken(TRPARENT, MS_RPARENT, ")", TG::LBrace, 5);
+ std::unique_ptr<SmNode> pRight(new SmMathSymbolNode(aToken));
+
+ SmNodeArray aRelationArray;
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+ aToken.cMathChar = u"";
+ aToken.eType = TIDENT;
+
+ auto i = rNodeStack.size() - nElementCount;
+ if (rNodeStack.size() - nElementCount > 1)
+ i += rNodeStack.size() - 1 - nElementCount;
+ aRelationArray.resize(i);
+ while (rNodeStack.size() > nElementCount)
+ {
+ auto pNode = std::move(rNodeStack.front());
+ rNodeStack.pop_front();
+ aRelationArray[--i] = pNode.release();
+ if (i > 1 && rNodeStack.size() > 1)
+ aRelationArray[--i] = new SmGlyphSpecialNode(aToken);
+ }
+
+ SmToken aDummy;
+ std::unique_ptr<SmStructureNode> pBody(new SmExpressionNode(aDummy));
+ pBody->SetSubNodes(std::move(aRelationArray));
+
+ pSNode->SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight));
+ // mfenced is always scalable. Stretchy keyword is not official, but in case of been in there
+ // can be used as a hint.
+ pSNode->SetScaleMode(SmScaleMode::Height);
+ GetSmImport().GetNodeStack().push_front(std::move(pSNode));
+}
+
+namespace
+{
+class SmXMLErrorContext_Impl : public SmXMLRowContext_Impl
+{
+public:
+ SmXMLErrorContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+}
+
+void SmXMLErrorContext_Impl::endFastElement(sal_Int32 /*nElement*/)
+{
+ /*Right now the error tag is completely ignored, what
+ can I do with it in starmath, ?, maybe we need a
+ report window ourselves, do a test for validity of
+ the xml input, use mirrors, and then generate
+ the markup inside the merror with a big red colour
+ of something. For now just throw them all away.
+ */
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+ while (rNodeStack.size() > nElementCount)
+ {
+ rNodeStack.pop_front();
+ }
+}
+
+namespace
+{
+class SmXMLNumberContext_Impl : public SmXMLImportContext
+{
+protected:
+ SmToken aToken;
+
+public:
+ SmXMLNumberContext_Impl(SmXMLImport& rImport)
+ : SmXMLImportContext(rImport)
+ {
+ aToken.cMathChar = u"";
+ aToken.nLevel = 5;
+ aToken.eType = TNUMBER;
+ }
+
+ virtual void TCharacters(const OUString& rChars) override;
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+}
+
+void SmXMLNumberContext_Impl::TCharacters(const OUString& rChars) { aToken.aText = rChars; }
+
+void SmXMLNumberContext_Impl::endFastElement(sal_Int32)
+{
+ GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_NUMBER));
+}
+
+namespace
+{
+class SmXMLAnnotationContext_Impl : public SmXMLImportContext
+{
+ sal_uInt8 mnStarMathVersion;
+
+public:
+ SmXMLAnnotationContext_Impl(SmXMLImport& rImport)
+ : SmXMLImportContext(rImport)
+ , mnStarMathVersion(0)
+ {
+ }
+
+ void SAL_CALL characters(const OUString& rChars) override;
+
+ void SAL_CALL startFastElement(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
+};
+}
+
+void SmXMLAnnotationContext_Impl::startFastElement(
+ sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ // sometimes they have namespace, sometimes not?
+ switch (aIter.getToken() & TOKEN_MASK)
+ {
+ case XML_ENCODING:
+ mnStarMathVersion
+ = aIter.toView() == "StarMath 5.0" ? 5 : aIter.toView() == "StarMath 6" ? 6 : 0;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("starmath", aIter);
+ break;
+ }
+ }
+}
+
+void SmXMLAnnotationContext_Impl::characters(const OUString& rChars)
+{
+ if (mnStarMathVersion)
+ {
+ GetSmImport().SetText(GetSmImport().GetText() + rChars);
+ GetSmImport().SetSmSyntaxVersion(mnStarMathVersion);
+ }
+}
+
+namespace
+{
+class SmXMLTextContext_Impl : public SmXMLImportContext
+{
+protected:
+ SmToken aToken;
+
+public:
+ SmXMLTextContext_Impl(SmXMLImport& rImport)
+ : SmXMLImportContext(rImport)
+ {
+ aToken.cMathChar = u"";
+ aToken.nLevel = 5;
+ aToken.eType = TTEXT;
+ }
+
+ virtual void TCharacters(const OUString& rChars) override;
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+}
+
+void SmXMLTextContext_Impl::TCharacters(const OUString& rChars) { aToken.aText = rChars; }
+
+void SmXMLTextContext_Impl::endFastElement(sal_Int32)
+{
+ GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_TEXT));
+}
+
+namespace
+{
+class SmXMLStringContext_Impl : public SmXMLImportContext
+{
+protected:
+ SmToken aToken;
+
+public:
+ SmXMLStringContext_Impl(SmXMLImport& rImport)
+ : SmXMLImportContext(rImport)
+ {
+ aToken.cMathChar = u"";
+ aToken.nLevel = 5;
+ aToken.eType = TTEXT;
+ }
+
+ virtual void TCharacters(const OUString& rChars) override;
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+}
+
+void SmXMLStringContext_Impl::TCharacters(const OUString& rChars)
+{
+ /*
+ The content of <ms> elements should be rendered with visible "escaping" of
+ certain characters in the content, including at least "double quote"
+ itself, and preferably whitespace other than individual blanks. The intent
+ is for the viewer to see that the expression is a string literal, and to
+ see exactly which characters form its content. For example, <ms>double
+ quote is "</ms> might be rendered as "double quote is \"".
+
+ Obviously this isn't fully done here.
+ */
+ aToken.aText = "\"" + rChars + "\"";
+}
+
+void SmXMLStringContext_Impl::endFastElement(sal_Int32)
+{
+ GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_FIXED));
+}
+
+namespace
+{
+class SmXMLIdentifierContext_Impl : public SmXMLImportContext
+{
+ SmXMLTokenAttrHelper maTokenAttrHelper;
+ SmXMLContext_Helper aStyleHelper;
+ SmToken aToken;
+
+public:
+ SmXMLIdentifierContext_Impl(SmXMLImport& rImport)
+ : SmXMLImportContext(rImport)
+ , maTokenAttrHelper(*this)
+ , aStyleHelper(*this)
+ {
+ aToken.cMathChar = u"";
+ aToken.nLevel = 5;
+ aToken.eType = TIDENT;
+ }
+
+ void TCharacters(const OUString& rChars) override;
+ void SAL_CALL
+ startFastElement(sal_Int32 /*nElement*/,
+ const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override
+ {
+ maTokenAttrHelper.RetrieveAttrs(xAttrList);
+ aStyleHelper.RetrieveAttrs(xAttrList);
+ };
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+}
+
+void SmXMLIdentifierContext_Impl::endFastElement(sal_Int32)
+{
+ std::unique_ptr<SmTextNode> pNode;
+ //we will handle identifier italic/normal here instead of with a standalone
+ //font node
+ if (((aStyleHelper.nIsItalic == -1) && (aToken.aText.getLength() > 1))
+ || ((aStyleHelper.nIsItalic == 0) && (aToken.aText.getLength() == 1)))
+ {
+ pNode.reset(new SmTextNode(aToken, FNT_FUNCTION));
+ pNode->GetFont().SetItalic(ITALIC_NONE);
+ aStyleHelper.nIsItalic = -1;
+ }
+ else
+ pNode.reset(new SmTextNode(aToken, FNT_VARIABLE));
+ if (aStyleHelper.nIsItalic != -1)
+ {
+ if (aStyleHelper.nIsItalic)
+ pNode->GetFont().SetItalic(ITALIC_NORMAL);
+ else
+ pNode->GetFont().SetItalic(ITALIC_NONE);
+ aStyleHelper.nIsItalic = -1;
+ }
+ GetSmImport().GetNodeStack().push_front(std::move(pNode));
+ aStyleHelper.ApplyAttrs();
+
+ maTokenAttrHelper.ApplyAttrs((aToken.aText.getLength() == 1) ? MathMLMathvariantValue::Italic
+ : MathMLMathvariantValue::Normal);
+}
+
+void SmXMLIdentifierContext_Impl::TCharacters(const OUString& rChars) { aToken.aText = rChars; }
+
+namespace
+{
+class SmXMLOperatorContext_Impl : public SmXMLImportContext
+{
+ SmXMLTokenAttrHelper maTokenAttrHelper;
+ bool bIsStretchy;
+ bool bIsFenced;
+ bool isPrefix;
+ bool isInfix;
+ bool isPostfix;
+ SmToken aToken;
+
+public:
+ SmXMLOperatorContext_Impl(SmXMLImport& rImport)
+ : SmXMLImportContext(rImport)
+ , maTokenAttrHelper(*this)
+ , bIsStretchy(false)
+ , bIsFenced(false)
+ , isPrefix(false)
+ , isInfix(false)
+ , isPostfix(false)
+ {
+ aToken.eType = TSPECIAL;
+ aToken.nLevel = 5;
+ }
+
+ void TCharacters(const OUString& rChars) override;
+ void SAL_CALL startFastElement(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+}
+
+void SmXMLOperatorContext_Impl::TCharacters(const OUString& rChars)
+{
+ aToken.setChar(rChars[0]);
+ SmToken bToken;
+ if (bIsFenced)
+ {
+ if (isPrefix)
+ bToken
+ = starmathdatabase::Identify_Prefix_SmXMLOperatorContext_Impl(aToken.cMathChar[0]);
+ else if (isInfix)
+ bToken = SmToken(TMLINE, MS_VERTLINE, "mline", TG::NONE, 0);
+ else if (isPostfix)
+ bToken
+ = starmathdatabase::Identify_Postfix_SmXMLOperatorContext_Impl(aToken.cMathChar[0]);
+ else
+ bToken = starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl(
+ aToken.cMathChar[0]);
+ }
+ else
+ bToken = starmathdatabase::Identify_SmXMLOperatorContext_Impl(aToken.cMathChar[0],
+ bIsStretchy);
+ if (bToken.eType != TERROR)
+ aToken = bToken;
+}
+
+void SmXMLOperatorContext_Impl::endFastElement(sal_Int32)
+{
+ std::unique_ptr<SmMathSymbolNode> pNode(new SmMathSymbolNode(aToken));
+ //For stretchy scaling the scaling must be retrieved from this node
+ //and applied to the expression itself so as to get the expression
+ //to scale the operator to the height of the expression itself
+ if (bIsStretchy)
+ pNode->SetScaleMode(SmScaleMode::Height);
+ GetSmImport().GetNodeStack().push_front(std::move(pNode));
+
+ // TODO: apply to non-alphabetic characters too
+ if (rtl::isAsciiAlpha(aToken.cMathChar[0]))
+ maTokenAttrHelper.ApplyAttrs(MathMLMathvariantValue::Normal);
+}
+
+void SmXMLOperatorContext_Impl::startFastElement(
+ sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ maTokenAttrHelper.RetrieveAttrs(xAttrList);
+
+ for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch (aIter.getToken())
+ {
+ case XML_STRETCHY:
+ bIsStretchy = IsXMLToken(aIter, XML_TRUE);
+ break;
+ case XML_FENCE:
+ bIsFenced = IsXMLToken(aIter, XML_TRUE);
+ break;
+ case XML_FORM:
+ isPrefix = IsXMLToken(aIter, XML_PREFIX); // <
+ isInfix = IsXMLToken(aIter, XML_INFIX); // |
+ isPostfix = IsXMLToken(aIter, XML_POSTFIX); // >
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("starmath", aIter);
+ break;
+ }
+ }
+}
+
+namespace
+{
+class SmXMLSpaceContext_Impl : public SmXMLImportContext
+{
+public:
+ SmXMLSpaceContext_Impl(SmXMLImport& rImport)
+ : SmXMLImportContext(rImport)
+ {
+ }
+
+ void SAL_CALL startFastElement(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
+};
+
+bool lcl_CountBlanks(const MathMLAttributeLengthValue& rLV, sal_Int32* pWide, sal_Int32* pNarrow)
+{
+ assert(pWide);
+ assert(pNarrow);
+ if (rLV.aNumber.GetNumerator() == 0)
+ {
+ *pWide = *pNarrow = 0;
+ return true;
+ }
+ // TODO: honor other units than em
+ if (rLV.eUnit != MathMLLengthUnit::Em)
+ return false;
+ if (rLV.aNumber.GetNumerator() < 0)
+ return false;
+ const Fraction aTwo(2, 1);
+ auto aWide = rLV.aNumber / aTwo;
+ auto nWide = static_cast<sal_Int32>(static_cast<tools::Long>(aWide));
+ if (nWide < 0)
+ return false;
+ const Fraction aPointFive(1, 2);
+ auto aNarrow = (rLV.aNumber - Fraction(nWide, 1) * aTwo) / aPointFive;
+ auto nNarrow = static_cast<sal_Int32>(static_cast<tools::Long>(aNarrow));
+ if (nNarrow < 0)
+ return false;
+ *pWide = nWide;
+ *pNarrow = nNarrow;
+ return true;
+}
+}
+
+void SmXMLSpaceContext_Impl::startFastElement(
+ sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ // There is no syntax in Math to specify blank nodes of arbitrary size yet.
+ MathMLAttributeLengthValue aLV;
+ sal_Int32 nWide = 0, nNarrow = 0;
+
+ for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ OUString sValue = aIter.toString();
+ switch (aIter.getToken())
+ {
+ case XML_WIDTH:
+ if (!ParseMathMLAttributeLengthValue(o3tl::trim(sValue), aLV)
+ || !lcl_CountBlanks(aLV, &nWide, &nNarrow))
+ SAL_WARN("starmath", "ignore mspace's width: " << sValue);
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("starmath", aIter);
+ break;
+ }
+ }
+ SmToken aToken;
+ aToken.eType = TBLANK;
+ aToken.cMathChar = u"";
+ aToken.nGroup = TG::Blank;
+ aToken.nLevel = 5;
+ std::unique_ptr<SmBlankNode> pBlank(new SmBlankNode(aToken));
+ if (nWide > 0)
+ pBlank->IncreaseBy(aToken, nWide);
+ if (nNarrow > 0)
+ {
+ aToken.eType = TSBLANK;
+ pBlank->IncreaseBy(aToken, nNarrow);
+ }
+ GetSmImport().GetNodeStack().push_front(std::move(pBlank));
+}
+
+namespace
+{
+class SmXMLSubContext_Impl : public SmXMLRowContext_Impl
+{
+protected:
+ void GenericEndElement(SmTokenType eType, SmSubSup aSubSup);
+
+public:
+ SmXMLSubContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TRSUB, RSUB); }
+};
+}
+
+void SmXMLSubContext_Impl::GenericEndElement(SmTokenType eType, SmSubSup eSubSup)
+{
+ /*The <msub> element requires exactly 2 arguments.*/
+ const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
+ OSL_ENSURE(bNodeCheck, "Sub has not two arguments");
+ if (!bNodeCheck)
+ return;
+
+ SmToken aToken;
+ aToken.cMathChar = u"";
+ aToken.eType = eType;
+ std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+
+ // initialize subnodes array
+ SmNodeArray aSubNodes;
+ aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
+ for (size_t i = 1; i < aSubNodes.size(); i++)
+ aSubNodes[i] = nullptr;
+
+ aSubNodes[eSubSup + 1] = popOrZero(rNodeStack).release();
+ aSubNodes[0] = popOrZero(rNodeStack).release();
+ pNode->SetSubNodes(std::move(aSubNodes));
+ rNodeStack.push_front(std::move(pNode));
+}
+
+namespace
+{
+class SmXMLSupContext_Impl : public SmXMLSubContext_Impl
+{
+public:
+ SmXMLSupContext_Impl(SmXMLImport& rImport)
+ : SmXMLSubContext_Impl(rImport)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TRSUP, RSUP); }
+};
+
+class SmXMLSubSupContext_Impl : public SmXMLRowContext_Impl
+{
+protected:
+ void GenericEndElement(SmTokenType eType, SmSubSup aSub, SmSubSup aSup);
+
+public:
+ SmXMLSubSupContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TRSUB, RSUB, RSUP); }
+};
+}
+
+void SmXMLSubSupContext_Impl::GenericEndElement(SmTokenType eType, SmSubSup aSub, SmSubSup aSup)
+{
+ /*The <msub> element requires exactly 3 arguments.*/
+ const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 3;
+ OSL_ENSURE(bNodeCheck, "SubSup has not three arguments");
+ if (!bNodeCheck)
+ return;
+
+ SmToken aToken;
+ aToken.cMathChar = u"";
+ aToken.eType = eType;
+ std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+
+ // initialize subnodes array
+ SmNodeArray aSubNodes;
+ aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
+ for (size_t i = 1; i < aSubNodes.size(); i++)
+ aSubNodes[i] = nullptr;
+
+ aSubNodes[aSup + 1] = popOrZero(rNodeStack).release();
+ aSubNodes[aSub + 1] = popOrZero(rNodeStack).release();
+ aSubNodes[0] = popOrZero(rNodeStack).release();
+ pNode->SetSubNodes(std::move(aSubNodes));
+ rNodeStack.push_front(std::move(pNode));
+}
+
+namespace
+{
+class SmXMLUnderContext_Impl : public SmXMLSubContext_Impl
+{
+protected:
+ sal_Int16 nAttrCount;
+
+public:
+ SmXMLUnderContext_Impl(SmXMLImport& rImport)
+ : SmXMLSubContext_Impl(rImport)
+ , nAttrCount(0)
+ {
+ }
+
+ void SAL_CALL startFastElement(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+ void HandleAccent();
+};
+}
+
+void SmXMLUnderContext_Impl::startFastElement(
+ sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ sax_fastparser::FastAttributeList& rAttribList
+ = sax_fastparser::castToFastAttributeList(xAttrList);
+ nAttrCount = rAttribList.getFastAttributeTokens().size();
+}
+
+void SmXMLUnderContext_Impl::HandleAccent()
+{
+ const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
+ OSL_ENSURE(bNodeCheck, "Sub has not two arguments");
+ if (!bNodeCheck)
+ return;
+
+ /*Just one special case for the underline thing*/
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+ std::unique_ptr<SmNode> pTest = popOrZero(rNodeStack);
+ SmToken aToken;
+ aToken.cMathChar = u"";
+ aToken.eType = TUNDERLINE;
+
+ std::unique_ptr<SmNode> pFirst;
+ std::unique_ptr<SmStructureNode> pNode(new SmAttributeNode(aToken));
+ if ((pTest->GetToken().cMathChar[0] & 0x0FFF) == 0x0332)
+ {
+ pFirst.reset(new SmRectangleNode(aToken));
+ }
+ else
+ pFirst = std::move(pTest);
+
+ std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack);
+ pNode->SetSubNodes(std::move(pFirst), std::move(pSecond));
+ pNode->SetScaleMode(SmScaleMode::Width);
+ rNodeStack.push_front(std::move(pNode));
+}
+
+void SmXMLUnderContext_Impl::endFastElement(sal_Int32)
+{
+ if (!nAttrCount)
+ GenericEndElement(TCSUB, CSUB);
+ else
+ HandleAccent();
+}
+
+namespace
+{
+class SmXMLOverContext_Impl : public SmXMLSubContext_Impl
+{
+protected:
+ sal_Int16 nAttrCount;
+
+public:
+ SmXMLOverContext_Impl(SmXMLImport& rImport)
+ : SmXMLSubContext_Impl(rImport)
+ , nAttrCount(0)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+ void SAL_CALL startFastElement(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
+ void HandleAccent();
+};
+}
+
+void SmXMLOverContext_Impl::startFastElement(
+ sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ sax_fastparser::FastAttributeList& rAttribList
+ = sax_fastparser::castToFastAttributeList(xAttrList);
+ nAttrCount = rAttribList.getFastAttributeTokens().size();
+}
+
+void SmXMLOverContext_Impl::endFastElement(sal_Int32)
+{
+ if (!nAttrCount)
+ GenericEndElement(TCSUP, CSUP);
+ else
+ HandleAccent();
+}
+
+void SmXMLOverContext_Impl::HandleAccent()
+{
+ const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
+ OSL_ENSURE(bNodeCheck, "Sub has not two arguments");
+ if (!bNodeCheck)
+ return;
+
+ SmToken aToken;
+ aToken.cMathChar = u"";
+ aToken.eType = TACUTE;
+
+ std::unique_ptr<SmAttributeNode> pNode(new SmAttributeNode(aToken));
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+
+ std::unique_ptr<SmNode> pFirst = popOrZero(rNodeStack);
+ std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack);
+ pNode->SetSubNodes(std::move(pFirst), std::move(pSecond));
+ pNode->SetScaleMode(SmScaleMode::Width);
+ rNodeStack.push_front(std::move(pNode));
+}
+
+namespace
+{
+class SmXMLUnderOverContext_Impl : public SmXMLSubSupContext_Impl
+{
+public:
+ SmXMLUnderOverContext_Impl(SmXMLImport& rImport)
+ : SmXMLSubSupContext_Impl(rImport)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TCSUB, CSUB, CSUP); }
+};
+
+class SmXMLMultiScriptsContext_Impl : public SmXMLSubSupContext_Impl
+{
+ bool bHasPrescripts;
+
+ void ProcessSubSupPairs(bool bIsPrescript);
+
+public:
+ SmXMLMultiScriptsContext_Impl(SmXMLImport& rImport)
+ : SmXMLSubSupContext_Impl(rImport)
+ , bHasPrescripts(false)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+ virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
+};
+
+class SmXMLNoneContext_Impl : public SmXMLImportContext
+{
+public:
+ SmXMLNoneContext_Impl(SmXMLImport& rImport)
+ : SmXMLImportContext(rImport)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+}
+
+void SmXMLNoneContext_Impl::endFastElement(sal_Int32)
+{
+ SmToken aToken;
+ aToken.cMathChar = u"";
+ aToken.aText.clear();
+ aToken.nLevel = 5;
+ aToken.eType = TIDENT;
+ GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_VARIABLE));
+}
+
+namespace
+{
+class SmXMLPrescriptsContext_Impl : public SmXMLImportContext
+{
+public:
+ SmXMLPrescriptsContext_Impl(SmXMLImport& rImport)
+ : SmXMLImportContext(rImport)
+ {
+ }
+};
+
+class SmXMLTableRowContext_Impl : public SmXMLRowContext_Impl
+{
+public:
+ SmXMLTableRowContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ {
+ }
+
+ virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
+};
+
+class SmXMLTableContext_Impl : public SmXMLTableRowContext_Impl
+{
+public:
+ SmXMLTableContext_Impl(SmXMLImport& rImport)
+ : SmXMLTableRowContext_Impl(rImport)
+ {
+ }
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+ virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
+};
+
+class SmXMLTableCellContext_Impl : public SmXMLRowContext_Impl
+{
+public:
+ SmXMLTableCellContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ {
+ }
+};
+
+class SmXMLAlignGroupContext_Impl : public SmXMLRowContext_Impl
+{
+public:
+ SmXMLAlignGroupContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ {
+ }
+
+ /*Don't do anything with alignment for now*/
+};
+
+class SmXMLActionContext_Impl : public SmXMLRowContext_Impl
+{
+ size_t mnSelection; // 1-based
+
+public:
+ SmXMLActionContext_Impl(SmXMLImport& rImport)
+ : SmXMLRowContext_Impl(rImport)
+ , mnSelection(1)
+ {
+ }
+
+ void SAL_CALL startFastElement(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+
+// NB: virtually inherit so we can multiply inherit properly
+// in SmXMLFlatDocContext_Impl
+class SmXMLOfficeContext_Impl : public virtual SvXMLImportContext
+{
+public:
+ SmXMLOfficeContext_Impl(SmXMLImport& rImport)
+ : SvXMLImportContext(rImport)
+ {
+ }
+
+ virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList) override;
+};
+}
+
+uno::Reference<xml::sax::XFastContextHandler> SmXMLOfficeContext_Impl::createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
+{
+ if (nElement == XML_ELEMENT(OFFICE, XML_META))
+ {
+ SAL_WARN("starmath",
+ "XML_TOK_DOC_META: should not have come here, maybe document is invalid?");
+ }
+ else if (nElement == XML_ELEMENT(OFFICE, XML_SETTINGS))
+ {
+ return new XMLDocumentSettingsContext(GetImport());
+ }
+ return nullptr;
+}
+
+namespace
+{
+// context for flat file xml format
+class SmXMLFlatDocContext_Impl : public SmXMLOfficeContext_Impl, public SvXMLMetaDocumentContext
+{
+public:
+ SmXMLFlatDocContext_Impl(SmXMLImport& i_rImport,
+ const uno::Reference<document::XDocumentProperties>& i_xDocProps);
+
+ virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList) override;
+};
+}
+
+SmXMLFlatDocContext_Impl::SmXMLFlatDocContext_Impl(
+ SmXMLImport& i_rImport, const uno::Reference<document::XDocumentProperties>& i_xDocProps)
+ : SvXMLImportContext(i_rImport)
+ , SmXMLOfficeContext_Impl(i_rImport)
+ , SvXMLMetaDocumentContext(i_rImport, i_xDocProps)
+{
+}
+
+uno::Reference<xml::sax::XFastContextHandler>
+ SAL_CALL SmXMLFlatDocContext_Impl::createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ // behave like meta base class iff we encounter office:meta
+ if (nElement == XML_ELEMENT(OFFICE, XML_META))
+ {
+ return SvXMLMetaDocumentContext::createFastChildContext(nElement, xAttrList);
+ }
+ else
+ {
+ return SmXMLOfficeContext_Impl::createFastChildContext(nElement, xAttrList);
+ }
+}
+
+uno::Reference<xml::sax::XFastContextHandler> SmXMLDocContext_Impl::createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
+{
+ uno::Reference<xml::sax::XFastContextHandler> xContext;
+
+ switch (nElement)
+ {
+ //Consider semantics a dummy except for any starmath annotations
+ case XML_ELEMENT(MATH, XML_SEMANTICS):
+ xContext = new SmXMLRowContext_Impl(GetSmImport());
+ break;
+ /*General Layout Schemata*/
+ case XML_ELEMENT(MATH, XML_MROW):
+ xContext = new SmXMLRowContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MENCLOSE):
+ xContext = new SmXMLEncloseContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MFRAC):
+ xContext = new SmXMLFracContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MSQRT):
+ xContext = new SmXMLSqrtContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MROOT):
+ xContext = new SmXMLRootContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MSTYLE):
+ xContext = new SmXMLStyleContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MERROR):
+ xContext = new SmXMLErrorContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MPADDED):
+ xContext = new SmXMLPaddedContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MPHANTOM):
+ xContext = new SmXMLPhantomContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MFENCED):
+ xContext = new SmXMLFencedContext_Impl(GetSmImport());
+ break;
+ /*Script and Limit Schemata*/
+ case XML_ELEMENT(MATH, XML_MSUB):
+ xContext = new SmXMLSubContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MSUP):
+ xContext = new SmXMLSupContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MSUBSUP):
+ xContext = new SmXMLSubSupContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MUNDER):
+ xContext = new SmXMLUnderContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MOVER):
+ xContext = new SmXMLOverContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MUNDEROVER):
+ xContext = new SmXMLUnderOverContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MMULTISCRIPTS):
+ xContext = new SmXMLMultiScriptsContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MTABLE):
+ xContext = new SmXMLTableContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MACTION):
+ xContext = new SmXMLActionContext_Impl(GetSmImport());
+ break;
+ default:
+ /*Basically there's an implicit mrow around certain bare
+ *elements, use a RowContext to see if this is one of
+ *those ones*/
+ rtl::Reference<SmXMLRowContext_Impl> aTempContext(
+ new SmXMLRowContext_Impl(GetSmImport()));
+
+ xContext = aTempContext->StrictCreateChildContext(nElement);
+ break;
+ }
+ return xContext;
+}
+
+void SmXMLDocContext_Impl::endFastElement(sal_Int32)
+{
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+
+ std::unique_ptr<SmNode> pContextNode = popOrZero(rNodeStack);
+
+ SmToken aDummy;
+ std::unique_ptr<SmStructureNode> pSNode(new SmLineNode(aDummy));
+ pSNode->SetSubNodes(std::move(pContextNode), nullptr);
+ rNodeStack.push_front(std::move(pSNode));
+
+ SmNodeArray LineArray;
+ auto n = rNodeStack.size();
+ LineArray.resize(n);
+ for (size_t j = 0; j < n; j++)
+ {
+ auto pNode = std::move(rNodeStack.front());
+ rNodeStack.pop_front();
+ LineArray[n - (j + 1)] = pNode.release();
+ }
+ std::unique_ptr<SmStructureNode> pSNode2(new SmTableNode(aDummy));
+ pSNode2->SetSubNodes(std::move(LineArray));
+ rNodeStack.push_front(std::move(pSNode2));
+}
+
+void SmXMLFracContext_Impl::endFastElement(sal_Int32)
+{
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+ const bool bNodeCheck = rNodeStack.size() - nElementCount == 2;
+ OSL_ENSURE(bNodeCheck, "Fraction (mfrac) tag is missing component");
+ if (!bNodeCheck)
+ return;
+
+ SmToken aToken;
+ aToken.cMathChar = u"";
+ aToken.eType = TFRAC;
+ std::unique_ptr<SmStructureNode> pSNode(new SmBinVerNode(aToken));
+ std::unique_ptr<SmNode> pOper(new SmRectangleNode(aToken));
+ std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack);
+ std::unique_ptr<SmNode> pFirst = popOrZero(rNodeStack);
+ pSNode->SetSubNodes(std::move(pFirst), std::move(pOper), std::move(pSecond));
+ rNodeStack.push_front(std::move(pSNode));
+}
+
+void SmXMLRootContext_Impl::endFastElement(sal_Int32)
+{
+ /*The <mroot> element requires exactly 2 arguments.*/
+ const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
+ OSL_ENSURE(bNodeCheck, "Root tag is missing component");
+ if (!bNodeCheck)
+ return;
+
+ SmToken aToken;
+ aToken.setChar(MS_SQRT); //Temporary: alert, based on StarSymbol font
+ aToken.eType = TNROOT;
+ std::unique_ptr<SmStructureNode> pSNode(new SmRootNode(aToken));
+ std::unique_ptr<SmNode> pOper(new SmRootSymbolNode(aToken));
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+ std::unique_ptr<SmNode> pIndex = popOrZero(rNodeStack);
+ std::unique_ptr<SmNode> pBase = popOrZero(rNodeStack);
+ pSNode->SetSubNodes(std::move(pIndex), std::move(pOper), std::move(pBase));
+ rNodeStack.push_front(std::move(pSNode));
+}
+
+void SmXMLSqrtContext_Impl::endFastElement(sal_Int32 nElement)
+{
+ /*
+ <msqrt> accepts any number of arguments; if this number is not 1, its
+ contents are treated as a single "inferred <mrow>" containing its
+ arguments
+ */
+ if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
+ SmXMLRowContext_Impl::endFastElement(nElement);
+
+ SmToken aToken;
+ aToken.setChar(MS_SQRT); //Temporary: alert, based on StarSymbol font
+ aToken.eType = TSQRT;
+ std::unique_ptr<SmStructureNode> pSNode(new SmRootNode(aToken));
+ std::unique_ptr<SmNode> pOper(new SmRootSymbolNode(aToken));
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+ pSNode->SetSubNodes(nullptr, std::move(pOper), popOrZero(rNodeStack));
+ rNodeStack.push_front(std::move(pSNode));
+}
+
+void SmXMLRowContext_Impl::endFastElement(sal_Int32)
+{
+ SmNodeArray aRelationArray;
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+
+ if (rNodeStack.size() > nElementCount)
+ {
+ auto nSize = rNodeStack.size() - nElementCount;
+
+ aRelationArray.resize(nSize);
+ for (auto j = nSize; j > 0; j--)
+ {
+ auto pNode = std::move(rNodeStack.front());
+ rNodeStack.pop_front();
+ aRelationArray[j - 1] = pNode.release();
+ }
+
+ //If the first or last element is an operator with stretchyness
+ //set then we must create a brace node here from those elements,
+ //removing the stretchness from the operators and applying it to
+ //ourselves, and creating the appropriate dummy StarMath none bracket
+ //to balance the arrangement
+ if (((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height)
+ && (aRelationArray[0]->GetType() == SmNodeType::Math))
+ || ((aRelationArray[nSize - 1]->GetScaleMode() == SmScaleMode::Height)
+ && (aRelationArray[nSize - 1]->GetType() == SmNodeType::Math)))
+ {
+ SmToken aToken;
+ aToken.cMathChar = u"";
+ aToken.nLevel = 5;
+
+ int nLeft = 0, nRight = 0;
+ if ((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height)
+ && (aRelationArray[0]->GetType() == SmNodeType::Math))
+ {
+ aToken = aRelationArray[0]->GetToken();
+ nLeft = 1;
+ }
+ else
+ aToken.cMathChar = u"";
+
+ aToken.eType = TLPARENT;
+ std::unique_ptr<SmNode> pLeft(new SmMathSymbolNode(aToken));
+
+ if ((aRelationArray[nSize - 1]->GetScaleMode() == SmScaleMode::Height)
+ && (aRelationArray[nSize - 1]->GetType() == SmNodeType::Math))
+ {
+ aToken = aRelationArray[nSize - 1]->GetToken();
+ nRight = 1;
+ }
+ else
+ aToken.cMathChar = u"";
+
+ aToken.eType = TRPARENT;
+ std::unique_ptr<SmNode> pRight(new SmMathSymbolNode(aToken));
+
+ SmNodeArray aRelationArray2;
+
+ //!! nSize-nLeft-nRight may be < 0 !!
+ int nRelArrSize = nSize - nLeft - nRight;
+ if (nRelArrSize > 0)
+ {
+ aRelationArray2.resize(nRelArrSize);
+ for (int i = 0; i < nRelArrSize; i++)
+ {
+ aRelationArray2[i] = aRelationArray[i + nLeft];
+ aRelationArray[i + nLeft] = nullptr;
+ }
+ }
+
+ SmToken aDummy;
+ std::unique_ptr<SmStructureNode> pSNode(new SmBraceNode(aToken));
+ std::unique_ptr<SmStructureNode> pBody(new SmExpressionNode(aDummy));
+ pBody->SetSubNodes(std::move(aRelationArray2));
+
+ pSNode->SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight));
+ pSNode->SetScaleMode(SmScaleMode::Height);
+ rNodeStack.push_front(std::move(pSNode));
+
+ for (auto a : aRelationArray)
+ delete a;
+
+ return;
+ }
+ }
+ else
+ {
+ // The elements msqrt, mstyle, merror, menclose, mpadded, mphantom, mtd, and math
+ // treat their content as a single inferred mrow in case their content is empty.
+ // Here an empty group {} is used to catch those cases and transform them without error
+ // to StarMath.
+ aRelationArray.resize(2);
+ SmToken aToken;
+ aToken.setChar(MS_LBRACE);
+ aToken.nLevel = 5;
+ aToken.eType = TLGROUP;
+ aToken.nGroup = TG::NONE;
+ aToken.aText = "{";
+ aRelationArray[0] = new SmLineNode(aToken);
+
+ aToken.setChar(MS_RBRACE);
+ aToken.nLevel = 0;
+ aToken.eType = TRGROUP;
+ aToken.nGroup = TG::NONE;
+ aToken.aText = "}";
+ aRelationArray[1] = new SmLineNode(aToken);
+ }
+
+ SmToken aDummy;
+ std::unique_ptr<SmStructureNode> pSNode(new SmExpressionNode(aDummy));
+ pSNode->SetSubNodes(std::move(aRelationArray));
+ rNodeStack.push_front(std::move(pSNode));
+}
+
+uno::Reference<xml::sax::XFastContextHandler>
+SmXMLRowContext_Impl::StrictCreateChildContext(sal_Int32 nElement)
+{
+ uno::Reference<xml::sax::XFastContextHandler> pContext;
+
+ switch (nElement)
+ {
+ /*Note that these should accept malignmark subelements, but do not*/
+ case XML_ELEMENT(MATH, XML_MN):
+ pContext = new SmXMLNumberContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MI):
+ pContext = new SmXMLIdentifierContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MO):
+ pContext = new SmXMLOperatorContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MTEXT):
+ pContext = new SmXMLTextContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MSPACE):
+ pContext = new SmXMLSpaceContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_MS):
+ pContext = new SmXMLStringContext_Impl(GetSmImport());
+ break;
+
+ /*Note: The maligngroup should only be seen when the row
+ * (or descendants) are in a table*/
+ case XML_ELEMENT(MATH, XML_MALIGNGROUP):
+ pContext = new SmXMLAlignGroupContext_Impl(GetSmImport());
+ break;
+
+ case XML_ELEMENT(MATH, XML_ANNOTATION):
+ pContext = new SmXMLAnnotationContext_Impl(GetSmImport());
+ break;
+
+ default:
+ break;
+ }
+ return pContext;
+}
+
+uno::Reference<xml::sax::XFastContextHandler> SmXMLRowContext_Impl::createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ uno::Reference<xml::sax::XFastContextHandler> xContext = StrictCreateChildContext(nElement);
+
+ if (!xContext)
+ {
+ //Hmm, unrecognized for this level, check to see if it's
+ //an element that can have an implicit schema around it
+ xContext = SmXMLDocContext_Impl::createFastChildContext(nElement, xAttrList);
+ }
+ return xContext;
+}
+
+uno::Reference<xml::sax::XFastContextHandler> SmXMLMultiScriptsContext_Impl::createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ uno::Reference<xml::sax::XFastContextHandler> xContext;
+
+ switch (nElement)
+ {
+ case XML_ELEMENT(MATH, XML_MPRESCRIPTS):
+ bHasPrescripts = true;
+ ProcessSubSupPairs(false);
+ xContext = new SmXMLPrescriptsContext_Impl(GetSmImport());
+ break;
+ case XML_ELEMENT(MATH, XML_NONE):
+ xContext = new SmXMLNoneContext_Impl(GetSmImport());
+ break;
+ default:
+ xContext = SmXMLRowContext_Impl::createFastChildContext(nElement, xAttrList);
+ break;
+ }
+ return xContext;
+}
+
+void SmXMLMultiScriptsContext_Impl::ProcessSubSupPairs(bool bIsPrescript)
+{
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+
+ if (rNodeStack.size() <= nElementCount)
+ return;
+
+ auto nCount = rNodeStack.size() - nElementCount - 1;
+ if (nCount == 0)
+ return;
+
+ if (nCount % 2 == 0)
+ {
+ SmToken aToken;
+ aToken.cMathChar = u"";
+ aToken.eType = bIsPrescript ? TLSUB : TRSUB;
+
+ SmNodeStack aReverseStack;
+ for (size_t i = 0; i < nCount + 1; i++)
+ {
+ auto pNode = std::move(rNodeStack.front());
+ rNodeStack.pop_front();
+ aReverseStack.push_front(std::move(pNode));
+ }
+
+ SmSubSup eSub = bIsPrescript ? LSUB : RSUB;
+ SmSubSup eSup = bIsPrescript ? LSUP : RSUP;
+
+ for (size_t i = 0; i < nCount; i += 2)
+ {
+ std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
+
+ // initialize subnodes array
+ SmNodeArray aSubNodes(1 + SUBSUP_NUM_ENTRIES);
+
+ /*On each loop the base and its sub sup pair becomes the
+ base for the next loop to which the next sub sup pair is
+ attached, i.e. wheels within wheels*/
+ aSubNodes[0] = popOrZero(aReverseStack).release();
+
+ std::unique_ptr<SmNode> pScriptNode = popOrZero(aReverseStack);
+
+ if (pScriptNode
+ && ((pScriptNode->GetToken().eType != TIDENT)
+ || (!pScriptNode->GetToken().aText.isEmpty())))
+ aSubNodes[eSub + 1] = pScriptNode.release();
+ pScriptNode = popOrZero(aReverseStack);
+ if (pScriptNode
+ && ((pScriptNode->GetToken().eType != TIDENT)
+ || (!pScriptNode->GetToken().aText.isEmpty())))
+ aSubNodes[eSup + 1] = pScriptNode.release();
+
+ pNode->SetSubNodes(std::move(aSubNodes));
+ aReverseStack.push_front(std::move(pNode));
+ }
+ assert(!aReverseStack.empty());
+ auto pNode = std::move(aReverseStack.front());
+ aReverseStack.pop_front();
+ rNodeStack.push_front(std::move(pNode));
+ }
+ else
+ {
+ // Ignore odd number of elements.
+ for (size_t i = 0; i < nCount; i++)
+ {
+ rNodeStack.pop_front();
+ }
+ }
+}
+
+void SmXMLTableContext_Impl::endFastElement(sal_Int32)
+{
+ SmNodeArray aExpressionArray;
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+ SmNodeStack aReverseStack;
+ aExpressionArray.resize(rNodeStack.size() - nElementCount);
+
+ size_t nRows = rNodeStack.size() - nElementCount;
+ size_t nCols = 0;
+
+ for (size_t i = nRows; i > 0; --i)
+ {
+ SmNode* pArray = rNodeStack.front().release();
+ rNodeStack.pop_front();
+ if (pArray->GetNumSubNodes() == 0)
+ {
+ //This is a little tricky, it is possible that there was
+ //be elements that were not inside a <mtd> pair, in which
+ //case they will not be in a row, i.e. they will not have
+ //SubNodes, so we have to wait until here before we can
+ //resolve the situation. Implicit surrounding tags are
+ //surprisingly difficult to get right within this
+ //architecture
+
+ SmNodeArray aRelationArray;
+ aRelationArray.resize(1);
+ aRelationArray[0] = pArray;
+ SmToken aDummy;
+ SmExpressionNode* pExprNode = new SmExpressionNode(aDummy);
+ pExprNode->SetSubNodes(std::move(aRelationArray));
+ pArray = pExprNode;
+ }
+
+ nCols = std::max(nCols, pArray->GetNumSubNodes());
+ aReverseStack.push_front(std::unique_ptr<SmNode>(pArray));
+ }
+ if (nCols > SAL_MAX_UINT16)
+ throw std::range_error("column limit");
+ if (nRows > SAL_MAX_UINT16)
+ throw std::range_error("row limit");
+ aExpressionArray.resize(nCols * nRows);
+ size_t j = 0;
+ for (auto& elem : aReverseStack)
+ {
+ std::unique_ptr<SmStructureNode> xArray(static_cast<SmStructureNode*>(elem.release()));
+ for (size_t i = 0; i < xArray->GetNumSubNodes(); ++i)
+ aExpressionArray[j++] = xArray->GetSubNode(i);
+ xArray->ClearSubNodes();
+ }
+ aReverseStack.clear();
+
+ SmToken aToken;
+ aToken.cMathChar = u"";
+ aToken.eType = TMATRIX;
+ std::unique_ptr<SmMatrixNode> pSNode(new SmMatrixNode(aToken));
+ pSNode->SetSubNodes(std::move(aExpressionArray));
+ pSNode->SetRowCol(nRows, nCols);
+ rNodeStack.push_front(std::move(pSNode));
+}
+
+uno::Reference<xml::sax::XFastContextHandler> SmXMLTableRowContext_Impl::createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ uno::Reference<xml::sax::XFastContextHandler> xContext;
+
+ switch (nElement)
+ {
+ case XML_ELEMENT(MATH, XML_MTD):
+ xContext = new SmXMLTableCellContext_Impl(GetSmImport());
+ break;
+ default:
+ xContext = SmXMLRowContext_Impl::createFastChildContext(nElement, xAttrList);
+ break;
+ }
+ return xContext;
+}
+
+uno::Reference<xml::sax::XFastContextHandler> SmXMLTableContext_Impl::createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ uno::Reference<xml::sax::XFastContextHandler> xContext;
+
+ switch (nElement)
+ {
+ case XML_ELEMENT(MATH, XML_MTR):
+ xContext = new SmXMLTableRowContext_Impl(GetSmImport());
+ break;
+ default:
+ xContext = SmXMLTableRowContext_Impl::createFastChildContext(nElement, xAttrList);
+ break;
+ }
+ return xContext;
+}
+
+void SmXMLMultiScriptsContext_Impl::endFastElement(sal_Int32)
+{
+ ProcessSubSupPairs(bHasPrescripts);
+}
+
+void SmXMLActionContext_Impl::startFastElement(
+ sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch (aIter.getToken())
+ {
+ case XML_SELECTION:
+ {
+ sal_Int32 n = aIter.toInt32();
+ if (n > 0)
+ mnSelection = static_cast<size_t>(n);
+ }
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("starmath", aIter);
+ break;
+ }
+ }
+}
+
+void SmXMLActionContext_Impl::endFastElement(sal_Int32)
+{
+ SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
+ auto nSize = rNodeStack.size();
+ if (nSize <= nElementCount)
+ {
+ // not compliant to maction's specification, e.g., no subexpressions
+ return;
+ }
+ assert(mnSelection > 0);
+ if (nSize < nElementCount + mnSelection)
+ {
+ // No selected subexpression exists, which is a MathML error;
+ // fallback to selecting the first
+ mnSelection = 1;
+ }
+ assert(nSize >= nElementCount + mnSelection);
+ for (auto i = nSize - (nElementCount + mnSelection); i > 0; i--)
+ {
+ rNodeStack.pop_front();
+ }
+ auto pSelected = std::move(rNodeStack.front());
+ rNodeStack.pop_front();
+ for (auto i = rNodeStack.size() - nElementCount; i > 0; i--)
+ {
+ rNodeStack.pop_front();
+ }
+ rNodeStack.push_front(std::move(pSelected));
+}
+
+SvXMLImportContext*
+SmXMLImport::CreateFastContext(sal_Int32 nElement,
+ const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
+{
+ SvXMLImportContext* pContext = nullptr;
+
+ switch (nElement)
+ {
+ case XML_ELEMENT(OFFICE, XML_DOCUMENT):
+ case XML_ELEMENT(OFFICE, XML_DOCUMENT_META):
+ {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(),
+ uno::UNO_QUERY_THROW);
+ pContext = ((nElement & TOKEN_MASK) == XML_DOCUMENT_META)
+ ? new SvXMLMetaDocumentContext(*this, xDPS->getDocumentProperties())
+ // flat OpenDocument file format -- this has not been tested...
+ : new SmXMLFlatDocContext_Impl(*this, xDPS->getDocumentProperties());
+ }
+ break;
+ default:
+ if (IsTokenInNamespace(nElement, XML_NAMESPACE_OFFICE))
+ pContext = new SmXMLOfficeContext_Impl(*this);
+ else
+ pContext = new SmXMLDocContext_Impl(*this);
+ }
+ return pContext;
+}
+
+SmXMLImport::~SmXMLImport() noexcept { cleanup(); }
+
+void SmXMLImport::SetViewSettings(const Sequence<PropertyValue>& aViewProps)
+{
+ uno::Reference<frame::XModel> xModel = GetModel();
+ if (!xModel.is())
+ return;
+
+ SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel);
+
+ if (!pModel)
+ return;
+
+ SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
+ if (!pDocShell)
+ return;
+
+ tools::Rectangle aRect(pDocShell->GetVisArea());
+
+ tools::Long nTmp = 0;
+
+ for (const PropertyValue& rValue : aViewProps)
+ {
+ if (rValue.Name == "ViewAreaTop")
+ {
+ rValue.Value >>= nTmp;
+ aRect.SaturatingSetPosY(nTmp);
+ }
+ else if (rValue.Name == "ViewAreaLeft")
+ {
+ rValue.Value >>= nTmp;
+ aRect.SaturatingSetPosX(nTmp);
+ }
+ else if (rValue.Name == "ViewAreaWidth")
+ {
+ rValue.Value >>= nTmp;
+ Size aSize(aRect.GetSize());
+ aSize.setWidth(nTmp);
+ aRect.SaturatingSetSize(aSize);
+ }
+ else if (rValue.Name == "ViewAreaHeight")
+ {
+ rValue.Value >>= nTmp;
+ Size aSize(aRect.GetSize());
+ aSize.setHeight(nTmp);
+ aRect.SaturatingSetSize(aSize);
+ }
+ }
+
+ pDocShell->SetVisArea(aRect);
+}
+
+void SmXMLImport::SetConfigurationSettings(const Sequence<PropertyValue>& aConfProps)
+{
+ uno::Reference<XPropertySet> xProps(GetModel(), UNO_QUERY);
+ if (!xProps.is())
+ return;
+
+ Reference<XPropertySetInfo> xInfo(xProps->getPropertySetInfo());
+ if (!xInfo.is())
+ return;
+
+ static const OUStringLiteral sFormula(u"Formula");
+ static const OUStringLiteral sBasicLibraries(u"BasicLibraries");
+ static const OUStringLiteral sDialogLibraries(u"DialogLibraries");
+ for (const PropertyValue& rValue : aConfProps)
+ {
+ if (rValue.Name != sFormula && rValue.Name != sBasicLibraries
+ && rValue.Name != sDialogLibraries)
+ {
+ try
+ {
+ if (xInfo->hasPropertyByName(rValue.Name))
+ xProps->setPropertyValue(rValue.Name, rValue.Value);
+ }
+ catch (const beans::PropertyVetoException&)
+ {
+ // dealing with read-only properties here. Nothing to do...
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("starmath");
+ }
+ }
+ }
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportMML(SvStream& rStream)
+{
+ SmGlobals::ensure();
+
+ SfxObjectShellLock xDocSh(new SmDocShell(SfxModelFlags::EMBEDDED_OBJECT));
+ xDocSh->DoInitNew();
+ uno::Reference<frame::XModel> xModel(xDocSh->GetModel());
+
+ uno::Reference<beans::XPropertySet> xInfoSet;
+ uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
+ uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
+
+ //SetLoading hack because the document properties will be re-initted
+ //by the xml filter and during the init, while it's considered uninitialized,
+ //setting a property will inform the document it's modified, which attempts
+ //to update the properties, which throws cause the properties are uninitialized
+ xDocSh->SetLoading(SfxLoadedFlags::NONE);
+
+ ErrCode nRet = ERRCODE_SFX_DOLOADFAILED;
+
+ try
+ {
+ nRet = SmXMLImportWrapper::ReadThroughComponent(xStream, xModel, xContext, xInfoSet,
+ "com.sun.star.comp.Math.XMLImporter", false,
+ false);
+ }
+ catch (...)
+ {
+ }
+
+ xDocSh->SetLoading(SfxLoadedFlags::ALL);
+
+ xDocSh->DoClose();
+
+ return nRet != ERRCODE_NONE;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/starmath/source/mathml/starmathdatabase.cxx b/starmath/source/mathml/starmathdatabase.cxx
new file mode 100644
index 000000000..66bdf3f34
--- /dev/null
+++ b/starmath/source/mathml/starmathdatabase.cxx
@@ -0,0 +1,794 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <starmathdatabase.hxx>
+#include <types.hxx>
+
+SmToken starmathdatabase::Identify_SmXMLOperatorContext_Impl(sal_Unicode cChar, bool bIsStretchy)
+{
+ switch (cChar)
+ {
+ case MS_COPROD:
+ return SmToken(TCOPROD, MS_COPROD, "coprod", TG::Oper, 5);
+ case MS_IIINT:
+ return SmToken(TIIINT, MS_IIINT, "iiint", TG::Oper, 5);
+ case MS_IINT:
+ return SmToken(TIINT, MS_IINT, "iint", TG::Oper, 5);
+ case MS_INT:
+ if (bIsStretchy)
+ return SmToken(TINTD, MS_INT, "intd", TG::Oper, 5);
+ else
+ return SmToken(TINT, MS_INT, "int", TG::Oper, 5);
+ case MS_LINT:
+ return SmToken(TLINT, MS_LINT, "lint", TG::Oper, 5);
+ case MS_LLINT:
+ return SmToken(TLLINT, MS_LLINT, "llint", TG::Oper, 5);
+ case MS_LLLINT:
+ return SmToken(TLLLINT, MS_LLLINT, "lllint", TG::Oper, 5);
+ case MS_PROD:
+ return SmToken(TPROD, MS_PROD, "prod", TG::Oper, 5);
+ case MS_SUM:
+ return SmToken(TSUM, MS_SUM, "sum", TG::Oper, 5);
+ case MS_FACT:
+ return SmToken(TFACT, MS_FACT, "!", TG::UnOper, 5);
+ case MS_NEG:
+ return SmToken(TNEG, MS_NEG, "neg", TG::UnOper, 5);
+ case MS_OMINUS:
+ return SmToken(TOMINUS, MS_OMINUS, "ominus", TG::Sum, 0);
+ case MS_OPLUS:
+ return SmToken(TOPLUS, MS_OPLUS, "oplus", TG::Sum, 0);
+ case MS_UNION:
+ return SmToken(TUNION, MS_UNION, "union", TG::Sum, 0);
+ case MS_OR:
+ return SmToken(TOR, MS_OR, "|", TG::Sum, 5);
+ case MS_PLUSMINUS:
+ return SmToken(TPLUSMINUS, MS_PLUSMINUS, "+-", TG::Sum | TG::UnOper, 5);
+ case MS_MINUSPLUS:
+ return SmToken(TMINUSPLUS, MS_MINUSPLUS, "-+", TG::Sum | TG::UnOper, 5);
+ case 0xe083:
+ case MS_PLUS:
+ return SmToken(TPLUS, MS_PLUS, "+", TG::Sum | TG::UnOper, 5);
+ case MS_MINUS:
+ return SmToken(TMINUS, MS_MINUS, "-", TG::Sum | TG::UnOper, 5);
+ case 0x2022:
+ case MS_CDOT:
+ return SmToken(TCDOT, MS_CDOT, "cdot", TG::Product, 0);
+ case MS_DIV:
+ return SmToken(TDIV, MS_DIV, "div", TG::Product, 0);
+ case MS_TIMES:
+ return SmToken(TTIMES, MS_TIMES, "times", TG::Product, 0);
+ case MS_INTERSECT:
+ return SmToken(TINTERSECT, MS_INTERSECT, "intersection", TG::Product, 0);
+ case MS_ODIVIDE:
+ return SmToken(TODIVIDE, MS_ODIVIDE, "odivide", TG::Product, 0);
+ case MS_ODOT:
+ return SmToken(TODOT, MS_ODOT, "odot", TG::Product, 0);
+ case MS_OTIMES:
+ return SmToken(TOTIMES, MS_OTIMES, "otimes", TG::Product, 0);
+ case MS_AND:
+ return SmToken(TAND, MS_AND, "&", TG::Product, 0);
+ case MS_MULTIPLY:
+ return SmToken(TMULTIPLY, MS_MULTIPLY, "*", TG::Product, 0);
+ case MS_SLASH:
+ if (bIsStretchy)
+ return SmToken(TWIDESLASH, MS_SLASH, "wideslash", TG::Product, 0);
+ else
+ return SmToken(TSLASH, MS_SLASH, "slash", TG::Product, 0);
+ case MS_BACKSLASH:
+ if (bIsStretchy)
+ return SmToken(TWIDEBACKSLASH, MS_BACKSLASH, "widebslash", TG::Product, 0);
+ else
+ return SmToken(TBACKSLASH, MS_BACKSLASH, "bslash", TG::Product, 0);
+ case MS_DEF:
+ return SmToken(TDEF, MS_DEF, "def", TG::Relation, 0);
+ case MS_LINE:
+ return SmToken(TDIVIDES, MS_LINE, "divides", TG::Relation, 0);
+ case MS_EQUIV:
+ return SmToken(TEQUIV, MS_EQUIV, "equiv", TG::Relation, 0);
+ case MS_GE:
+ return SmToken(TGE, MS_GE, ">=", TG::Relation, 0);
+ case MS_GESLANT:
+ return SmToken(TGESLANT, MS_GESLANT, "geslant", TG::Relation, 0);
+ case MS_GG:
+ return SmToken(TGG, MS_GG, ">>", TG::Relation, 0);
+ case MS_GT:
+ return SmToken(TGT, MS_GT, ">", TG::Relation, 0);
+ case MS_IN:
+ return SmToken(TIN, MS_IN, "in", TG::Relation, 0);
+ case MS_LE:
+ return SmToken(TLE, MS_LE, "<=", TG::Relation, 0);
+ case MS_LESLANT:
+ return SmToken(TLESLANT, MS_LESLANT, "leslant", TG::Relation, 0);
+ case MS_LL:
+ return SmToken(TLL, MS_LL, "<<", TG::Relation, 0);
+ case MS_LT:
+ return SmToken(TLT, MS_LT, "<", TG::Relation, 0);
+ case MS_NDIVIDES:
+ return SmToken(TNDIVIDES, MS_NDIVIDES, "ndivides", TG::Relation, 0);
+ case MS_NEQ:
+ return SmToken(TNEQ, MS_NEQ, "<>", TG::Relation, 0);
+ case MS_NOTIN:
+ return SmToken(TNOTIN, MS_NOTIN, "notin", TG::Relation, 0);
+ case MS_NOTPRECEDES:
+ return SmToken(TNOTPRECEDES, MS_NOTPRECEDES, "nprec", TG::Relation, 0);
+ case MS_NSUBSET:
+ return SmToken(TNSUBSET, MS_NSUBSET, "nsubset", TG::Relation, 0);
+ case MS_NSUBSETEQ:
+ return SmToken(TNSUBSETEQ, MS_NSUBSETEQ, "nsubseteq", TG::Relation, 0);
+ case MS_NOTSUCCEEDS:
+ return SmToken(TNOTSUCCEEDS, MS_NOTSUCCEEDS, "nsucc", TG::Relation, 0);
+ case MS_NSUPSET:
+ return SmToken(TNSUPSET, MS_NSUPSET, "nsupset", TG::Relation, 0);
+ case MS_NSUPSETEQ:
+ return SmToken(TNSUPSETEQ, MS_NSUPSETEQ, "nsupseteq", TG::Relation, 0);
+ case MS_ORTHO:
+ return SmToken(TORTHO, MS_ORTHO, "ortho", TG::Relation, 0);
+ case MS_NI:
+ return SmToken(TNI, MS_NI, "owns", TG::Relation, 0);
+ case MS_DLINE:
+ return SmToken(TPARALLEL, MS_DLINE, "parallel", TG::Relation, 0);
+ case MS_PRECEDES:
+ return SmToken(TPRECEDES, MS_PRECEDES, "prec", TG::Relation, 0);
+ case MS_PRECEDESEQUAL:
+ return SmToken(TPRECEDESEQUAL, MS_PRECEDESEQUAL, "preccurlyeq", TG::Relation, 0);
+ case MS_PRECEDESEQUIV:
+ return SmToken(TPRECEDESEQUIV, MS_PRECEDESEQUIV, "precsim", TG::Relation, 0);
+ case MS_PROP:
+ return SmToken(TPROP, MS_PROP, "prop", TG::Relation, 0);
+ case MS_SIM:
+ return SmToken(TSIM, MS_SIM, "sim", TG::Relation, 0);
+ case 0x2245:
+ case MS_SIMEQ:
+ return SmToken(TSIMEQ, MS_SIMEQ, "simeq", TG::Relation, 0);
+ case MS_SUBSET:
+ return SmToken(TSUBSET, MS_SUBSET, "subset", TG::Relation, 0);
+ case MS_SUBSETEQ:
+ return SmToken(TSUBSETEQ, MS_SUBSETEQ, "subseteq", TG::Relation, 0);
+ case MS_SUCCEEDS:
+ return SmToken(TSUCCEEDS, MS_SUCCEEDS, "succ", TG::Relation, 0);
+ case MS_SUCCEEDSEQUAL:
+ return SmToken(TSUCCEEDSEQUAL, MS_SUCCEEDSEQUAL, "succcurlyeq", TG::Relation, 0);
+ case MS_SUCCEEDSEQUIV:
+ return SmToken(TSUCCEEDSEQUIV, MS_SUCCEEDSEQUIV, "succsim", TG::Relation, 0);
+ case MS_SUPSET:
+ return SmToken(TSUPSET, MS_SUPSET, "supset", TG::Relation, 0);
+ case MS_SUPSETEQ:
+ return SmToken(TSUPSETEQ, MS_SUPSETEQ, "supseteq", TG::Relation, 0);
+ case MS_RIGHTARROW:
+ return SmToken(TTOWARD, MS_RIGHTARROW, "toward", TG::Relation, 0);
+ case MS_TRANSL:
+ return SmToken(TTRANSL, MS_TRANSL, "transl", TG::Relation, 0);
+ case MS_TRANSR:
+ return SmToken(TTRANSR, MS_TRANSR, "transr", TG::Relation, 0);
+ case MS_ASSIGN:
+ return SmToken(TASSIGN, MS_ASSIGN, "=", TG::Relation, 0);
+ case MS_LANGLE:
+ return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5);
+ case MS_LMATHANGLE:
+ return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5);
+ case MS_LBRACE:
+ return SmToken(TLBRACE, MS_LBRACE, "lbrace", TG::LBrace, 5);
+ case MS_LCEIL:
+ return SmToken(TLCEIL, MS_LCEIL, "lceil", TG::LBrace, 5);
+ case MS_LFLOOR:
+ return SmToken(TLFLOOR, MS_LFLOOR, "lfloor", TG::LBrace, 5);
+ case MS_LDBRACKET:
+ return SmToken(TLDBRACKET, MS_LDBRACKET, "ldbracket", TG::LBrace, 5);
+ case MS_LBRACKET:
+ return SmToken(TLBRACKET, MS_LBRACKET, "[", TG::LBrace, 5);
+ case MS_LPARENT:
+ return SmToken(TLPARENT, MS_LPARENT, "(", TG::LBrace, 5);
+ case MS_RANGLE:
+ return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5);
+ case MS_RMATHANGLE:
+ return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5);
+ case MS_RBRACE:
+ return SmToken(TRBRACE, MS_RBRACE, "rbrace", TG::RBrace, 5);
+ case MS_RCEIL:
+ return SmToken(TRCEIL, MS_RCEIL, "rceil", TG::RBrace, 5);
+ case MS_RFLOOR:
+ return SmToken(TRFLOOR, MS_RFLOOR, "rfloor", TG::RBrace, 5);
+ case MS_RDBRACKET:
+ return SmToken(TRDBRACKET, MS_RDBRACKET, "rdbracket", TG::RBrace, 5);
+ case MS_RBRACKET:
+ return SmToken(TRBRACKET, MS_RBRACKET, "]", TG::RBrace, 5);
+ case MS_RPARENT:
+ return SmToken(TRPARENT, MS_RPARENT, ")", TG::RBrace, 5);
+ case MS_NONE:
+ return SmToken(TNONE, MS_NONE, "none", TG::RBrace | TG::LBrace, 5);
+ default:
+ return SmToken(TERROR, MS_NONE, "", TG::NONE, SAL_MAX_UINT16);
+ }
+}
+
+SmToken starmathdatabase::Identify_Prefix_SmXMLOperatorContext_Impl(sal_Unicode cChar)
+{
+ switch (cChar)
+ {
+ case MS_VERTLINE:
+ return SmToken(TLLINE, MS_VERTLINE, "lline", TG::LBrace, 5);
+ case MS_DVERTLINE:
+ return SmToken(TLDLINE, MS_DVERTLINE, "ldline", TG::LBrace, 5);
+ case MS_LANGLE:
+ return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5);
+ case MS_LMATHANGLE:
+ return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5);
+ case MS_LBRACE:
+ return SmToken(TLBRACE, MS_LBRACE, "lbrace", TG::LBrace, 5);
+ case MS_LCEIL:
+ return SmToken(TLCEIL, MS_LCEIL, "lceil", TG::LBrace, 5);
+ case MS_LFLOOR:
+ return SmToken(TLFLOOR, MS_LFLOOR, "lfloor", TG::LBrace, 5);
+ case MS_LDBRACKET:
+ return SmToken(TLDBRACKET, MS_LDBRACKET, "ldbracket", TG::LBrace, 5);
+ case MS_LBRACKET:
+ return SmToken(TLBRACKET, MS_LBRACKET, "[", TG::LBrace, 5);
+ case MS_LPARENT:
+ return SmToken(TLPARENT, MS_LPARENT, "(", TG::LBrace, 5);
+ case MS_RANGLE:
+ return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5);
+ case MS_RMATHANGLE:
+ return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5);
+ case MS_RBRACE:
+ return SmToken(TRBRACE, MS_RBRACE, "rbrace", TG::RBrace, 5);
+ case MS_RCEIL:
+ return SmToken(TRCEIL, MS_RCEIL, "rceil", TG::RBrace, 5);
+ case MS_RFLOOR:
+ return SmToken(TRFLOOR, MS_RFLOOR, "rfloor", TG::RBrace, 5);
+ case MS_RDBRACKET:
+ return SmToken(TRDBRACKET, MS_RDBRACKET, "rdbracket", TG::RBrace, 5);
+ case MS_RBRACKET:
+ return SmToken(TRBRACKET, MS_RBRACKET, "]", TG::RBrace, 5);
+ case MS_RPARENT:
+ return SmToken(TRPARENT, MS_RPARENT, ")", TG::RBrace, 5);
+ case MS_NONE:
+ return SmToken(TNONE, MS_NONE, "none", TG::LBrace | TG::RBrace, 5);
+ default:
+ return SmToken(TERROR, MS_NONE, "", TG::NONE, SAL_MAX_UINT16);
+ }
+}
+
+SmToken starmathdatabase::Identify_Postfix_SmXMLOperatorContext_Impl(sal_Unicode cChar)
+{
+ switch (cChar)
+ {
+ case MS_VERTLINE:
+ return SmToken(TRLINE, MS_VERTLINE, "rline", TG::RBrace, 5);
+ case MS_DVERTLINE:
+ return SmToken(TRDLINE, MS_DVERTLINE, "rdline", TG::RBrace, 5);
+ case MS_LANGLE:
+ return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5);
+ case MS_LMATHANGLE:
+ return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5);
+ case MS_LBRACE:
+ return SmToken(TLBRACE, MS_LBRACE, "lbrace", TG::LBrace, 5);
+ case MS_LCEIL:
+ return SmToken(TLCEIL, MS_LCEIL, "lceil", TG::LBrace, 5);
+ case MS_LFLOOR:
+ return SmToken(TLFLOOR, MS_LFLOOR, "lfloor", TG::LBrace, 5);
+ case MS_LDBRACKET:
+ return SmToken(TLDBRACKET, MS_LDBRACKET, "ldbracket", TG::LBrace, 5);
+ case MS_LBRACKET:
+ return SmToken(TLBRACKET, MS_LBRACKET, "[", TG::LBrace, 5);
+ case MS_LPARENT:
+ return SmToken(TLPARENT, MS_LPARENT, "(", TG::LBrace, 5);
+ case MS_RANGLE:
+ return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5);
+ case MS_RMATHANGLE:
+ return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5);
+ case MS_RBRACE:
+ return SmToken(TRBRACE, MS_RBRACE, "rbrace", TG::RBrace, 5);
+ case MS_RCEIL:
+ return SmToken(TRCEIL, MS_RCEIL, "rceil", TG::RBrace, 5);
+ case MS_RFLOOR:
+ return SmToken(TRFLOOR, MS_RFLOOR, "rfloor", TG::RBrace, 5);
+ case MS_RDBRACKET:
+ return SmToken(TRDBRACKET, MS_RDBRACKET, "rdbracket", TG::RBrace, 5);
+ case MS_RBRACKET:
+ return SmToken(TRBRACKET, MS_RBRACKET, "]", TG::RBrace, 5);
+ case MS_RPARENT:
+ return SmToken(TRPARENT, MS_RPARENT, ")", TG::RBrace, 5);
+ case MS_NONE:
+ return SmToken(TNONE, MS_NONE, "none", TG::LBrace | TG::RBrace, 5);
+ default:
+ return SmToken(TERROR, MS_NONE, "", TG::NONE, SAL_MAX_UINT16);
+ }
+}
+
+SmToken starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl(sal_Unicode cChar)
+{
+ switch (cChar)
+ {
+ case MS_VERTLINE:
+ return SmToken(TLRLINE, MS_VERTLINE, "lrline", TG::LBrace | TG::RBrace, 5);
+ case MS_DVERTLINE:
+ return SmToken(TLRDLINE, MS_DVERTLINE, "lrdline", TG::LBrace | TG::RBrace, 5);
+ case MS_LANGLE:
+ return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5);
+ case MS_LMATHANGLE:
+ return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5);
+ case MS_LBRACE:
+ return SmToken(TLBRACE, MS_LBRACE, "lbrace", TG::LBrace, 5);
+ case MS_LCEIL:
+ return SmToken(TLCEIL, MS_LCEIL, "lceil", TG::LBrace, 5);
+ case MS_LFLOOR:
+ return SmToken(TLFLOOR, MS_LFLOOR, "lfloor", TG::LBrace, 5);
+ case MS_LDBRACKET:
+ return SmToken(TLDBRACKET, MS_LDBRACKET, "ldbracket", TG::LBrace, 5);
+ case MS_LBRACKET:
+ return SmToken(TLBRACKET, MS_LBRACKET, "[", TG::LBrace, 5);
+ case MS_LPARENT:
+ return SmToken(TLPARENT, MS_LPARENT, "(", TG::LBrace, 5);
+ case MS_RANGLE:
+ return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5);
+ case MS_RMATHANGLE:
+ return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5);
+ case MS_RBRACE:
+ return SmToken(TRBRACE, MS_RBRACE, "rbrace", TG::RBrace, 5);
+ case MS_RCEIL:
+ return SmToken(TRCEIL, MS_RCEIL, "rceil", TG::RBrace, 5);
+ case MS_RFLOOR:
+ return SmToken(TRFLOOR, MS_RFLOOR, "rfloor", TG::RBrace, 5);
+ case MS_RDBRACKET:
+ return SmToken(TRDBRACKET, MS_RDBRACKET, "rdbracket", TG::RBrace, 5);
+ case MS_RBRACKET:
+ return SmToken(TRBRACKET, MS_RBRACKET, "]", TG::RBrace, 5);
+ case MS_RPARENT:
+ return SmToken(TRPARENT, MS_RPARENT, ")", TG::RBrace, 5);
+ case MS_NONE:
+ return SmToken(TNONE, MS_NONE, "none", TG::LBrace | TG::RBrace, 5);
+ default:
+ return SmToken(TERROR, MS_NONE, "", TG::NONE, SAL_MAX_UINT16);
+ }
+}
+
+const SmColorTokenTableEntry starmathdatabase::aColorTokenTableParse[]
+ = { { "aliceblue", THTMLCOL, COL_SM_ALICEBLUE },
+ { "antiquewhite", THTMLCOL, COL_SM_ANTIQUEWHITE },
+ { "aqua", TMATHMLCOL, COL_SM_AQUA },
+ { "aquamarine", THTMLCOL, COL_SM_AQUAMARINE },
+ { "azure", THTMLCOL, COL_SM_AZURE },
+ { "beige", THTMLCOL, COL_SM_BEIGE },
+ { "bisque", THTMLCOL, COL_SM_BISQUE },
+ { "black", TMATHMLCOL, COL_SM_BLACK },
+ { "blanchedalmond", THTMLCOL, COL_SM_BLANCHEDALMOND },
+ { "blue", TMATHMLCOL, COL_SM_BLUE },
+ { "blueviolet", THTMLCOL, COL_SM_BLUEVIOLET },
+ { "brown", THTMLCOL, COL_SM_BROWN },
+ { "burlywood", THTMLCOL, COL_SM_BURLYWOOD },
+ { "cadetblue", THTMLCOL, COL_SM_CADETBLUE },
+ { "chartreuse", THTMLCOL, COL_SM_CHARTREUSE },
+ { "chocolate", THTMLCOL, COL_SM_CHOCOLATE },
+ { "coral", THTMLCOL, COL_SM_CORAL },
+ { "cornflowerblue", THTMLCOL, COL_SM_CORNFLOWERBLUE },
+ { "cornsilk", THTMLCOL, COL_SM_CORNSILK },
+ { "crimson", THTMLCOL, COL_SM_CRIMSON },
+ { "cyan", TMATHMLCOL, COL_SM_CYAN },
+ { "darkblue", THTMLCOL, COL_SM_DARKBLUE },
+ { "darkcyan", THTMLCOL, COL_SM_DARKCYAN },
+ { "darkgoldenrod", THTMLCOL, COL_SM_DARKGOLDENROD },
+ { "darkgray", THTMLCOL, COL_SM_DARKGRAY },
+ { "darkgreen", THTMLCOL, COL_SM_DARKGREEN },
+ { "darkgrey", THTMLCOL, COL_SM_DARKGREY },
+ { "darkkhaki", THTMLCOL, COL_SM_DARKKHAKI },
+ { "darkmagenta", THTMLCOL, COL_SM_DARKMAGENTA },
+ { "darkolivegreen", THTMLCOL, COL_SM_DARKOLIVEGREEN },
+ { "darkorange", THTMLCOL, COL_SM_DARKORANGE },
+ { "darkorchid", THTMLCOL, COL_SM_DARKORCHID },
+ { "darkred", THTMLCOL, COL_SM_DARKRED },
+ { "darksalmon", THTMLCOL, COL_SM_DARKSALMON },
+ { "darkseagreen", THTMLCOL, COL_SM_DARKSEAGREEN },
+ { "darkslateblue", THTMLCOL, COL_SM_DARKSLATEBLUE },
+ { "darkslategray", THTMLCOL, COL_SM_DARKSLATEGRAY },
+ { "darkslategrey", THTMLCOL, COL_SM_DARKSLATEGREY },
+ { "darkturquoise", THTMLCOL, COL_SM_DARKTURQUOISE },
+ { "darkviolet", THTMLCOL, COL_SM_DARKVIOLET },
+ { "debian", TICONICCOL, COL_SM_DEBIAN_MAGENTA },
+ { "deeppink", THTMLCOL, COL_SM_DEEPPINK },
+ { "deepskyblue", THTMLCOL, COL_SM_DEEPSKYBLUE },
+ { "dimgray", THTMLCOL, COL_SM_DIMGRAY },
+ { "dimgrey", THTMLCOL, COL_SM_DIMGREY },
+ { "dodgerblue", THTMLCOL, COL_SM_DODGERBLUE },
+ { "dvip", TDVIPSNAMESCOL, COL_SM_BLACK },
+ { "firebrick", THTMLCOL, COL_SM_FIREBRICK },
+ { "floralwhite", THTMLCOL, COL_SM_FLORALWHITE },
+ { "forestgreen", THTMLCOL, COL_SM_FORESTGREEN },
+ { "fuchsia", TMATHMLCOL, COL_SM_FUCHSIA },
+ { "gainsboro", THTMLCOL, COL_SM_GAINSBORO },
+ { "ghostwhite", THTMLCOL, COL_SM_GHOSTWHITE },
+ { "gold", THTMLCOL, COL_SM_GOLD },
+ { "goldenrod", THTMLCOL, COL_SM_GOLDENROD },
+ { "gray", TMATHMLCOL, COL_SM_GRAY },
+ { "green", TMATHMLCOL, COL_SM_GREEN },
+ { "greenyellow", THTMLCOL, COL_SM_GREENYELLOW },
+ { "grey", THTMLCOL, COL_SM_GREY },
+ { "hex", THEX, COL_SM_BLACK },
+ { "honeydew", THTMLCOL, COL_SM_HONEYDEW },
+ { "hotpink", THTMLCOL, COL_SM_HOTPINK },
+ { "indianred", THTMLCOL, COL_SM_INDIANRED },
+ { "indigo", THTMLCOL, COL_SM_INDIGO },
+ { "ivory", THTMLCOL, COL_SM_IVORY },
+ { "khaki", THTMLCOL, COL_SM_KHAKI },
+ { "lavender", THTMLCOL, COL_SM_LAVENDER },
+ { "lavenderblush", THTMLCOL, COL_SM_LAVENDERBLUSH },
+ { "lawngreen", THTMLCOL, COL_SM_LAWNGREEN },
+ { "lemonchiffon", THTMLCOL, COL_SM_LEMONCHIFFON },
+ { "lightblue", THTMLCOL, COL_SM_LIGHTBLUE },
+ { "lightcoral", THTMLCOL, COL_SM_LIGHTCORAL },
+ { "lightcyan", THTMLCOL, COL_SM_LIGHTCYAN },
+ { "lightgoldenrodyellow", THTMLCOL, COL_SM_LIGHTGOLDENRODYELLOW },
+ { "lightgray", THTMLCOL, COL_SM_LIGHTGRAY },
+ { "lightgreen", THTMLCOL, COL_SM_LIGHTGREEN },
+ { "lightgrey", THTMLCOL, COL_SM_LIGHTGREY },
+ { "lightpink", THTMLCOL, COL_SM_LIGHTPINK },
+ { "lightsalmon", THTMLCOL, COL_SM_LIGHTSALMON },
+ { "lightseagreen", THTMLCOL, COL_SM_LIGHTSEAGREEN },
+ { "lightskyblue", THTMLCOL, COL_SM_LIGHTSKYBLUE },
+ { "lightslategray", THTMLCOL, COL_SM_LIGHTSLATEGRAY },
+ { "lightslategrey", THTMLCOL, COL_SM_LIGHTSLATEGREY },
+ { "lightsteelblue", THTMLCOL, COL_SM_LIGHTSTEELBLUE },
+ { "lightyellow", THTMLCOL, COL_SM_LIGHTYELLOW },
+ { "lime", TMATHMLCOL, COL_SM_LIME },
+ { "limegreen", THTMLCOL, COL_SM_LIMEGREEN },
+ { "linen", THTMLCOL, COL_SM_LINEN },
+ { "lo", TICONICCOL, COL_SM_LO_GREEN },
+ { "magenta", TMATHMLCOL, COL_SM_MAGENTA },
+ { "maroon", TMATHMLCOL, COL_SM_MAROON },
+ { "mediumaquamarine", THTMLCOL, COL_SM_MEDIUMAQUAMARINE },
+ { "mediumblue", THTMLCOL, COL_SM_MEDIUMBLUE },
+ { "mediumorchid", THTMLCOL, COL_SM_MEDIUMORCHID },
+ { "mediumpurple", THTMLCOL, COL_SM_MEDIUMPURPLE },
+ { "mediumseagreen", THTMLCOL, COL_SM_MEDIUMSEAGREEN },
+ { "mediumslateblue", THTMLCOL, COL_SM_MEDIUMSLATEBLUE },
+ { "mediumspringgreen", THTMLCOL, COL_SM_MEDIUMSPRINGGREEN },
+ { "mediumturquoise", THTMLCOL, COL_SM_MEDIUMTURQUOISE },
+ { "mediumvioletred", THTMLCOL, COL_SM_MEDIUMVIOLETRED },
+ { "midnightblue", THTMLCOL, COL_SM_MIDNIGHTBLUE },
+ { "mintcream", THTMLCOL, COL_SM_MINTCREAM },
+ { "mistyrose", THTMLCOL, COL_SM_MISTYROSE },
+ { "moccasin", THTMLCOL, COL_SM_MOCCASIN },
+ { "navajowhite", THTMLCOL, COL_SM_NAVAJOWHITE },
+ { "navy", TMATHMLCOL, COL_SM_NAVY },
+ { "oldlace", THTMLCOL, COL_SM_OLDLACE },
+ { "olive", TMATHMLCOL, COL_SM_OLIVE },
+ { "olivedrab", THTMLCOL, COL_SM_OLIVEDRAB },
+ { "orange", THTMLCOL, COL_SM_ORANGE },
+ { "orangered", THTMLCOL, COL_SM_ORANGERED },
+ { "orchid", THTMLCOL, COL_SM_ORCHID },
+ { "palegoldenrod", THTMLCOL, COL_SM_PALEGOLDENROD },
+ { "palegreen", THTMLCOL, COL_SM_PALEGREEN },
+ { "paleturquoise", THTMLCOL, COL_SM_PALETURQUOISE },
+ { "palevioletred", THTMLCOL, COL_SM_PALEVIOLETRED },
+ { "papayawhip", THTMLCOL, COL_SM_PAPAYAWHIP },
+ { "peachpuff", THTMLCOL, COL_SM_PEACHPUFF },
+ { "peru", THTMLCOL, COL_SM_PERU },
+ { "pink", THTMLCOL, COL_SM_PINK },
+ { "plum", THTMLCOL, COL_SM_PLUM },
+ { "powderblue", THTMLCOL, COL_SM_POWDERBLUE },
+ { "purple", TMATHMLCOL, COL_SM_PURPLE },
+ { "rebeccapurple", THTMLCOL, COL_SM_REBECCAPURPLE },
+ { "red", TMATHMLCOL, COL_SM_RED },
+ { "rgb", TRGB, COL_AUTO },
+ { "rgba", TRGBA, COL_AUTO },
+ { "rosybrown", THTMLCOL, COL_SM_ROSYBROWN },
+ { "royalblue", THTMLCOL, COL_SM_ROYALBLUE },
+ { "saddlebrown", THTMLCOL, COL_SM_SADDLEBROWN },
+ { "salmon", THTMLCOL, COL_SM_SALMON },
+ { "sandybrown", THTMLCOL, COL_SM_SANDYBROWN },
+ { "seagreen", THTMLCOL, COL_SM_SEAGREEN },
+ { "seashell", THTMLCOL, COL_SM_SEASHELL },
+ { "sienna", THTMLCOL, COL_SM_SIENNA },
+ { "silver", TMATHMLCOL, COL_SM_SILVER },
+ { "skyblue", THTMLCOL, COL_SM_SKYBLUE },
+ { "slateblue", THTMLCOL, COL_SM_SLATEBLUE },
+ { "slategray", THTMLCOL, COL_SM_SLATEGRAY },
+ { "slategrey", THTMLCOL, COL_SM_SLATEGREY },
+ { "snow", THTMLCOL, COL_SM_SNOW },
+ { "springgreen", THTMLCOL, COL_SM_SPRINGGREEN },
+ { "steelblue", THTMLCOL, COL_SM_STEELBLUE },
+ { "tan", THTMLCOL, COL_SM_TAN },
+ { "teal", TMATHMLCOL, COL_SM_TEAL },
+ { "thistle", THTMLCOL, COL_SM_THISTLE },
+ { "tomato", THTMLCOL, COL_SM_TOMATO },
+ { "turquoise", THTMLCOL, COL_SM_TURQUOISE },
+ { "ubuntu", TICONICCOL, COL_SM_UBUNTU_ORANGE },
+ { "violet", THTMLCOL, COL_SM_VIOLET },
+ { "wheat", THTMLCOL, COL_SM_WHEAT },
+ { "white", TMATHMLCOL, COL_SM_WHITE },
+ { "whitesmoke", THTMLCOL, COL_SM_WHITESMOKE },
+ { "yellow", TMATHMLCOL, COL_SM_YELLOW },
+ { "yellowgreen", THTMLCOL, COL_SM_YELLOWGREEN } };
+
+const SmColorTokenTableEntry starmathdatabase::aColorTokenTableHTML[]
+ = { { "aliceblue", THTMLCOL, COL_SM_ALICEBLUE },
+ { "antiquewhite", THTMLCOL, COL_SM_ANTIQUEWHITE },
+ { "aqua", TMATHMLCOL, COL_SM_AQUA },
+ { "aquamarine", THTMLCOL, COL_SM_AQUAMARINE },
+ { "azure", THTMLCOL, COL_SM_AZURE },
+ { "beige", THTMLCOL, COL_SM_BEIGE },
+ { "bisque", THTMLCOL, COL_SM_BISQUE },
+ { "black", TMATHMLCOL, COL_SM_BLACK },
+ { "blanchedalmond", THTMLCOL, COL_SM_BLANCHEDALMOND },
+ { "blue", TMATHMLCOL, COL_SM_BLUE },
+ { "blueviolet", THTMLCOL, COL_SM_BLUEVIOLET },
+ { "brown", THTMLCOL, COL_SM_BROWN },
+ { "burlywood", THTMLCOL, COL_SM_BURLYWOOD },
+ { "cadetblue", THTMLCOL, COL_SM_CADETBLUE },
+ { "chartreuse", THTMLCOL, COL_SM_CHARTREUSE },
+ { "chocolate", THTMLCOL, COL_SM_CHOCOLATE },
+ { "coral", THTMLCOL, COL_SM_CORAL },
+ { "cornflowerblue", THTMLCOL, COL_SM_CORNFLOWERBLUE },
+ { "cornsilk", THTMLCOL, COL_SM_CORNSILK },
+ { "crimson", THTMLCOL, COL_SM_CRIMSON },
+ { "cyan", TMATHMLCOL, COL_SM_CYAN },
+ { "darkblue", THTMLCOL, COL_SM_DARKBLUE },
+ { "darkcyan", THTMLCOL, COL_SM_DARKCYAN },
+ { "darkgoldenrod", THTMLCOL, COL_SM_DARKGOLDENROD },
+ { "darkgray", THTMLCOL, COL_SM_DARKGRAY },
+ { "darkgreen", THTMLCOL, COL_SM_DARKGREEN },
+ { "darkgrey", THTMLCOL, COL_SM_DARKGREY },
+ { "darkkhaki", THTMLCOL, COL_SM_DARKKHAKI },
+ { "darkmagenta", THTMLCOL, COL_SM_DARKMAGENTA },
+ { "darkolivegreen", THTMLCOL, COL_SM_DARKOLIVEGREEN },
+ { "darkorange", THTMLCOL, COL_SM_DARKORANGE },
+ { "darkorchid", THTMLCOL, COL_SM_DARKORCHID },
+ { "darkred", THTMLCOL, COL_SM_DARKRED },
+ { "darksalmon", THTMLCOL, COL_SM_DARKSALMON },
+ { "darkseagreen", THTMLCOL, COL_SM_DARKSEAGREEN },
+ { "darkslateblue", THTMLCOL, COL_SM_DARKSLATEBLUE },
+ { "darkslategray", THTMLCOL, COL_SM_DARKSLATEGRAY },
+ { "darkslategrey", THTMLCOL, COL_SM_DARKSLATEGREY },
+ { "darkturquoise", THTMLCOL, COL_SM_DARKTURQUOISE },
+ { "darkviolet", THTMLCOL, COL_SM_DARKVIOLET },
+ { "deeppink", THTMLCOL, COL_SM_DEEPPINK },
+ { "deepskyblue", THTMLCOL, COL_SM_DEEPSKYBLUE },
+ { "dimgray", THTMLCOL, COL_SM_DIMGRAY },
+ { "dimgrey", THTMLCOL, COL_SM_DIMGREY },
+ { "dodgerblue", THTMLCOL, COL_SM_DODGERBLUE },
+ { "firebrick", THTMLCOL, COL_SM_FIREBRICK },
+ { "floralwhite", THTMLCOL, COL_SM_FLORALWHITE },
+ { "forestgreen", THTMLCOL, COL_SM_FORESTGREEN },
+ { "fuchsia", TMATHMLCOL, COL_SM_FUCHSIA },
+ { "gainsboro", THTMLCOL, COL_SM_GAINSBORO },
+ { "ghostwhite", THTMLCOL, COL_SM_GHOSTWHITE },
+ { "gold", THTMLCOL, COL_SM_GOLD },
+ { "goldenrod", THTMLCOL, COL_SM_GOLDENROD },
+ { "gray", TMATHMLCOL, COL_SM_GRAY },
+ { "green", TMATHMLCOL, COL_SM_GREEN },
+ { "greenyellow", THTMLCOL, COL_SM_GREENYELLOW },
+ { "grey", THTMLCOL, COL_SM_GREY },
+ { "honeydew", THTMLCOL, COL_SM_HONEYDEW },
+ { "hotpink", THTMLCOL, COL_SM_HOTPINK },
+ { "indianred", THTMLCOL, COL_SM_INDIANRED },
+ { "indigo", THTMLCOL, COL_SM_INDIGO },
+ { "ivory", THTMLCOL, COL_SM_IVORY },
+ { "khaki", THTMLCOL, COL_SM_KHAKI },
+ { "lavender", THTMLCOL, COL_SM_LAVENDER },
+ { "lavenderblush", THTMLCOL, COL_SM_LAVENDERBLUSH },
+ { "lawngreen", THTMLCOL, COL_SM_LAWNGREEN },
+ { "lemonchiffon", THTMLCOL, COL_SM_LEMONCHIFFON },
+ { "lightblue", THTMLCOL, COL_SM_LIGHTBLUE },
+ { "lightcoral", THTMLCOL, COL_SM_LIGHTCORAL },
+ { "lightcyan", THTMLCOL, COL_SM_LIGHTCYAN },
+ { "lightgoldenrodyellow", THTMLCOL, COL_SM_LIGHTGOLDENRODYELLOW },
+ { "lightgray", THTMLCOL, COL_SM_LIGHTGRAY },
+ { "lightgreen", THTMLCOL, COL_SM_LIGHTGREEN },
+ { "lightgrey", THTMLCOL, COL_SM_LIGHTGREY },
+ { "lightpink", THTMLCOL, COL_SM_LIGHTPINK },
+ { "lightsalmon", THTMLCOL, COL_SM_LIGHTSALMON },
+ { "lightseagreen", THTMLCOL, COL_SM_LIGHTSEAGREEN },
+ { "lightskyblue", THTMLCOL, COL_SM_LIGHTSKYBLUE },
+ { "lightslategray", THTMLCOL, COL_SM_LIGHTSLATEGRAY },
+ { "lightslategrey", THTMLCOL, COL_SM_LIGHTSLATEGREY },
+ { "lightsteelblue", THTMLCOL, COL_SM_LIGHTSTEELBLUE },
+ { "lightyellow", THTMLCOL, COL_SM_LIGHTYELLOW },
+ { "lime", TMATHMLCOL, COL_SM_LIME },
+ { "limegreen", THTMLCOL, COL_SM_LIMEGREEN },
+ { "linen", THTMLCOL, COL_SM_LINEN },
+ { "magenta", TMATHMLCOL, COL_SM_MAGENTA },
+ { "maroon", TMATHMLCOL, COL_SM_MAROON },
+ { "mediumaquamarine", THTMLCOL, COL_SM_MEDIUMAQUAMARINE },
+ { "mediumblue", THTMLCOL, COL_SM_MEDIUMBLUE },
+ { "mediumorchid", THTMLCOL, COL_SM_MEDIUMORCHID },
+ { "mediumpurple", THTMLCOL, COL_SM_MEDIUMPURPLE },
+ { "mediumseagreen", THTMLCOL, COL_SM_MEDIUMSEAGREEN },
+ { "mediumslateblue", THTMLCOL, COL_SM_MEDIUMSLATEBLUE },
+ { "mediumspringgreen", THTMLCOL, COL_SM_MEDIUMSPRINGGREEN },
+ { "mediumturquoise", THTMLCOL, COL_SM_MEDIUMTURQUOISE },
+ { "mediumvioletred", THTMLCOL, COL_SM_MEDIUMVIOLETRED },
+ { "midnightblue", THTMLCOL, COL_SM_MIDNIGHTBLUE },
+ { "mintcream", THTMLCOL, COL_SM_MINTCREAM },
+ { "mistyrose", THTMLCOL, COL_SM_MISTYROSE },
+ { "moccasin", THTMLCOL, COL_SM_MOCCASIN },
+ { "navajowhite", THTMLCOL, COL_SM_NAVAJOWHITE },
+ { "navy", TMATHMLCOL, COL_SM_NAVY },
+ { "oldlace", THTMLCOL, COL_SM_OLDLACE },
+ { "olive", TMATHMLCOL, COL_SM_OLIVE },
+ { "olivedrab", THTMLCOL, COL_SM_OLIVEDRAB },
+ { "orange", THTMLCOL, COL_SM_ORANGE },
+ { "orangered", THTMLCOL, COL_SM_ORANGERED },
+ { "orchid", THTMLCOL, COL_SM_ORCHID },
+ { "palegoldenrod", THTMLCOL, COL_SM_PALEGOLDENROD },
+ { "palegreen", THTMLCOL, COL_SM_PALEGREEN },
+ { "paleturquoise", THTMLCOL, COL_SM_PALETURQUOISE },
+ { "palevioletred", THTMLCOL, COL_SM_PALEVIOLETRED },
+ { "papayawhip", THTMLCOL, COL_SM_PAPAYAWHIP },
+ { "peachpuff", THTMLCOL, COL_SM_PEACHPUFF },
+ { "peru", THTMLCOL, COL_SM_PERU },
+ { "pink", THTMLCOL, COL_SM_PINK },
+ { "plum", THTMLCOL, COL_SM_PLUM },
+ { "powderblue", THTMLCOL, COL_SM_POWDERBLUE },
+ { "purple", TMATHMLCOL, COL_SM_PURPLE },
+ { "rebeccapurple", THTMLCOL, COL_SM_REBECCAPURPLE },
+ { "red", TMATHMLCOL, COL_SM_RED },
+ { "rosybrown", THTMLCOL, COL_SM_ROSYBROWN },
+ { "royalblue", THTMLCOL, COL_SM_ROYALBLUE },
+ { "saddlebrown", THTMLCOL, COL_SM_SADDLEBROWN },
+ { "salmon", THTMLCOL, COL_SM_SALMON },
+ { "sandybrown", THTMLCOL, COL_SM_SANDYBROWN },
+ { "seagreen", THTMLCOL, COL_SM_SEAGREEN },
+ { "seashell", THTMLCOL, COL_SM_SEASHELL },
+ { "sienna", THTMLCOL, COL_SM_SIENNA },
+ { "silver", TMATHMLCOL, COL_SM_SILVER },
+ { "skyblue", THTMLCOL, COL_SM_SKYBLUE },
+ { "slateblue", THTMLCOL, COL_SM_SLATEBLUE },
+ { "slategray", THTMLCOL, COL_SM_SLATEGRAY },
+ { "slategrey", THTMLCOL, COL_SM_SLATEGREY },
+ { "snow", THTMLCOL, COL_SM_SNOW },
+ { "springgreen", THTMLCOL, COL_SM_SPRINGGREEN },
+ { "steelblue", THTMLCOL, COL_SM_STEELBLUE },
+ { "tan", THTMLCOL, COL_SM_TAN },
+ { "teal", TMATHMLCOL, COL_SM_TEAL },
+ { "thistle", THTMLCOL, COL_SM_THISTLE },
+ { "tomato", THTMLCOL, COL_SM_TOMATO },
+ { "turquoise", THTMLCOL, COL_SM_TURQUOISE },
+ { "violet", THTMLCOL, COL_SM_VIOLET },
+ { "wheat", THTMLCOL, COL_SM_WHEAT },
+ { "white", TMATHMLCOL, COL_SM_WHITE },
+ { "whitesmoke", THTMLCOL, COL_SM_WHITESMOKE },
+ { "yellow", TMATHMLCOL, COL_SM_YELLOW },
+ { "yellowgreen", THTMLCOL, COL_SM_YELLOWGREEN } };
+
+const SmColorTokenTableEntry starmathdatabase::aColorTokenTableDVIPS[]
+ = { { "apricot", TDVIPSNAMESCOL, COL_SM_DIV_APRICOT },
+ { "aquamarine", TDVIPSNAMESCOL, COL_SM_DIV_AQUAMARINE },
+ { "bittersweet", TDVIPSNAMESCOL, COL_SM_DIV_BITTERSWEET },
+ { "black", TDVIPSNAMESCOL, COL_SM_BLACK },
+ { "blue", TDVIPSNAMESCOL, COL_SM_BLACK } };
+
+const SmColorTokenTableEntry starmathdatabase::aColorTokenTableMATHML[] = {
+ // clang-format off
+ { "aqua", TMATHMLCOL, COL_SM_AQUA },
+ { "black", TMATHMLCOL, COL_SM_BLACK },
+ { "blue", TMATHMLCOL, COL_SM_BLUE },
+ { "fuchsia", TMATHMLCOL, COL_SM_FUCHSIA },
+ { "gray", TMATHMLCOL, COL_SM_GRAY },
+ { "green", TMATHMLCOL, COL_SM_GREEN },
+ { "lime", TMATHMLCOL, COL_SM_LIME },
+ { "maroon", TMATHMLCOL, COL_SM_MAROON },
+ { "navy", TMATHMLCOL, COL_SM_NAVY },
+ { "olive", TMATHMLCOL, COL_SM_OLIVE },
+ { "purple", TMATHMLCOL, COL_SM_PURPLE },
+ { "red", TMATHMLCOL, COL_SM_RED },
+ { "silver", TMATHMLCOL, COL_SM_SILVER },
+ { "teal", TMATHMLCOL, COL_SM_TEAL },
+ { "white", TMATHMLCOL, COL_SM_WHITE },
+ { "yellow", TMATHMLCOL, COL_SM_YELLOW }
+ // clang-format on
+};
+
+const SmColorTokenTableEntry starmathdatabase::aColorTokenTableERROR[]
+ = { { "", TERROR, COL_SM_BLACK } };
+
+SmColorTokenTableEntry starmathdatabase::Identify_Color_Parser(sal_uInt32 cColor)
+{
+ for (auto i = std::begin(aColorTokenTableParse); i < std::end(aColorTokenTableParse); ++i)
+ if (i->equals(cColor))
+ return i;
+ for (auto i = std::begin(aColorTokenTableDVIPS); i < std::end(aColorTokenTableDVIPS); ++i)
+ if (i->equals(cColor))
+ return i;
+ if ((cColor & 0x00FFFFFF) == cColor)
+ return SmColorTokenTableEntry("", TRGB, cColor);
+ else
+ return SmColorTokenTableEntry("", TRGBA, cColor);
+}
+
+SmColorTokenTableEntry starmathdatabase::Identify_Color_HTML(sal_uInt32 cColor)
+{
+ for (auto i = std::begin(aColorTokenTableHTML); i < std::end(aColorTokenTableHTML); ++i)
+ if (i->equals(cColor))
+ return i;
+ if ((cColor & 0x00FFFFFF) == cColor)
+ return SmColorTokenTableEntry("", TRGB, cColor);
+ else
+ return SmColorTokenTableEntry("", TRGBA, cColor);
+}
+
+SmColorTokenTableEntry starmathdatabase::Identify_Color_MATHML(sal_uInt32 cColor)
+{
+ for (auto i = std::begin(aColorTokenTableMATHML); i < std::end(aColorTokenTableMATHML); ++i)
+ if (i->equals(cColor))
+ return i;
+ if ((cColor & 0x00FFFFFF) == cColor)
+ return SmColorTokenTableEntry("", TRGB, cColor);
+ else
+ return SmColorTokenTableEntry("", TRGBA, cColor);
+}
+
+SmColorTokenTableEntry starmathdatabase::Identify_Color_DVIPSNAMES(sal_uInt32 cColor)
+{
+ for (auto i = std::begin(aColorTokenTableDVIPS); i < std::end(aColorTokenTableDVIPS); ++i)
+ if (i->equals(cColor))
+ return i;
+ if ((cColor & 0x00FFFFFF) == cColor)
+ return SmColorTokenTableEntry("", TRGB, cColor);
+ else
+ return SmColorTokenTableEntry("", TRGBA, cColor);
+}
+
+const SmColorTokenTableEntry*
+starmathdatabase::Identify_ColorName_Parser(std::u16string_view colorname)
+{
+ if (colorname.empty())
+ return &aColorTokenTableERROR[0];
+ for (auto i = std::begin(aColorTokenTableParse); i < std::end(aColorTokenTableParse); ++i)
+ {
+ sal_Int32 matches = o3tl::compareToIgnoreAsciiCase(colorname, i->aIdent);
+ if (matches == 0)
+ return i;
+ if (matches < 0)
+ break;
+ }
+ return &aColorTokenTableERROR[0];
+}
+SmColorTokenTableEntry starmathdatabase::Identify_ColorName_HTML(std::u16string_view colorname)
+{
+ if (colorname.empty())
+ return SmColorTokenTableEntry("", TERROR, COL_SM_BLACK);
+ if (colorname[0] == '#')
+ {
+ Color col = Color::STRtoRGB(colorname);
+ return SmColorTokenTableEntry("", TRGB, col);
+ }
+ for (auto i = std::begin(aColorTokenTableHTML); i < std::end(aColorTokenTableHTML); ++i)
+ {
+ sal_Int32 matches = o3tl::compareToIgnoreAsciiCase(colorname, i->aIdent);
+ if (matches == 0)
+ return i;
+ if (matches < 0)
+ break;
+ }
+ return SmColorTokenTableEntry("", TERROR, COL_SM_BLACK);
+}
+const SmColorTokenTableEntry*
+starmathdatabase::Identify_ColorName_DVIPSNAMES(std::u16string_view colorname)
+{
+ if (colorname.empty())
+ return &aColorTokenTableERROR[0];
+ for (auto i = std::begin(aColorTokenTableDVIPS); i < std::end(aColorTokenTableDVIPS); ++i)
+ {
+ sal_Int32 matches = o3tl::compareToIgnoreAsciiCase(colorname, i->aIdent);
+ if (matches == 0)
+ return i;
+ if (matches < 0)
+ break;
+ }
+ return &aColorTokenTableERROR[0];
+}
diff --git a/starmath/source/mathml/xparsmlbase.cxx b/starmath/source/mathml/xparsmlbase.cxx
new file mode 100644
index 000000000..7e0e93ab7
--- /dev/null
+++ b/starmath/source/mathml/xparsmlbase.cxx
@@ -0,0 +1,2166 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <xparsmlbase.hxx>
+
+static ::css::beans::Pair<::rtl::OUString, ::rtl::OUString>
+ icustomMathmlHtmlEntitiesData[starmathdatabase::STARMATH_MATHMLHTML_ENTITY_NUMBER] = {
+ // clang-format off
+ { u"AElig", u"\u00C6" },
+ { u"AMP", u"\u0026" },
+ { u"Aacute", u"\u00C1" },
+ { u"Abreve", u"\u0102" },
+ { u"Acirc", u"\u00C2" },
+ { u"Acy", u"\u0410" },
+ { u"Afr", u"\U0001D504" },
+ { u"Agrave", u"\u00C0" },
+ { u"Alpha", u"\u0391" },
+ { u"Amacr", u"\u0100" },
+ { u"And", u"\u2A53" },
+ { u"Aogon", u"\u0104" },
+ { u"Aopf", u"\U0001D538" },
+ { u"ApplyFunction", u"\u2061" },
+ { u"Aring", u"\u00C5" },
+ { u"Ascr", u"\U0001D49C" },
+ { u"Assign", u"\u2254" },
+ { u"Atilde", u"\u00C3" },
+ { u"Auml", u"\u00C4" },
+ { u"Backslash", u"\u2216" },
+ { u"Barv", u"\u2AE7" },
+ { u"Barwed", u"\u2306" },
+ { u"Bcy", u"\u0411" },
+ { u"Because", u"\u2235" },
+ { u"Bernoullis", u"\u212C" },
+ { u"Beta", u"\u0392" },
+ { u"Bfr", u"\U0001D505" },
+ { u"Bopf", u"\U0001D539" },
+ { u"Breve", u"\u02D8" },
+ { u"Bscr", u"\u212C" },
+ { u"Bumpeq", u"\u224E" },
+ { u"CHcy", u"\u0427" },
+ { u"COPY", u"\u00A9" },
+ { u"Cacute", u"\u0106" },
+ { u"Cap", u"\u22D2" },
+ { u"CapitalDifferentialD", u"\u2145" },
+ { u"Cayleys", u"\u212D" },
+ { u"Ccaron", u"\u010C" },
+ { u"Ccedil", u"\u00C7" },
+ { u"Ccirc", u"\u0108" },
+ { u"Cconint", u"\u2230" },
+ { u"Cdot", u"\u010A" },
+ { u"Cedilla", u"\u00B8" },
+ { u"CenterDot", u"\u00B7" },
+ { u"Cfr", u"\u212D" },
+ { u"Chi", u"\u03A7" },
+ { u"CircleDot", u"\u2299" },
+ { u"CircleMinus", u"\u2296" },
+ { u"CirclePlus", u"\u2295" },
+ { u"CircleTimes", u"\u2297" },
+ { u"ClockwiseContourIntegral", u"\u2232" },
+ { u"CloseCurlyDoubleQuote", u"\u201D" },
+ { u"CloseCurlyQuote", u"\u2019" },
+ { u"Colon", u"\u2237" },
+ { u"Colone", u"\u2A74" },
+ { u"Congruent", u"\u2261" },
+ { u"Conint", u"\u222F" },
+ { u"ContourIntegral", u"\u222E" },
+ { u"Copf", u"\u2102" },
+ { u"Coproduct", u"\u2210" },
+ { u"CounterClockwiseContourIntegral", u"\u2233" },
+ { u"Cross", u"\u2A2F" },
+ { u"Cscr", u"\U0001D49E" },
+ { u"Cup", u"\u22D3" },
+ { u"CupCap", u"\u224D" },
+ { u"DD", u"\u2145" },
+ { u"DDotrahd", u"\u2911" },
+ { u"DJcy", u"\u0402" },
+ { u"DScy", u"\u0405" },
+ { u"DZcy", u"\u040F" },
+ { u"Dagger", u"\u2021" },
+ { u"Darr", u"\u21A1" },
+ { u"Dashv", u"\u2AE4" },
+ { u"Dcaron", u"\u010E" },
+ { u"Dcy", u"\u0414" },
+ { u"Del", u"\u2207" },
+ { u"Delta", u"\u0394" },
+ { u"Dfr", u"\U0001D507" },
+ { u"DiacriticalAcute", u"\u00B4" },
+ { u"DiacriticalDot", u"\u02D9" },
+ { u"DiacriticalDoubleAcute", u"\u02DD" },
+ { u"DiacriticalGrave", u"\u0060" },
+ { u"DiacriticalTilde", u"\u02DC" },
+ { u"Diamond", u"\u22C4" },
+ { u"DifferentialD", u"\u2146" },
+ { u"Dopf", u"\U0001D53B" },
+ { u"Dot", u"\u00A8" },
+ { u"DotDot", u"\u20DC" },
+ { u"DotEqual", u"\u2250" },
+ { u"DoubleContourIntegral", u"\u222F" },
+ { u"DoubleDot", u"\u00A8" },
+ { u"DoubleDownArrow", u"\u21D3" },
+ { u"DoubleLeftArrow", u"\u21D0" },
+ { u"DoubleLeftRightArrow", u"\u21D4" },
+ { u"DoubleLeftTee", u"\u2AE4" },
+ { u"DoubleLongLeftArrow", u"\u27F8" },
+ { u"DoubleLongLeftRightArrow", u"\u27FA" },
+ { u"DoubleLongRightArrow", u"\u27F9" },
+ { u"DoubleRightArrow", u"\u21D2" },
+ { u"DoubleRightTee", u"\u22A8" },
+ { u"DoubleUpArrow", u"\u21D1" },
+ { u"DoubleUpDownArrow", u"\u21D5" },
+ { u"DoubleVerticalBar", u"\u2225" },
+ { u"DownArrow", u"\u2193" },
+ { u"DownArrowBar", u"\u2913" },
+ { u"DownArrowUpArrow", u"\u21F5" },
+ { u"DownBreve", u"\u0311" },
+ { u"DownLeftRightVector", u"\u2950" },
+ { u"DownLeftTeeVector", u"\u295E" },
+ { u"DownLeftVector", u"\u21BD" },
+ { u"DownLeftVectorBar", u"\u2956" },
+ { u"DownRightTeeVector", u"\u295F" },
+ { u"DownRightVector", u"\u21C1" },
+ { u"DownRightVectorBar", u"\u2957" },
+ { u"DownTee", u"\u22A4" },
+ { u"DownTeeArrow", u"\u21A7" },
+ { u"Downarrow", u"\u21D3" },
+ { u"Dscr", u"\U0001D49F" },
+ { u"Dstrok", u"\u0110" },
+ { u"ENG", u"\u014A" },
+ { u"ETH", u"\u00D0" },
+ { u"Eacute", u"\u00C9" },
+ { u"Ecaron", u"\u011A" },
+ { u"Ecirc", u"\u00CA" },
+ { u"Ecy", u"\u042D" },
+ { u"Edot", u"\u0116" },
+ { u"Efr", u"\U0001D508" },
+ { u"Egrave", u"\u00C8" },
+ { u"Element", u"\u2208" },
+ { u"Emacr", u"\u0112" },
+ { u"EmptySmallSquare", u"\u25FB" },
+ { u"EmptyVerySmallSquare", u"\u25AB" },
+ { u"Eogon", u"\u0118" },
+ { u"Eopf", u"\U0001D53C" },
+ { u"Epsilon", u"\u0395" },
+ { u"Equal", u"\u2A75" },
+ { u"EqualTilde", u"\u2242" },
+ { u"Equilibrium", u"\u21CC" },
+ { u"Escr", u"\u2130" },
+ { u"Esim", u"\u2A73" },
+ { u"Eta", u"\u0397" },
+ { u"Euml", u"\u00CB" },
+ { u"Exists", u"\u2203" },
+ { u"ExponentialE", u"\u2147" },
+ { u"Fcy", u"\u0424" },
+ { u"Ffr", u"\U0001D509" },
+ { u"FilledSmallSquare", u"\u25FC" },
+ { u"FilledVerySmallSquare", u"\u25AA" },
+ { u"Fopf", u"\U0001D53D" },
+ { u"ForAll", u"\u2200" },
+ { u"Fouriertrf", u"\u2131" },
+ { u"Fscr", u"\u2131" },
+ { u"GJcy", u"\u0403" },
+ { u"GT", u"\u003E" },
+ { u"Gamma", u"\u0393" },
+ { u"Gammad", u"\u03DC" },
+ { u"Gbreve", u"\u011E" },
+ { u"Gcedil", u"\u0122" },
+ { u"Gcirc", u"\u011C" },
+ { u"Gcy", u"\u0413" },
+ { u"Gdot", u"\u0120" },
+ { u"Gfr", u"\U0001D50A" },
+ { u"Gg", u"\u22D9" },
+ { u"Gopf", u"\U0001D53E" },
+ { u"GreaterEqual", u"\u2265" },
+ { u"GreaterEqualLess", u"\u22DB" },
+ { u"GreaterFullEqual", u"\u2267" },
+ { u"GreaterGreater", u"\u2AA2" },
+ { u"GreaterLess", u"\u2277" },
+ { u"GreaterSlantEqual", u"\u2A7E" },
+ { u"GreaterTilde", u"\u2273" },
+ { u"Gscr", u"\U0001D4A2" },
+ { u"Gt", u"\u226B" },
+ { u"HARDcy", u"\u042A" },
+ { u"Hacek", u"\u02C7" },
+ { u"Hat", u"\u005E" },
+ { u"Hcirc", u"\u0124" },
+ { u"Hfr", u"\u210C" },
+ { u"HilbertSpace", u"\u210B" },
+ { u"Hopf", u"\u210D" },
+ { u"HorizontalLine", u"\u2500" },
+ { u"Hscr", u"\u210B" },
+ { u"Hstrok", u"\u0126" },
+ { u"HumpDownHump", u"\u224E" },
+ { u"HumpEqual", u"\u224F" },
+ { u"IEcy", u"\u0415" },
+ { u"IJlig", u"\u0132" },
+ { u"IOcy", u"\u0401" },
+ { u"Iacute", u"\u00CD" },
+ { u"Icirc", u"\u00CE" },
+ { u"Icy", u"\u0418" },
+ { u"Idot", u"\u0130" },
+ { u"Ifr", u"\u2111" },
+ { u"Igrave", u"\u00CC" },
+ { u"Im", u"\u2111" },
+ { u"Imacr", u"\u012A" },
+ { u"ImaginaryI", u"\u2148" },
+ { u"Implies", u"\u21D2" },
+ { u"Int", u"\u222C" },
+ { u"Integral", u"\u222B" },
+ { u"Intersection", u"\u22C2" },
+ { u"InvisibleComma", u"\u2063" },
+ { u"InvisibleTimes", u"\u2062" },
+ { u"Iogon", u"\u012E" },
+ { u"Iopf", u"\U0001D540" },
+ { u"Iota", u"\u0399" },
+ { u"Iscr", u"\u2110" },
+ { u"Itilde", u"\u0128" },
+ { u"Iukcy", u"\u0406" },
+ { u"Iuml", u"\u00CF" },
+ { u"Jcirc", u"\u0134" },
+ { u"Jcy", u"\u0419" },
+ { u"Jfr", u"\U0001D50D" },
+ { u"Jopf", u"\U0001D541" },
+ { u"Jscr", u"\U0001D4A5" },
+ { u"Jsercy", u"\u0408" },
+ { u"Jukcy", u"\u0404" },
+ { u"KHcy", u"\u0425" },
+ { u"KJcy", u"\u040C" },
+ { u"Kappa", u"\u039A" },
+ { u"Kcedil", u"\u0136" },
+ { u"Kcy", u"\u041A" },
+ { u"Kfr", u"\U0001D50E" },
+ { u"Kopf", u"\U0001D542" },
+ { u"Kscr", u"\U0001D4A6" },
+ { u"LJcy", u"\u0409" },
+ { u"LT", u"\u003C" },
+ { u"Lacute", u"\u0139" },
+ { u"Lambda", u"\u039B" },
+ { u"Lang", u"\u27EA" },
+ { u"Laplacetrf", u"\u2112" },
+ { u"Larr", u"\u219E" },
+ { u"Lcaron", u"\u013D" },
+ { u"Lcedil", u"\u013B" },
+ { u"Lcy", u"\u041B" },
+ { u"LeftAngleBracket", u"\u27E8" },
+ { u"LeftArrow", u"\u2190" },
+ { u"LeftArrowBar", u"\u21E4" },
+ { u"LeftArrowRightArrow", u"\u21C6" },
+ { u"LeftCeiling", u"\u2308" },
+ { u"LeftDoubleBracket", u"\u27E6" },
+ { u"LeftDownTeeVector", u"\u2961" },
+ { u"LeftDownVector", u"\u21C3" },
+ { u"LeftDownVectorBar", u"\u2959" },
+ { u"LeftFloor", u"\u230A" },
+ { u"LeftRightArrow", u"\u2194" },
+ { u"LeftRightVector", u"\u294E" },
+ { u"LeftTee", u"\u22A3" },
+ { u"LeftTeeArrow", u"\u21A4" },
+ { u"LeftTeeVector", u"\u295A" },
+ { u"LeftTriangle", u"\u22B2" },
+ { u"LeftTriangleBar", u"\u29CF" },
+ { u"LeftTriangleEqual", u"\u22B4" },
+ { u"LeftUpDownVector", u"\u2951" },
+ { u"LeftUpTeeVector", u"\u2960" },
+ { u"LeftUpVector", u"\u21BF" },
+ { u"LeftUpVectorBar", u"\u2958" },
+ { u"LeftVector", u"\u21BC" },
+ { u"LeftVectorBar", u"\u2952" },
+ { u"Leftarrow", u"\u21D0" },
+ { u"Leftrightarrow", u"\u21D4" },
+ { u"LessEqualGreater", u"\u22DA" },
+ { u"LessFullEqual", u"\u2266" },
+ { u"LessGreater", u"\u2276" },
+ { u"LessLess", u"\u2AA1" },
+ { u"LessSlantEqual", u"\u2A7D" },
+ { u"LessTilde", u"\u2272" },
+ { u"Lfr", u"\U0001D50F" },
+ { u"Ll", u"\u22D8" },
+ { u"Lleftarrow", u"\u21DA" },
+ { u"Lmidot", u"\u013F" },
+ { u"LongLeftArrow", u"\u27F5" },
+ { u"LongLeftRightArrow", u"\u27F7" },
+ { u"LongRightArrow", u"\u27F6" },
+ { u"Longleftarrow", u"\u27F8" },
+ { u"Longleftrightarrow", u"\u27FA" },
+ { u"Longrightarrow", u"\u27F9" },
+ { u"Lopf", u"\U0001D543" },
+ { u"LowerLeftArrow", u"\u2199" },
+ { u"LowerRightArrow", u"\u2198" },
+ { u"Lscr", u"\u2112" },
+ { u"Lsh", u"\u21B0" },
+ { u"Lstrok", u"\u0141" },
+ { u"Lt", u"\u226A" },
+ { u"Map", u"\u2905" },
+ { u"Mcy", u"\u041C" },
+ { u"MediumSpace", u"\u205F" },
+ { u"Mellintrf", u"\u2133" },
+ { u"Mfr", u"\U0001D510" },
+ { u"MinusPlus", u"\u2213" },
+ { u"Mopf", u"\U0001D544" },
+ { u"Mscr", u"\u2133" },
+ { u"Mu", u"\u039C" },
+ { u"NJcy", u"\u040A" },
+ { u"Nacute", u"\u0143" },
+ { u"Ncaron", u"\u0147" },
+ { u"Ncedil", u"\u0145" },
+ { u"Ncy", u"\u041D" },
+ { u"NegativeMediumSpace", u"\u200B" },
+ { u"NegativeThickSpace", u"\u200B" },
+ { u"NegativeThinSpace", u"\u200B" },
+ { u"NegativeVeryThinSpace", u"\u200B" },
+ { u"NestedGreaterGreater", u"\u226B" },
+ { u"NestedLessLess", u"\u226A" },
+ { u"NewLine", u"\u000A" },
+ { u"Nfr", u"\U0001D511" },
+ { u"NoBreak", u"\u2060" },
+ { u"NonBreakingSpace", u"\u00A0" },
+ { u"Nopf", u"\u2115" },
+ { u"Not", u"\u2AEC" },
+ { u"NotCongruent", u"\u2262" },
+ { u"NotCupCap", u"\u226D" },
+ { u"NotDoubleVerticalBar", u"\u2226" },
+ { u"NotElement", u"\u2209" },
+ { u"NotEqual", u"\u2260" },
+ { u"NotEqualTilde", u"\u2242\u0338" },
+ { u"NotExists", u"\u2204" },
+ { u"NotGreater", u"\u226F" },
+ { u"NotGreaterEqual", u"\u2271" },
+ { u"NotGreaterFullEqual", u"\u2267\u0338" },
+ { u"NotGreaterGreater", u"\u226B\u0338" },
+ { u"NotGreaterLess", u"\u2279" },
+ { u"NotGreaterSlantEqual", u"\u2A7E\u0338" },
+ { u"NotGreaterTilde", u"\u2275" },
+ { u"NotHumpDownHump", u"\u224E\u0338" },
+ { u"NotHumpEqual", u"\u224F\u0338" },
+ { u"NotLeftTriangle", u"\u22EA" },
+ { u"NotLeftTriangleBar", u"\u29CF\u0338" },
+ { u"NotLeftTriangleEqual", u"\u22EC" },
+ { u"NotLess", u"\u226E" },
+ { u"NotLessEqual", u"\u2270" },
+ { u"NotLessGreater", u"\u2278" },
+ { u"NotLessLess", u"\u226A\u0338" },
+ { u"NotLessSlantEqual", u"\u2A7D\u0338" },
+ { u"NotLessTilde", u"\u2274" },
+ { u"NotNestedGreaterGreater", u"\u2AA2\u0338" },
+ { u"NotNestedLessLess", u"\u2AA1\u0338" },
+ { u"NotPrecedes", u"\u2280" },
+ { u"NotPrecedesEqual", u"\u2AAF\u0338" },
+ { u"NotPrecedesSlantEqual", u"\u22E0" },
+ { u"NotReverseElement", u"\u220C" },
+ { u"NotRightTriangle", u"\u22EB" },
+ { u"NotRightTriangleBar", u"\u29D0\u0338" },
+ { u"NotRightTriangleEqual", u"\u22ED" },
+ { u"NotSquareSubset", u"\u228F\u0338" },
+ { u"NotSquareSubsetEqual", u"\u22E2" },
+ { u"NotSquareSuperset", u"\u2290\u0338" },
+ { u"NotSquareSupersetEqual", u"\u22E3" },
+ { u"NotSubset", u"\u2282\u20D2" },
+ { u"NotSubsetEqual", u"\u2288" },
+ { u"NotSucceeds", u"\u2281" },
+ { u"NotSucceedsEqual", u"\u2AB0\u0338" },
+ { u"NotSucceedsSlantEqual", u"\u22E1" },
+ { u"NotSucceedsTilde", u"\u227F\u0338" },
+ { u"NotSuperset", u"\u2283\u20D2" },
+ { u"NotSupersetEqual", u"\u2289" },
+ { u"NotTilde", u"\u2241" },
+ { u"NotTildeEqual", u"\u2244" },
+ { u"NotTildeFullEqual", u"\u2247" },
+ { u"NotTildeTilde", u"\u2249" },
+ { u"NotVerticalBar", u"\u2224" },
+ { u"Nscr", u"\U0001D4A9" },
+ { u"Ntilde", u"\u00D1" },
+ { u"Nu", u"\u039D" },
+ { u"OElig", u"\u0152" },
+ { u"Oacute", u"\u00D3" },
+ { u"Ocirc", u"\u00D4" },
+ { u"Ocy", u"\u041E" },
+ { u"Odblac", u"\u0150" },
+ { u"Ofr", u"\U0001D512" },
+ { u"Ograve", u"\u00D2" },
+ { u"Omacr", u"\u014C" },
+ { u"Omega", u"\u03A9" },
+ { u"Omicron", u"\u039F" },
+ { u"Oopf", u"\U0001D546" },
+ { u"OpenCurlyDoubleQuote", u"\u201C" },
+ { u"OpenCurlyQuote", u"\u2018" },
+ { u"Or", u"\u2A54" },
+ { u"Oscr", u"\U0001D4AA" },
+ { u"Oslash", u"\u00D8" },
+ { u"Otilde", u"\u00D5" },
+ { u"Otimes", u"\u2A37" },
+ { u"Ouml", u"\u00D6" },
+ { u"OverBar", u"\u203E" },
+ { u"OverBrace", u"\u23DE" },
+ { u"OverBracket", u"\u23B4" },
+ { u"OverParenthesis", u"\u23DC" },
+ { u"PartialD", u"\u2202" },
+ { u"Pcy", u"\u041F" },
+ { u"Pfr", u"\U0001D513" },
+ { u"Phi", u"\u03A6" },
+ { u"Pi", u"\u03A0" },
+ { u"PlusMinus", u"\u00B1" },
+ { u"Poincareplane", u"\u210C" },
+ { u"Popf", u"\u2119" },
+ { u"Pr", u"\u2ABB" },
+ { u"Precedes", u"\u227A" },
+ { u"PrecedesEqual", u"\u2AAF" },
+ { u"PrecedesSlantEqual", u"\u227C" },
+ { u"PrecedesTilde", u"\u227E" },
+ { u"Prime", u"\u2033" },
+ { u"Product", u"\u220F" },
+ { u"Proportion", u"\u2237" },
+ { u"Proportional", u"\u221D" },
+ { u"Pscr", u"\U0001D4AB" },
+ { u"Psi", u"\u03A8" },
+ { u"QUOT", u"\u0022" },
+ { u"Qfr", u"\U0001D514" },
+ { u"Qopf", u"\u211A" },
+ { u"Qscr", u"\U0001D4AC" },
+ { u"RBarr", u"\u2910" },
+ { u"REG", u"\u00AE" },
+ { u"Racute", u"\u0154" },
+ { u"Rang", u"\u27EB" },
+ { u"Rarr", u"\u21A0" },
+ { u"Rarrtl", u"\u2916" },
+ { u"Rcaron", u"\u0158" },
+ { u"Rcedil", u"\u0156" },
+ { u"Rcy", u"\u0420" },
+ { u"Re", u"\u211C" },
+ { u"ReverseElement", u"\u220B" },
+ { u"ReverseEquilibrium", u"\u21CB" },
+ { u"ReverseUpEquilibrium", u"\u296F" },
+ { u"Rfr", u"\u211C" },
+ { u"Rho", u"\u03A1" },
+ { u"RightAngleBracket", u"\u27E9" },
+ { u"RightArrow", u"\u2192" },
+ { u"RightArrowBar", u"\u21E5" },
+ { u"RightArrowLeftArrow", u"\u21C4" },
+ { u"RightCeiling", u"\u2309" },
+ { u"RightDoubleBracket", u"\u27E7" },
+ { u"RightDownTeeVector", u"\u295D" },
+ { u"RightDownVector", u"\u21C2" },
+ { u"RightDownVectorBar", u"\u2955" },
+ { u"RightFloor", u"\u230B" },
+ { u"RightTee", u"\u22A2" },
+ { u"RightTeeArrow", u"\u21A6" },
+ { u"RightTeeVector", u"\u295B" },
+ { u"RightTriangle", u"\u22B3" },
+ { u"RightTriangleBar", u"\u29D0" },
+ { u"RightTriangleEqual", u"\u22B5" },
+ { u"RightUpDownVector", u"\u294F" },
+ { u"RightUpTeeVector", u"\u295C" },
+ { u"RightUpVector", u"\u21BE" },
+ { u"RightUpVectorBar", u"\u2954" },
+ { u"RightVector", u"\u21C0" },
+ { u"RightVectorBar", u"\u2953" },
+ { u"Rightarrow", u"\u21D2" },
+ { u"Ropf", u"\u211D" },
+ { u"RoundImplies", u"\u2970" },
+ { u"Rrightarrow", u"\u21DB" },
+ { u"Rscr", u"\u211B" },
+ { u"Rsh", u"\u21B1" },
+ { u"RuleDelayed", u"\u29F4" },
+ { u"SHCHcy", u"\u0429" },
+ { u"SHcy", u"\u0428" },
+ { u"SOFTcy", u"\u042C" },
+ { u"Sacute", u"\u015A" },
+ { u"Sc", u"\u2ABC" },
+ { u"Scaron", u"\u0160" },
+ { u"Scedil", u"\u015E" },
+ { u"Scirc", u"\u015C" },
+ { u"Scy", u"\u0421" },
+ { u"Sfr", u"\U0001D516" },
+ { u"ShortDownArrow", u"\u2193" },
+ { u"ShortLeftArrow", u"\u2190" },
+ { u"ShortRightArrow", u"\u2192" },
+ { u"ShortUpArrow", u"\u2191" },
+ { u"Sigma", u"\u03A3" },
+ { u"SmallCircle", u"\u2218" },
+ { u"Sopf", u"\U0001D54A" },
+ { u"Sqrt", u"\u221A" },
+ { u"Square", u"\u25A1" },
+ { u"SquareIntersection", u"\u2293" },
+ { u"SquareSubset", u"\u228F" },
+ { u"SquareSubsetEqual", u"\u2291" },
+ { u"SquareSuperset", u"\u2290" },
+ { u"SquareSupersetEqual", u"\u2292" },
+ { u"SquareUnion", u"\u2294" },
+ { u"Sscr", u"\U0001D4AE" },
+ { u"Star", u"\u22C6" },
+ { u"Sub", u"\u22D0" },
+ { u"Subset", u"\u22D0" },
+ { u"SubsetEqual", u"\u2286" },
+ { u"Succeeds", u"\u227B" },
+ { u"SucceedsEqual", u"\u2AB0" },
+ { u"SucceedsSlantEqual", u"\u227D" },
+ { u"SucceedsTilde", u"\u227F" },
+ { u"SuchThat", u"\u220B" },
+ { u"Sum", u"\u2211" },
+ { u"Sup", u"\u22D1" },
+ { u"Superset", u"\u2283" },
+ { u"SupersetEqual", u"\u2287" },
+ { u"Supset", u"\u22D1" },
+ { u"THORN", u"\u00DE" },
+ { u"TRADE", u"\u2122" },
+ { u"TSHcy", u"\u040B" },
+ { u"TScy", u"\u0426" },
+ { u"Tab", u"\u0009" },
+ { u"Tau", u"\u03A4" },
+ { u"Tcaron", u"\u0164" },
+ { u"Tcedil", u"\u0162" },
+ { u"Tcy", u"\u0422" },
+ { u"Tfr", u"\U0001D517" },
+ { u"Therefore", u"\u2234" },
+ { u"Theta", u"\u0398" },
+ { u"ThickSpace", u"\u205F\u200A" },
+ { u"ThinSpace", u"\u2009" },
+ { u"Tilde", u"\u223C" },
+ { u"TildeEqual", u"\u2243" },
+ { u"TildeFullEqual", u"\u2245" },
+ { u"TildeTilde", u"\u2248" },
+ { u"Topf", u"\U0001D54B" },
+ { u"TripleDot", u"\u20DB" },
+ { u"Tscr", u"\U0001D4AF" },
+ { u"Tstrok", u"\u0166" },
+ { u"Uacute", u"\u00DA" },
+ { u"Uarr", u"\u219F" },
+ { u"Uarrocir", u"\u2949" },
+ { u"Ubrcy", u"\u040E" },
+ { u"Ubreve", u"\u016C" },
+ { u"Ucirc", u"\u00DB" },
+ { u"Ucy", u"\u0423" },
+ { u"Udblac", u"\u0170" },
+ { u"Ufr", u"\U0001D518" },
+ { u"Ugrave", u"\u00D9" },
+ { u"Umacr", u"\u016A" },
+ { u"UnderBar", u"\u005F" },
+ { u"UnderBrace", u"\u23DF" },
+ { u"UnderBracket", u"\u23B5" },
+ { u"UnderParenthesis", u"\u23DD" },
+ { u"Union", u"\u22C3" },
+ { u"UnionPlus", u"\u228E" },
+ { u"Uogon", u"\u0172" },
+ { u"Uopf", u"\U0001D54C" },
+ { u"UpArrow", u"\u2191" },
+ { u"UpArrowBar", u"\u2912" },
+ { u"UpArrowDownArrow", u"\u21C5" },
+ { u"UpDownArrow", u"\u2195" },
+ { u"UpEquilibrium", u"\u296E" },
+ { u"UpTee", u"\u22A5" },
+ { u"UpTeeArrow", u"\u21A5" },
+ { u"Uparrow", u"\u21D1" },
+ { u"Updownarrow", u"\u21D5" },
+ { u"UpperLeftArrow", u"\u2196" },
+ { u"UpperRightArrow", u"\u2197" },
+ { u"Upsi", u"\u03D2" },
+ { u"Upsilon", u"\u03A5" },
+ { u"Uring", u"\u016E" },
+ { u"Uscr", u"\U0001D4B0" },
+ { u"Utilde", u"\u0168" },
+ { u"Uuml", u"\u00DC" },
+ { u"VDash", u"\u22AB" },
+ { u"Vbar", u"\u2AEB" },
+ { u"Vcy", u"\u0412" },
+ { u"Vdash", u"\u22A9" },
+ { u"Vdashl", u"\u2AE6" },
+ { u"Vee", u"\u22C1" },
+ { u"Verbar", u"\u2016" },
+ { u"Vert", u"\u2016" },
+ { u"VerticalBar", u"\u2223" },
+ { u"VerticalLine", u"\u007C" },
+ { u"VerticalSeparator", u"\u2758" },
+ { u"VerticalTilde", u"\u2240" },
+ { u"VeryThinSpace", u"\u200A" },
+ { u"Vfr", u"\U0001D519" },
+ { u"Vopf", u"\U0001D54D" },
+ { u"Vscr", u"\U0001D4B1" },
+ { u"Vvdash", u"\u22AA" },
+ { u"Wcirc", u"\u0174" },
+ { u"Wedge", u"\u22C0" },
+ { u"Wfr", u"\U0001D51A" },
+ { u"Wopf", u"\U0001D54E" },
+ { u"Wscr", u"\U0001D4B2" },
+ { u"Xfr", u"\U0001D51B" },
+ { u"Xi", u"\u039E" },
+ { u"Xopf", u"\U0001D54F" },
+ { u"Xscr", u"\U0001D4B3" },
+ { u"YAcy", u"\u042F" },
+ { u"YIcy", u"\u0407" },
+ { u"YUcy", u"\u042E" },
+ { u"Yacute", u"\u00DD" },
+ { u"Ycirc", u"\u0176" },
+ { u"Ycy", u"\u042B" },
+ { u"Yfr", u"\U0001D51C" },
+ { u"Yopf", u"\U0001D550" },
+ { u"Yscr", u"\U0001D4B4" },
+ { u"Yuml", u"\u0178" },
+ { u"ZHcy", u"\u0416" },
+ { u"Zacute", u"\u0179" },
+ { u"Zcaron", u"\u017D" },
+ { u"Zcy", u"\u0417" },
+ { u"Zdot", u"\u017B" },
+ { u"ZeroWidthSpace", u"\u200B" },
+ { u"Zeta", u"\u0396" },
+ { u"Zfr", u"\u2128" },
+ { u"Zopf", u"\u2124" },
+ { u"Zscr", u"\U0001D4B5" },
+ { u"aacute", u"\u00E1" },
+ { u"abreve", u"\u0103" },
+ { u"ac", u"\u223E" },
+ { u"acE", u"\u223E\u0333" },
+ { u"acd", u"\u223F" },
+ { u"acirc", u"\u00E2" },
+ { u"acute", u"\u00B4" },
+ { u"acy", u"\u0430" },
+ { u"aelig", u"\u00E6" },
+ { u"af", u"\u2061" },
+ { u"afr", u"\U0001D51E" },
+ { u"agrave", u"\u00E0" },
+ { u"alefsym", u"\u2135" },
+ { u"aleph", u"\u2135" },
+ { u"alpha", u"\u03B1" },
+ { u"amacr", u"\u0101" },
+ { u"amalg", u"\u2A3F" },
+ { u"amp", u"\u0026" },
+ { u"and", u"\u2227" },
+ { u"andand", u"\u2A55" },
+ { u"andd", u"\u2A5C" },
+ { u"andslope", u"\u2A58" },
+ { u"andv", u"\u2A5A" },
+ { u"ang", u"\u2220" },
+ { u"ange", u"\u29A4" },
+ { u"angle", u"\u2220" },
+ { u"angmsd", u"\u2221" },
+ { u"angmsdaa", u"\u29A8" },
+ { u"angmsdab", u"\u29A9" },
+ { u"angmsdac", u"\u29AA" },
+ { u"angmsdad", u"\u29AB" },
+ { u"angmsdae", u"\u29AC" },
+ { u"angmsdaf", u"\u29AD" },
+ { u"angmsdag", u"\u29AE" },
+ { u"angmsdah", u"\u29AF" },
+ { u"angrt", u"\u221F" },
+ { u"angrtvb", u"\u22BE" },
+ { u"angrtvbd", u"\u299D" },
+ { u"angsph", u"\u2222" },
+ { u"angst", u"\u00C5" },
+ { u"angzarr", u"\u237C" },
+ { u"aogon", u"\u0105" },
+ { u"aopf", u"\U0001D552" },
+ { u"ap", u"\u2248" },
+ { u"apE", u"\u2A70" },
+ { u"apacir", u"\u2A6F" },
+ { u"ape", u"\u224A" },
+ { u"apid", u"\u224B" },
+ { u"apos", u"\u0027" },
+ { u"approx", u"\u2248" },
+ { u"approxeq", u"\u224A" },
+ { u"aring", u"\u00E5" },
+ { u"ascr", u"\U0001D4B6" },
+ { u"ast", u"\u002A" },
+ { u"asymp", u"\u2248" },
+ { u"asympeq", u"\u224D" },
+ { u"atilde", u"\u00E3" },
+ { u"auml", u"\u00E4" },
+ { u"awconint", u"\u2233" },
+ { u"awint", u"\u2A11" },
+ { u"bNot", u"\u2AED" },
+ { u"backcong", u"\u224C" },
+ { u"backepsilon", u"\u03F6" },
+ { u"backprime", u"\u2035" },
+ { u"backsim", u"\u223D" },
+ { u"backsimeq", u"\u22CD" },
+ { u"barvee", u"\u22BD" },
+ { u"barwed", u"\u2305" },
+ { u"barwedge", u"\u2305" },
+ { u"bbrk", u"\u23B5" },
+ { u"bbrktbrk", u"\u23B6" },
+ { u"bcong", u"\u224C" },
+ { u"bcy", u"\u0431" },
+ { u"bdquo", u"\u201E" },
+ { u"becaus", u"\u2235" },
+ { u"because", u"\u2235" },
+ { u"bemptyv", u"\u29B0" },
+ { u"bepsi", u"\u03F6" },
+ { u"bernou", u"\u212C" },
+ { u"beta", u"\u03B2" },
+ { u"beth", u"\u2136" },
+ { u"between", u"\u226C" },
+ { u"bfr", u"\U0001D51F" },
+ { u"bigcap", u"\u22C2" },
+ { u"bigcirc", u"\u25EF" },
+ { u"bigcup", u"\u22C3" },
+ { u"bigodot", u"\u2A00" },
+ { u"bigoplus", u"\u2A01" },
+ { u"bigotimes", u"\u2A02" },
+ { u"bigsqcup", u"\u2A06" },
+ { u"bigstar", u"\u2605" },
+ { u"bigtriangledown", u"\u25BD" },
+ { u"bigtriangleup", u"\u25B3" },
+ { u"biguplus", u"\u2A04" },
+ { u"bigvee", u"\u22C1" },
+ { u"bigwedge", u"\u22C0" },
+ { u"bkarow", u"\u290D" },
+ { u"blacklozenge", u"\u29EB" },
+ { u"blacksquare", u"\u25AA" },
+ { u"blacktriangle", u"\u25B4" },
+ { u"blacktriangledown", u"\u25BE" },
+ { u"blacktriangleleft", u"\u25C2" },
+ { u"blacktriangleright", u"\u25B8" },
+ { u"blank", u"\u2423" },
+ { u"blk12", u"\u2592" },
+ { u"blk14", u"\u2591" },
+ { u"blk34", u"\u2593" },
+ { u"block", u"\u2588" },
+ { u"bne", u"\u003D\u20E5" },
+ { u"bnequiv", u"\u2261\u20E5" },
+ { u"bnot", u"\u2310" },
+ { u"bopf", u"\U0001D553" },
+ { u"bot", u"\u22A5" },
+ { u"bottom", u"\u22A5" },
+ { u"bowtie", u"\u22C8" },
+ { u"boxDL", u"\u2557" },
+ { u"boxDR", u"\u2554" },
+ { u"boxDl", u"\u2556" },
+ { u"boxDr", u"\u2553" },
+ { u"boxH", u"\u2550" },
+ { u"boxHD", u"\u2566" },
+ { u"boxHU", u"\u2569" },
+ { u"boxHd", u"\u2564" },
+ { u"boxHu", u"\u2567" },
+ { u"boxUL", u"\u255D" },
+ { u"boxUR", u"\u255A" },
+ { u"boxUl", u"\u255C" },
+ { u"boxUr", u"\u2559" },
+ { u"boxV", u"\u2551" },
+ { u"boxVH", u"\u256C" },
+ { u"boxVL", u"\u2563" },
+ { u"boxVR", u"\u2560" },
+ { u"boxVh", u"\u256B" },
+ { u"boxVl", u"\u2562" },
+ { u"boxVr", u"\u255F" },
+ { u"boxbox", u"\u29C9" },
+ { u"boxdL", u"\u2555" },
+ { u"boxdR", u"\u2552" },
+ { u"boxdl", u"\u2510" },
+ { u"boxdr", u"\u250C" },
+ { u"boxh", u"\u2500" },
+ { u"boxhD", u"\u2565" },
+ { u"boxhU", u"\u2568" },
+ { u"boxhd", u"\u252C" },
+ { u"boxhu", u"\u2534" },
+ { u"boxminus", u"\u229F" },
+ { u"boxplus", u"\u229E" },
+ { u"boxtimes", u"\u22A0" },
+ { u"boxuL", u"\u255B" },
+ { u"boxuR", u"\u2558" },
+ { u"boxul", u"\u2518" },
+ { u"boxur", u"\u2514" },
+ { u"boxv", u"\u2502" },
+ { u"boxvH", u"\u256A" },
+ { u"boxvL", u"\u2561" },
+ { u"boxvR", u"\u255E" },
+ { u"boxvh", u"\u253C" },
+ { u"boxvl", u"\u2524" },
+ { u"boxvr", u"\u251C" },
+ { u"bprime", u"\u2035" },
+ { u"breve", u"\u02D8" },
+ { u"brvbar", u"\u00A6" },
+ { u"bscr", u"\U0001D4B7" },
+ { u"bsemi", u"\u204F" },
+ { u"bsim", u"\u223D" },
+ { u"bsime", u"\u22CD" },
+ { u"bsol", u"\u005C" },
+ { u"bsolb", u"\u29C5" },
+ { u"bsolhsub", u"\u27C8" },
+ { u"bull", u"\u2022" },
+ { u"bullet", u"\u2022" },
+ { u"bump", u"\u224E" },
+ { u"bumpE", u"\u2AAE" },
+ { u"bumpe", u"\u224F" },
+ { u"bumpeq", u"\u224F" },
+ { u"cacute", u"\u0107" },
+ { u"cap", u"\u2229" },
+ { u"capand", u"\u2A44" },
+ { u"capbrcup", u"\u2A49" },
+ { u"capcap", u"\u2A4B" },
+ { u"capcup", u"\u2A47" },
+ { u"capdot", u"\u2A40" },
+ { u"caps", u"\u2229\uFE00" },
+ { u"caret", u"\u2041" },
+ { u"caron", u"\u02C7" },
+ { u"ccaps", u"\u2A4D" },
+ { u"ccaron", u"\u010D" },
+ { u"ccedil", u"\u00E7" },
+ { u"ccirc", u"\u0109" },
+ { u"ccups", u"\u2A4C" },
+ { u"ccupssm", u"\u2A50" },
+ { u"cdot", u"\u010B" },
+ { u"cedil", u"\u00B8" },
+ { u"cemptyv", u"\u29B2" },
+ { u"cent", u"\u00A2" },
+ { u"centerdot", u"\u00B7" },
+ { u"cfr", u"\U0001D520" },
+ { u"chcy", u"\u0447" },
+ { u"check", u"\u2713" },
+ { u"checkmark", u"\u2713" },
+ { u"chi", u"\u03C7" },
+ { u"cir", u"\u25CB" },
+ { u"cirE", u"\u29C3" },
+ { u"circ", u"\u02C6" },
+ { u"circeq", u"\u2257" },
+ { u"circlearrowleft", u"\u21BA" },
+ { u"circlearrowright", u"\u21BB" },
+ { u"circledR", u"\u00AE" },
+ { u"circledS", u"\u24C8" },
+ { u"circledast", u"\u229B" },
+ { u"circledcirc", u"\u229A" },
+ { u"circleddash", u"\u229D" },
+ { u"cire", u"\u2257" },
+ { u"cirfnint", u"\u2A10" },
+ { u"cirmid", u"\u2AEF" },
+ { u"cirscir", u"\u29C2" },
+ { u"clubs", u"\u2663" },
+ { u"clubsuit", u"\u2663" },
+ { u"colon", u"\u003A" },
+ { u"colone", u"\u2254" },
+ { u"coloneq", u"\u2254" },
+ { u"comma", u"\u002C" },
+ { u"commat", u"\u0040" },
+ { u"comp", u"\u2201" },
+ { u"compfn", u"\u2218" },
+ { u"complement", u"\u2201" },
+ { u"complexes", u"\u2102" },
+ { u"cong", u"\u2245" },
+ { u"congdot", u"\u2A6D" },
+ { u"conint", u"\u222E" },
+ { u"copf", u"\U0001D554" },
+ { u"coprod", u"\u2210" },
+ { u"copy", u"\u00A9" },
+ { u"copysr", u"\u2117" },
+ { u"crarr", u"\u21B5" },
+ { u"cross", u"\u2717" },
+ { u"cscr", u"\U0001D4B8" },
+ { u"csub", u"\u2ACF" },
+ { u"csube", u"\u2AD1" },
+ { u"csup", u"\u2AD0" },
+ { u"csupe", u"\u2AD2" },
+ { u"ctdot", u"\u22EF" },
+ { u"cudarrl", u"\u2938" },
+ { u"cudarrr", u"\u2935" },
+ { u"cuepr", u"\u22DE" },
+ { u"cuesc", u"\u22DF" },
+ { u"cularr", u"\u21B6" },
+ { u"cularrp", u"\u293D" },
+ { u"cup", u"\u222A" },
+ { u"cupbrcap", u"\u2A48" },
+ { u"cupcap", u"\u2A46" },
+ { u"cupcup", u"\u2A4A" },
+ { u"cupdot", u"\u228D" },
+ { u"cupor", u"\u2A45" },
+ { u"cups", u"\u222A\uFE00" },
+ { u"curarr", u"\u21B7" },
+ { u"curarrm", u"\u293C" },
+ { u"curlyeqprec", u"\u22DE" },
+ { u"curlyeqsucc", u"\u22DF" },
+ { u"curlyvee", u"\u22CE" },
+ { u"curlywedge", u"\u22CF" },
+ { u"curren", u"\u00A4" },
+ { u"curvearrowleft", u"\u21B6" },
+ { u"curvearrowright", u"\u21B7" },
+ { u"cuvee", u"\u22CE" },
+ { u"cuwed", u"\u22CF" },
+ { u"cwconint", u"\u2232" },
+ { u"cwint", u"\u2231" },
+ { u"cylcty", u"\u232D" },
+ { u"dArr", u"\u21D3" },
+ { u"dHar", u"\u2965" },
+ { u"dagger", u"\u2020" },
+ { u"daleth", u"\u2138" },
+ { u"darr", u"\u2193" },
+ { u"dash", u"\u2010" },
+ { u"dashv", u"\u22A3" },
+ { u"dbkarow", u"\u290F" },
+ { u"dblac", u"\u02DD" },
+ { u"dcaron", u"\u010F" },
+ { u"dcy", u"\u0434" },
+ { u"dd", u"\u2146" },
+ { u"ddagger", u"\u2021" },
+ { u"ddarr", u"\u21CA" },
+ { u"ddotseq", u"\u2A77" },
+ { u"deg", u"\u00B0" },
+ { u"delta", u"\u03B4" },
+ { u"demptyv", u"\u29B1" },
+ { u"dfisht", u"\u297F" },
+ { u"dfr", u"\U0001D521" },
+ { u"dharl", u"\u21C3" },
+ { u"dharr", u"\u21C2" },
+ { u"diam", u"\u22C4" },
+ { u"diamond", u"\u22C4" },
+ { u"diamondsuit", u"\u2666" },
+ { u"diams", u"\u2666" },
+ { u"die", u"\u00A8" },
+ { u"digamma", u"\u03DD" },
+ { u"disin", u"\u22F2" },
+ { u"div", u"\u00F7" },
+ { u"divide", u"\u00F7" },
+ { u"divideontimes", u"\u22C7" },
+ { u"divonx", u"\u22C7" },
+ { u"djcy", u"\u0452" },
+ { u"dlcorn", u"\u231E" },
+ { u"dlcrop", u"\u230D" },
+ { u"dollar", u"\u0024" },
+ { u"dopf", u"\U0001D555" },
+ { u"dot", u"\u02D9" },
+ { u"doteq", u"\u2250" },
+ { u"doteqdot", u"\u2251" },
+ { u"dotminus", u"\u2238" },
+ { u"dotplus", u"\u2214" },
+ { u"dotsquare", u"\u22A1" },
+ { u"doublebarwedge", u"\u2306" },
+ { u"downarrow", u"\u2193" },
+ { u"downdownarrows", u"\u21CA" },
+ { u"downharpoonleft", u"\u21C3" },
+ { u"downharpoonright", u"\u21C2" },
+ { u"drbkarow", u"\u2910" },
+ { u"drcorn", u"\u231F" },
+ { u"drcrop", u"\u230C" },
+ { u"dscr", u"\U0001D4B9" },
+ { u"dscy", u"\u0455" },
+ { u"dsol", u"\u29F6" },
+ { u"dstrok", u"\u0111" },
+ { u"dtdot", u"\u22F1" },
+ { u"dtri", u"\u25BF" },
+ { u"dtrif", u"\u25BE" },
+ { u"duarr", u"\u21F5" },
+ { u"duhar", u"\u296F" },
+ { u"dwangle", u"\u29A6" },
+ { u"dzcy", u"\u045F" },
+ { u"dzigrarr", u"\u27FF" },
+ { u"eDDot", u"\u2A77" },
+ { u"eDot", u"\u2251" },
+ { u"eacute", u"\u00E9" },
+ { u"easter", u"\u2A6E" },
+ { u"ecaron", u"\u011B" },
+ { u"ecir", u"\u2256" },
+ { u"ecirc", u"\u00EA" },
+ { u"ecolon", u"\u2255" },
+ { u"ecy", u"\u044D" },
+ { u"edot", u"\u0117" },
+ { u"ee", u"\u2147" },
+ { u"efDot", u"\u2252" },
+ { u"efr", u"\U0001D522" },
+ { u"eg", u"\u2A9A" },
+ { u"egrave", u"\u00E8" },
+ { u"egs", u"\u2A96" },
+ { u"egsdot", u"\u2A98" },
+ { u"el", u"\u2A99" },
+ { u"elinters", u"\u23E7" },
+ { u"ell", u"\u2113" },
+ { u"els", u"\u2A95" },
+ { u"elsdot", u"\u2A97" },
+ { u"emacr", u"\u0113" },
+ { u"empty", u"\u2205" },
+ { u"emptyset", u"\u2205" },
+ { u"emptyv", u"\u2205" },
+ { u"emsp", u"\u2003" },
+ { u"emsp13", u"\u2004" },
+ { u"emsp14", u"\u2005" },
+ { u"eng", u"\u014B" },
+ { u"ensp", u"\u2002" },
+ { u"eogon", u"\u0119" },
+ { u"eopf", u"\U0001D556" },
+ { u"epar", u"\u22D5" },
+ { u"eparsl", u"\u29E3" },
+ { u"eplus", u"\u2A71" },
+ { u"epsi", u"\u03B5" },
+ { u"epsilon", u"\u03B5" },
+ { u"epsiv", u"\u03F5" },
+ { u"eqcirc", u"\u2256" },
+ { u"eqcolon", u"\u2255" },
+ { u"eqsim", u"\u2242" },
+ { u"eqslantgtr", u"\u2A96" },
+ { u"eqslantless", u"\u2A95" },
+ { u"equals", u"\u003D" },
+ { u"equest", u"\u225F" },
+ { u"equiv", u"\u2261" },
+ { u"equivDD", u"\u2A78" },
+ { u"eqvparsl", u"\u29E5" },
+ { u"erDot", u"\u2253" },
+ { u"erarr", u"\u2971" },
+ { u"escr", u"\u212F" },
+ { u"esdot", u"\u2250" },
+ { u"esim", u"\u2242" },
+ { u"eta", u"\u03B7" },
+ { u"eth", u"\u00F0" },
+ { u"euml", u"\u00EB" },
+ { u"euro", u"\u20AC" },
+ { u"excl", u"\u0021" },
+ { u"exist", u"\u2203" },
+ { u"expectation", u"\u2130" },
+ { u"exponentiale", u"\u2147" },
+ { u"fallingdotseq", u"\u2252" },
+ { u"fcy", u"\u0444" },
+ { u"female", u"\u2640" },
+ { u"ffilig", u"\uFB03" },
+ { u"fflig", u"\uFB00" },
+ { u"ffllig", u"\uFB04" },
+ { u"ffr", u"\U0001D523" },
+ { u"filig", u"\uFB01" },
+ { u"fjlig", u"\u0066\u006A" },
+ { u"flat", u"\u266D" },
+ { u"fllig", u"\uFB02" },
+ { u"fltns", u"\u25B1" },
+ { u"fnof", u"\u0192" },
+ { u"fopf", u"\U0001D557" },
+ { u"forall", u"\u2200" },
+ { u"fork", u"\u22D4" },
+ { u"forkv", u"\u2AD9" },
+ { u"fpartint", u"\u2A0D" },
+ { u"frac12", u"\u00BD" },
+ { u"frac13", u"\u2153" },
+ { u"frac14", u"\u00BC" },
+ { u"frac15", u"\u2155" },
+ { u"frac16", u"\u2159" },
+ { u"frac18", u"\u215B" },
+ { u"frac23", u"\u2154" },
+ { u"frac25", u"\u2156" },
+ { u"frac34", u"\u00BE" },
+ { u"frac35", u"\u2157" },
+ { u"frac38", u"\u215C" },
+ { u"frac45", u"\u2158" },
+ { u"frac56", u"\u215A" },
+ { u"frac58", u"\u215D" },
+ { u"frac78", u"\u215E" },
+ { u"frasl", u"\u2044" },
+ { u"frown", u"\u2322" },
+ { u"fscr", u"\U0001D4BB" },
+ { u"gE", u"\u2267" },
+ { u"gEl", u"\u2A8C" },
+ { u"gacute", u"\u01F5" },
+ { u"gamma", u"\u03B3" },
+ { u"gammad", u"\u03DD" },
+ { u"gap", u"\u2A86" },
+ { u"gbreve", u"\u011F" },
+ { u"gcirc", u"\u011D" },
+ { u"gcy", u"\u0433" },
+ { u"gdot", u"\u0121" },
+ { u"ge", u"\u2265" },
+ { u"gel", u"\u22DB" },
+ { u"geq", u"\u2265" },
+ { u"geqq", u"\u2267" },
+ { u"geqslant", u"\u2A7E" },
+ { u"ges", u"\u2A7E" },
+ { u"gescc", u"\u2AA9" },
+ { u"gesdot", u"\u2A80" },
+ { u"gesdoto", u"\u2A82" },
+ { u"gesdotol", u"\u2A84" },
+ { u"gesl", u"\u22DB\uFE00" },
+ { u"gesles", u"\u2A94" },
+ { u"gfr", u"\U0001D524" },
+ { u"gg", u"\u226B" },
+ { u"ggg", u"\u22D9" },
+ { u"gimel", u"\u2137" },
+ { u"gjcy", u"\u0453" },
+ { u"gl", u"\u2277" },
+ { u"glE", u"\u2A92" },
+ { u"gla", u"\u2AA5" },
+ { u"glj", u"\u2AA4" },
+ { u"gnE", u"\u2269" },
+ { u"gnap", u"\u2A8A" },
+ { u"gnapprox", u"\u2A8A" },
+ { u"gne", u"\u2A88" },
+ { u"gneq", u"\u2A88" },
+ { u"gneqq", u"\u2269" },
+ { u"gnsim", u"\u22E7" },
+ { u"gopf", u"\U0001D558" },
+ { u"grave", u"\u0060" },
+ { u"gscr", u"\u210A" },
+ { u"gsim", u"\u2273" },
+ { u"gsime", u"\u2A8E" },
+ { u"gsiml", u"\u2A90" },
+ { u"gt", u"\u003E" },
+ { u"gtcc", u"\u2AA7" },
+ { u"gtcir", u"\u2A7A" },
+ { u"gtdot", u"\u22D7" },
+ { u"gtlPar", u"\u2995" },
+ { u"gtquest", u"\u2A7C" },
+ { u"gtrapprox", u"\u2A86" },
+ { u"gtrarr", u"\u2978" },
+ { u"gtrdot", u"\u22D7" },
+ { u"gtreqless", u"\u22DB" },
+ { u"gtreqqless", u"\u2A8C" },
+ { u"gtrless", u"\u2277" },
+ { u"gtrsim", u"\u2273" },
+ { u"gvertneqq", u"\u2269\uFE00" },
+ { u"gvnE", u"\u2269\uFE00" },
+ { u"hArr", u"\u21D4" },
+ { u"hairsp", u"\u200A" },
+ { u"half", u"\u00BD" },
+ { u"hamilt", u"\u210B" },
+ { u"hardcy", u"\u044A" },
+ { u"harr", u"\u2194" },
+ { u"harrcir", u"\u2948" },
+ { u"harrw", u"\u21AD" },
+ { u"hbar", u"\u210F" },
+ { u"hcirc", u"\u0125" },
+ { u"hearts", u"\u2665" },
+ { u"heartsuit", u"\u2665" },
+ { u"hellip", u"\u2026" },
+ { u"hercon", u"\u22B9" },
+ { u"hfr", u"\U0001D525" },
+ { u"hksearow", u"\u2925" },
+ { u"hkswarow", u"\u2926" },
+ { u"hoarr", u"\u21FF" },
+ { u"homtht", u"\u223B" },
+ { u"hookleftarrow", u"\u21A9" },
+ { u"hookrightarrow", u"\u21AA" },
+ { u"hopf", u"\U0001D559" },
+ { u"horbar", u"\u2015" },
+ { u"hscr", u"\U0001D4BD" },
+ { u"hslash", u"\u210F" },
+ { u"hstrok", u"\u0127" },
+ { u"hybull", u"\u2043" },
+ { u"hyphen", u"\u2010" },
+ { u"iacute", u"\u00ED" },
+ { u"ic", u"\u2063" },
+ { u"icirc", u"\u00EE" },
+ { u"icy", u"\u0438" },
+ { u"iecy", u"\u0435" },
+ { u"iexcl", u"\u00A1" },
+ { u"iff", u"\u21D4" },
+ { u"ifr", u"\U0001D526" },
+ { u"igrave", u"\u00EC" },
+ { u"ii", u"\u2148" },
+ { u"iiiint", u"\u2A0C" },
+ { u"iiint", u"\u222D" },
+ { u"iinfin", u"\u29DC" },
+ { u"iiota", u"\u2129" },
+ { u"ijlig", u"\u0133" },
+ { u"imacr", u"\u012B" },
+ { u"image", u"\u2111" },
+ { u"imagline", u"\u2110" },
+ { u"imagpart", u"\u2111" },
+ { u"imath", u"\u0131" },
+ { u"imof", u"\u22B7" },
+ { u"imped", u"\u01B5" },
+ { u"in", u"\u2208" },
+ { u"incare", u"\u2105" },
+ { u"infin", u"\u221E" },
+ { u"infintie", u"\u29DD" },
+ { u"inodot", u"\u0131" },
+ { u"int", u"\u222B" },
+ { u"intcal", u"\u22BA" },
+ { u"integers", u"\u2124" },
+ { u"intercal", u"\u22BA" },
+ { u"intlarhk", u"\u2A17" },
+ { u"intprod", u"\u2A3C" },
+ { u"iocy", u"\u0451" },
+ { u"iogon", u"\u012F" },
+ { u"iopf", u"\U0001D55A" },
+ { u"iota", u"\u03B9" },
+ { u"iprod", u"\u2A3C" },
+ { u"iquest", u"\u00BF" },
+ { u"iscr", u"\U0001D4BE" },
+ { u"isin", u"\u2208" },
+ { u"isinE", u"\u22F9" },
+ { u"isindot", u"\u22F5" },
+ { u"isins", u"\u22F4" },
+ { u"isinsv", u"\u22F3" },
+ { u"isinv", u"\u2208" },
+ { u"it", u"\u2062" },
+ { u"itilde", u"\u0129" },
+ { u"iukcy", u"\u0456" },
+ { u"iuml", u"\u00EF" },
+ { u"jcirc", u"\u0135" },
+ { u"jcy", u"\u0439" },
+ { u"jfr", u"\U0001D527" },
+ { u"jmath", u"\u0237" },
+ { u"jopf", u"\U0001D55B" },
+ { u"jscr", u"\U0001D4BF" },
+ { u"jsercy", u"\u0458" },
+ { u"jukcy", u"\u0454" },
+ { u"kappa", u"\u03BA" },
+ { u"kappav", u"\u03F0" },
+ { u"kcedil", u"\u0137" },
+ { u"kcy", u"\u043A" },
+ { u"kfr", u"\U0001D528" },
+ { u"kgreen", u"\u0138" },
+ { u"khcy", u"\u0445" },
+ { u"kjcy", u"\u045C" },
+ { u"kopf", u"\U0001D55C" },
+ { u"kscr", u"\U0001D4C0" },
+ { u"lAarr", u"\u21DA" },
+ { u"lArr", u"\u21D0" },
+ { u"lAtail", u"\u291B" },
+ { u"lBarr", u"\u290E" },
+ { u"lE", u"\u2266" },
+ { u"lEg", u"\u2A8B" },
+ { u"lHar", u"\u2962" },
+ { u"lacute", u"\u013A" },
+ { u"laemptyv", u"\u29B4" },
+ { u"lagran", u"\u2112" },
+ { u"lambda", u"\u03BB" },
+ { u"lang", u"\u27E8" },
+ { u"langd", u"\u2991" },
+ { u"langle", u"\u27E8" },
+ { u"lap", u"\u2A85" },
+ { u"laquo", u"\u00AB" },
+ { u"larr", u"\u2190" },
+ { u"larrb", u"\u21E4" },
+ { u"larrbfs", u"\u291F" },
+ { u"larrfs", u"\u291D" },
+ { u"larrhk", u"\u21A9" },
+ { u"larrlp", u"\u21AB" },
+ { u"larrpl", u"\u2939" },
+ { u"larrsim", u"\u2973" },
+ { u"larrtl", u"\u21A2" },
+ { u"lat", u"\u2AAB" },
+ { u"latail", u"\u2919" },
+ { u"late", u"\u2AAD" },
+ { u"lates", u"\u2AAD\uFE00" },
+ { u"lbarr", u"\u290C" },
+ { u"lbbrk", u"\u2772" },
+ { u"lbrace", u"\u007B" },
+ { u"lbrack", u"\u005B" },
+ { u"lbrke", u"\u298B" },
+ { u"lbrksld", u"\u298F" },
+ { u"lbrkslu", u"\u298D" },
+ { u"lcaron", u"\u013E" },
+ { u"lcedil", u"\u013C" },
+ { u"lceil", u"\u2308" },
+ { u"lcub", u"\u007B" },
+ { u"lcy", u"\u043B" },
+ { u"ldca", u"\u2936" },
+ { u"ldquo", u"\u201C" },
+ { u"ldquor", u"\u201E" },
+ { u"ldrdhar", u"\u2967" },
+ { u"ldrushar", u"\u294B" },
+ { u"ldsh", u"\u21B2" },
+ { u"le", u"\u2264" },
+ { u"leftarrow", u"\u2190" },
+ { u"leftarrowtail", u"\u21A2" },
+ { u"leftharpoondown", u"\u21BD" },
+ { u"leftharpoonup", u"\u21BC" },
+ { u"leftleftarrows", u"\u21C7" },
+ { u"leftrightarrow", u"\u2194" },
+ { u"leftrightarrows", u"\u21C6" },
+ { u"leftrightharpoons", u"\u21CB" },
+ { u"leftrightsquigarrow", u"\u21AD" },
+ { u"leftthreetimes", u"\u22CB" },
+ { u"leg", u"\u22DA" },
+ { u"leq", u"\u2264" },
+ { u"leqq", u"\u2266" },
+ { u"leqslant", u"\u2A7D" },
+ { u"les", u"\u2A7D" },
+ { u"lescc", u"\u2AA8" },
+ { u"lesdot", u"\u2A7F" },
+ { u"lesdoto", u"\u2A81" },
+ { u"lesdotor", u"\u2A83" },
+ { u"lesg", u"\u22DA\uFE00" },
+ { u"lesges", u"\u2A93" },
+ { u"lessapprox", u"\u2A85" },
+ { u"lessdot", u"\u22D6" },
+ { u"lesseqgtr", u"\u22DA" },
+ { u"lesseqqgtr", u"\u2A8B" },
+ { u"lessgtr", u"\u2276" },
+ { u"lesssim", u"\u2272" },
+ { u"lfisht", u"\u297C" },
+ { u"lfloor", u"\u230A" },
+ { u"lfr", u"\U0001D529" },
+ { u"lg", u"\u2276" },
+ { u"lgE", u"\u2A91" },
+ { u"lhard", u"\u21BD" },
+ { u"lharu", u"\u21BC" },
+ { u"lharul", u"\u296A" },
+ { u"lhblk", u"\u2584" },
+ { u"ljcy", u"\u0459" },
+ { u"ll", u"\u226A" },
+ { u"llarr", u"\u21C7" },
+ { u"llcorner", u"\u231E" },
+ { u"llhard", u"\u296B" },
+ { u"lltri", u"\u25FA" },
+ { u"lmidot", u"\u0140" },
+ { u"lmoust", u"\u23B0" },
+ { u"lmoustache", u"\u23B0" },
+ { u"lnE", u"\u2268" },
+ { u"lnap", u"\u2A89" },
+ { u"lnapprox", u"\u2A89" },
+ { u"lne", u"\u2A87" },
+ { u"lneq", u"\u2A87" },
+ { u"lneqq", u"\u2268" },
+ { u"lnsim", u"\u22E6" },
+ { u"loang", u"\u27EC" },
+ { u"loarr", u"\u21FD" },
+ { u"lobrk", u"\u27E6" },
+ { u"longleftarrow", u"\u27F5" },
+ { u"longleftrightarrow", u"\u27F7" },
+ { u"longmapsto", u"\u27FC" },
+ { u"longrightarrow", u"\u27F6" },
+ { u"looparrowleft", u"\u21AB" },
+ { u"looparrowright", u"\u21AC" },
+ { u"lopar", u"\u2985" },
+ { u"lopf", u"\U0001D55D" },
+ { u"loplus", u"\u2A2D" },
+ { u"lotimes", u"\u2A34" },
+ { u"lowast", u"\u2217" },
+ { u"lowbar", u"\u005F" },
+ { u"loz", u"\u25CA" },
+ { u"lozenge", u"\u25CA" },
+ { u"lozf", u"\u29EB" },
+ { u"lpar", u"\u0028" },
+ { u"lparlt", u"\u2993" },
+ { u"lrarr", u"\u21C6" },
+ { u"lrcorner", u"\u231F" },
+ { u"lrhar", u"\u21CB" },
+ { u"lrhard", u"\u296D" },
+ { u"lrm", u"\u200E" },
+ { u"lrtri", u"\u22BF" },
+ { u"lsaquo", u"\u2039" },
+ { u"lscr", u"\U0001D4C1" },
+ { u"lsh", u"\u21B0" },
+ { u"lsim", u"\u2272" },
+ { u"lsime", u"\u2A8D" },
+ { u"lsimg", u"\u2A8F" },
+ { u"lsqb", u"\u005B" },
+ { u"lsquo", u"\u2018" },
+ { u"lsquor", u"\u201A" },
+ { u"lstrok", u"\u0142" },
+ { u"lt", u"\u003C" },
+ { u"ltcc", u"\u2AA6" },
+ { u"ltcir", u"\u2A79" },
+ { u"ltdot", u"\u22D6" },
+ { u"lthree", u"\u22CB" },
+ { u"ltimes", u"\u22C9" },
+ { u"ltlarr", u"\u2976" },
+ { u"ltquest", u"\u2A7B" },
+ { u"ltrPar", u"\u2996" },
+ { u"ltri", u"\u25C3" },
+ { u"ltrie", u"\u22B4" },
+ { u"ltrif", u"\u25C2" },
+ { u"lurdshar", u"\u294A" },
+ { u"luruhar", u"\u2966" },
+ { u"lvertneqq", u"\u2268\uFE00" },
+ { u"lvnE", u"\u2268\uFE00" },
+ { u"mDDot", u"\u223A" },
+ { u"macr", u"\u00AF" },
+ { u"male", u"\u2642" },
+ { u"malt", u"\u2720" },
+ { u"maltese", u"\u2720" },
+ { u"map", u"\u21A6" },
+ { u"mapsto", u"\u21A6" },
+ { u"mapstodown", u"\u21A7" },
+ { u"mapstoleft", u"\u21A4" },
+ { u"mapstoup", u"\u21A5" },
+ { u"marker", u"\u25AE" },
+ { u"mcomma", u"\u2A29" },
+ { u"mcy", u"\u043C" },
+ { u"mdash", u"\u2014" },
+ { u"measuredangle", u"\u2221" },
+ { u"mfr", u"\U0001D52A" },
+ { u"mho", u"\u2127" },
+ { u"micro", u"\u00B5" },
+ { u"mid", u"\u2223" },
+ { u"midast", u"\u002A" },
+ { u"midcir", u"\u2AF0" },
+ { u"middot", u"\u00B7" },
+ { u"minus", u"\u2212" },
+ { u"minusb", u"\u229F" },
+ { u"minusd", u"\u2238" },
+ { u"minusdu", u"\u2A2A" },
+ { u"mlcp", u"\u2ADB" },
+ { u"mldr", u"\u2026" },
+ { u"mnplus", u"\u2213" },
+ { u"models", u"\u22A7" },
+ { u"mopf", u"\U0001D55E" },
+ { u"mp", u"\u2213" },
+ { u"mscr", u"\U0001D4C2" },
+ { u"mstpos", u"\u223E" },
+ { u"mu", u"\u03BC" },
+ { u"multimap", u"\u22B8" },
+ { u"mumap", u"\u22B8" },
+ { u"nGg", u"\u22D9\u0338" },
+ { u"nGt", u"\u226B\u20D2" },
+ { u"nGtv", u"\u226B\u0338" },
+ { u"nLeftarrow", u"\u21CD" },
+ { u"nLeftrightarrow", u"\u21CE" },
+ { u"nLl", u"\u22D8\u0338" },
+ { u"nLt", u"\u226A\u20D2" },
+ { u"nLtv", u"\u226A\u0338" },
+ { u"nRightarrow", u"\u21CF" },
+ { u"nVDash", u"\u22AF" },
+ { u"nVdash", u"\u22AE" },
+ { u"nabla", u"\u2207" },
+ { u"nacute", u"\u0144" },
+ { u"nang", u"\u2220\u20D2" },
+ { u"nap", u"\u2249" },
+ { u"napE", u"\u2A70\u0338" },
+ { u"napid", u"\u224B\u0338" },
+ { u"napos", u"\u0149" },
+ { u"napprox", u"\u2249" },
+ { u"natur", u"\u266E" },
+ { u"natural", u"\u266E" },
+ { u"naturals", u"\u2115" },
+ { u"nbsp", u"\u00A0" },
+ { u"nbump", u"\u224E\u0338" },
+ { u"nbumpe", u"\u224F\u0338" },
+ { u"ncap", u"\u2A43" },
+ { u"ncaron", u"\u0148" },
+ { u"ncedil", u"\u0146" },
+ { u"ncong", u"\u2247" },
+ { u"ncongdot", u"\u2A6D\u0338" },
+ { u"ncup", u"\u2A42" },
+ { u"ncy", u"\u043D" },
+ { u"ndash", u"\u2013" },
+ { u"ne", u"\u2260" },
+ { u"neArr", u"\u21D7" },
+ { u"nearhk", u"\u2924" },
+ { u"nearr", u"\u2197" },
+ { u"nearrow", u"\u2197" },
+ { u"nedot", u"\u2250\u0338" },
+ { u"nequiv", u"\u2262" },
+ { u"nesear", u"\u2928" },
+ { u"nesim", u"\u2242\u0338" },
+ { u"nexist", u"\u2204" },
+ { u"nexists", u"\u2204" },
+ { u"nfr", u"\U0001D52B" },
+ { u"ngE", u"\u2267\u0338" },
+ { u"nge", u"\u2271" },
+ { u"ngeq", u"\u2271" },
+ { u"ngeqq", u"\u2267\u0338" },
+ { u"ngeqslant", u"\u2A7E\u0338" },
+ { u"nges", u"\u2A7E\u0338" },
+ { u"ngsim", u"\u2275" },
+ { u"ngt", u"\u226F" },
+ { u"ngtr", u"\u226F" },
+ { u"nhArr", u"\u21CE" },
+ { u"nharr", u"\u21AE" },
+ { u"nhpar", u"\u2AF2" },
+ { u"ni", u"\u220B" },
+ { u"nis", u"\u22FC" },
+ { u"nisd", u"\u22FA" },
+ { u"niv", u"\u220B" },
+ { u"njcy", u"\u045A" },
+ { u"nlArr", u"\u21CD" },
+ { u"nlE", u"\u2266\u0338" },
+ { u"nlarr", u"\u219A" },
+ { u"nldr", u"\u2025" },
+ { u"nle", u"\u2270" },
+ { u"nleftarrow", u"\u219A" },
+ { u"nleftrightarrow", u"\u21AE" },
+ { u"nleq", u"\u2270" },
+ { u"nleqq", u"\u2266\u0338" },
+ { u"nleqslant", u"\u2A7D\u0338" },
+ { u"nles", u"\u2A7D\u0338" },
+ { u"nless", u"\u226E" },
+ { u"nlsim", u"\u2274" },
+ { u"nlt", u"\u226E" },
+ { u"nltri", u"\u22EA" },
+ { u"nltrie", u"\u22EC" },
+ { u"nmid", u"\u2224" },
+ { u"nopf", u"\U0001D55F" },
+ { u"not", u"\u00AC" },
+ { u"notin", u"\u2209" },
+ { u"notinE", u"\u22F9\u0338" },
+ { u"notindot", u"\u22F5\u0338" },
+ { u"notinva", u"\u2209" },
+ { u"notinvb", u"\u22F7" },
+ { u"notinvc", u"\u22F6" },
+ { u"notni", u"\u220C" },
+ { u"notniva", u"\u220C" },
+ { u"notnivb", u"\u22FE" },
+ { u"notnivc", u"\u22FD" },
+ { u"npar", u"\u2226" },
+ { u"nparallel", u"\u2226" },
+ { u"nparsl", u"\u2AFD\u20E5" },
+ { u"npart", u"\u2202\u0338" },
+ { u"npolint", u"\u2A14" },
+ { u"npr", u"\u2280" },
+ { u"nprcue", u"\u22E0" },
+ { u"npre", u"\u2AAF\u0338" },
+ { u"nprec", u"\u2280" },
+ { u"npreceq", u"\u2AAF\u0338" },
+ { u"nrArr", u"\u21CF" },
+ { u"nrarr", u"\u219B" },
+ { u"nrarrc", u"\u2933\u0338" },
+ { u"nrarrw", u"\u219D\u0338" },
+ { u"nrightarrow", u"\u219B" },
+ { u"nrtri", u"\u22EB" },
+ { u"nrtrie", u"\u22ED" },
+ { u"nsc", u"\u2281" },
+ { u"nsccue", u"\u22E1" },
+ { u"nsce", u"\u2AB0\u0338" },
+ { u"nscr", u"\U0001D4C3" },
+ { u"nshortmid", u"\u2224" },
+ { u"nshortparallel", u"\u2226" },
+ { u"nsim", u"\u2241" },
+ { u"nsime", u"\u2244" },
+ { u"nsimeq", u"\u2244" },
+ { u"nsmid", u"\u2224" },
+ { u"nspar", u"\u2226" },
+ { u"nsqsube", u"\u22E2" },
+ { u"nsqsupe", u"\u22E3" },
+ { u"nsub", u"\u2284" },
+ { u"nsubE", u"\u2AC5\u0338" },
+ { u"nsube", u"\u2288" },
+ { u"nsubset", u"\u2282\u20D2" },
+ { u"nsubseteq", u"\u2288" },
+ { u"nsubseteqq", u"\u2AC5\u0338" },
+ { u"nsucc", u"\u2281" },
+ { u"nsucceq", u"\u2AB0\u0338" },
+ { u"nsup", u"\u2285" },
+ { u"nsupE", u"\u2AC6\u0338" },
+ { u"nsupe", u"\u2289" },
+ { u"nsupset", u"\u2283\u20D2" },
+ { u"nsupseteq", u"\u2289" },
+ { u"nsupseteqq", u"\u2AC6\u0338" },
+ { u"ntgl", u"\u2279" },
+ { u"ntilde", u"\u00F1" },
+ { u"ntlg", u"\u2278" },
+ { u"ntriangleleft", u"\u22EA" },
+ { u"ntrianglelefteq", u"\u22EC" },
+ { u"ntriangleright", u"\u22EB" },
+ { u"ntrianglerighteq", u"\u22ED" },
+ { u"nu", u"\u03BD" },
+ { u"num", u"\u0023" },
+ { u"numero", u"\u2116" },
+ { u"numsp", u"\u2007" },
+ { u"nvDash", u"\u22AD" },
+ { u"nvHarr", u"\u2904" },
+ { u"nvap", u"\u224D\u20D2" },
+ { u"nvdash", u"\u22AC" },
+ { u"nvge", u"\u2265\u20D2" },
+ { u"nvgt", u"\u003E\u20D2" },
+ { u"nvinfin", u"\u29DE" },
+ { u"nvlArr", u"\u2902" },
+ { u"nvle", u"\u2264\u20D2" },
+ { u"nvlt", u"\u003C\u20D2" },
+ { u"nvltrie", u"\u22B4\u20D2" },
+ { u"nvrArr", u"\u2903" },
+ { u"nvrtrie", u"\u22B5\u20D2" },
+ { u"nvsim", u"\u223C\u20D2" },
+ { u"nwArr", u"\u21D6" },
+ { u"nwarhk", u"\u2923" },
+ { u"nwarr", u"\u2196" },
+ { u"nwarrow", u"\u2196" },
+ { u"nwnear", u"\u2927" },
+ { u"oS", u"\u24C8" },
+ { u"oacute", u"\u00F3" },
+ { u"oast", u"\u229B" },
+ { u"ocir", u"\u229A" },
+ { u"ocirc", u"\u00F4" },
+ { u"ocy", u"\u043E" },
+ { u"odash", u"\u229D" },
+ { u"odblac", u"\u0151" },
+ { u"odiv", u"\u2A38" },
+ { u"odot", u"\u2299" },
+ { u"odsold", u"\u29BC" },
+ { u"oelig", u"\u0153" },
+ { u"ofcir", u"\u29BF" },
+ { u"ofr", u"\U0001D52C" },
+ { u"ogon", u"\u02DB" },
+ { u"ograve", u"\u00F2" },
+ { u"ogt", u"\u29C1" },
+ { u"ohbar", u"\u29B5" },
+ { u"ohm", u"\u03A9" },
+ { u"oint", u"\u222E" },
+ { u"olarr", u"\u21BA" },
+ { u"olcir", u"\u29BE" },
+ { u"olcross", u"\u29BB" },
+ { u"oline", u"\u203E" },
+ { u"olt", u"\u29C0" },
+ { u"omacr", u"\u014D" },
+ { u"omega", u"\u03C9" },
+ { u"omicron", u"\u03BF" },
+ { u"omid", u"\u29B6" },
+ { u"ominus", u"\u2296" },
+ { u"oopf", u"\U0001D560" },
+ { u"opar", u"\u29B7" },
+ { u"operp", u"\u29B9" },
+ { u"oplus", u"\u2295" },
+ { u"or", u"\u2228" },
+ { u"orarr", u"\u21BB" },
+ { u"ord", u"\u2A5D" },
+ { u"order", u"\u2134" },
+ { u"orderof", u"\u2134" },
+ { u"ordf", u"\u00AA" },
+ { u"ordm", u"\u00BA" },
+ { u"origof", u"\u22B6" },
+ { u"oror", u"\u2A56" },
+ { u"orslope", u"\u2A57" },
+ { u"orv", u"\u2A5B" },
+ { u"oscr", u"\u2134" },
+ { u"oslash", u"\u00F8" },
+ { u"osol", u"\u2298" },
+ { u"otilde", u"\u00F5" },
+ { u"otimes", u"\u2297" },
+ { u"otimesas", u"\u2A36" },
+ { u"ouml", u"\u00F6" },
+ { u"ovbar", u"\u233D" },
+ { u"par", u"\u2225" },
+ { u"para", u"\u00B6" },
+ { u"parallel", u"\u2225" },
+ { u"parsim", u"\u2AF3" },
+ { u"parsl", u"\u2AFD" },
+ { u"part", u"\u2202" },
+ { u"pcy", u"\u043F" },
+ { u"percnt", u"\u0025" },
+ { u"period", u"\u002E" },
+ { u"permil", u"\u2030" },
+ { u"perp", u"\u22A5" },
+ { u"pertenk", u"\u2031" },
+ { u"pfr", u"\U0001D52D" },
+ { u"phi", u"\u03C6" },
+ { u"phiv", u"\u03D5" },
+ { u"phmmat", u"\u2133" },
+ { u"phone", u"\u260E" },
+ { u"pi", u"\u03C0" },
+ { u"pitchfork", u"\u22D4" },
+ { u"piv", u"\u03D6" },
+ { u"planck", u"\u210F" },
+ { u"planckh", u"\u210E" },
+ { u"plankv", u"\u210F" },
+ { u"plus", u"\u002B" },
+ { u"plusacir", u"\u2A23" },
+ { u"plusb", u"\u229E" },
+ { u"pluscir", u"\u2A22" },
+ { u"plusdo", u"\u2214" },
+ { u"plusdu", u"\u2A25" },
+ { u"pluse", u"\u2A72" },
+ { u"plusmn", u"\u00B1" },
+ { u"plussim", u"\u2A26" },
+ { u"plustwo", u"\u2A27" },
+ { u"pm", u"\u00B1" },
+ { u"pointint", u"\u2A15" },
+ { u"popf", u"\U0001D561" },
+ { u"pound", u"\u00A3" },
+ { u"pr", u"\u227A" },
+ { u"prE", u"\u2AB3" },
+ { u"prap", u"\u2AB7" },
+ { u"prcue", u"\u227C" },
+ { u"pre", u"\u2AAF" },
+ { u"prec", u"\u227A" },
+ { u"precapprox", u"\u2AB7" },
+ { u"preccurlyeq", u"\u227C" },
+ { u"preceq", u"\u2AAF" },
+ { u"precnapprox", u"\u2AB9" },
+ { u"precneqq", u"\u2AB5" },
+ { u"precnsim", u"\u22E8" },
+ { u"precsim", u"\u227E" },
+ { u"prime", u"\u2032" },
+ { u"primes", u"\u2119" },
+ { u"prnE", u"\u2AB5" },
+ { u"prnap", u"\u2AB9" },
+ { u"prnsim", u"\u22E8" },
+ { u"prod", u"\u220F" },
+ { u"profalar", u"\u232E" },
+ { u"profline", u"\u2312" },
+ { u"profsurf", u"\u2313" },
+ { u"prop", u"\u221D" },
+ { u"propto", u"\u221D" },
+ { u"prsim", u"\u227E" },
+ { u"prurel", u"\u22B0" },
+ { u"pscr", u"\U0001D4C5" },
+ { u"psi", u"\u03C8" },
+ { u"puncsp", u"\u2008" },
+ { u"qfr", u"\U0001D52E" },
+ { u"qint", u"\u2A0C" },
+ { u"qopf", u"\U0001D562" },
+ { u"qprime", u"\u2057" },
+ { u"qscr", u"\U0001D4C6" },
+ { u"quaternions", u"\u210D" },
+ { u"quatint", u"\u2A16" },
+ { u"quest", u"\u003F" },
+ { u"questeq", u"\u225F" },
+ { u"quot", u"\u0022" },
+ { u"rAarr", u"\u21DB" },
+ { u"rArr", u"\u21D2" },
+ { u"rAtail", u"\u291C" },
+ { u"rBarr", u"\u290F" },
+ { u"rHar", u"\u2964" },
+ { u"race", u"\u223D\u0331" },
+ { u"racute", u"\u0155" },
+ { u"radic", u"\u221A" },
+ { u"raemptyv", u"\u29B3" },
+ { u"rang", u"\u27E9" },
+ { u"rangd", u"\u2992" },
+ { u"range", u"\u29A5" },
+ { u"rangle", u"\u27E9" },
+ { u"raquo", u"\u00BB" },
+ { u"rarr", u"\u2192" },
+ { u"rarrap", u"\u2975" },
+ { u"rarrb", u"\u21E5" },
+ { u"rarrbfs", u"\u2920" },
+ { u"rarrc", u"\u2933" },
+ { u"rarrfs", u"\u291E" },
+ { u"rarrhk", u"\u21AA" },
+ { u"rarrlp", u"\u21AC" },
+ { u"rarrpl", u"\u2945" },
+ { u"rarrsim", u"\u2974" },
+ { u"rarrtl", u"\u21A3" },
+ { u"rarrw", u"\u219D" },
+ { u"ratail", u"\u291A" },
+ { u"ratio", u"\u2236" },
+ { u"rationals", u"\u211A" },
+ { u"rbarr", u"\u290D" },
+ { u"rbbrk", u"\u2773" },
+ { u"rbrace", u"\u007D" },
+ { u"rbrack", u"\u005D" },
+ { u"rbrke", u"\u298C" },
+ { u"rbrksld", u"\u298E" },
+ { u"rbrkslu", u"\u2990" },
+ { u"rcaron", u"\u0159" },
+ { u"rcedil", u"\u0157" },
+ { u"rceil", u"\u2309" },
+ { u"rcub", u"\u007D" },
+ { u"rcy", u"\u0440" },
+ { u"rdca", u"\u2937" },
+ { u"rdldhar", u"\u2969" },
+ { u"rdquo", u"\u201D" },
+ { u"rdquor", u"\u201D" },
+ { u"rdsh", u"\u21B3" },
+ { u"real", u"\u211C" },
+ { u"realine", u"\u211B" },
+ { u"realpart", u"\u211C" },
+ { u"reals", u"\u211D" },
+ { u"rect", u"\u25AD" },
+ { u"reg", u"\u00AE" },
+ { u"rfisht", u"\u297D" },
+ { u"rfloor", u"\u230B" },
+ { u"rfr", u"\U0001D52F" },
+ { u"rhard", u"\u21C1" },
+ { u"rharu", u"\u21C0" },
+ { u"rharul", u"\u296C" },
+ { u"rho", u"\u03C1" },
+ { u"rhov", u"\u03F1" },
+ { u"rightarrow", u"\u2192" },
+ { u"rightarrowtail", u"\u21A3" },
+ { u"rightharpoondown", u"\u21C1" },
+ { u"rightharpoonup", u"\u21C0" },
+ { u"rightleftarrows", u"\u21C4" },
+ { u"rightleftharpoons", u"\u21CC" },
+ { u"rightrightarrows", u"\u21C9" },
+ { u"rightsquigarrow", u"\u219D" },
+ { u"rightthreetimes", u"\u22CC" },
+ { u"ring", u"\u02DA" },
+ { u"risingdotseq", u"\u2253" },
+ { u"rlarr", u"\u21C4" },
+ { u"rlhar", u"\u21CC" },
+ { u"rlm", u"\u200F" },
+ { u"rmoust", u"\u23B1" },
+ { u"rmoustache", u"\u23B1" },
+ { u"rnmid", u"\u2AEE" },
+ { u"roang", u"\u27ED" },
+ { u"roarr", u"\u21FE" },
+ { u"robrk", u"\u27E7" },
+ { u"ropar", u"\u2986" },
+ { u"ropf", u"\U0001D563" },
+ { u"roplus", u"\u2A2E" },
+ { u"rotimes", u"\u2A35" },
+ { u"rpar", u"\u0029" },
+ { u"rpargt", u"\u2994" },
+ { u"rppolint", u"\u2A12" },
+ { u"rrarr", u"\u21C9" },
+ { u"rsaquo", u"\u203A" },
+ { u"rscr", u"\U0001D4C7" },
+ { u"rsh", u"\u21B1" },
+ { u"rsqb", u"\u005D" },
+ { u"rsquo", u"\u2019" },
+ { u"rsquor", u"\u2019" },
+ { u"rthree", u"\u22CC" },
+ { u"rtimes", u"\u22CA" },
+ { u"rtri", u"\u25B9" },
+ { u"rtrie", u"\u22B5" },
+ { u"rtrif", u"\u25B8" },
+ { u"rtriltri", u"\u29CE" },
+ { u"ruluhar", u"\u2968" },
+ { u"rx", u"\u211E" },
+ { u"sacute", u"\u015B" },
+ { u"sbquo", u"\u201A" },
+ { u"sc", u"\u227B" },
+ { u"scE", u"\u2AB4" },
+ { u"scap", u"\u2AB8" },
+ { u"scaron", u"\u0161" },
+ { u"sccue", u"\u227D" },
+ { u"sce", u"\u2AB0" },
+ { u"scedil", u"\u015F" },
+ { u"scirc", u"\u015D" },
+ { u"scnE", u"\u2AB6" },
+ { u"scnap", u"\u2ABA" },
+ { u"scnsim", u"\u22E9" },
+ { u"scpolint", u"\u2A13" },
+ { u"scsim", u"\u227F" },
+ { u"scy", u"\u0441" },
+ { u"sdot", u"\u22C5" },
+ { u"sdotb", u"\u22A1" },
+ { u"sdote", u"\u2A66" },
+ { u"seArr", u"\u21D8" },
+ { u"searhk", u"\u2925" },
+ { u"searr", u"\u2198" },
+ { u"searrow", u"\u2198" },
+ { u"sect", u"\u00A7" },
+ { u"semi", u"\u003B" },
+ { u"seswar", u"\u2929" },
+ { u"setminus", u"\u2216" },
+ { u"setmn", u"\u2216" },
+ { u"sext", u"\u2736" },
+ { u"sfr", u"\U0001D530" },
+ { u"sfrown", u"\u2322" },
+ { u"sharp", u"\u266F" },
+ { u"shchcy", u"\u0449" },
+ { u"shcy", u"\u0448" },
+ { u"shortmid", u"\u2223" },
+ { u"shortparallel", u"\u2225" },
+ { u"shy", u"\u00AD" },
+ { u"sigma", u"\u03C3" },
+ { u"sigmaf", u"\u03C2" },
+ { u"sigmav", u"\u03C2" },
+ { u"sim", u"\u223C" },
+ { u"simdot", u"\u2A6A" },
+ { u"sime", u"\u2243" },
+ { u"simeq", u"\u2243" },
+ { u"simg", u"\u2A9E" },
+ { u"simgE", u"\u2AA0" },
+ { u"siml", u"\u2A9D" },
+ { u"simlE", u"\u2A9F" },
+ { u"simne", u"\u2246" },
+ { u"simplus", u"\u2A24" },
+ { u"simrarr", u"\u2972" },
+ { u"slarr", u"\u2190" },
+ { u"smallsetminus", u"\u2216" },
+ { u"smashp", u"\u2A33" },
+ { u"smeparsl", u"\u29E4" },
+ { u"smid", u"\u2223" },
+ { u"smile", u"\u2323" },
+ { u"smt", u"\u2AAA" },
+ { u"smte", u"\u2AAC" },
+ { u"smtes", u"\u2AAC\uFE00" },
+ { u"softcy", u"\u044C" },
+ { u"sol", u"\u002F" },
+ { u"solb", u"\u29C4" },
+ { u"solbar", u"\u233F" },
+ { u"sopf", u"\U0001D564" },
+ { u"spades", u"\u2660" },
+ { u"spadesuit", u"\u2660" },
+ { u"spar", u"\u2225" },
+ { u"sqcap", u"\u2293" },
+ { u"sqcaps", u"\u2293\uFE00" },
+ { u"sqcup", u"\u2294" },
+ { u"sqcups", u"\u2294\uFE00" },
+ { u"sqsub", u"\u228F" },
+ { u"sqsube", u"\u2291" },
+ { u"sqsubset", u"\u228F" },
+ { u"sqsubseteq", u"\u2291" },
+ { u"sqsup", u"\u2290" },
+ { u"sqsupe", u"\u2292" },
+ { u"sqsupset", u"\u2290" },
+ { u"sqsupseteq", u"\u2292" },
+ { u"squ", u"\u25A1" },
+ { u"square", u"\u25A1" },
+ { u"squarf", u"\u25AA" },
+ { u"squf", u"\u25AA" },
+ { u"srarr", u"\u2192" },
+ { u"sscr", u"\U0001D4C8" },
+ { u"ssetmn", u"\u2216" },
+ { u"ssmile", u"\u2323" },
+ { u"sstarf", u"\u22C6" },
+ { u"star", u"\u2606" },
+ { u"starf", u"\u2605" },
+ { u"straightepsilon", u"\u03F5" },
+ { u"straightphi", u"\u03D5" },
+ { u"strns", u"\u00AF" },
+ { u"sub", u"\u2282" },
+ { u"subE", u"\u2AC5" },
+ { u"subdot", u"\u2ABD" },
+ { u"sube", u"\u2286" },
+ { u"subedot", u"\u2AC3" },
+ { u"submult", u"\u2AC1" },
+ { u"subnE", u"\u2ACB" },
+ { u"subne", u"\u228A" },
+ { u"subplus", u"\u2ABF" },
+ { u"subrarr", u"\u2979" },
+ { u"subset", u"\u2282" },
+ { u"subseteq", u"\u2286" },
+ { u"subseteqq", u"\u2AC5" },
+ { u"subsetneq", u"\u228A" },
+ { u"subsetneqq", u"\u2ACB" },
+ { u"subsim", u"\u2AC7" },
+ { u"subsub", u"\u2AD5" },
+ { u"subsup", u"\u2AD3" },
+ { u"succ", u"\u227B" },
+ { u"succapprox", u"\u2AB8" },
+ { u"succcurlyeq", u"\u227D" },
+ { u"succeq", u"\u2AB0" },
+ { u"succnapprox", u"\u2ABA" },
+ { u"succneqq", u"\u2AB6" },
+ { u"succnsim", u"\u22E9" },
+ { u"succsim", u"\u227F" },
+ { u"sum", u"\u2211" },
+ { u"sung", u"\u266A" },
+ { u"sup", u"\u2283" },
+ { u"sup1", u"\u00B9" },
+ { u"sup2", u"\u00B2" },
+ { u"sup3", u"\u00B3" },
+ { u"supE", u"\u2AC6" },
+ { u"supdot", u"\u2ABE" },
+ { u"supdsub", u"\u2AD8" },
+ { u"supe", u"\u2287" },
+ { u"supedot", u"\u2AC4" },
+ { u"suphsol", u"\u27C9" },
+ { u"suphsub", u"\u2AD7" },
+ { u"suplarr", u"\u297B" },
+ { u"supmult", u"\u2AC2" },
+ { u"supnE", u"\u2ACC" },
+ { u"supne", u"\u228B" },
+ { u"supplus", u"\u2AC0" },
+ { u"supset", u"\u2283" },
+ { u"supseteq", u"\u2287" },
+ { u"supseteqq", u"\u2AC6" },
+ { u"supsetneq", u"\u228B" },
+ { u"supsetneqq", u"\u2ACC" },
+ { u"supsim", u"\u2AC8" },
+ { u"supsub", u"\u2AD4" },
+ { u"supsup", u"\u2AD6" },
+ { u"swArr", u"\u21D9" },
+ { u"swarhk", u"\u2926" },
+ { u"swarr", u"\u2199" },
+ { u"swarrow", u"\u2199" },
+ { u"swnwar", u"\u292A" },
+ { u"szlig", u"\u00DF" },
+ { u"target", u"\u2316" },
+ { u"tau", u"\u03C4" },
+ { u"tbrk", u"\u23B4" },
+ { u"tcaron", u"\u0165" },
+ { u"tcedil", u"\u0163" },
+ { u"tcy", u"\u0442" },
+ { u"tdot", u"\u20DB" },
+ { u"telrec", u"\u2315" },
+ { u"tfr", u"\U0001D531" },
+ { u"there4", u"\u2234" },
+ { u"therefore", u"\u2234" },
+ { u"theta", u"\u03B8" },
+ { u"thetasym", u"\u03D1" },
+ { u"thetav", u"\u03D1" },
+ { u"thickapprox", u"\u2248" },
+ { u"thicksim", u"\u223C" },
+ { u"thinsp", u"\u2009" },
+ { u"thkap", u"\u2248" },
+ { u"thksim", u"\u223C" },
+ { u"thorn", u"\u00FE" },
+ { u"tilde", u"\u02DC" },
+ { u"times", u"\u00D7" },
+ { u"timesb", u"\u22A0" },
+ { u"timesbar", u"\u2A31" },
+ { u"timesd", u"\u2A30" },
+ { u"tint", u"\u222D" },
+ { u"toea", u"\u2928" },
+ { u"top", u"\u22A4" },
+ { u"topbot", u"\u2336" },
+ { u"topcir", u"\u2AF1" },
+ { u"topf", u"\U0001D565" },
+ { u"topfork", u"\u2ADA" },
+ { u"tosa", u"\u2929" },
+ { u"tprime", u"\u2034" },
+ { u"trade", u"\u2122" },
+ { u"triangle", u"\u25B5" },
+ { u"triangledown", u"\u25BF" },
+ { u"triangleleft", u"\u25C3" },
+ { u"trianglelefteq", u"\u22B4" },
+ { u"triangleq", u"\u225C" },
+ { u"triangleright", u"\u25B9" },
+ { u"trianglerighteq", u"\u22B5" },
+ { u"tridot", u"\u25EC" },
+ { u"trie", u"\u225C" },
+ { u"triminus", u"\u2A3A" },
+ { u"triplus", u"\u2A39" },
+ { u"trisb", u"\u29CD" },
+ { u"tritime", u"\u2A3B" },
+ { u"trpezium", u"\u23E2" },
+ { u"tscr", u"\U0001D4C9" },
+ { u"tscy", u"\u0446" },
+ { u"tshcy", u"\u045B" },
+ { u"tstrok", u"\u0167" },
+ { u"twixt", u"\u226C" },
+ { u"twoheadleftarrow", u"\u219E" },
+ { u"twoheadrightarrow", u"\u21A0" },
+ { u"uArr", u"\u21D1" },
+ { u"uHar", u"\u2963" },
+ { u"uacute", u"\u00FA" },
+ { u"uarr", u"\u2191" },
+ { u"ubrcy", u"\u045E" },
+ { u"ubreve", u"\u016D" },
+ { u"ucirc", u"\u00FB" },
+ { u"ucy", u"\u0443" },
+ { u"udarr", u"\u21C5" },
+ { u"udblac", u"\u0171" },
+ { u"udhar", u"\u296E" },
+ { u"ufisht", u"\u297E" },
+ { u"ufr", u"\U0001D532" },
+ { u"ugrave", u"\u00F9" },
+ { u"uharl", u"\u21BF" },
+ { u"uharr", u"\u21BE" },
+ { u"uhblk", u"\u2580" },
+ { u"ulcorn", u"\u231C" },
+ { u"ulcorner", u"\u231C" },
+ { u"ulcrop", u"\u230F" },
+ { u"ultri", u"\u25F8" },
+ { u"umacr", u"\u016B" },
+ { u"uml", u"\u00A8" },
+ { u"uogon", u"\u0173" },
+ { u"uopf", u"\U0001D566" },
+ { u"uparrow", u"\u2191" },
+ { u"updownarrow", u"\u2195" },
+ { u"upharpoonleft", u"\u21BF" },
+ { u"upharpoonright", u"\u21BE" },
+ { u"uplus", u"\u228E" },
+ { u"upsi", u"\u03C5" },
+ { u"upsih", u"\u03D2" },
+ { u"upsilon", u"\u03C5" },
+ { u"upuparrows", u"\u21C8" },
+ { u"urcorn", u"\u231D" },
+ { u"urcorner", u"\u231D" },
+ { u"urcrop", u"\u230E" },
+ { u"uring", u"\u016F" },
+ { u"urtri", u"\u25F9" },
+ { u"uscr", u"\U0001D4CA" },
+ { u"utdot", u"\u22F0" },
+ { u"utilde", u"\u0169" },
+ { u"utri", u"\u25B5" },
+ { u"utrif", u"\u25B4" },
+ { u"uuarr", u"\u21C8" },
+ { u"uuml", u"\u00FC" },
+ { u"uwangle", u"\u29A7" },
+ { u"vArr", u"\u21D5" },
+ { u"vBar", u"\u2AE8" },
+ { u"vBarv", u"\u2AE9" },
+ { u"vDash", u"\u22A8" },
+ { u"vangrt", u"\u299C" },
+ { u"varepsilon", u"\u03F5" },
+ { u"varkappa", u"\u03F0" },
+ { u"varnothing", u"\u2205" },
+ { u"varphi", u"\u03D5" },
+ { u"varpi", u"\u03D6" },
+ { u"varpropto", u"\u221D" },
+ { u"varr", u"\u2195" },
+ { u"varrho", u"\u03F1" },
+ { u"varsigma", u"\u03C2" },
+ { u"varsubsetneq", u"\u228A\uFE00" },
+ { u"varsubsetneqq", u"\u2ACB\uFE00" },
+ { u"varsupsetneq", u"\u228B\uFE00" },
+ { u"varsupsetneqq", u"\u2ACC\uFE00" },
+ { u"vartheta", u"\u03D1" },
+ { u"vartriangleleft", u"\u22B2" },
+ { u"vartriangleright", u"\u22B3" },
+ { u"vcy", u"\u0432" },
+ { u"vdash", u"\u22A2" },
+ { u"vee", u"\u2228" },
+ { u"veebar", u"\u22BB" },
+ { u"veeeq", u"\u225A" },
+ { u"vellip", u"\u22EE" },
+ { u"verbar", u"\u007C" },
+ { u"vert", u"\u007C" },
+ { u"vfr", u"\U0001D533" },
+ { u"vltri", u"\u22B2" },
+ { u"vnsub", u"\u2282\u20D2" },
+ { u"vnsup", u"\u2283\u20D2" },
+ { u"vopf", u"\U0001D567" },
+ { u"vprop", u"\u221D" },
+ { u"vrtri", u"\u22B3" },
+ { u"vscr", u"\U0001D4CB" },
+ { u"vsubnE", u"\u2ACB\uFE00" },
+ { u"vsubne", u"\u228A\uFE00" },
+ { u"vsupnE", u"\u2ACC\uFE00" },
+ { u"vsupne", u"\u228B\uFE00" },
+ { u"vzigzag", u"\u299A" },
+ { u"wcirc", u"\u0175" },
+ { u"wedbar", u"\u2A5F" },
+ { u"wedge", u"\u2227" },
+ { u"wedgeq", u"\u2259" },
+ { u"weierp", u"\u2118" },
+ { u"wfr", u"\U0001D534" },
+ { u"wopf", u"\U0001D568" },
+ { u"wp", u"\u2118" },
+ { u"wr", u"\u2240" },
+ { u"wreath", u"\u2240" },
+ { u"wscr", u"\U0001D4CC" },
+ { u"xcap", u"\u22C2" },
+ { u"xcirc", u"\u25EF" },
+ { u"xcup", u"\u22C3" },
+ { u"xdtri", u"\u25BD" },
+ { u"xfr", u"\U0001D535" },
+ { u"xhArr", u"\u27FA" },
+ { u"xharr", u"\u27F7" },
+ { u"xi", u"\u03BE" },
+ { u"xlArr", u"\u27F8" },
+ { u"xlarr", u"\u27F5" },
+ { u"xmap", u"\u27FC" },
+ { u"xnis", u"\u22FB" },
+ { u"xodot", u"\u2A00" },
+ { u"xopf", u"\U0001D569" },
+ { u"xoplus", u"\u2A01" },
+ { u"xotime", u"\u2A02" },
+ { u"xrArr", u"\u27F9" },
+ { u"xrarr", u"\u27F6" },
+ { u"xscr", u"\U0001D4CD" },
+ { u"xsqcup", u"\u2A06" },
+ { u"xuplus", u"\u2A04" },
+ { u"xutri", u"\u25B3" },
+ { u"xvee", u"\u22C1" },
+ { u"xwedge", u"\u22C0" },
+ { u"yacute", u"\u00FD" },
+ { u"yacy", u"\u044F" },
+ { u"ycirc", u"\u0177" },
+ { u"ycy", u"\u044B" },
+ { u"yen", u"\u00A5" },
+ { u"yfr", u"\U0001D536" },
+ { u"yicy", u"\u0457" },
+ { u"yopf", u"\U0001D56A" },
+ { u"yscr", u"\U0001D4CE" },
+ { u"yucy", u"\u044E" },
+ { u"yuml", u"\u00FF" },
+ { u"zacute", u"\u017A" },
+ { u"zcaron", u"\u017E" },
+ { u"zcy", u"\u0437" },
+ { u"zdot", u"\u017C" },
+ { u"zeetrf", u"\u2128" },
+ { u"zeta", u"\u03B6" },
+ { u"zfr", u"\U0001D537" },
+ { u"zhcy", u"\u0436" },
+ { u"zigrarr", u"\u21DD" },
+ { u"zopf", u"\U0001D56B" },
+ { u"zscr", u"\U0001D4CF" },
+ { u"zwj", u"\u200D" },
+ { u"zwnj", u"\u200C" }
+ // clang-format on
+ };
+
+const ::css::uno::Sequence<::css::beans::Pair<OUString, OUString>>
+ starmathdatabase::icustomMathmlHtmlEntities(
+ icustomMathmlHtmlEntitiesData, starmathdatabase::STARMATH_MATHMLHTML_ENTITY_NUMBER);
+
+static ::css::beans::Pair<::rtl::OUString, ::rtl::OUString>
+ icustomMathmlHtmlEntitiesNamesExportData[2] = {
+ // clang-format off
+ { u"&sigma;", u"\u03C3"},
+ { u"&infin;", u"\u221E"}
+ // clang-format on
+ };
+const ::css::uno::Sequence<::css::beans::Pair<::rtl::OUString, ::rtl::OUString>>
+ starmathdatabase::icustomMathmlHtmlEntitiesExport(icustomMathmlHtmlEntitiesNamesExportData, 2);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */