summaryrefslogtreecommitdiffstats
path: root/starmath/source/mathml
diff options
context:
space:
mode:
Diffstat (limited to 'starmath/source/mathml')
-rw-r--r--starmath/source/mathml/attribute.cxx479
-rw-r--r--starmath/source/mathml/def.cxx124
-rw-r--r--starmath/source/mathml/element.cxx136
-rw-r--r--starmath/source/mathml/export.cxx1090
-rw-r--r--starmath/source/mathml/import.cxx1405
-rw-r--r--starmath/source/mathml/iterator.cxx77
-rw-r--r--starmath/source/mathml/mathmlMo.cxx1128
-rw-r--r--starmath/source/mathml/mathmlattr.cxx165
-rw-r--r--starmath/source/mathml/mathmlexport.cxx1443
-rw-r--r--starmath/source/mathml/mathmlimport.cxx2673
-rw-r--r--starmath/source/mathml/starmathdatabase.cxx794
-rw-r--r--starmath/source/mathml/xparsmlbase.cxx2166
12 files changed, 11680 insertions, 0 deletions
diff --git a/starmath/source/mathml/attribute.cxx b/starmath/source/mathml/attribute.cxx
new file mode 100644
index 0000000000..ca4a86290d
--- /dev/null
+++ b/starmath/source/mathml/attribute.cxx
@@ -0,0 +1,479 @@
+/* -*- 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""_ustr);
+ 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"_ustr);
+ 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%"_ustr);
+ 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%"_ustr);
+ 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%"_ustr);
+ 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"_ustr);
+ 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 0000000000..484dcd6653
--- /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 0000000000..4f8f2a64ff
--- /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 0000000000..923668f454
--- /dev/null
+++ b/starmath/source/mathml/export.cxx
@@ -0,0 +1,1090 @@
+/* -*- 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 doc shell
+ SmDocShell* pDocShell = static_cast<SmDocShell*>(m_xModel->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& rMediumItemSet = 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 = rMediumItemSet.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"_ustr, 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
+ = rMediumItemSet.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, m_xModel, 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, m_xModel, u"content.xml", xContext, xInfoSet,
+ u"com.sun.star.comp.Math.XMLContentExporter", 5);
+ else
+ bRet = WriteThroughComponentS(xStg, m_xModel, 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, m_xModel, 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, m_xModel, xContext, xInfoSet,
+ u"com.sun.star.comp.Math.XMLContentExporter", 5);
+ else
+ bRet = WriteThroughComponentOS(xOut, m_xModel, 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""_ustr;
+
+ //Get model
+ uno::Reference<lang::XComponent> xModelComp = m_xModel;
+ SAL_WARN_IF(xModelComp == nullptr, "starmath", "Missing model component");
+ SmModel* pModel = m_xModel.get();
+ SAL_WARN_IF(pModel == nullptr, "starmath", "Failed to get threw uno tunnel");
+ if (xModelComp == nullptr || pModel == nullptr)
+ return u""_ustr;
+
+ // Get doc shell
+ SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
+ if (pDocShell == nullptr)
+ {
+ SAL_WARN("starmath", "Failed to fetch sm document");
+ return u""_ustr;
+ }
+
+ // 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 = dynamic_cast<SmXMLExport*>(xFilter.get());
+ if (pFilter == nullptr)
+ {
+ SAL_WARN("starmath", "Failed to fetch SmMLExport");
+ return false;
+ }
+ xFilter->filter(aProps);
+ return pFilter->GetSuccess();
+ }
+
+ // filter
+ SmMLExport* pFilter = dynamic_cast<SmMLExport*>(xFilter.get());
+
+ // 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(u"text/xml"_ustr));
+
+ // 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""_ustr;
+
+ // 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
+/*************************************************************************************************/
+
+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(u""_ustr, 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 0000000000..d857e56930
--- /dev/null
+++ b/starmath/source/mathml/import.cxx
@@ -0,0 +1,1405 @@
+/* -*- 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;
+ }
+
+ // Try to get an XStatusIndicator from the Medium
+ uno::Reference<task::XStatusIndicator> xStatusIndicator;
+
+ // Get model via uno
+ SmModel* pModel = m_xModel.get();
+ 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
+ const SfxUnoAnyItem* pItem = rMedium.GetItemSet().GetItem(SID_PROGRESS_STATUSBAR_CONTROL);
+ if (pItem != nullptr)
+ pItem->GetValue() >>= xStatusIndicator;
+ }
+
+ // Create property list
+ static const comphelper::PropertyMapEntry aInfoMap[]
+ = { { u"PrivateData"_ustr, 0, cppu::UnoType<XInterface>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { u"BaseURI"_ustr, 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { u"StreamRelPath"_ustr, 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { u"StreamName"_ustr, 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"_ustr);
+ 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(), m_xModel, u"meta.xml", xContext,
+ xInfoSet,
+ u"com.sun.star.comp.Math.MLOasisMetaImporter", 6);
+ else
+ nWarn
+ = ReadThroughComponentS(rMedium.GetStorage(), m_xModel, 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(), m_xModel, u"settings.xml", xContext,
+ xInfoSet,
+ u"com.sun.star.comp.Math.MLOasisSettingsImporter", 6);
+ else
+ nWarn
+ = ReadThroughComponentS(rMedium.GetStorage(), m_xModel, u"settings.xml", xContext,
+ xInfoSet, u"com.sun.star.comp.Math.XMLSettingsImporter", 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(3);
+
+ // Read document
+ // read a component from storage
+ if (m_pDocShell->GetSmSyntaxVersion() == 5)
+ nWarn = ReadThroughComponentS(rMedium.GetStorage(), m_xModel, u"content.xml", xContext,
+ xInfoSet, u"com.sun.star.comp.Math.XMLImporter", 5);
+ else
+ nWarn = ReadThroughComponentS(rMedium.GetStorage(), m_xModel, 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, m_xModel, xContext, xInfoSet,
+ u"com.sun.star.comp.Math.XMLImporter", false, 5);
+ else
+ nError = ReadThroughComponentIS(xInputStream, m_xModel, 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 = m_xModel.get();
+ 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"_ustr, 0, cppu::UnoType<XInterface>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { u"BaseURI"_ustr, 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { u"StreamRelPath"_ustr, 0, ::cppu::UnoType<OUString>::get(),
+ beans::PropertyAttribute::MAYBEVOID, 0 },
+ { u"StreamName"_ustr, 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 = dynamic_cast<SmXMLImport*>(xFilter.get());
+ if (pXMlImport != nullptr && pXMlImport->GetSuccess())
+ return ERRCODE_NONE;
+ else
+ {
+ SAL_WARN("starmath", "Filter failed on file input");
+ // However this can not be included since it's not public
+ if (pXMlImport == nullptr)
+ return ERRCODE_NONE;
+ return ERRCODE_SFX_DOLOADFAILED;
+ }
+ }
+
+ m_pMlImport = dynamic_cast<SmMLImport*>(xFilter.get());
+ 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%"_ustr) };
+ }
+ 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
+/*************************************************************************************************/
+
+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 constexpr OUStringLiteral sFormula(u"Formula");
+ static constexpr OUStringLiteral sBasicLibraries(u"BasicLibraries");
+ static constexpr 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 0000000000..24de35c183
--- /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 0000000000..8ee7536e1c
--- /dev/null
+++ b/starmath/source/mathml/mathmlMo.cxx
@@ -0,0 +1,1128 @@
+/* -*- 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"_ustr, moOpDF::prefix, 10, 0, 0, moOpDP::fence | moOpDP::nonedp },
+ { u"\u2019"_ustr, moOpDF::postfix, 10, 0, 0, moOpDP::fence | moOpDP::nonedp },
+ { u"\u201C"_ustr, moOpDF::prefix, 10, 0, 0, moOpDP::fence | moOpDP::nonedp },
+ { u"\u201D"_ustr, moOpDF::postfix, 10, 0, 0, moOpDP::fence | moOpDP::nonedp },
+ { u"("_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u")"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"["_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"]"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"{"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"|"_ustr, moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"||"_ustr, moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"|||"_ustr, moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"}"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2016"_ustr, moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence },
+ { u"\u2308"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2309"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u230A"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u230B"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2329"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u232A"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2772"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2773"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27E6"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27E7"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27E8"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27E9"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27EA"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27EB"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27EC"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27ED"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27EE"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u27EF"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2980"_ustr, moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence },
+ { u"\u2983"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2984"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2985"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2986"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2987"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2988"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2989"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u298A"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u298B"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u298C"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u298D"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u298E"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u298F"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2990"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2991"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2992"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2993"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2994"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2995"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2996"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2997"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2998"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u29FC"_ustr, moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u29FD"_ustr, moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u";"_ustr, moOpDF::infix, 30, 0, 3, moOpDP::separator | moOpDP::linebreakstyleAfter },
+ { u","_ustr, moOpDF::infix, 40, 0, 3, moOpDP::separator | moOpDP::linebreakstyleAfter },
+ { u"\u2063"_ustr, moOpDF::infix, 40, 0, 0,
+ moOpDP::separator | moOpDP::linebreakstyleAfter },
+ { u"\u2234"_ustr, moOpDF::infix, 70, 5, 5, moOpDP::nonedp },
+ { u"\u2235"_ustr, moOpDF::infix, 70, 5, 5, moOpDP::nonedp },
+ { u"->"_ustr, moOpDF::infix, 90, 5, 5, moOpDP::nonedp },
+ { u".."_ustr, moOpDF::postfix, 100, 0, 0, moOpDP::nonedp },
+ { u"..."_ustr, moOpDF::postfix, 100, 0, 0, moOpDP::nonedp },
+ { u":"_ustr, moOpDF::infix, 100, 1, 2, moOpDP::nonedp },
+ { u"\u03F6"_ustr, moOpDF::infix, 110, 5, 5, moOpDP::nonedp },
+ { u"\u2026"_ustr, moOpDF::infix, 150, 0, 0, moOpDP::nonedp },
+ { u"\u22EE"_ustr, moOpDF::infix, 150, 5, 5, moOpDP::nonedp },
+ { u"\u22EF"_ustr, moOpDF::infix, 150, 0, 0, moOpDP::nonedp },
+ { u"\u22F1"_ustr, moOpDF::infix, 150, 5, 5, moOpDP::nonedp },
+ { u"\u220B"_ustr, moOpDF::infix, 160, 5, 5, moOpDP::nonedp },
+ { u"\u22A2"_ustr, moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22A3"_ustr, moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22A4"_ustr, moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22A8"_ustr, moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22A9"_ustr, moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22AC"_ustr, moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22AD"_ustr, moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22AE"_ustr, moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u22AF"_ustr, moOpDF::infix, 170, 5, 5, moOpDP::nonedp },
+ { u"\u2228"_ustr, moOpDF::infix, 190, 4, 4, moOpDP::nonedp },
+ { u"&&"_ustr, moOpDF::infix, 200, 4, 4, moOpDP::nonedp },
+ { u"\u2227"_ustr, moOpDF::infix, 200, 4, 4, moOpDP::nonedp },
+ { u"\u2200"_ustr, moOpDF::prefix, 230, 2, 1, moOpDP::nonedp },
+ { u"\u2203"_ustr, moOpDF::prefix, 230, 2, 1, moOpDP::nonedp },
+ { u"\u2204"_ustr, moOpDF::prefix, 230, 2, 1, moOpDP::nonedp },
+ { u"\u2201"_ustr, moOpDF::infix, 240, 1, 2, moOpDP::nonedp },
+ { u"\u2208"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2209"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u220C"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2282"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2282\u20D2"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2283"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2283\u20D2"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2284"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2285"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2286"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2287"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2288"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u2289"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u228A"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"\u228B"_ustr, moOpDF::infix, 240, 5, 5, moOpDP::nonedp },
+ { u"<="_ustr, moOpDF::infix, 241, 5, 5, moOpDP::nonedp },
+ { u"\u2264"_ustr, moOpDF::infix, 241, 5, 5, moOpDP::nonedp },
+ { u"\u2265"_ustr, moOpDF::infix, 242, 5, 5, moOpDP::nonedp },
+ { u">"_ustr, moOpDF::infix, 243, 5, 5, moOpDP::nonedp },
+ { u">="_ustr, moOpDF::infix, 243, 5, 5, moOpDP::nonedp },
+ { u"\u226F"_ustr, moOpDF::infix, 244, 5, 5, moOpDP::nonedp },
+ { u"&lt"_ustr, moOpDF::infix, 245, 5, 5, moOpDP::nonedp },
+ { u"\u226E"_ustr, moOpDF::infix, 246, 5, 5, moOpDP::nonedp },
+ { u"\u2248"_ustr, moOpDF::infix, 247, 5, 5, moOpDP::nonedp },
+ { u"\u223C"_ustr, moOpDF::infix, 250, 5, 5, moOpDP::nonedp },
+ { u"\u2249"_ustr, moOpDF::infix, 250, 5, 5, moOpDP::nonedp },
+ { u"\u2262"_ustr, moOpDF::infix, 252, 5, 5, moOpDP::nonedp },
+ { u"\u2260"_ustr, moOpDF::infix, 255, 5, 5, moOpDP::nonedp },
+ { u"!="_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"*="_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"+="_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"-="_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"/="_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u":="_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"="_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"=="_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u221D"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2224"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2225"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2226"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2241"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2243"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2244"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2245"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2246"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2247"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u224D"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2254"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2257"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2259"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u225A"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u225B"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u225C"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u225F"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2261"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2268"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2269"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u226A"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u226A\u0338"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u226B"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u226B\u0338"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u226D"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2270"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2271"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u227A"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u227B"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u227C"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u227D"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2280"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2281"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22A5"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22B4"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22B5"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22C9"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u22CA"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u22CB"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u22CC"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u22D4"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22D6"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22D7"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22D8"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22D9"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22EA"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22EB"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22EC"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u22ED"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u25A0"_ustr, moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25A1"_ustr, moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25AA"_ustr, moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25AB"_ustr, moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25AD"_ustr, moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25AE"_ustr, moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25AF"_ustr, moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25B0"_ustr, moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25B1"_ustr, moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u25B3"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25B4"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25B5"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25B6"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25B7"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25B8"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25B9"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25BC"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25BD"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25BE"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25BF"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C0"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C1"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C2"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C3"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C4"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C5"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C6"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C7"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C8"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25C9"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25CC"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25CD"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25CE"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25CF"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25D6"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25D7"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u25E6"_ustr, moOpDF::infix, 260, 4, 4, moOpDP::nonedp },
+ { u"\u29C0"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u29C1"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u29E3"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u29E4"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u29E5"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u29E6"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u29F3"_ustr, moOpDF::infix, 260, 3, 3, moOpDP::nonedp },
+ { u"\u2A87"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2A88"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2AAF"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2AAF\u0338"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2AB0"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2AB0\u0338"_ustr, moOpDF::infix, 260, 5, 5, moOpDP::nonedp },
+ { u"\u2044"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::stretchy },
+ { u"\u2206"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u220A"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u220D"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u220E"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2215"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::stretchy },
+ { u"\u2217"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2218"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2219"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u221F"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2223"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2236"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2237"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2238"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2239"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u223A"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u223B"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u223D"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u223D\u0331"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u223E"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u223F"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2242"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2242\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224A"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224B"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224C"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224E"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224E\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224F"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u224F\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2250"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2251"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2252"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2253"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2255"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2256"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2258"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u225D"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u225E"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2263"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2266"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2266\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2267"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u226C"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2272"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2273"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2274"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2275"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2276"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2277"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2278"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2279"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u227E"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u227F"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u227F\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u228C"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u228D"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u228E"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u228F"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u228F\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2290"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2290\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2291"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2292"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2293"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2294"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u229A"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u229B"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u229C"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u229D"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22A6"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22A7"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22AA"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22AB"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B0"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B1"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B2"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B3"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B6"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B7"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22B9"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22BA"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22BB"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22BC"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22BD"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22BE"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u22BF"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u22C4"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22C6"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22C7"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22C8"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22CD"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22CE"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22CF"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22D0"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22D1"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22D2"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22D3"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u22D5"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22DA"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22DB"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22DC"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22DD"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22DE"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22DF"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E0"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E1"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E2"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E3"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E4"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E5"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E6"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E7"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E8"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22E9"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F0"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F2"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F3"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F4"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F5"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F6"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F7"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F8"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22F9"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22FA"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22FB"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22FC"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22FD"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22FE"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u22FF"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u25B2"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2758"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2981"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2982"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A0"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A1"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A2"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A3"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A4"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A5"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A6"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A7"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A8"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29A9"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29AA"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29AB"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29AC"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29AD"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29AE"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29AF"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B0"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B1"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B2"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B3"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B4"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B5"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29B6"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29B7"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29B8"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29B9"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29BA"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29BB"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29BC"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29BD"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29BE"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29BF"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29C2"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29C3"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29C4"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29C5"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29C6"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29C7"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29C8"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29C9"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29CA"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29CB"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29CC"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29CD"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29CE"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29CF"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29CF\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D0"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D0\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D1"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D2"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D3"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D4"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D5"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29D6"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29D7"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29D8"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29D9"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29DB"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29DC"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29DD"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29DE"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29E0"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29E1"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u29E2"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29E7"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29E8"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29E9"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29EA"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29EB"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29EC"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29ED"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29EE"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29F0"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29F1"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29F2"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29F5"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29F6"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29F7"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29F8"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29F9"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29FA"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29FB"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u29FE"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u29FF"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A1D"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2A1E"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2A1F"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2A20"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2A21"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"\u2A22"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A23"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A24"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A25"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A26"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A27"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A28"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A29"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A2A"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A2B"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A2C"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A2D"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A2E"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A30"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A31"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A32"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A33"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A34"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A35"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A36"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A37"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A38"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A39"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A3A"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A3B"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A3C"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A3D"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A3E"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A40"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A41"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A42"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A43"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A44"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A45"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A46"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A47"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A48"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A49"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A4A"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A4B"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A4C"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A4D"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A4E"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A4F"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A50"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A51"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A52"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A53"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A54"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A55"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A56"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A57"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A58"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A59"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A5A"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A5B"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A5C"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A5D"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A5E"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A5F"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A60"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A61"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A62"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A63"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A64"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A65"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A66"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A67"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A68"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A69"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A6A"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A6B"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A6C"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A6D"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A6E"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A6F"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A70"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A71"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A72"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2A73"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A74"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A75"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A76"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A77"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A78"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A79"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7A"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7B"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7C"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7D"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7D\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7E"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7E\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A7F"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A80"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A81"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A82"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A83"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A84"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A85"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A86"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A89"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A8A"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A8B"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A8C"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A8D"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A8E"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A8F"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A90"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A91"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A92"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A93"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A94"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A95"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A96"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A97"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A98"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A99"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A9A"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A9B"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A9C"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A9D"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A9E"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2A9F"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA0"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA1"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA1\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA2"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA2\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA3"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA4"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA5"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA6"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA7"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA8"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AA9"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AAA"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AAB"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AAC"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AAD"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AAE"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB1"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB2"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB3"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB4"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB5"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB6"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB7"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB8"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AB9"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ABA"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ABB"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ABC"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ABD"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ABE"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ABF"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC0"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC1"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC2"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC3"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC4"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC5"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC6"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC7"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC8"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AC9"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ACA"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ACB"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ACC"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ACD"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ACE"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ACF"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD0"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD1"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD2"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD3"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD4"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD5"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD6"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD7"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD8"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AD9"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ADA"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ADB"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ADD"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ADD\u0338"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ADE"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2ADF"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE0"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE1"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE2"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE3"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE4"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE5"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE6"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE7"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE8"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AE9"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AEA"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AEB"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AEC"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AED"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AEE"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AEF"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF0"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF1"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF2"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF3"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF4"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2AF5"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2AF6"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2AF7"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF8"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AF9"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AFA"_ustr, moOpDF::infix, 265, 5, 5, moOpDP::nonedp },
+ { u"\u2AFB"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2AFD"_ustr, moOpDF::infix, 265, 4, 4, moOpDP::nonedp },
+ { u"\u2AFE"_ustr, moOpDF::infix, 265, 3, 3, moOpDP::nonedp },
+ { u"|"_ustr, moOpDF::infix, 270, 2, 2, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"||"_ustr, moOpDF::infix, 270, 2, 2, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"|||"_ustr, moOpDF::infix, 270, 2, 2, moOpDP::stretchyfence | moOpDP::symmetric },
+ { u"\u2190"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2191"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2192"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2193"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2194"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2195"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2196"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2197"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2198"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2199"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u219A"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u219B"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u219C"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u219D"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u219E"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u219F"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21A0"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21A1"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21A2"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21A3"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21A4"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21A5"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21A6"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21A7"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21A8"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21A9"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21AA"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21AB"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21AC"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21AD"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21AE"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21AF"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B0"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B1"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B2"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B3"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B4"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B5"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21B6"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21B7"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21B8"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21B9"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21BA"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21BB"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21BC"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21BD"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21BE"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21BF"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21C0"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21C1"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21C2"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21C3"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21C4"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21C5"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21C6"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21C7"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21C8"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21C9"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21CA"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21CB"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21CC"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21CD"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21CE"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21CF"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21D0"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21D1"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21D2"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21D3"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21D4"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21D5"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21D6"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21D7"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21D8"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21D9"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21DA"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21DB"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21DC"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21DD"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21DE"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21DF"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21E0"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21E1"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21E2"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21E3"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21E4"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21E5"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21E6"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21E7"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21E8"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21E9"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21EA"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21EB"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21EC"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21ED"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21EE"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21EF"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21F0"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21F1"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21F2"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u21F3"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21F4"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21F5"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u21F6"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21F7"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21F8"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21F9"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21FA"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21FB"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21FC"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u21FD"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21FE"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u21FF"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u22B8"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u27F0"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u27F1"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u27F5"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27F6"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27F7"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27F8"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27F9"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27FA"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27FB"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27FC"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27FD"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27FE"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u27FF"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2900"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2901"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2902"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2903"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2904"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2905"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2906"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2907"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2908"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2909"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u290A"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u290B"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u290C"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u290D"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u290E"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u290F"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2910"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2911"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2912"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2913"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2914"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2915"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2916"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2917"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2918"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2919"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u291A"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u291B"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u291C"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u291D"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u291E"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u291F"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2920"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2921"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2922"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2923"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2924"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2925"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2926"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2927"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2928"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2929"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u292A"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u292B"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u292C"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u292D"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u292E"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u292F"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2930"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2931"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2932"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2933"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2934"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2935"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2936"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2937"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2938"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2939"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u293A"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u293B"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u293C"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u293D"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u293E"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u293F"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2940"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2941"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2942"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2943"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2944"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2945"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2946"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2947"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2948"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2949"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u294A"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u294B"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u294C"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u294D"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u294E"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u294F"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2950"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2951"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2952"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2953"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2954"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2955"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2956"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2957"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2958"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2959"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u295A"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u295B"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u295C"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u295D"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u295E"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u295F"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2960"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2961"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2962"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2963"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2964"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2965"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2966"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2967"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2968"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2969"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u296A"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u296B"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u296C"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u296D"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u296E"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u296F"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2970"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2971"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2972"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2973"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2974"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2975"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2976"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2977"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2978"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u2979"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u297A"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u297B"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u297C"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u297D"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::accent },
+ { u"\u297E"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u297F"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2999"_ustr, moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u299A"_ustr, moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u299B"_ustr, moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u299C"_ustr, moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u299D"_ustr, moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u299E"_ustr, moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u299F"_ustr, moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u29DF"_ustr, moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u29EF"_ustr, moOpDF::infix, 270, 3, 3, moOpDP::nonedp },
+ { u"\u29F4"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::nonedp },
+ { u"\u2B45"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"\u2B46"_ustr, moOpDF::infix, 270, 5, 5, moOpDP::stretchy },
+ { u"+"_ustr, moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"+"_ustr, moOpDF::prefix, 275, 0, 1, moOpDP::nonedp },
+ { u"-"_ustr, moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"-"_ustr, moOpDF::prefix, 275, 0, 1, moOpDP::nonedp },
+ { u"\u00B1"_ustr, moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"\u00B1"_ustr, moOpDF::prefix, 275, 0, 1, moOpDP::nonedp },
+ { u"\u2212"_ustr, moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"\u2212"_ustr, moOpDF::prefix, 275, 0, 1, moOpDP::nonedp },
+ { u"\u2213"_ustr, moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"\u2213"_ustr, moOpDF::prefix, 275, 0, 1, moOpDP::nonedp },
+ { u"\u2214"_ustr, moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"\u229E"_ustr, moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"\u229F"_ustr, moOpDF::infix, 275, 4, 4, moOpDP::nonedp },
+ { u"\u2211"_ustr, moOpDF::prefix, 290, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A0A"_ustr, moOpDF::prefix, 290, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A0B"_ustr, moOpDF::prefix, 290, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u222C"_ustr, moOpDF::prefix, 300, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u222D"_ustr, moOpDF::prefix, 300, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2295"_ustr, moOpDF::infix, 300, 4, 4, moOpDP::nonedp },
+ { u"\u2296"_ustr, moOpDF::infix, 300, 4, 4, moOpDP::nonedp },
+ { u"\u2298"_ustr, moOpDF::infix, 300, 4, 4, moOpDP::nonedp },
+ { u"\u2A01"_ustr, moOpDF::prefix, 300, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u222B"_ustr, moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u222E"_ustr, moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u222F"_ustr, moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2230"_ustr, moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2231"_ustr, moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2232"_ustr, moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2233"_ustr, moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A0C"_ustr, moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A0D"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A0E"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A0F"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A10"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A11"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A12"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A13"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A14"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A15"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A16"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A17"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A18"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A19"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A1A"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A1B"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u2A1C"_ustr, moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric },
+ { u"\u22C3"_ustr, moOpDF::prefix, 320, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A03"_ustr, moOpDF::prefix, 320, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A04"_ustr, moOpDF::prefix, 320, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u22C0"_ustr, moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u22C1"_ustr, moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u22C2"_ustr, moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A00"_ustr, moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A02"_ustr, moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A05"_ustr, moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A06"_ustr, moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A07"_ustr, moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A08"_ustr, moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2A09"_ustr, moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2AFC"_ustr, moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2AFF"_ustr, moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2240"_ustr, moOpDF::infix, 340, 4, 4, moOpDP::nonedp },
+ { u"\u220F"_ustr, moOpDF::prefix, 350, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2210"_ustr, moOpDF::prefix, 350, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric },
+ { u"\u2229"_ustr, moOpDF::infix, 350, 4, 4, moOpDP::nonedp },
+ { u"\u222A"_ustr, moOpDF::infix, 350, 4, 4, moOpDP::nonedp },
+ { u"*"_ustr, moOpDF::infix, 390, 3, 3, moOpDP::nonedp },
+ { u"."_ustr, moOpDF::infix, 390, 3, 3, moOpDP::nonedp },
+ { u"\u00D7"_ustr, moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u2022"_ustr, moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u2043"_ustr, moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u2062"_ustr, moOpDF::infix, 390, 0, 0, moOpDP::nonedp },
+ { u"\u22A0"_ustr, moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u22A1"_ustr, moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u22C5"_ustr, moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u2A2F"_ustr, moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u2A3F"_ustr, moOpDF::infix, 390, 4, 4, moOpDP::nonedp },
+ { u"\u00B7"_ustr, moOpDF::infix, 400, 4, 4, moOpDP::nonedp },
+ { u"\u2297"_ustr, moOpDF::infix, 410, 4, 4, moOpDP::nonedp },
+ { u"%"_ustr, moOpDF::infix, 640, 3, 3, moOpDP::nonedp },
+ { u"\\"_ustr, moOpDF::infix, 650, 0, 0, moOpDP::nonedp },
+ { u"\u2216"_ustr, moOpDF::infix, 650, 4, 4, moOpDP::nonedp },
+ { u"/"_ustr, moOpDF::infix, 660, 1, 1, moOpDP::nonedp },
+ { u"\u00F7"_ustr, moOpDF::infix, 660, 4, 4, moOpDP::nonedp },
+ { u"\u2220"_ustr, moOpDF::prefix, 670, 0, 0, moOpDP::nonedp },
+ { u"\u2221"_ustr, moOpDF::prefix, 670, 0, 0, moOpDP::nonedp },
+ { u"\u2222"_ustr, moOpDF::prefix, 670, 0, 0, moOpDP::nonedp },
+ { u"\u00AC"_ustr, moOpDF::prefix, 680, 2, 1, moOpDP::nonedp },
+ { u"\u2299"_ustr, moOpDF::infix, 710, 4, 4, moOpDP::nonedp },
+ { u"\u2202"_ustr, moOpDF::prefix, 740, 2, 1, moOpDP::nonedp },
+ { u"\u2207"_ustr, moOpDF::prefix, 740, 2, 1, moOpDP::nonedp },
+ { u"**"_ustr, moOpDF::infix, 780, 1, 1, moOpDP::nonedp },
+ { u"<>"_ustr, moOpDF::infix, 780, 1, 1, moOpDP::nonedp },
+ { u"^"_ustr, moOpDF::infix, 780, 1, 1, moOpDP::nonedp },
+ { u"\u2032"_ustr, moOpDF::postfix, 800, 0, 0, moOpDP::nonedp },
+ { u"\u266D"_ustr, moOpDF::postfix, 800, 0, 2, moOpDP::nonedp },
+ { u"\u266E"_ustr, moOpDF::postfix, 800, 0, 2, moOpDP::nonedp },
+ { u"\u266F"_ustr, moOpDF::postfix, 800, 0, 2, moOpDP::nonedp },
+ { u"!"_ustr, moOpDF::postfix, 810, 1, 0, moOpDP::nonedp },
+ { u"!!"_ustr, moOpDF::postfix, 810, 1, 0, moOpDP::nonedp },
+ { u"//"_ustr, moOpDF::infix, 820, 1, 1, moOpDP::nonedp },
+ { u"@"_ustr, moOpDF::infix, 825, 1, 1, moOpDP::nonedp },
+ { u"?"_ustr, moOpDF::infix, 835, 1, 1, moOpDP::nonedp },
+ { u"\u2145"_ustr, moOpDF::prefix, 845, 2, 1, moOpDP::nonedp },
+ { u"\u2146"_ustr, moOpDF::prefix, 845, 2, 0, moOpDP::nonedp },
+ { u"\u221A"_ustr, moOpDF::prefix, 845, 1, 1, moOpDP::stretchy },
+ { u"\u221B"_ustr, moOpDF::prefix, 845, 1, 1, moOpDP::nonedp },
+ { u"\u221C"_ustr, moOpDF::prefix, 845, 1, 1, moOpDP::nonedp },
+ { u"\u2061"_ustr, moOpDF::infix, 850, 0, 0, moOpDP::nonedp },
+ { u"\""_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"&"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::nonedp },
+ { u"\'"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"++"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::nonedp },
+ { u"--"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::nonedp },
+ { u"^"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"_"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"`"_ustr, moOpDF::postfix, 880, 0, 00, moOpDP::accent },
+ { u"~"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u00A8"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00AA"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00AF"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u00B0"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::nonedp },
+ { u"\u00B2"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00B3"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00B4"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00B8"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00B9"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u00BA"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02C6"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u02C7"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u02C9"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u02CA"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02CB"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02CD"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u02D8"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02D9"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02DA"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02DC"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u02DD"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u02F7"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u0302"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u0311"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u201A"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u201B"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u201E"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u201F"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u2033"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u2034"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u2035"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u2036"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u2037"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u203E"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u2057"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u2064"_ustr, moOpDF::infix, 880, 0, 0, moOpDP::nonedp },
+ { u"\u20DB"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u20DC"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::accent },
+ { u"\u23B4"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23B5"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23DC"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23DD"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23DE"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23DF"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23E0"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"\u23E1"_ustr, moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent },
+ { u"_"_ustr, 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 0000000000..5e54f0d92e
--- /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 0000000000..1c18e716e7
--- /dev/null
+++ b/starmath/source/mathml/mathmlexport.cxx
@@ -0,0 +1,1443 @@
+/* -*- 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 <comphelper/genericpropertyset.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#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_uInt32 cChar) { return 0xE000 <= cChar && cChar <= 0xF8FF; }
+
+sal_uInt32 ConvertMathToMathML(std::u16string_view rText, sal_Int32 nIndex = 0)
+{
+ auto cRes = o3tl::iterateCodePoints(rText, &nIndex);
+ if (IsInPrivateUseArea(cRes))
+ {
+ 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");
+
+ const SfxUnoAnyItem* pItem
+ = rMedium.GetItemSet().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 OUString sUsePrettyPrinting(u"UsePrettyPrinting"_ustr);
+ static constexpr OUString sBaseURI(u"BaseURI"_ustr);
+ static constexpr OUString sStreamRelPath(u"StreamRelPath"_ustr);
+ static constexpr OUString sStreamName(u"StreamName"_ustr);
+
+ // 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;
+ 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 = dynamic_cast<SmXMLExport*>(xFilter.get());
+ 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 constexpr OUStringLiteral sMediaType = u"MediaType";
+ static constexpr OUStringLiteral sTextXml = u"text/xml";
+ xSet->setPropertyValue(sMediaType, Any(OUString(sTextXml)));
+
+ // all streams must be encrypted in encrypted document
+ static constexpr 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)
+{
+}
+
+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*/
+ comphelper::AttributeList& 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)
+ {
+ if (!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);
+ }
+ if (pDocShell->GetFormat().IsRightToLeft())
+ {
+ // If the Math equation is set right-to-left, we attach a dir="rtl"
+ // attribute on the <math> root. We don't do anything if it is set
+ // left-to-right, the default dir="ltr" value will be used.
+ AddAttribute(XML_NAMESPACE_MATH, XML_DIR, XML_RTL);
+ }
+ }
+
+ 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_Int16 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));
+ }
+ auto nArse = ConvertMathToMathML(pTemp->GetText());
+ OSL_ENSURE(nArse != 0xffff, "Non existent symbol");
+ GetDocHandler()->characters(OUString(&nArse, 1));
+}
+
+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, 1)));
+ sStrBuf.append('%');
+ break;
+ case FontSizeType::DIVIDE:
+ ::sax::Converter::convertDouble(sStrBuf,
+ static_cast<double>(Fraction(100, 1) / 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
+ double mytest
+ = o3tl::convert<double>(pFontNode->GetFont().GetFontSize().Height(),
+ SmO3tlLengthUnit(), o3tl::Length::pt);
+
+ if (pFontNode->GetSizeType() == FontSizeType::MINUS)
+ mytest -= static_cast<double>(aFrac);
+ else
+ mytest += static_cast<double>(aFrac);
+
+ 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:
+ {
+ const SmTextNode* pTemp = static_cast<const SmTextNode*>(pNode);
+ if (pTemp->GetText().isEmpty())
+ {
+ // 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 0000000000..7bc3e5b913
--- /dev/null
+++ b/starmath/source/mathml/mathmlimport.cxx
@@ -0,0 +1,2673 @@
+/* -*- 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 <comphelper/diagnose_ex.hxx>
+#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());
+
+ OSL_ENSURE(m_xModel.is(), "XMLReader::Read: got no model");
+
+ // try to get an XStatusIndicator from the Medium
+ uno::Reference<task::XStatusIndicator> xStatusIndicator;
+
+ bool bEmbedded = false;
+ SmModel* pModel = m_xModel.get();
+
+ SmDocShell* pDocShell = pModel ? static_cast<SmDocShell*>(pModel->GetObjectShell()) : nullptr;
+ if (pDocShell)
+ {
+ OSL_ENSURE(pDocShell->GetMedium() == &rMedium, "different SfxMedium found");
+
+ const SfxUnoAnyItem* pItem = rMedium.GetItemSet().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");
+ 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(), m_xModel, "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(), m_xModel, "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(), m_xModel, "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, m_xModel, 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 = dynamic_cast<SmXMLImport*>(xFilter.get());
+ 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())
+{
+}
+
+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));
+}
+
+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 = dynamic_cast<SmModel*>(xModel.get());
+
+ 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""_ustr;
+ 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""_ustr;
+ 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""_ustr;
+ 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:
+ OUString cBegin;
+ OUString 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();
+ break;
+ case XML_CLOSE:
+ cEnd = aIter.toString();
+ 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""_ustr;
+ 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""_ustr;
+ 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""_ustr;
+ 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""_ustr;
+ 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""_ustr;
+ 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""_ustr;
+ 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);
+ SmToken bToken;
+ if (bIsFenced)
+ {
+ if (isPrefix)
+ bToken = starmathdatabase::Identify_Prefix_SmXMLOperatorContext_Impl(aToken.cMathChar);
+ else if (isInfix)
+ bToken = SmToken(TMLINE, MS_VERTLINE, "mline", TG::NONE, 0);
+ else if (isPostfix)
+ bToken = starmathdatabase::Identify_Postfix_SmXMLOperatorContext_Impl(aToken.cMathChar);
+ else
+ bToken = starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl(
+ aToken.cMathChar);
+ }
+ else
+ bToken
+ = starmathdatabase::Identify_SmXMLOperatorContext_Impl(aToken.cMathChar, 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""_ustr;
+ 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""_ustr;
+ 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""_ustr;
+ 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""_ustr;
+ 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""_ustr;
+ 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""_ustr;
+ 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""_ustr;
+ 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""_ustr;
+ 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""_ustr;
+
+ 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""_ustr;
+
+ 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""_ustr;
+ 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""_ustr;
+ 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 = dynamic_cast<SmModel*>(xModel.get());
+
+ 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 constexpr OUStringLiteral sFormula(u"Formula");
+ static constexpr OUStringLiteral sBasicLibraries(u"BasicLibraries");
+ static constexpr 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 0000000000..6eb6d209c8
--- /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(std::u16string_view rText,
+ bool bIsStretchy, sal_Int32 nIndex)
+{
+ auto cChar = o3tl::iterateCodePoints(rText, &nIndex);
+ 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_MAJ:
+ return SmToken(TSUM, MS_MAJ, "maj", 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(std::u16string_view rText,
+ sal_Int32 nIndex)
+{
+ auto cChar = o3tl::iterateCodePoints(rText, &nIndex);
+ 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(std::u16string_view rText,
+ sal_Int32 nIndex)
+{
+ auto cChar = o3tl::iterateCodePoints(rText, &nIndex);
+ 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(std::u16string_view rText,
+ sal_Int32 nIndex)
+{
+ auto cChar = o3tl::iterateCodePoints(rText, &nIndex);
+ 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_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 0000000000..ccfcf0049e
--- /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"_ustr, u"\u00C6"_ustr },
+ { u"AMP"_ustr, u"\u0026"_ustr },
+ { u"Aacute"_ustr, u"\u00C1"_ustr },
+ { u"Abreve"_ustr, u"\u0102"_ustr },
+ { u"Acirc"_ustr, u"\u00C2"_ustr },
+ { u"Acy"_ustr, u"\u0410"_ustr },
+ { u"Afr"_ustr, u"\U0001D504"_ustr },
+ { u"Agrave"_ustr, u"\u00C0"_ustr },
+ { u"Alpha"_ustr, u"\u0391"_ustr },
+ { u"Amacr"_ustr, u"\u0100"_ustr },
+ { u"And"_ustr, u"\u2A53"_ustr },
+ { u"Aogon"_ustr, u"\u0104"_ustr },
+ { u"Aopf"_ustr, u"\U0001D538"_ustr },
+ { u"ApplyFunction"_ustr, u"\u2061"_ustr },
+ { u"Aring"_ustr, u"\u00C5"_ustr },
+ { u"Ascr"_ustr, u"\U0001D49C"_ustr },
+ { u"Assign"_ustr, u"\u2254"_ustr },
+ { u"Atilde"_ustr, u"\u00C3"_ustr },
+ { u"Auml"_ustr, u"\u00C4"_ustr },
+ { u"Backslash"_ustr, u"\u2216"_ustr },
+ { u"Barv"_ustr, u"\u2AE7"_ustr },
+ { u"Barwed"_ustr, u"\u2306"_ustr },
+ { u"Bcy"_ustr, u"\u0411"_ustr },
+ { u"Because"_ustr, u"\u2235"_ustr },
+ { u"Bernoullis"_ustr, u"\u212C"_ustr },
+ { u"Beta"_ustr, u"\u0392"_ustr },
+ { u"Bfr"_ustr, u"\U0001D505"_ustr },
+ { u"Bopf"_ustr, u"\U0001D539"_ustr },
+ { u"Breve"_ustr, u"\u02D8"_ustr },
+ { u"Bscr"_ustr, u"\u212C"_ustr },
+ { u"Bumpeq"_ustr, u"\u224E"_ustr },
+ { u"CHcy"_ustr, u"\u0427"_ustr },
+ { u"COPY"_ustr, u"\u00A9"_ustr },
+ { u"Cacute"_ustr, u"\u0106"_ustr },
+ { u"Cap"_ustr, u"\u22D2"_ustr },
+ { u"CapitalDifferentialD"_ustr, u"\u2145"_ustr },
+ { u"Cayleys"_ustr, u"\u212D"_ustr },
+ { u"Ccaron"_ustr, u"\u010C"_ustr },
+ { u"Ccedil"_ustr, u"\u00C7"_ustr },
+ { u"Ccirc"_ustr, u"\u0108"_ustr },
+ { u"Cconint"_ustr, u"\u2230"_ustr },
+ { u"Cdot"_ustr, u"\u010A"_ustr },
+ { u"Cedilla"_ustr, u"\u00B8"_ustr },
+ { u"CenterDot"_ustr, u"\u00B7"_ustr },
+ { u"Cfr"_ustr, u"\u212D"_ustr },
+ { u"Chi"_ustr, u"\u03A7"_ustr },
+ { u"CircleDot"_ustr, u"\u2299"_ustr },
+ { u"CircleMinus"_ustr, u"\u2296"_ustr },
+ { u"CirclePlus"_ustr, u"\u2295"_ustr },
+ { u"CircleTimes"_ustr, u"\u2297"_ustr },
+ { u"ClockwiseContourIntegral"_ustr, u"\u2232"_ustr },
+ { u"CloseCurlyDoubleQuote"_ustr, u"\u201D"_ustr },
+ { u"CloseCurlyQuote"_ustr, u"\u2019"_ustr },
+ { u"Colon"_ustr, u"\u2237"_ustr },
+ { u"Colone"_ustr, u"\u2A74"_ustr },
+ { u"Congruent"_ustr, u"\u2261"_ustr },
+ { u"Conint"_ustr, u"\u222F"_ustr },
+ { u"ContourIntegral"_ustr, u"\u222E"_ustr },
+ { u"Copf"_ustr, u"\u2102"_ustr },
+ { u"Coproduct"_ustr, u"\u2210"_ustr },
+ { u"CounterClockwiseContourIntegral"_ustr, u"\u2233"_ustr },
+ { u"Cross"_ustr, u"\u2A2F"_ustr },
+ { u"Cscr"_ustr, u"\U0001D49E"_ustr },
+ { u"Cup"_ustr, u"\u22D3"_ustr },
+ { u"CupCap"_ustr, u"\u224D"_ustr },
+ { u"DD"_ustr, u"\u2145"_ustr },
+ { u"DDotrahd"_ustr, u"\u2911"_ustr },
+ { u"DJcy"_ustr, u"\u0402"_ustr },
+ { u"DScy"_ustr, u"\u0405"_ustr },
+ { u"DZcy"_ustr, u"\u040F"_ustr },
+ { u"Dagger"_ustr, u"\u2021"_ustr },
+ { u"Darr"_ustr, u"\u21A1"_ustr },
+ { u"Dashv"_ustr, u"\u2AE4"_ustr },
+ { u"Dcaron"_ustr, u"\u010E"_ustr },
+ { u"Dcy"_ustr, u"\u0414"_ustr },
+ { u"Del"_ustr, u"\u2207"_ustr },
+ { u"Delta"_ustr, u"\u0394"_ustr },
+ { u"Dfr"_ustr, u"\U0001D507"_ustr },
+ { u"DiacriticalAcute"_ustr, u"\u00B4"_ustr },
+ { u"DiacriticalDot"_ustr, u"\u02D9"_ustr },
+ { u"DiacriticalDoubleAcute"_ustr, u"\u02DD"_ustr },
+ { u"DiacriticalGrave"_ustr, u"\u0060"_ustr },
+ { u"DiacriticalTilde"_ustr, u"\u02DC"_ustr },
+ { u"Diamond"_ustr, u"\u22C4"_ustr },
+ { u"DifferentialD"_ustr, u"\u2146"_ustr },
+ { u"Dopf"_ustr, u"\U0001D53B"_ustr },
+ { u"Dot"_ustr, u"\u00A8"_ustr },
+ { u"DotDot"_ustr, u"\u20DC"_ustr },
+ { u"DotEqual"_ustr, u"\u2250"_ustr },
+ { u"DoubleContourIntegral"_ustr, u"\u222F"_ustr },
+ { u"DoubleDot"_ustr, u"\u00A8"_ustr },
+ { u"DoubleDownArrow"_ustr, u"\u21D3"_ustr },
+ { u"DoubleLeftArrow"_ustr, u"\u21D0"_ustr },
+ { u"DoubleLeftRightArrow"_ustr, u"\u21D4"_ustr },
+ { u"DoubleLeftTee"_ustr, u"\u2AE4"_ustr },
+ { u"DoubleLongLeftArrow"_ustr, u"\u27F8"_ustr },
+ { u"DoubleLongLeftRightArrow"_ustr, u"\u27FA"_ustr },
+ { u"DoubleLongRightArrow"_ustr, u"\u27F9"_ustr },
+ { u"DoubleRightArrow"_ustr, u"\u21D2"_ustr },
+ { u"DoubleRightTee"_ustr, u"\u22A8"_ustr },
+ { u"DoubleUpArrow"_ustr, u"\u21D1"_ustr },
+ { u"DoubleUpDownArrow"_ustr, u"\u21D5"_ustr },
+ { u"DoubleVerticalBar"_ustr, u"\u2225"_ustr },
+ { u"DownArrow"_ustr, u"\u2193"_ustr },
+ { u"DownArrowBar"_ustr, u"\u2913"_ustr },
+ { u"DownArrowUpArrow"_ustr, u"\u21F5"_ustr },
+ { u"DownBreve"_ustr, u"\u0311"_ustr },
+ { u"DownLeftRightVector"_ustr, u"\u2950"_ustr },
+ { u"DownLeftTeeVector"_ustr, u"\u295E"_ustr },
+ { u"DownLeftVector"_ustr, u"\u21BD"_ustr },
+ { u"DownLeftVectorBar"_ustr, u"\u2956"_ustr },
+ { u"DownRightTeeVector"_ustr, u"\u295F"_ustr },
+ { u"DownRightVector"_ustr, u"\u21C1"_ustr },
+ { u"DownRightVectorBar"_ustr, u"\u2957"_ustr },
+ { u"DownTee"_ustr, u"\u22A4"_ustr },
+ { u"DownTeeArrow"_ustr, u"\u21A7"_ustr },
+ { u"Downarrow"_ustr, u"\u21D3"_ustr },
+ { u"Dscr"_ustr, u"\U0001D49F"_ustr },
+ { u"Dstrok"_ustr, u"\u0110"_ustr },
+ { u"ENG"_ustr, u"\u014A"_ustr },
+ { u"ETH"_ustr, u"\u00D0"_ustr },
+ { u"Eacute"_ustr, u"\u00C9"_ustr },
+ { u"Ecaron"_ustr, u"\u011A"_ustr },
+ { u"Ecirc"_ustr, u"\u00CA"_ustr },
+ { u"Ecy"_ustr, u"\u042D"_ustr },
+ { u"Edot"_ustr, u"\u0116"_ustr },
+ { u"Efr"_ustr, u"\U0001D508"_ustr },
+ { u"Egrave"_ustr, u"\u00C8"_ustr },
+ { u"Element"_ustr, u"\u2208"_ustr },
+ { u"Emacr"_ustr, u"\u0112"_ustr },
+ { u"EmptySmallSquare"_ustr, u"\u25FB"_ustr },
+ { u"EmptyVerySmallSquare"_ustr, u"\u25AB"_ustr },
+ { u"Eogon"_ustr, u"\u0118"_ustr },
+ { u"Eopf"_ustr, u"\U0001D53C"_ustr },
+ { u"Epsilon"_ustr, u"\u0395"_ustr },
+ { u"Equal"_ustr, u"\u2A75"_ustr },
+ { u"EqualTilde"_ustr, u"\u2242"_ustr },
+ { u"Equilibrium"_ustr, u"\u21CC"_ustr },
+ { u"Escr"_ustr, u"\u2130"_ustr },
+ { u"Esim"_ustr, u"\u2A73"_ustr },
+ { u"Eta"_ustr, u"\u0397"_ustr },
+ { u"Euml"_ustr, u"\u00CB"_ustr },
+ { u"Exists"_ustr, u"\u2203"_ustr },
+ { u"ExponentialE"_ustr, u"\u2147"_ustr },
+ { u"Fcy"_ustr, u"\u0424"_ustr },
+ { u"Ffr"_ustr, u"\U0001D509"_ustr },
+ { u"FilledSmallSquare"_ustr, u"\u25FC"_ustr },
+ { u"FilledVerySmallSquare"_ustr, u"\u25AA"_ustr },
+ { u"Fopf"_ustr, u"\U0001D53D"_ustr },
+ { u"ForAll"_ustr, u"\u2200"_ustr },
+ { u"Fouriertrf"_ustr, u"\u2131"_ustr },
+ { u"Fscr"_ustr, u"\u2131"_ustr },
+ { u"GJcy"_ustr, u"\u0403"_ustr },
+ { u"GT"_ustr, u"\u003E"_ustr },
+ { u"Gamma"_ustr, u"\u0393"_ustr },
+ { u"Gammad"_ustr, u"\u03DC"_ustr },
+ { u"Gbreve"_ustr, u"\u011E"_ustr },
+ { u"Gcedil"_ustr, u"\u0122"_ustr },
+ { u"Gcirc"_ustr, u"\u011C"_ustr },
+ { u"Gcy"_ustr, u"\u0413"_ustr },
+ { u"Gdot"_ustr, u"\u0120"_ustr },
+ { u"Gfr"_ustr, u"\U0001D50A"_ustr },
+ { u"Gg"_ustr, u"\u22D9"_ustr },
+ { u"Gopf"_ustr, u"\U0001D53E"_ustr },
+ { u"GreaterEqual"_ustr, u"\u2265"_ustr },
+ { u"GreaterEqualLess"_ustr, u"\u22DB"_ustr },
+ { u"GreaterFullEqual"_ustr, u"\u2267"_ustr },
+ { u"GreaterGreater"_ustr, u"\u2AA2"_ustr },
+ { u"GreaterLess"_ustr, u"\u2277"_ustr },
+ { u"GreaterSlantEqual"_ustr, u"\u2A7E"_ustr },
+ { u"GreaterTilde"_ustr, u"\u2273"_ustr },
+ { u"Gscr"_ustr, u"\U0001D4A2"_ustr },
+ { u"Gt"_ustr, u"\u226B"_ustr },
+ { u"HARDcy"_ustr, u"\u042A"_ustr },
+ { u"Hacek"_ustr, u"\u02C7"_ustr },
+ { u"Hat"_ustr, u"\u005E"_ustr },
+ { u"Hcirc"_ustr, u"\u0124"_ustr },
+ { u"Hfr"_ustr, u"\u210C"_ustr },
+ { u"HilbertSpace"_ustr, u"\u210B"_ustr },
+ { u"Hopf"_ustr, u"\u210D"_ustr },
+ { u"HorizontalLine"_ustr, u"\u2500"_ustr },
+ { u"Hscr"_ustr, u"\u210B"_ustr },
+ { u"Hstrok"_ustr, u"\u0126"_ustr },
+ { u"HumpDownHump"_ustr, u"\u224E"_ustr },
+ { u"HumpEqual"_ustr, u"\u224F"_ustr },
+ { u"IEcy"_ustr, u"\u0415"_ustr },
+ { u"IJlig"_ustr, u"\u0132"_ustr },
+ { u"IOcy"_ustr, u"\u0401"_ustr },
+ { u"Iacute"_ustr, u"\u00CD"_ustr },
+ { u"Icirc"_ustr, u"\u00CE"_ustr },
+ { u"Icy"_ustr, u"\u0418"_ustr },
+ { u"Idot"_ustr, u"\u0130"_ustr },
+ { u"Ifr"_ustr, u"\u2111"_ustr },
+ { u"Igrave"_ustr, u"\u00CC"_ustr },
+ { u"Im"_ustr, u"\u2111"_ustr },
+ { u"Imacr"_ustr, u"\u012A"_ustr },
+ { u"ImaginaryI"_ustr, u"\u2148"_ustr },
+ { u"Implies"_ustr, u"\u21D2"_ustr },
+ { u"Int"_ustr, u"\u222C"_ustr },
+ { u"Integral"_ustr, u"\u222B"_ustr },
+ { u"Intersection"_ustr, u"\u22C2"_ustr },
+ { u"InvisibleComma"_ustr, u"\u2063"_ustr },
+ { u"InvisibleTimes"_ustr, u"\u2062"_ustr },
+ { u"Iogon"_ustr, u"\u012E"_ustr },
+ { u"Iopf"_ustr, u"\U0001D540"_ustr },
+ { u"Iota"_ustr, u"\u0399"_ustr },
+ { u"Iscr"_ustr, u"\u2110"_ustr },
+ { u"Itilde"_ustr, u"\u0128"_ustr },
+ { u"Iukcy"_ustr, u"\u0406"_ustr },
+ { u"Iuml"_ustr, u"\u00CF"_ustr },
+ { u"Jcirc"_ustr, u"\u0134"_ustr },
+ { u"Jcy"_ustr, u"\u0419"_ustr },
+ { u"Jfr"_ustr, u"\U0001D50D"_ustr },
+ { u"Jopf"_ustr, u"\U0001D541"_ustr },
+ { u"Jscr"_ustr, u"\U0001D4A5"_ustr },
+ { u"Jsercy"_ustr, u"\u0408"_ustr },
+ { u"Jukcy"_ustr, u"\u0404"_ustr },
+ { u"KHcy"_ustr, u"\u0425"_ustr },
+ { u"KJcy"_ustr, u"\u040C"_ustr },
+ { u"Kappa"_ustr, u"\u039A"_ustr },
+ { u"Kcedil"_ustr, u"\u0136"_ustr },
+ { u"Kcy"_ustr, u"\u041A"_ustr },
+ { u"Kfr"_ustr, u"\U0001D50E"_ustr },
+ { u"Kopf"_ustr, u"\U0001D542"_ustr },
+ { u"Kscr"_ustr, u"\U0001D4A6"_ustr },
+ { u"LJcy"_ustr, u"\u0409"_ustr },
+ { u"LT"_ustr, u"\u003C"_ustr },
+ { u"Lacute"_ustr, u"\u0139"_ustr },
+ { u"Lambda"_ustr, u"\u039B"_ustr },
+ { u"Lang"_ustr, u"\u27EA"_ustr },
+ { u"Laplacetrf"_ustr, u"\u2112"_ustr },
+ { u"Larr"_ustr, u"\u219E"_ustr },
+ { u"Lcaron"_ustr, u"\u013D"_ustr },
+ { u"Lcedil"_ustr, u"\u013B"_ustr },
+ { u"Lcy"_ustr, u"\u041B"_ustr },
+ { u"LeftAngleBracket"_ustr, u"\u27E8"_ustr },
+ { u"LeftArrow"_ustr, u"\u2190"_ustr },
+ { u"LeftArrowBar"_ustr, u"\u21E4"_ustr },
+ { u"LeftArrowRightArrow"_ustr, u"\u21C6"_ustr },
+ { u"LeftCeiling"_ustr, u"\u2308"_ustr },
+ { u"LeftDoubleBracket"_ustr, u"\u27E6"_ustr },
+ { u"LeftDownTeeVector"_ustr, u"\u2961"_ustr },
+ { u"LeftDownVector"_ustr, u"\u21C3"_ustr },
+ { u"LeftDownVectorBar"_ustr, u"\u2959"_ustr },
+ { u"LeftFloor"_ustr, u"\u230A"_ustr },
+ { u"LeftRightArrow"_ustr, u"\u2194"_ustr },
+ { u"LeftRightVector"_ustr, u"\u294E"_ustr },
+ { u"LeftTee"_ustr, u"\u22A3"_ustr },
+ { u"LeftTeeArrow"_ustr, u"\u21A4"_ustr },
+ { u"LeftTeeVector"_ustr, u"\u295A"_ustr },
+ { u"LeftTriangle"_ustr, u"\u22B2"_ustr },
+ { u"LeftTriangleBar"_ustr, u"\u29CF"_ustr },
+ { u"LeftTriangleEqual"_ustr, u"\u22B4"_ustr },
+ { u"LeftUpDownVector"_ustr, u"\u2951"_ustr },
+ { u"LeftUpTeeVector"_ustr, u"\u2960"_ustr },
+ { u"LeftUpVector"_ustr, u"\u21BF"_ustr },
+ { u"LeftUpVectorBar"_ustr, u"\u2958"_ustr },
+ { u"LeftVector"_ustr, u"\u21BC"_ustr },
+ { u"LeftVectorBar"_ustr, u"\u2952"_ustr },
+ { u"Leftarrow"_ustr, u"\u21D0"_ustr },
+ { u"Leftrightarrow"_ustr, u"\u21D4"_ustr },
+ { u"LessEqualGreater"_ustr, u"\u22DA"_ustr },
+ { u"LessFullEqual"_ustr, u"\u2266"_ustr },
+ { u"LessGreater"_ustr, u"\u2276"_ustr },
+ { u"LessLess"_ustr, u"\u2AA1"_ustr },
+ { u"LessSlantEqual"_ustr, u"\u2A7D"_ustr },
+ { u"LessTilde"_ustr, u"\u2272"_ustr },
+ { u"Lfr"_ustr, u"\U0001D50F"_ustr },
+ { u"Ll"_ustr, u"\u22D8"_ustr },
+ { u"Lleftarrow"_ustr, u"\u21DA"_ustr },
+ { u"Lmidot"_ustr, u"\u013F"_ustr },
+ { u"LongLeftArrow"_ustr, u"\u27F5"_ustr },
+ { u"LongLeftRightArrow"_ustr, u"\u27F7"_ustr },
+ { u"LongRightArrow"_ustr, u"\u27F6"_ustr },
+ { u"Longleftarrow"_ustr, u"\u27F8"_ustr },
+ { u"Longleftrightarrow"_ustr, u"\u27FA"_ustr },
+ { u"Longrightarrow"_ustr, u"\u27F9"_ustr },
+ { u"Lopf"_ustr, u"\U0001D543"_ustr },
+ { u"LowerLeftArrow"_ustr, u"\u2199"_ustr },
+ { u"LowerRightArrow"_ustr, u"\u2198"_ustr },
+ { u"Lscr"_ustr, u"\u2112"_ustr },
+ { u"Lsh"_ustr, u"\u21B0"_ustr },
+ { u"Lstrok"_ustr, u"\u0141"_ustr },
+ { u"Lt"_ustr, u"\u226A"_ustr },
+ { u"Map"_ustr, u"\u2905"_ustr },
+ { u"Mcy"_ustr, u"\u041C"_ustr },
+ { u"MediumSpace"_ustr, u"\u205F"_ustr },
+ { u"Mellintrf"_ustr, u"\u2133"_ustr },
+ { u"Mfr"_ustr, u"\U0001D510"_ustr },
+ { u"MinusPlus"_ustr, u"\u2213"_ustr },
+ { u"Mopf"_ustr, u"\U0001D544"_ustr },
+ { u"Mscr"_ustr, u"\u2133"_ustr },
+ { u"Mu"_ustr, u"\u039C"_ustr },
+ { u"NJcy"_ustr, u"\u040A"_ustr },
+ { u"Nacute"_ustr, u"\u0143"_ustr },
+ { u"Ncaron"_ustr, u"\u0147"_ustr },
+ { u"Ncedil"_ustr, u"\u0145"_ustr },
+ { u"Ncy"_ustr, u"\u041D"_ustr },
+ { u"NegativeMediumSpace"_ustr, u"\u200B"_ustr },
+ { u"NegativeThickSpace"_ustr, u"\u200B"_ustr },
+ { u"NegativeThinSpace"_ustr, u"\u200B"_ustr },
+ { u"NegativeVeryThinSpace"_ustr, u"\u200B"_ustr },
+ { u"NestedGreaterGreater"_ustr, u"\u226B"_ustr },
+ { u"NestedLessLess"_ustr, u"\u226A"_ustr },
+ { u"NewLine"_ustr, u"\u000A"_ustr },
+ { u"Nfr"_ustr, u"\U0001D511"_ustr },
+ { u"NoBreak"_ustr, u"\u2060"_ustr },
+ { u"NonBreakingSpace"_ustr, u"\u00A0"_ustr },
+ { u"Nopf"_ustr, u"\u2115"_ustr },
+ { u"Not"_ustr, u"\u2AEC"_ustr },
+ { u"NotCongruent"_ustr, u"\u2262"_ustr },
+ { u"NotCupCap"_ustr, u"\u226D"_ustr },
+ { u"NotDoubleVerticalBar"_ustr, u"\u2226"_ustr },
+ { u"NotElement"_ustr, u"\u2209"_ustr },
+ { u"NotEqual"_ustr, u"\u2260"_ustr },
+ { u"NotEqualTilde"_ustr, u"\u2242\u0338"_ustr },
+ { u"NotExists"_ustr, u"\u2204"_ustr },
+ { u"NotGreater"_ustr, u"\u226F"_ustr },
+ { u"NotGreaterEqual"_ustr, u"\u2271"_ustr },
+ { u"NotGreaterFullEqual"_ustr, u"\u2267\u0338"_ustr },
+ { u"NotGreaterGreater"_ustr, u"\u226B\u0338"_ustr },
+ { u"NotGreaterLess"_ustr, u"\u2279"_ustr },
+ { u"NotGreaterSlantEqual"_ustr, u"\u2A7E\u0338"_ustr },
+ { u"NotGreaterTilde"_ustr, u"\u2275"_ustr },
+ { u"NotHumpDownHump"_ustr, u"\u224E\u0338"_ustr },
+ { u"NotHumpEqual"_ustr, u"\u224F\u0338"_ustr },
+ { u"NotLeftTriangle"_ustr, u"\u22EA"_ustr },
+ { u"NotLeftTriangleBar"_ustr, u"\u29CF\u0338"_ustr },
+ { u"NotLeftTriangleEqual"_ustr, u"\u22EC"_ustr },
+ { u"NotLess"_ustr, u"\u226E"_ustr },
+ { u"NotLessEqual"_ustr, u"\u2270"_ustr },
+ { u"NotLessGreater"_ustr, u"\u2278"_ustr },
+ { u"NotLessLess"_ustr, u"\u226A\u0338"_ustr },
+ { u"NotLessSlantEqual"_ustr, u"\u2A7D\u0338"_ustr },
+ { u"NotLessTilde"_ustr, u"\u2274"_ustr },
+ { u"NotNestedGreaterGreater"_ustr, u"\u2AA2\u0338"_ustr },
+ { u"NotNestedLessLess"_ustr, u"\u2AA1\u0338"_ustr },
+ { u"NotPrecedes"_ustr, u"\u2280"_ustr },
+ { u"NotPrecedesEqual"_ustr, u"\u2AAF\u0338"_ustr },
+ { u"NotPrecedesSlantEqual"_ustr, u"\u22E0"_ustr },
+ { u"NotReverseElement"_ustr, u"\u220C"_ustr },
+ { u"NotRightTriangle"_ustr, u"\u22EB"_ustr },
+ { u"NotRightTriangleBar"_ustr, u"\u29D0\u0338"_ustr },
+ { u"NotRightTriangleEqual"_ustr, u"\u22ED"_ustr },
+ { u"NotSquareSubset"_ustr, u"\u228F\u0338"_ustr },
+ { u"NotSquareSubsetEqual"_ustr, u"\u22E2"_ustr },
+ { u"NotSquareSuperset"_ustr, u"\u2290\u0338"_ustr },
+ { u"NotSquareSupersetEqual"_ustr, u"\u22E3"_ustr },
+ { u"NotSubset"_ustr, u"\u2282\u20D2"_ustr },
+ { u"NotSubsetEqual"_ustr, u"\u2288"_ustr },
+ { u"NotSucceeds"_ustr, u"\u2281"_ustr },
+ { u"NotSucceedsEqual"_ustr, u"\u2AB0\u0338"_ustr },
+ { u"NotSucceedsSlantEqual"_ustr, u"\u22E1"_ustr },
+ { u"NotSucceedsTilde"_ustr, u"\u227F\u0338"_ustr },
+ { u"NotSuperset"_ustr, u"\u2283\u20D2"_ustr },
+ { u"NotSupersetEqual"_ustr, u"\u2289"_ustr },
+ { u"NotTilde"_ustr, u"\u2241"_ustr },
+ { u"NotTildeEqual"_ustr, u"\u2244"_ustr },
+ { u"NotTildeFullEqual"_ustr, u"\u2247"_ustr },
+ { u"NotTildeTilde"_ustr, u"\u2249"_ustr },
+ { u"NotVerticalBar"_ustr, u"\u2224"_ustr },
+ { u"Nscr"_ustr, u"\U0001D4A9"_ustr },
+ { u"Ntilde"_ustr, u"\u00D1"_ustr },
+ { u"Nu"_ustr, u"\u039D"_ustr },
+ { u"OElig"_ustr, u"\u0152"_ustr },
+ { u"Oacute"_ustr, u"\u00D3"_ustr },
+ { u"Ocirc"_ustr, u"\u00D4"_ustr },
+ { u"Ocy"_ustr, u"\u041E"_ustr },
+ { u"Odblac"_ustr, u"\u0150"_ustr },
+ { u"Ofr"_ustr, u"\U0001D512"_ustr },
+ { u"Ograve"_ustr, u"\u00D2"_ustr },
+ { u"Omacr"_ustr, u"\u014C"_ustr },
+ { u"Omega"_ustr, u"\u03A9"_ustr },
+ { u"Omicron"_ustr, u"\u039F"_ustr },
+ { u"Oopf"_ustr, u"\U0001D546"_ustr },
+ { u"OpenCurlyDoubleQuote"_ustr, u"\u201C"_ustr },
+ { u"OpenCurlyQuote"_ustr, u"\u2018"_ustr },
+ { u"Or"_ustr, u"\u2A54"_ustr },
+ { u"Oscr"_ustr, u"\U0001D4AA"_ustr },
+ { u"Oslash"_ustr, u"\u00D8"_ustr },
+ { u"Otilde"_ustr, u"\u00D5"_ustr },
+ { u"Otimes"_ustr, u"\u2A37"_ustr },
+ { u"Ouml"_ustr, u"\u00D6"_ustr },
+ { u"OverBar"_ustr, u"\u203E"_ustr },
+ { u"OverBrace"_ustr, u"\u23DE"_ustr },
+ { u"OverBracket"_ustr, u"\u23B4"_ustr },
+ { u"OverParenthesis"_ustr, u"\u23DC"_ustr },
+ { u"PartialD"_ustr, u"\u2202"_ustr },
+ { u"Pcy"_ustr, u"\u041F"_ustr },
+ { u"Pfr"_ustr, u"\U0001D513"_ustr },
+ { u"Phi"_ustr, u"\u03A6"_ustr },
+ { u"Pi"_ustr, u"\u03A0"_ustr },
+ { u"PlusMinus"_ustr, u"\u00B1"_ustr },
+ { u"Poincareplane"_ustr, u"\u210C"_ustr },
+ { u"Popf"_ustr, u"\u2119"_ustr },
+ { u"Pr"_ustr, u"\u2ABB"_ustr },
+ { u"Precedes"_ustr, u"\u227A"_ustr },
+ { u"PrecedesEqual"_ustr, u"\u2AAF"_ustr },
+ { u"PrecedesSlantEqual"_ustr, u"\u227C"_ustr },
+ { u"PrecedesTilde"_ustr, u"\u227E"_ustr },
+ { u"Prime"_ustr, u"\u2033"_ustr },
+ { u"Product"_ustr, u"\u220F"_ustr },
+ { u"Proportion"_ustr, u"\u2237"_ustr },
+ { u"Proportional"_ustr, u"\u221D"_ustr },
+ { u"Pscr"_ustr, u"\U0001D4AB"_ustr },
+ { u"Psi"_ustr, u"\u03A8"_ustr },
+ { u"QUOT"_ustr, u"\u0022"_ustr },
+ { u"Qfr"_ustr, u"\U0001D514"_ustr },
+ { u"Qopf"_ustr, u"\u211A"_ustr },
+ { u"Qscr"_ustr, u"\U0001D4AC"_ustr },
+ { u"RBarr"_ustr, u"\u2910"_ustr },
+ { u"REG"_ustr, u"\u00AE"_ustr },
+ { u"Racute"_ustr, u"\u0154"_ustr },
+ { u"Rang"_ustr, u"\u27EB"_ustr },
+ { u"Rarr"_ustr, u"\u21A0"_ustr },
+ { u"Rarrtl"_ustr, u"\u2916"_ustr },
+ { u"Rcaron"_ustr, u"\u0158"_ustr },
+ { u"Rcedil"_ustr, u"\u0156"_ustr },
+ { u"Rcy"_ustr, u"\u0420"_ustr },
+ { u"Re"_ustr, u"\u211C"_ustr },
+ { u"ReverseElement"_ustr, u"\u220B"_ustr },
+ { u"ReverseEquilibrium"_ustr, u"\u21CB"_ustr },
+ { u"ReverseUpEquilibrium"_ustr, u"\u296F"_ustr },
+ { u"Rfr"_ustr, u"\u211C"_ustr },
+ { u"Rho"_ustr, u"\u03A1"_ustr },
+ { u"RightAngleBracket"_ustr, u"\u27E9"_ustr },
+ { u"RightArrow"_ustr, u"\u2192"_ustr },
+ { u"RightArrowBar"_ustr, u"\u21E5"_ustr },
+ { u"RightArrowLeftArrow"_ustr, u"\u21C4"_ustr },
+ { u"RightCeiling"_ustr, u"\u2309"_ustr },
+ { u"RightDoubleBracket"_ustr, u"\u27E7"_ustr },
+ { u"RightDownTeeVector"_ustr, u"\u295D"_ustr },
+ { u"RightDownVector"_ustr, u"\u21C2"_ustr },
+ { u"RightDownVectorBar"_ustr, u"\u2955"_ustr },
+ { u"RightFloor"_ustr, u"\u230B"_ustr },
+ { u"RightTee"_ustr, u"\u22A2"_ustr },
+ { u"RightTeeArrow"_ustr, u"\u21A6"_ustr },
+ { u"RightTeeVector"_ustr, u"\u295B"_ustr },
+ { u"RightTriangle"_ustr, u"\u22B3"_ustr },
+ { u"RightTriangleBar"_ustr, u"\u29D0"_ustr },
+ { u"RightTriangleEqual"_ustr, u"\u22B5"_ustr },
+ { u"RightUpDownVector"_ustr, u"\u294F"_ustr },
+ { u"RightUpTeeVector"_ustr, u"\u295C"_ustr },
+ { u"RightUpVector"_ustr, u"\u21BE"_ustr },
+ { u"RightUpVectorBar"_ustr, u"\u2954"_ustr },
+ { u"RightVector"_ustr, u"\u21C0"_ustr },
+ { u"RightVectorBar"_ustr, u"\u2953"_ustr },
+ { u"Rightarrow"_ustr, u"\u21D2"_ustr },
+ { u"Ropf"_ustr, u"\u211D"_ustr },
+ { u"RoundImplies"_ustr, u"\u2970"_ustr },
+ { u"Rrightarrow"_ustr, u"\u21DB"_ustr },
+ { u"Rscr"_ustr, u"\u211B"_ustr },
+ { u"Rsh"_ustr, u"\u21B1"_ustr },
+ { u"RuleDelayed"_ustr, u"\u29F4"_ustr },
+ { u"SHCHcy"_ustr, u"\u0429"_ustr },
+ { u"SHcy"_ustr, u"\u0428"_ustr },
+ { u"SOFTcy"_ustr, u"\u042C"_ustr },
+ { u"Sacute"_ustr, u"\u015A"_ustr },
+ { u"Sc"_ustr, u"\u2ABC"_ustr },
+ { u"Scaron"_ustr, u"\u0160"_ustr },
+ { u"Scedil"_ustr, u"\u015E"_ustr },
+ { u"Scirc"_ustr, u"\u015C"_ustr },
+ { u"Scy"_ustr, u"\u0421"_ustr },
+ { u"Sfr"_ustr, u"\U0001D516"_ustr },
+ { u"ShortDownArrow"_ustr, u"\u2193"_ustr },
+ { u"ShortLeftArrow"_ustr, u"\u2190"_ustr },
+ { u"ShortRightArrow"_ustr, u"\u2192"_ustr },
+ { u"ShortUpArrow"_ustr, u"\u2191"_ustr },
+ { u"Sigma"_ustr, u"\u03A3"_ustr },
+ { u"SmallCircle"_ustr, u"\u2218"_ustr },
+ { u"Sopf"_ustr, u"\U0001D54A"_ustr },
+ { u"Sqrt"_ustr, u"\u221A"_ustr },
+ { u"Square"_ustr, u"\u25A1"_ustr },
+ { u"SquareIntersection"_ustr, u"\u2293"_ustr },
+ { u"SquareSubset"_ustr, u"\u228F"_ustr },
+ { u"SquareSubsetEqual"_ustr, u"\u2291"_ustr },
+ { u"SquareSuperset"_ustr, u"\u2290"_ustr },
+ { u"SquareSupersetEqual"_ustr, u"\u2292"_ustr },
+ { u"SquareUnion"_ustr, u"\u2294"_ustr },
+ { u"Sscr"_ustr, u"\U0001D4AE"_ustr },
+ { u"Star"_ustr, u"\u22C6"_ustr },
+ { u"Sub"_ustr, u"\u22D0"_ustr },
+ { u"Subset"_ustr, u"\u22D0"_ustr },
+ { u"SubsetEqual"_ustr, u"\u2286"_ustr },
+ { u"Succeeds"_ustr, u"\u227B"_ustr },
+ { u"SucceedsEqual"_ustr, u"\u2AB0"_ustr },
+ { u"SucceedsSlantEqual"_ustr, u"\u227D"_ustr },
+ { u"SucceedsTilde"_ustr, u"\u227F"_ustr },
+ { u"SuchThat"_ustr, u"\u220B"_ustr },
+ { u"Sum"_ustr, u"\u2211"_ustr },
+ { u"Sup"_ustr, u"\u22D1"_ustr },
+ { u"Superset"_ustr, u"\u2283"_ustr },
+ { u"SupersetEqual"_ustr, u"\u2287"_ustr },
+ { u"Supset"_ustr, u"\u22D1"_ustr },
+ { u"THORN"_ustr, u"\u00DE"_ustr },
+ { u"TRADE"_ustr, u"\u2122"_ustr },
+ { u"TSHcy"_ustr, u"\u040B"_ustr },
+ { u"TScy"_ustr, u"\u0426"_ustr },
+ { u"Tab"_ustr, u"\u0009"_ustr },
+ { u"Tau"_ustr, u"\u03A4"_ustr },
+ { u"Tcaron"_ustr, u"\u0164"_ustr },
+ { u"Tcedil"_ustr, u"\u0162"_ustr },
+ { u"Tcy"_ustr, u"\u0422"_ustr },
+ { u"Tfr"_ustr, u"\U0001D517"_ustr },
+ { u"Therefore"_ustr, u"\u2234"_ustr },
+ { u"Theta"_ustr, u"\u0398"_ustr },
+ { u"ThickSpace"_ustr, u"\u205F\u200A"_ustr },
+ { u"ThinSpace"_ustr, u"\u2009"_ustr },
+ { u"Tilde"_ustr, u"\u223C"_ustr },
+ { u"TildeEqual"_ustr, u"\u2243"_ustr },
+ { u"TildeFullEqual"_ustr, u"\u2245"_ustr },
+ { u"TildeTilde"_ustr, u"\u2248"_ustr },
+ { u"Topf"_ustr, u"\U0001D54B"_ustr },
+ { u"TripleDot"_ustr, u"\u20DB"_ustr },
+ { u"Tscr"_ustr, u"\U0001D4AF"_ustr },
+ { u"Tstrok"_ustr, u"\u0166"_ustr },
+ { u"Uacute"_ustr, u"\u00DA"_ustr },
+ { u"Uarr"_ustr, u"\u219F"_ustr },
+ { u"Uarrocir"_ustr, u"\u2949"_ustr },
+ { u"Ubrcy"_ustr, u"\u040E"_ustr },
+ { u"Ubreve"_ustr, u"\u016C"_ustr },
+ { u"Ucirc"_ustr, u"\u00DB"_ustr },
+ { u"Ucy"_ustr, u"\u0423"_ustr },
+ { u"Udblac"_ustr, u"\u0170"_ustr },
+ { u"Ufr"_ustr, u"\U0001D518"_ustr },
+ { u"Ugrave"_ustr, u"\u00D9"_ustr },
+ { u"Umacr"_ustr, u"\u016A"_ustr },
+ { u"UnderBar"_ustr, u"\u005F"_ustr },
+ { u"UnderBrace"_ustr, u"\u23DF"_ustr },
+ { u"UnderBracket"_ustr, u"\u23B5"_ustr },
+ { u"UnderParenthesis"_ustr, u"\u23DD"_ustr },
+ { u"Union"_ustr, u"\u22C3"_ustr },
+ { u"UnionPlus"_ustr, u"\u228E"_ustr },
+ { u"Uogon"_ustr, u"\u0172"_ustr },
+ { u"Uopf"_ustr, u"\U0001D54C"_ustr },
+ { u"UpArrow"_ustr, u"\u2191"_ustr },
+ { u"UpArrowBar"_ustr, u"\u2912"_ustr },
+ { u"UpArrowDownArrow"_ustr, u"\u21C5"_ustr },
+ { u"UpDownArrow"_ustr, u"\u2195"_ustr },
+ { u"UpEquilibrium"_ustr, u"\u296E"_ustr },
+ { u"UpTee"_ustr, u"\u22A5"_ustr },
+ { u"UpTeeArrow"_ustr, u"\u21A5"_ustr },
+ { u"Uparrow"_ustr, u"\u21D1"_ustr },
+ { u"Updownarrow"_ustr, u"\u21D5"_ustr },
+ { u"UpperLeftArrow"_ustr, u"\u2196"_ustr },
+ { u"UpperRightArrow"_ustr, u"\u2197"_ustr },
+ { u"Upsi"_ustr, u"\u03D2"_ustr },
+ { u"Upsilon"_ustr, u"\u03A5"_ustr },
+ { u"Uring"_ustr, u"\u016E"_ustr },
+ { u"Uscr"_ustr, u"\U0001D4B0"_ustr },
+ { u"Utilde"_ustr, u"\u0168"_ustr },
+ { u"Uuml"_ustr, u"\u00DC"_ustr },
+ { u"VDash"_ustr, u"\u22AB"_ustr },
+ { u"Vbar"_ustr, u"\u2AEB"_ustr },
+ { u"Vcy"_ustr, u"\u0412"_ustr },
+ { u"Vdash"_ustr, u"\u22A9"_ustr },
+ { u"Vdashl"_ustr, u"\u2AE6"_ustr },
+ { u"Vee"_ustr, u"\u22C1"_ustr },
+ { u"Verbar"_ustr, u"\u2016"_ustr },
+ { u"Vert"_ustr, u"\u2016"_ustr },
+ { u"VerticalBar"_ustr, u"\u2223"_ustr },
+ { u"VerticalLine"_ustr, u"\u007C"_ustr },
+ { u"VerticalSeparator"_ustr, u"\u2758"_ustr },
+ { u"VerticalTilde"_ustr, u"\u2240"_ustr },
+ { u"VeryThinSpace"_ustr, u"\u200A"_ustr },
+ { u"Vfr"_ustr, u"\U0001D519"_ustr },
+ { u"Vopf"_ustr, u"\U0001D54D"_ustr },
+ { u"Vscr"_ustr, u"\U0001D4B1"_ustr },
+ { u"Vvdash"_ustr, u"\u22AA"_ustr },
+ { u"Wcirc"_ustr, u"\u0174"_ustr },
+ { u"Wedge"_ustr, u"\u22C0"_ustr },
+ { u"Wfr"_ustr, u"\U0001D51A"_ustr },
+ { u"Wopf"_ustr, u"\U0001D54E"_ustr },
+ { u"Wscr"_ustr, u"\U0001D4B2"_ustr },
+ { u"Xfr"_ustr, u"\U0001D51B"_ustr },
+ { u"Xi"_ustr, u"\u039E"_ustr },
+ { u"Xopf"_ustr, u"\U0001D54F"_ustr },
+ { u"Xscr"_ustr, u"\U0001D4B3"_ustr },
+ { u"YAcy"_ustr, u"\u042F"_ustr },
+ { u"YIcy"_ustr, u"\u0407"_ustr },
+ { u"YUcy"_ustr, u"\u042E"_ustr },
+ { u"Yacute"_ustr, u"\u00DD"_ustr },
+ { u"Ycirc"_ustr, u"\u0176"_ustr },
+ { u"Ycy"_ustr, u"\u042B"_ustr },
+ { u"Yfr"_ustr, u"\U0001D51C"_ustr },
+ { u"Yopf"_ustr, u"\U0001D550"_ustr },
+ { u"Yscr"_ustr, u"\U0001D4B4"_ustr },
+ { u"Yuml"_ustr, u"\u0178"_ustr },
+ { u"ZHcy"_ustr, u"\u0416"_ustr },
+ { u"Zacute"_ustr, u"\u0179"_ustr },
+ { u"Zcaron"_ustr, u"\u017D"_ustr },
+ { u"Zcy"_ustr, u"\u0417"_ustr },
+ { u"Zdot"_ustr, u"\u017B"_ustr },
+ { u"ZeroWidthSpace"_ustr, u"\u200B"_ustr },
+ { u"Zeta"_ustr, u"\u0396"_ustr },
+ { u"Zfr"_ustr, u"\u2128"_ustr },
+ { u"Zopf"_ustr, u"\u2124"_ustr },
+ { u"Zscr"_ustr, u"\U0001D4B5"_ustr },
+ { u"aacute"_ustr, u"\u00E1"_ustr },
+ { u"abreve"_ustr, u"\u0103"_ustr },
+ { u"ac"_ustr, u"\u223E"_ustr },
+ { u"acE"_ustr, u"\u223E\u0333"_ustr },
+ { u"acd"_ustr, u"\u223F"_ustr },
+ { u"acirc"_ustr, u"\u00E2"_ustr },
+ { u"acute"_ustr, u"\u00B4"_ustr },
+ { u"acy"_ustr, u"\u0430"_ustr },
+ { u"aelig"_ustr, u"\u00E6"_ustr },
+ { u"af"_ustr, u"\u2061"_ustr },
+ { u"afr"_ustr, u"\U0001D51E"_ustr },
+ { u"agrave"_ustr, u"\u00E0"_ustr },
+ { u"alefsym"_ustr, u"\u2135"_ustr },
+ { u"aleph"_ustr, u"\u2135"_ustr },
+ { u"alpha"_ustr, u"\u03B1"_ustr },
+ { u"amacr"_ustr, u"\u0101"_ustr },
+ { u"amalg"_ustr, u"\u2A3F"_ustr },
+ { u"amp"_ustr, u"\u0026"_ustr },
+ { u"and"_ustr, u"\u2227"_ustr },
+ { u"andand"_ustr, u"\u2A55"_ustr },
+ { u"andd"_ustr, u"\u2A5C"_ustr },
+ { u"andslope"_ustr, u"\u2A58"_ustr },
+ { u"andv"_ustr, u"\u2A5A"_ustr },
+ { u"ang"_ustr, u"\u2220"_ustr },
+ { u"ange"_ustr, u"\u29A4"_ustr },
+ { u"angle"_ustr, u"\u2220"_ustr },
+ { u"angmsd"_ustr, u"\u2221"_ustr },
+ { u"angmsdaa"_ustr, u"\u29A8"_ustr },
+ { u"angmsdab"_ustr, u"\u29A9"_ustr },
+ { u"angmsdac"_ustr, u"\u29AA"_ustr },
+ { u"angmsdad"_ustr, u"\u29AB"_ustr },
+ { u"angmsdae"_ustr, u"\u29AC"_ustr },
+ { u"angmsdaf"_ustr, u"\u29AD"_ustr },
+ { u"angmsdag"_ustr, u"\u29AE"_ustr },
+ { u"angmsdah"_ustr, u"\u29AF"_ustr },
+ { u"angrt"_ustr, u"\u221F"_ustr },
+ { u"angrtvb"_ustr, u"\u22BE"_ustr },
+ { u"angrtvbd"_ustr, u"\u299D"_ustr },
+ { u"angsph"_ustr, u"\u2222"_ustr },
+ { u"angst"_ustr, u"\u00C5"_ustr },
+ { u"angzarr"_ustr, u"\u237C"_ustr },
+ { u"aogon"_ustr, u"\u0105"_ustr },
+ { u"aopf"_ustr, u"\U0001D552"_ustr },
+ { u"ap"_ustr, u"\u2248"_ustr },
+ { u"apE"_ustr, u"\u2A70"_ustr },
+ { u"apacir"_ustr, u"\u2A6F"_ustr },
+ { u"ape"_ustr, u"\u224A"_ustr },
+ { u"apid"_ustr, u"\u224B"_ustr },
+ { u"apos"_ustr, u"\u0027"_ustr },
+ { u"approx"_ustr, u"\u2248"_ustr },
+ { u"approxeq"_ustr, u"\u224A"_ustr },
+ { u"aring"_ustr, u"\u00E5"_ustr },
+ { u"ascr"_ustr, u"\U0001D4B6"_ustr },
+ { u"ast"_ustr, u"\u002A"_ustr },
+ { u"asymp"_ustr, u"\u2248"_ustr },
+ { u"asympeq"_ustr, u"\u224D"_ustr },
+ { u"atilde"_ustr, u"\u00E3"_ustr },
+ { u"auml"_ustr, u"\u00E4"_ustr },
+ { u"awconint"_ustr, u"\u2233"_ustr },
+ { u"awint"_ustr, u"\u2A11"_ustr },
+ { u"bNot"_ustr, u"\u2AED"_ustr },
+ { u"backcong"_ustr, u"\u224C"_ustr },
+ { u"backepsilon"_ustr, u"\u03F6"_ustr },
+ { u"backprime"_ustr, u"\u2035"_ustr },
+ { u"backsim"_ustr, u"\u223D"_ustr },
+ { u"backsimeq"_ustr, u"\u22CD"_ustr },
+ { u"barvee"_ustr, u"\u22BD"_ustr },
+ { u"barwed"_ustr, u"\u2305"_ustr },
+ { u"barwedge"_ustr, u"\u2305"_ustr },
+ { u"bbrk"_ustr, u"\u23B5"_ustr },
+ { u"bbrktbrk"_ustr, u"\u23B6"_ustr },
+ { u"bcong"_ustr, u"\u224C"_ustr },
+ { u"bcy"_ustr, u"\u0431"_ustr },
+ { u"bdquo"_ustr, u"\u201E"_ustr },
+ { u"becaus"_ustr, u"\u2235"_ustr },
+ { u"because"_ustr, u"\u2235"_ustr },
+ { u"bemptyv"_ustr, u"\u29B0"_ustr },
+ { u"bepsi"_ustr, u"\u03F6"_ustr },
+ { u"bernou"_ustr, u"\u212C"_ustr },
+ { u"beta"_ustr, u"\u03B2"_ustr },
+ { u"beth"_ustr, u"\u2136"_ustr },
+ { u"between"_ustr, u"\u226C"_ustr },
+ { u"bfr"_ustr, u"\U0001D51F"_ustr },
+ { u"bigcap"_ustr, u"\u22C2"_ustr },
+ { u"bigcirc"_ustr, u"\u25EF"_ustr },
+ { u"bigcup"_ustr, u"\u22C3"_ustr },
+ { u"bigodot"_ustr, u"\u2A00"_ustr },
+ { u"bigoplus"_ustr, u"\u2A01"_ustr },
+ { u"bigotimes"_ustr, u"\u2A02"_ustr },
+ { u"bigsqcup"_ustr, u"\u2A06"_ustr },
+ { u"bigstar"_ustr, u"\u2605"_ustr },
+ { u"bigtriangledown"_ustr, u"\u25BD"_ustr },
+ { u"bigtriangleup"_ustr, u"\u25B3"_ustr },
+ { u"biguplus"_ustr, u"\u2A04"_ustr },
+ { u"bigvee"_ustr, u"\u22C1"_ustr },
+ { u"bigwedge"_ustr, u"\u22C0"_ustr },
+ { u"bkarow"_ustr, u"\u290D"_ustr },
+ { u"blacklozenge"_ustr, u"\u29EB"_ustr },
+ { u"blacksquare"_ustr, u"\u25AA"_ustr },
+ { u"blacktriangle"_ustr, u"\u25B4"_ustr },
+ { u"blacktriangledown"_ustr, u"\u25BE"_ustr },
+ { u"blacktriangleleft"_ustr, u"\u25C2"_ustr },
+ { u"blacktriangleright"_ustr, u"\u25B8"_ustr },
+ { u"blank"_ustr, u"\u2423"_ustr },
+ { u"blk12"_ustr, u"\u2592"_ustr },
+ { u"blk14"_ustr, u"\u2591"_ustr },
+ { u"blk34"_ustr, u"\u2593"_ustr },
+ { u"block"_ustr, u"\u2588"_ustr },
+ { u"bne"_ustr, u"\u003D\u20E5"_ustr },
+ { u"bnequiv"_ustr, u"\u2261\u20E5"_ustr },
+ { u"bnot"_ustr, u"\u2310"_ustr },
+ { u"bopf"_ustr, u"\U0001D553"_ustr },
+ { u"bot"_ustr, u"\u22A5"_ustr },
+ { u"bottom"_ustr, u"\u22A5"_ustr },
+ { u"bowtie"_ustr, u"\u22C8"_ustr },
+ { u"boxDL"_ustr, u"\u2557"_ustr },
+ { u"boxDR"_ustr, u"\u2554"_ustr },
+ { u"boxDl"_ustr, u"\u2556"_ustr },
+ { u"boxDr"_ustr, u"\u2553"_ustr },
+ { u"boxH"_ustr, u"\u2550"_ustr },
+ { u"boxHD"_ustr, u"\u2566"_ustr },
+ { u"boxHU"_ustr, u"\u2569"_ustr },
+ { u"boxHd"_ustr, u"\u2564"_ustr },
+ { u"boxHu"_ustr, u"\u2567"_ustr },
+ { u"boxUL"_ustr, u"\u255D"_ustr },
+ { u"boxUR"_ustr, u"\u255A"_ustr },
+ { u"boxUl"_ustr, u"\u255C"_ustr },
+ { u"boxUr"_ustr, u"\u2559"_ustr },
+ { u"boxV"_ustr, u"\u2551"_ustr },
+ { u"boxVH"_ustr, u"\u256C"_ustr },
+ { u"boxVL"_ustr, u"\u2563"_ustr },
+ { u"boxVR"_ustr, u"\u2560"_ustr },
+ { u"boxVh"_ustr, u"\u256B"_ustr },
+ { u"boxVl"_ustr, u"\u2562"_ustr },
+ { u"boxVr"_ustr, u"\u255F"_ustr },
+ { u"boxbox"_ustr, u"\u29C9"_ustr },
+ { u"boxdL"_ustr, u"\u2555"_ustr },
+ { u"boxdR"_ustr, u"\u2552"_ustr },
+ { u"boxdl"_ustr, u"\u2510"_ustr },
+ { u"boxdr"_ustr, u"\u250C"_ustr },
+ { u"boxh"_ustr, u"\u2500"_ustr },
+ { u"boxhD"_ustr, u"\u2565"_ustr },
+ { u"boxhU"_ustr, u"\u2568"_ustr },
+ { u"boxhd"_ustr, u"\u252C"_ustr },
+ { u"boxhu"_ustr, u"\u2534"_ustr },
+ { u"boxminus"_ustr, u"\u229F"_ustr },
+ { u"boxplus"_ustr, u"\u229E"_ustr },
+ { u"boxtimes"_ustr, u"\u22A0"_ustr },
+ { u"boxuL"_ustr, u"\u255B"_ustr },
+ { u"boxuR"_ustr, u"\u2558"_ustr },
+ { u"boxul"_ustr, u"\u2518"_ustr },
+ { u"boxur"_ustr, u"\u2514"_ustr },
+ { u"boxv"_ustr, u"\u2502"_ustr },
+ { u"boxvH"_ustr, u"\u256A"_ustr },
+ { u"boxvL"_ustr, u"\u2561"_ustr },
+ { u"boxvR"_ustr, u"\u255E"_ustr },
+ { u"boxvh"_ustr, u"\u253C"_ustr },
+ { u"boxvl"_ustr, u"\u2524"_ustr },
+ { u"boxvr"_ustr, u"\u251C"_ustr },
+ { u"bprime"_ustr, u"\u2035"_ustr },
+ { u"breve"_ustr, u"\u02D8"_ustr },
+ { u"brvbar"_ustr, u"\u00A6"_ustr },
+ { u"bscr"_ustr, u"\U0001D4B7"_ustr },
+ { u"bsemi"_ustr, u"\u204F"_ustr },
+ { u"bsim"_ustr, u"\u223D"_ustr },
+ { u"bsime"_ustr, u"\u22CD"_ustr },
+ { u"bsol"_ustr, u"\u005C"_ustr },
+ { u"bsolb"_ustr, u"\u29C5"_ustr },
+ { u"bsolhsub"_ustr, u"\u27C8"_ustr },
+ { u"bull"_ustr, u"\u2022"_ustr },
+ { u"bullet"_ustr, u"\u2022"_ustr },
+ { u"bump"_ustr, u"\u224E"_ustr },
+ { u"bumpE"_ustr, u"\u2AAE"_ustr },
+ { u"bumpe"_ustr, u"\u224F"_ustr },
+ { u"bumpeq"_ustr, u"\u224F"_ustr },
+ { u"cacute"_ustr, u"\u0107"_ustr },
+ { u"cap"_ustr, u"\u2229"_ustr },
+ { u"capand"_ustr, u"\u2A44"_ustr },
+ { u"capbrcup"_ustr, u"\u2A49"_ustr },
+ { u"capcap"_ustr, u"\u2A4B"_ustr },
+ { u"capcup"_ustr, u"\u2A47"_ustr },
+ { u"capdot"_ustr, u"\u2A40"_ustr },
+ { u"caps"_ustr, u"\u2229\uFE00"_ustr },
+ { u"caret"_ustr, u"\u2041"_ustr },
+ { u"caron"_ustr, u"\u02C7"_ustr },
+ { u"ccaps"_ustr, u"\u2A4D"_ustr },
+ { u"ccaron"_ustr, u"\u010D"_ustr },
+ { u"ccedil"_ustr, u"\u00E7"_ustr },
+ { u"ccirc"_ustr, u"\u0109"_ustr },
+ { u"ccups"_ustr, u"\u2A4C"_ustr },
+ { u"ccupssm"_ustr, u"\u2A50"_ustr },
+ { u"cdot"_ustr, u"\u010B"_ustr },
+ { u"cedil"_ustr, u"\u00B8"_ustr },
+ { u"cemptyv"_ustr, u"\u29B2"_ustr },
+ { u"cent"_ustr, u"\u00A2"_ustr },
+ { u"centerdot"_ustr, u"\u00B7"_ustr },
+ { u"cfr"_ustr, u"\U0001D520"_ustr },
+ { u"chcy"_ustr, u"\u0447"_ustr },
+ { u"check"_ustr, u"\u2713"_ustr },
+ { u"checkmark"_ustr, u"\u2713"_ustr },
+ { u"chi"_ustr, u"\u03C7"_ustr },
+ { u"cir"_ustr, u"\u25CB"_ustr },
+ { u"cirE"_ustr, u"\u29C3"_ustr },
+ { u"circ"_ustr, u"\u02C6"_ustr },
+ { u"circeq"_ustr, u"\u2257"_ustr },
+ { u"circlearrowleft"_ustr, u"\u21BA"_ustr },
+ { u"circlearrowright"_ustr, u"\u21BB"_ustr },
+ { u"circledR"_ustr, u"\u00AE"_ustr },
+ { u"circledS"_ustr, u"\u24C8"_ustr },
+ { u"circledast"_ustr, u"\u229B"_ustr },
+ { u"circledcirc"_ustr, u"\u229A"_ustr },
+ { u"circleddash"_ustr, u"\u229D"_ustr },
+ { u"cire"_ustr, u"\u2257"_ustr },
+ { u"cirfnint"_ustr, u"\u2A10"_ustr },
+ { u"cirmid"_ustr, u"\u2AEF"_ustr },
+ { u"cirscir"_ustr, u"\u29C2"_ustr },
+ { u"clubs"_ustr, u"\u2663"_ustr },
+ { u"clubsuit"_ustr, u"\u2663"_ustr },
+ { u"colon"_ustr, u"\u003A"_ustr },
+ { u"colone"_ustr, u"\u2254"_ustr },
+ { u"coloneq"_ustr, u"\u2254"_ustr },
+ { u"comma"_ustr, u"\u002C"_ustr },
+ { u"commat"_ustr, u"\u0040"_ustr },
+ { u"comp"_ustr, u"\u2201"_ustr },
+ { u"compfn"_ustr, u"\u2218"_ustr },
+ { u"complement"_ustr, u"\u2201"_ustr },
+ { u"complexes"_ustr, u"\u2102"_ustr },
+ { u"cong"_ustr, u"\u2245"_ustr },
+ { u"congdot"_ustr, u"\u2A6D"_ustr },
+ { u"conint"_ustr, u"\u222E"_ustr },
+ { u"copf"_ustr, u"\U0001D554"_ustr },
+ { u"coprod"_ustr, u"\u2210"_ustr },
+ { u"copy"_ustr, u"\u00A9"_ustr },
+ { u"copysr"_ustr, u"\u2117"_ustr },
+ { u"crarr"_ustr, u"\u21B5"_ustr },
+ { u"cross"_ustr, u"\u2717"_ustr },
+ { u"cscr"_ustr, u"\U0001D4B8"_ustr },
+ { u"csub"_ustr, u"\u2ACF"_ustr },
+ { u"csube"_ustr, u"\u2AD1"_ustr },
+ { u"csup"_ustr, u"\u2AD0"_ustr },
+ { u"csupe"_ustr, u"\u2AD2"_ustr },
+ { u"ctdot"_ustr, u"\u22EF"_ustr },
+ { u"cudarrl"_ustr, u"\u2938"_ustr },
+ { u"cudarrr"_ustr, u"\u2935"_ustr },
+ { u"cuepr"_ustr, u"\u22DE"_ustr },
+ { u"cuesc"_ustr, u"\u22DF"_ustr },
+ { u"cularr"_ustr, u"\u21B6"_ustr },
+ { u"cularrp"_ustr, u"\u293D"_ustr },
+ { u"cup"_ustr, u"\u222A"_ustr },
+ { u"cupbrcap"_ustr, u"\u2A48"_ustr },
+ { u"cupcap"_ustr, u"\u2A46"_ustr },
+ { u"cupcup"_ustr, u"\u2A4A"_ustr },
+ { u"cupdot"_ustr, u"\u228D"_ustr },
+ { u"cupor"_ustr, u"\u2A45"_ustr },
+ { u"cups"_ustr, u"\u222A\uFE00"_ustr },
+ { u"curarr"_ustr, u"\u21B7"_ustr },
+ { u"curarrm"_ustr, u"\u293C"_ustr },
+ { u"curlyeqprec"_ustr, u"\u22DE"_ustr },
+ { u"curlyeqsucc"_ustr, u"\u22DF"_ustr },
+ { u"curlyvee"_ustr, u"\u22CE"_ustr },
+ { u"curlywedge"_ustr, u"\u22CF"_ustr },
+ { u"curren"_ustr, u"\u00A4"_ustr },
+ { u"curvearrowleft"_ustr, u"\u21B6"_ustr },
+ { u"curvearrowright"_ustr, u"\u21B7"_ustr },
+ { u"cuvee"_ustr, u"\u22CE"_ustr },
+ { u"cuwed"_ustr, u"\u22CF"_ustr },
+ { u"cwconint"_ustr, u"\u2232"_ustr },
+ { u"cwint"_ustr, u"\u2231"_ustr },
+ { u"cylcty"_ustr, u"\u232D"_ustr },
+ { u"dArr"_ustr, u"\u21D3"_ustr },
+ { u"dHar"_ustr, u"\u2965"_ustr },
+ { u"dagger"_ustr, u"\u2020"_ustr },
+ { u"daleth"_ustr, u"\u2138"_ustr },
+ { u"darr"_ustr, u"\u2193"_ustr },
+ { u"dash"_ustr, u"\u2010"_ustr },
+ { u"dashv"_ustr, u"\u22A3"_ustr },
+ { u"dbkarow"_ustr, u"\u290F"_ustr },
+ { u"dblac"_ustr, u"\u02DD"_ustr },
+ { u"dcaron"_ustr, u"\u010F"_ustr },
+ { u"dcy"_ustr, u"\u0434"_ustr },
+ { u"dd"_ustr, u"\u2146"_ustr },
+ { u"ddagger"_ustr, u"\u2021"_ustr },
+ { u"ddarr"_ustr, u"\u21CA"_ustr },
+ { u"ddotseq"_ustr, u"\u2A77"_ustr },
+ { u"deg"_ustr, u"\u00B0"_ustr },
+ { u"delta"_ustr, u"\u03B4"_ustr },
+ { u"demptyv"_ustr, u"\u29B1"_ustr },
+ { u"dfisht"_ustr, u"\u297F"_ustr },
+ { u"dfr"_ustr, u"\U0001D521"_ustr },
+ { u"dharl"_ustr, u"\u21C3"_ustr },
+ { u"dharr"_ustr, u"\u21C2"_ustr },
+ { u"diam"_ustr, u"\u22C4"_ustr },
+ { u"diamond"_ustr, u"\u22C4"_ustr },
+ { u"diamondsuit"_ustr, u"\u2666"_ustr },
+ { u"diams"_ustr, u"\u2666"_ustr },
+ { u"die"_ustr, u"\u00A8"_ustr },
+ { u"digamma"_ustr, u"\u03DD"_ustr },
+ { u"disin"_ustr, u"\u22F2"_ustr },
+ { u"div"_ustr, u"\u00F7"_ustr },
+ { u"divide"_ustr, u"\u00F7"_ustr },
+ { u"divideontimes"_ustr, u"\u22C7"_ustr },
+ { u"divonx"_ustr, u"\u22C7"_ustr },
+ { u"djcy"_ustr, u"\u0452"_ustr },
+ { u"dlcorn"_ustr, u"\u231E"_ustr },
+ { u"dlcrop"_ustr, u"\u230D"_ustr },
+ { u"dollar"_ustr, u"\u0024"_ustr },
+ { u"dopf"_ustr, u"\U0001D555"_ustr },
+ { u"dot"_ustr, u"\u02D9"_ustr },
+ { u"doteq"_ustr, u"\u2250"_ustr },
+ { u"doteqdot"_ustr, u"\u2251"_ustr },
+ { u"dotminus"_ustr, u"\u2238"_ustr },
+ { u"dotplus"_ustr, u"\u2214"_ustr },
+ { u"dotsquare"_ustr, u"\u22A1"_ustr },
+ { u"doublebarwedge"_ustr, u"\u2306"_ustr },
+ { u"downarrow"_ustr, u"\u2193"_ustr },
+ { u"downdownarrows"_ustr, u"\u21CA"_ustr },
+ { u"downharpoonleft"_ustr, u"\u21C3"_ustr },
+ { u"downharpoonright"_ustr, u"\u21C2"_ustr },
+ { u"drbkarow"_ustr, u"\u2910"_ustr },
+ { u"drcorn"_ustr, u"\u231F"_ustr },
+ { u"drcrop"_ustr, u"\u230C"_ustr },
+ { u"dscr"_ustr, u"\U0001D4B9"_ustr },
+ { u"dscy"_ustr, u"\u0455"_ustr },
+ { u"dsol"_ustr, u"\u29F6"_ustr },
+ { u"dstrok"_ustr, u"\u0111"_ustr },
+ { u"dtdot"_ustr, u"\u22F1"_ustr },
+ { u"dtri"_ustr, u"\u25BF"_ustr },
+ { u"dtrif"_ustr, u"\u25BE"_ustr },
+ { u"duarr"_ustr, u"\u21F5"_ustr },
+ { u"duhar"_ustr, u"\u296F"_ustr },
+ { u"dwangle"_ustr, u"\u29A6"_ustr },
+ { u"dzcy"_ustr, u"\u045F"_ustr },
+ { u"dzigrarr"_ustr, u"\u27FF"_ustr },
+ { u"eDDot"_ustr, u"\u2A77"_ustr },
+ { u"eDot"_ustr, u"\u2251"_ustr },
+ { u"eacute"_ustr, u"\u00E9"_ustr },
+ { u"easter"_ustr, u"\u2A6E"_ustr },
+ { u"ecaron"_ustr, u"\u011B"_ustr },
+ { u"ecir"_ustr, u"\u2256"_ustr },
+ { u"ecirc"_ustr, u"\u00EA"_ustr },
+ { u"ecolon"_ustr, u"\u2255"_ustr },
+ { u"ecy"_ustr, u"\u044D"_ustr },
+ { u"edot"_ustr, u"\u0117"_ustr },
+ { u"ee"_ustr, u"\u2147"_ustr },
+ { u"efDot"_ustr, u"\u2252"_ustr },
+ { u"efr"_ustr, u"\U0001D522"_ustr },
+ { u"eg"_ustr, u"\u2A9A"_ustr },
+ { u"egrave"_ustr, u"\u00E8"_ustr },
+ { u"egs"_ustr, u"\u2A96"_ustr },
+ { u"egsdot"_ustr, u"\u2A98"_ustr },
+ { u"el"_ustr, u"\u2A99"_ustr },
+ { u"elinters"_ustr, u"\u23E7"_ustr },
+ { u"ell"_ustr, u"\u2113"_ustr },
+ { u"els"_ustr, u"\u2A95"_ustr },
+ { u"elsdot"_ustr, u"\u2A97"_ustr },
+ { u"emacr"_ustr, u"\u0113"_ustr },
+ { u"empty"_ustr, u"\u2205"_ustr },
+ { u"emptyset"_ustr, u"\u2205"_ustr },
+ { u"emptyv"_ustr, u"\u2205"_ustr },
+ { u"emsp"_ustr, u"\u2003"_ustr },
+ { u"emsp13"_ustr, u"\u2004"_ustr },
+ { u"emsp14"_ustr, u"\u2005"_ustr },
+ { u"eng"_ustr, u"\u014B"_ustr },
+ { u"ensp"_ustr, u"\u2002"_ustr },
+ { u"eogon"_ustr, u"\u0119"_ustr },
+ { u"eopf"_ustr, u"\U0001D556"_ustr },
+ { u"epar"_ustr, u"\u22D5"_ustr },
+ { u"eparsl"_ustr, u"\u29E3"_ustr },
+ { u"eplus"_ustr, u"\u2A71"_ustr },
+ { u"epsi"_ustr, u"\u03B5"_ustr },
+ { u"epsilon"_ustr, u"\u03B5"_ustr },
+ { u"epsiv"_ustr, u"\u03F5"_ustr },
+ { u"eqcirc"_ustr, u"\u2256"_ustr },
+ { u"eqcolon"_ustr, u"\u2255"_ustr },
+ { u"eqsim"_ustr, u"\u2242"_ustr },
+ { u"eqslantgtr"_ustr, u"\u2A96"_ustr },
+ { u"eqslantless"_ustr, u"\u2A95"_ustr },
+ { u"equals"_ustr, u"\u003D"_ustr },
+ { u"equest"_ustr, u"\u225F"_ustr },
+ { u"equiv"_ustr, u"\u2261"_ustr },
+ { u"equivDD"_ustr, u"\u2A78"_ustr },
+ { u"eqvparsl"_ustr, u"\u29E5"_ustr },
+ { u"erDot"_ustr, u"\u2253"_ustr },
+ { u"erarr"_ustr, u"\u2971"_ustr },
+ { u"escr"_ustr, u"\u212F"_ustr },
+ { u"esdot"_ustr, u"\u2250"_ustr },
+ { u"esim"_ustr, u"\u2242"_ustr },
+ { u"eta"_ustr, u"\u03B7"_ustr },
+ { u"eth"_ustr, u"\u00F0"_ustr },
+ { u"euml"_ustr, u"\u00EB"_ustr },
+ { u"euro"_ustr, u"\u20AC"_ustr },
+ { u"excl"_ustr, u"\u0021"_ustr },
+ { u"exist"_ustr, u"\u2203"_ustr },
+ { u"expectation"_ustr, u"\u2130"_ustr },
+ { u"exponentiale"_ustr, u"\u2147"_ustr },
+ { u"fallingdotseq"_ustr, u"\u2252"_ustr },
+ { u"fcy"_ustr, u"\u0444"_ustr },
+ { u"female"_ustr, u"\u2640"_ustr },
+ { u"ffilig"_ustr, u"\uFB03"_ustr },
+ { u"fflig"_ustr, u"\uFB00"_ustr },
+ { u"ffllig"_ustr, u"\uFB04"_ustr },
+ { u"ffr"_ustr, u"\U0001D523"_ustr },
+ { u"filig"_ustr, u"\uFB01"_ustr },
+ { u"fjlig"_ustr, u"\u0066\u006A"_ustr },
+ { u"flat"_ustr, u"\u266D"_ustr },
+ { u"fllig"_ustr, u"\uFB02"_ustr },
+ { u"fltns"_ustr, u"\u25B1"_ustr },
+ { u"fnof"_ustr, u"\u0192"_ustr },
+ { u"fopf"_ustr, u"\U0001D557"_ustr },
+ { u"forall"_ustr, u"\u2200"_ustr },
+ { u"fork"_ustr, u"\u22D4"_ustr },
+ { u"forkv"_ustr, u"\u2AD9"_ustr },
+ { u"fpartint"_ustr, u"\u2A0D"_ustr },
+ { u"frac12"_ustr, u"\u00BD"_ustr },
+ { u"frac13"_ustr, u"\u2153"_ustr },
+ { u"frac14"_ustr, u"\u00BC"_ustr },
+ { u"frac15"_ustr, u"\u2155"_ustr },
+ { u"frac16"_ustr, u"\u2159"_ustr },
+ { u"frac18"_ustr, u"\u215B"_ustr },
+ { u"frac23"_ustr, u"\u2154"_ustr },
+ { u"frac25"_ustr, u"\u2156"_ustr },
+ { u"frac34"_ustr, u"\u00BE"_ustr },
+ { u"frac35"_ustr, u"\u2157"_ustr },
+ { u"frac38"_ustr, u"\u215C"_ustr },
+ { u"frac45"_ustr, u"\u2158"_ustr },
+ { u"frac56"_ustr, u"\u215A"_ustr },
+ { u"frac58"_ustr, u"\u215D"_ustr },
+ { u"frac78"_ustr, u"\u215E"_ustr },
+ { u"frasl"_ustr, u"\u2044"_ustr },
+ { u"frown"_ustr, u"\u2322"_ustr },
+ { u"fscr"_ustr, u"\U0001D4BB"_ustr },
+ { u"gE"_ustr, u"\u2267"_ustr },
+ { u"gEl"_ustr, u"\u2A8C"_ustr },
+ { u"gacute"_ustr, u"\u01F5"_ustr },
+ { u"gamma"_ustr, u"\u03B3"_ustr },
+ { u"gammad"_ustr, u"\u03DD"_ustr },
+ { u"gap"_ustr, u"\u2A86"_ustr },
+ { u"gbreve"_ustr, u"\u011F"_ustr },
+ { u"gcirc"_ustr, u"\u011D"_ustr },
+ { u"gcy"_ustr, u"\u0433"_ustr },
+ { u"gdot"_ustr, u"\u0121"_ustr },
+ { u"ge"_ustr, u"\u2265"_ustr },
+ { u"gel"_ustr, u"\u22DB"_ustr },
+ { u"geq"_ustr, u"\u2265"_ustr },
+ { u"geqq"_ustr, u"\u2267"_ustr },
+ { u"geqslant"_ustr, u"\u2A7E"_ustr },
+ { u"ges"_ustr, u"\u2A7E"_ustr },
+ { u"gescc"_ustr, u"\u2AA9"_ustr },
+ { u"gesdot"_ustr, u"\u2A80"_ustr },
+ { u"gesdoto"_ustr, u"\u2A82"_ustr },
+ { u"gesdotol"_ustr, u"\u2A84"_ustr },
+ { u"gesl"_ustr, u"\u22DB\uFE00"_ustr },
+ { u"gesles"_ustr, u"\u2A94"_ustr },
+ { u"gfr"_ustr, u"\U0001D524"_ustr },
+ { u"gg"_ustr, u"\u226B"_ustr },
+ { u"ggg"_ustr, u"\u22D9"_ustr },
+ { u"gimel"_ustr, u"\u2137"_ustr },
+ { u"gjcy"_ustr, u"\u0453"_ustr },
+ { u"gl"_ustr, u"\u2277"_ustr },
+ { u"glE"_ustr, u"\u2A92"_ustr },
+ { u"gla"_ustr, u"\u2AA5"_ustr },
+ { u"glj"_ustr, u"\u2AA4"_ustr },
+ { u"gnE"_ustr, u"\u2269"_ustr },
+ { u"gnap"_ustr, u"\u2A8A"_ustr },
+ { u"gnapprox"_ustr, u"\u2A8A"_ustr },
+ { u"gne"_ustr, u"\u2A88"_ustr },
+ { u"gneq"_ustr, u"\u2A88"_ustr },
+ { u"gneqq"_ustr, u"\u2269"_ustr },
+ { u"gnsim"_ustr, u"\u22E7"_ustr },
+ { u"gopf"_ustr, u"\U0001D558"_ustr },
+ { u"grave"_ustr, u"\u0060"_ustr },
+ { u"gscr"_ustr, u"\u210A"_ustr },
+ { u"gsim"_ustr, u"\u2273"_ustr },
+ { u"gsime"_ustr, u"\u2A8E"_ustr },
+ { u"gsiml"_ustr, u"\u2A90"_ustr },
+ { u"gt"_ustr, u"\u003E"_ustr },
+ { u"gtcc"_ustr, u"\u2AA7"_ustr },
+ { u"gtcir"_ustr, u"\u2A7A"_ustr },
+ { u"gtdot"_ustr, u"\u22D7"_ustr },
+ { u"gtlPar"_ustr, u"\u2995"_ustr },
+ { u"gtquest"_ustr, u"\u2A7C"_ustr },
+ { u"gtrapprox"_ustr, u"\u2A86"_ustr },
+ { u"gtrarr"_ustr, u"\u2978"_ustr },
+ { u"gtrdot"_ustr, u"\u22D7"_ustr },
+ { u"gtreqless"_ustr, u"\u22DB"_ustr },
+ { u"gtreqqless"_ustr, u"\u2A8C"_ustr },
+ { u"gtrless"_ustr, u"\u2277"_ustr },
+ { u"gtrsim"_ustr, u"\u2273"_ustr },
+ { u"gvertneqq"_ustr, u"\u2269\uFE00"_ustr },
+ { u"gvnE"_ustr, u"\u2269\uFE00"_ustr },
+ { u"hArr"_ustr, u"\u21D4"_ustr },
+ { u"hairsp"_ustr, u"\u200A"_ustr },
+ { u"half"_ustr, u"\u00BD"_ustr },
+ { u"hamilt"_ustr, u"\u210B"_ustr },
+ { u"hardcy"_ustr, u"\u044A"_ustr },
+ { u"harr"_ustr, u"\u2194"_ustr },
+ { u"harrcir"_ustr, u"\u2948"_ustr },
+ { u"harrw"_ustr, u"\u21AD"_ustr },
+ { u"hbar"_ustr, u"\u210F"_ustr },
+ { u"hcirc"_ustr, u"\u0125"_ustr },
+ { u"hearts"_ustr, u"\u2665"_ustr },
+ { u"heartsuit"_ustr, u"\u2665"_ustr },
+ { u"hellip"_ustr, u"\u2026"_ustr },
+ { u"hercon"_ustr, u"\u22B9"_ustr },
+ { u"hfr"_ustr, u"\U0001D525"_ustr },
+ { u"hksearow"_ustr, u"\u2925"_ustr },
+ { u"hkswarow"_ustr, u"\u2926"_ustr },
+ { u"hoarr"_ustr, u"\u21FF"_ustr },
+ { u"homtht"_ustr, u"\u223B"_ustr },
+ { u"hookleftarrow"_ustr, u"\u21A9"_ustr },
+ { u"hookrightarrow"_ustr, u"\u21AA"_ustr },
+ { u"hopf"_ustr, u"\U0001D559"_ustr },
+ { u"horbar"_ustr, u"\u2015"_ustr },
+ { u"hscr"_ustr, u"\U0001D4BD"_ustr },
+ { u"hslash"_ustr, u"\u210F"_ustr },
+ { u"hstrok"_ustr, u"\u0127"_ustr },
+ { u"hybull"_ustr, u"\u2043"_ustr },
+ { u"hyphen"_ustr, u"\u2010"_ustr },
+ { u"iacute"_ustr, u"\u00ED"_ustr },
+ { u"ic"_ustr, u"\u2063"_ustr },
+ { u"icirc"_ustr, u"\u00EE"_ustr },
+ { u"icy"_ustr, u"\u0438"_ustr },
+ { u"iecy"_ustr, u"\u0435"_ustr },
+ { u"iexcl"_ustr, u"\u00A1"_ustr },
+ { u"iff"_ustr, u"\u21D4"_ustr },
+ { u"ifr"_ustr, u"\U0001D526"_ustr },
+ { u"igrave"_ustr, u"\u00EC"_ustr },
+ { u"ii"_ustr, u"\u2148"_ustr },
+ { u"iiiint"_ustr, u"\u2A0C"_ustr },
+ { u"iiint"_ustr, u"\u222D"_ustr },
+ { u"iinfin"_ustr, u"\u29DC"_ustr },
+ { u"iiota"_ustr, u"\u2129"_ustr },
+ { u"ijlig"_ustr, u"\u0133"_ustr },
+ { u"imacr"_ustr, u"\u012B"_ustr },
+ { u"image"_ustr, u"\u2111"_ustr },
+ { u"imagline"_ustr, u"\u2110"_ustr },
+ { u"imagpart"_ustr, u"\u2111"_ustr },
+ { u"imath"_ustr, u"\u0131"_ustr },
+ { u"imof"_ustr, u"\u22B7"_ustr },
+ { u"imped"_ustr, u"\u01B5"_ustr },
+ { u"in"_ustr, u"\u2208"_ustr },
+ { u"incare"_ustr, u"\u2105"_ustr },
+ { u"infin"_ustr, u"\u221E"_ustr },
+ { u"infintie"_ustr, u"\u29DD"_ustr },
+ { u"inodot"_ustr, u"\u0131"_ustr },
+ { u"int"_ustr, u"\u222B"_ustr },
+ { u"intcal"_ustr, u"\u22BA"_ustr },
+ { u"integers"_ustr, u"\u2124"_ustr },
+ { u"intercal"_ustr, u"\u22BA"_ustr },
+ { u"intlarhk"_ustr, u"\u2A17"_ustr },
+ { u"intprod"_ustr, u"\u2A3C"_ustr },
+ { u"iocy"_ustr, u"\u0451"_ustr },
+ { u"iogon"_ustr, u"\u012F"_ustr },
+ { u"iopf"_ustr, u"\U0001D55A"_ustr },
+ { u"iota"_ustr, u"\u03B9"_ustr },
+ { u"iprod"_ustr, u"\u2A3C"_ustr },
+ { u"iquest"_ustr, u"\u00BF"_ustr },
+ { u"iscr"_ustr, u"\U0001D4BE"_ustr },
+ { u"isin"_ustr, u"\u2208"_ustr },
+ { u"isinE"_ustr, u"\u22F9"_ustr },
+ { u"isindot"_ustr, u"\u22F5"_ustr },
+ { u"isins"_ustr, u"\u22F4"_ustr },
+ { u"isinsv"_ustr, u"\u22F3"_ustr },
+ { u"isinv"_ustr, u"\u2208"_ustr },
+ { u"it"_ustr, u"\u2062"_ustr },
+ { u"itilde"_ustr, u"\u0129"_ustr },
+ { u"iukcy"_ustr, u"\u0456"_ustr },
+ { u"iuml"_ustr, u"\u00EF"_ustr },
+ { u"jcirc"_ustr, u"\u0135"_ustr },
+ { u"jcy"_ustr, u"\u0439"_ustr },
+ { u"jfr"_ustr, u"\U0001D527"_ustr },
+ { u"jmath"_ustr, u"\u0237"_ustr },
+ { u"jopf"_ustr, u"\U0001D55B"_ustr },
+ { u"jscr"_ustr, u"\U0001D4BF"_ustr },
+ { u"jsercy"_ustr, u"\u0458"_ustr },
+ { u"jukcy"_ustr, u"\u0454"_ustr },
+ { u"kappa"_ustr, u"\u03BA"_ustr },
+ { u"kappav"_ustr, u"\u03F0"_ustr },
+ { u"kcedil"_ustr, u"\u0137"_ustr },
+ { u"kcy"_ustr, u"\u043A"_ustr },
+ { u"kfr"_ustr, u"\U0001D528"_ustr },
+ { u"kgreen"_ustr, u"\u0138"_ustr },
+ { u"khcy"_ustr, u"\u0445"_ustr },
+ { u"kjcy"_ustr, u"\u045C"_ustr },
+ { u"kopf"_ustr, u"\U0001D55C"_ustr },
+ { u"kscr"_ustr, u"\U0001D4C0"_ustr },
+ { u"lAarr"_ustr, u"\u21DA"_ustr },
+ { u"lArr"_ustr, u"\u21D0"_ustr },
+ { u"lAtail"_ustr, u"\u291B"_ustr },
+ { u"lBarr"_ustr, u"\u290E"_ustr },
+ { u"lE"_ustr, u"\u2266"_ustr },
+ { u"lEg"_ustr, u"\u2A8B"_ustr },
+ { u"lHar"_ustr, u"\u2962"_ustr },
+ { u"lacute"_ustr, u"\u013A"_ustr },
+ { u"laemptyv"_ustr, u"\u29B4"_ustr },
+ { u"lagran"_ustr, u"\u2112"_ustr },
+ { u"lambda"_ustr, u"\u03BB"_ustr },
+ { u"lang"_ustr, u"\u27E8"_ustr },
+ { u"langd"_ustr, u"\u2991"_ustr },
+ { u"langle"_ustr, u"\u27E8"_ustr },
+ { u"lap"_ustr, u"\u2A85"_ustr },
+ { u"laquo"_ustr, u"\u00AB"_ustr },
+ { u"larr"_ustr, u"\u2190"_ustr },
+ { u"larrb"_ustr, u"\u21E4"_ustr },
+ { u"larrbfs"_ustr, u"\u291F"_ustr },
+ { u"larrfs"_ustr, u"\u291D"_ustr },
+ { u"larrhk"_ustr, u"\u21A9"_ustr },
+ { u"larrlp"_ustr, u"\u21AB"_ustr },
+ { u"larrpl"_ustr, u"\u2939"_ustr },
+ { u"larrsim"_ustr, u"\u2973"_ustr },
+ { u"larrtl"_ustr, u"\u21A2"_ustr },
+ { u"lat"_ustr, u"\u2AAB"_ustr },
+ { u"latail"_ustr, u"\u2919"_ustr },
+ { u"late"_ustr, u"\u2AAD"_ustr },
+ { u"lates"_ustr, u"\u2AAD\uFE00"_ustr },
+ { u"lbarr"_ustr, u"\u290C"_ustr },
+ { u"lbbrk"_ustr, u"\u2772"_ustr },
+ { u"lbrace"_ustr, u"\u007B"_ustr },
+ { u"lbrack"_ustr, u"\u005B"_ustr },
+ { u"lbrke"_ustr, u"\u298B"_ustr },
+ { u"lbrksld"_ustr, u"\u298F"_ustr },
+ { u"lbrkslu"_ustr, u"\u298D"_ustr },
+ { u"lcaron"_ustr, u"\u013E"_ustr },
+ { u"lcedil"_ustr, u"\u013C"_ustr },
+ { u"lceil"_ustr, u"\u2308"_ustr },
+ { u"lcub"_ustr, u"\u007B"_ustr },
+ { u"lcy"_ustr, u"\u043B"_ustr },
+ { u"ldca"_ustr, u"\u2936"_ustr },
+ { u"ldquo"_ustr, u"\u201C"_ustr },
+ { u"ldquor"_ustr, u"\u201E"_ustr },
+ { u"ldrdhar"_ustr, u"\u2967"_ustr },
+ { u"ldrushar"_ustr, u"\u294B"_ustr },
+ { u"ldsh"_ustr, u"\u21B2"_ustr },
+ { u"le"_ustr, u"\u2264"_ustr },
+ { u"leftarrow"_ustr, u"\u2190"_ustr },
+ { u"leftarrowtail"_ustr, u"\u21A2"_ustr },
+ { u"leftharpoondown"_ustr, u"\u21BD"_ustr },
+ { u"leftharpoonup"_ustr, u"\u21BC"_ustr },
+ { u"leftleftarrows"_ustr, u"\u21C7"_ustr },
+ { u"leftrightarrow"_ustr, u"\u2194"_ustr },
+ { u"leftrightarrows"_ustr, u"\u21C6"_ustr },
+ { u"leftrightharpoons"_ustr, u"\u21CB"_ustr },
+ { u"leftrightsquigarrow"_ustr, u"\u21AD"_ustr },
+ { u"leftthreetimes"_ustr, u"\u22CB"_ustr },
+ { u"leg"_ustr, u"\u22DA"_ustr },
+ { u"leq"_ustr, u"\u2264"_ustr },
+ { u"leqq"_ustr, u"\u2266"_ustr },
+ { u"leqslant"_ustr, u"\u2A7D"_ustr },
+ { u"les"_ustr, u"\u2A7D"_ustr },
+ { u"lescc"_ustr, u"\u2AA8"_ustr },
+ { u"lesdot"_ustr, u"\u2A7F"_ustr },
+ { u"lesdoto"_ustr, u"\u2A81"_ustr },
+ { u"lesdotor"_ustr, u"\u2A83"_ustr },
+ { u"lesg"_ustr, u"\u22DA\uFE00"_ustr },
+ { u"lesges"_ustr, u"\u2A93"_ustr },
+ { u"lessapprox"_ustr, u"\u2A85"_ustr },
+ { u"lessdot"_ustr, u"\u22D6"_ustr },
+ { u"lesseqgtr"_ustr, u"\u22DA"_ustr },
+ { u"lesseqqgtr"_ustr, u"\u2A8B"_ustr },
+ { u"lessgtr"_ustr, u"\u2276"_ustr },
+ { u"lesssim"_ustr, u"\u2272"_ustr },
+ { u"lfisht"_ustr, u"\u297C"_ustr },
+ { u"lfloor"_ustr, u"\u230A"_ustr },
+ { u"lfr"_ustr, u"\U0001D529"_ustr },
+ { u"lg"_ustr, u"\u2276"_ustr },
+ { u"lgE"_ustr, u"\u2A91"_ustr },
+ { u"lhard"_ustr, u"\u21BD"_ustr },
+ { u"lharu"_ustr, u"\u21BC"_ustr },
+ { u"lharul"_ustr, u"\u296A"_ustr },
+ { u"lhblk"_ustr, u"\u2584"_ustr },
+ { u"ljcy"_ustr, u"\u0459"_ustr },
+ { u"ll"_ustr, u"\u226A"_ustr },
+ { u"llarr"_ustr, u"\u21C7"_ustr },
+ { u"llcorner"_ustr, u"\u231E"_ustr },
+ { u"llhard"_ustr, u"\u296B"_ustr },
+ { u"lltri"_ustr, u"\u25FA"_ustr },
+ { u"lmidot"_ustr, u"\u0140"_ustr },
+ { u"lmoust"_ustr, u"\u23B0"_ustr },
+ { u"lmoustache"_ustr, u"\u23B0"_ustr },
+ { u"lnE"_ustr, u"\u2268"_ustr },
+ { u"lnap"_ustr, u"\u2A89"_ustr },
+ { u"lnapprox"_ustr, u"\u2A89"_ustr },
+ { u"lne"_ustr, u"\u2A87"_ustr },
+ { u"lneq"_ustr, u"\u2A87"_ustr },
+ { u"lneqq"_ustr, u"\u2268"_ustr },
+ { u"lnsim"_ustr, u"\u22E6"_ustr },
+ { u"loang"_ustr, u"\u27EC"_ustr },
+ { u"loarr"_ustr, u"\u21FD"_ustr },
+ { u"lobrk"_ustr, u"\u27E6"_ustr },
+ { u"longleftarrow"_ustr, u"\u27F5"_ustr },
+ { u"longleftrightarrow"_ustr, u"\u27F7"_ustr },
+ { u"longmapsto"_ustr, u"\u27FC"_ustr },
+ { u"longrightarrow"_ustr, u"\u27F6"_ustr },
+ { u"looparrowleft"_ustr, u"\u21AB"_ustr },
+ { u"looparrowright"_ustr, u"\u21AC"_ustr },
+ { u"lopar"_ustr, u"\u2985"_ustr },
+ { u"lopf"_ustr, u"\U0001D55D"_ustr },
+ { u"loplus"_ustr, u"\u2A2D"_ustr },
+ { u"lotimes"_ustr, u"\u2A34"_ustr },
+ { u"lowast"_ustr, u"\u2217"_ustr },
+ { u"lowbar"_ustr, u"\u005F"_ustr },
+ { u"loz"_ustr, u"\u25CA"_ustr },
+ { u"lozenge"_ustr, u"\u25CA"_ustr },
+ { u"lozf"_ustr, u"\u29EB"_ustr },
+ { u"lpar"_ustr, u"\u0028"_ustr },
+ { u"lparlt"_ustr, u"\u2993"_ustr },
+ { u"lrarr"_ustr, u"\u21C6"_ustr },
+ { u"lrcorner"_ustr, u"\u231F"_ustr },
+ { u"lrhar"_ustr, u"\u21CB"_ustr },
+ { u"lrhard"_ustr, u"\u296D"_ustr },
+ { u"lrm"_ustr, u"\u200E"_ustr },
+ { u"lrtri"_ustr, u"\u22BF"_ustr },
+ { u"lsaquo"_ustr, u"\u2039"_ustr },
+ { u"lscr"_ustr, u"\U0001D4C1"_ustr },
+ { u"lsh"_ustr, u"\u21B0"_ustr },
+ { u"lsim"_ustr, u"\u2272"_ustr },
+ { u"lsime"_ustr, u"\u2A8D"_ustr },
+ { u"lsimg"_ustr, u"\u2A8F"_ustr },
+ { u"lsqb"_ustr, u"\u005B"_ustr },
+ { u"lsquo"_ustr, u"\u2018"_ustr },
+ { u"lsquor"_ustr, u"\u201A"_ustr },
+ { u"lstrok"_ustr, u"\u0142"_ustr },
+ { u"lt"_ustr, u"\u003C"_ustr },
+ { u"ltcc"_ustr, u"\u2AA6"_ustr },
+ { u"ltcir"_ustr, u"\u2A79"_ustr },
+ { u"ltdot"_ustr, u"\u22D6"_ustr },
+ { u"lthree"_ustr, u"\u22CB"_ustr },
+ { u"ltimes"_ustr, u"\u22C9"_ustr },
+ { u"ltlarr"_ustr, u"\u2976"_ustr },
+ { u"ltquest"_ustr, u"\u2A7B"_ustr },
+ { u"ltrPar"_ustr, u"\u2996"_ustr },
+ { u"ltri"_ustr, u"\u25C3"_ustr },
+ { u"ltrie"_ustr, u"\u22B4"_ustr },
+ { u"ltrif"_ustr, u"\u25C2"_ustr },
+ { u"lurdshar"_ustr, u"\u294A"_ustr },
+ { u"luruhar"_ustr, u"\u2966"_ustr },
+ { u"lvertneqq"_ustr, u"\u2268\uFE00"_ustr },
+ { u"lvnE"_ustr, u"\u2268\uFE00"_ustr },
+ { u"mDDot"_ustr, u"\u223A"_ustr },
+ { u"macr"_ustr, u"\u00AF"_ustr },
+ { u"male"_ustr, u"\u2642"_ustr },
+ { u"malt"_ustr, u"\u2720"_ustr },
+ { u"maltese"_ustr, u"\u2720"_ustr },
+ { u"map"_ustr, u"\u21A6"_ustr },
+ { u"mapsto"_ustr, u"\u21A6"_ustr },
+ { u"mapstodown"_ustr, u"\u21A7"_ustr },
+ { u"mapstoleft"_ustr, u"\u21A4"_ustr },
+ { u"mapstoup"_ustr, u"\u21A5"_ustr },
+ { u"marker"_ustr, u"\u25AE"_ustr },
+ { u"mcomma"_ustr, u"\u2A29"_ustr },
+ { u"mcy"_ustr, u"\u043C"_ustr },
+ { u"mdash"_ustr, u"\u2014"_ustr },
+ { u"measuredangle"_ustr, u"\u2221"_ustr },
+ { u"mfr"_ustr, u"\U0001D52A"_ustr },
+ { u"mho"_ustr, u"\u2127"_ustr },
+ { u"micro"_ustr, u"\u00B5"_ustr },
+ { u"mid"_ustr, u"\u2223"_ustr },
+ { u"midast"_ustr, u"\u002A"_ustr },
+ { u"midcir"_ustr, u"\u2AF0"_ustr },
+ { u"middot"_ustr, u"\u00B7"_ustr },
+ { u"minus"_ustr, u"\u2212"_ustr },
+ { u"minusb"_ustr, u"\u229F"_ustr },
+ { u"minusd"_ustr, u"\u2238"_ustr },
+ { u"minusdu"_ustr, u"\u2A2A"_ustr },
+ { u"mlcp"_ustr, u"\u2ADB"_ustr },
+ { u"mldr"_ustr, u"\u2026"_ustr },
+ { u"mnplus"_ustr, u"\u2213"_ustr },
+ { u"models"_ustr, u"\u22A7"_ustr },
+ { u"mopf"_ustr, u"\U0001D55E"_ustr },
+ { u"mp"_ustr, u"\u2213"_ustr },
+ { u"mscr"_ustr, u"\U0001D4C2"_ustr },
+ { u"mstpos"_ustr, u"\u223E"_ustr },
+ { u"mu"_ustr, u"\u03BC"_ustr },
+ { u"multimap"_ustr, u"\u22B8"_ustr },
+ { u"mumap"_ustr, u"\u22B8"_ustr },
+ { u"nGg"_ustr, u"\u22D9\u0338"_ustr },
+ { u"nGt"_ustr, u"\u226B\u20D2"_ustr },
+ { u"nGtv"_ustr, u"\u226B\u0338"_ustr },
+ { u"nLeftarrow"_ustr, u"\u21CD"_ustr },
+ { u"nLeftrightarrow"_ustr, u"\u21CE"_ustr },
+ { u"nLl"_ustr, u"\u22D8\u0338"_ustr },
+ { u"nLt"_ustr, u"\u226A\u20D2"_ustr },
+ { u"nLtv"_ustr, u"\u226A\u0338"_ustr },
+ { u"nRightarrow"_ustr, u"\u21CF"_ustr },
+ { u"nVDash"_ustr, u"\u22AF"_ustr },
+ { u"nVdash"_ustr, u"\u22AE"_ustr },
+ { u"nabla"_ustr, u"\u2207"_ustr },
+ { u"nacute"_ustr, u"\u0144"_ustr },
+ { u"nang"_ustr, u"\u2220\u20D2"_ustr },
+ { u"nap"_ustr, u"\u2249"_ustr },
+ { u"napE"_ustr, u"\u2A70\u0338"_ustr },
+ { u"napid"_ustr, u"\u224B\u0338"_ustr },
+ { u"napos"_ustr, u"\u0149"_ustr },
+ { u"napprox"_ustr, u"\u2249"_ustr },
+ { u"natur"_ustr, u"\u266E"_ustr },
+ { u"natural"_ustr, u"\u266E"_ustr },
+ { u"naturals"_ustr, u"\u2115"_ustr },
+ { u"nbsp"_ustr, u"\u00A0"_ustr },
+ { u"nbump"_ustr, u"\u224E\u0338"_ustr },
+ { u"nbumpe"_ustr, u"\u224F\u0338"_ustr },
+ { u"ncap"_ustr, u"\u2A43"_ustr },
+ { u"ncaron"_ustr, u"\u0148"_ustr },
+ { u"ncedil"_ustr, u"\u0146"_ustr },
+ { u"ncong"_ustr, u"\u2247"_ustr },
+ { u"ncongdot"_ustr, u"\u2A6D\u0338"_ustr },
+ { u"ncup"_ustr, u"\u2A42"_ustr },
+ { u"ncy"_ustr, u"\u043D"_ustr },
+ { u"ndash"_ustr, u"\u2013"_ustr },
+ { u"ne"_ustr, u"\u2260"_ustr },
+ { u"neArr"_ustr, u"\u21D7"_ustr },
+ { u"nearhk"_ustr, u"\u2924"_ustr },
+ { u"nearr"_ustr, u"\u2197"_ustr },
+ { u"nearrow"_ustr, u"\u2197"_ustr },
+ { u"nedot"_ustr, u"\u2250\u0338"_ustr },
+ { u"nequiv"_ustr, u"\u2262"_ustr },
+ { u"nesear"_ustr, u"\u2928"_ustr },
+ { u"nesim"_ustr, u"\u2242\u0338"_ustr },
+ { u"nexist"_ustr, u"\u2204"_ustr },
+ { u"nexists"_ustr, u"\u2204"_ustr },
+ { u"nfr"_ustr, u"\U0001D52B"_ustr },
+ { u"ngE"_ustr, u"\u2267\u0338"_ustr },
+ { u"nge"_ustr, u"\u2271"_ustr },
+ { u"ngeq"_ustr, u"\u2271"_ustr },
+ { u"ngeqq"_ustr, u"\u2267\u0338"_ustr },
+ { u"ngeqslant"_ustr, u"\u2A7E\u0338"_ustr },
+ { u"nges"_ustr, u"\u2A7E\u0338"_ustr },
+ { u"ngsim"_ustr, u"\u2275"_ustr },
+ { u"ngt"_ustr, u"\u226F"_ustr },
+ { u"ngtr"_ustr, u"\u226F"_ustr },
+ { u"nhArr"_ustr, u"\u21CE"_ustr },
+ { u"nharr"_ustr, u"\u21AE"_ustr },
+ { u"nhpar"_ustr, u"\u2AF2"_ustr },
+ { u"ni"_ustr, u"\u220B"_ustr },
+ { u"nis"_ustr, u"\u22FC"_ustr },
+ { u"nisd"_ustr, u"\u22FA"_ustr },
+ { u"niv"_ustr, u"\u220B"_ustr },
+ { u"njcy"_ustr, u"\u045A"_ustr },
+ { u"nlArr"_ustr, u"\u21CD"_ustr },
+ { u"nlE"_ustr, u"\u2266\u0338"_ustr },
+ { u"nlarr"_ustr, u"\u219A"_ustr },
+ { u"nldr"_ustr, u"\u2025"_ustr },
+ { u"nle"_ustr, u"\u2270"_ustr },
+ { u"nleftarrow"_ustr, u"\u219A"_ustr },
+ { u"nleftrightarrow"_ustr, u"\u21AE"_ustr },
+ { u"nleq"_ustr, u"\u2270"_ustr },
+ { u"nleqq"_ustr, u"\u2266\u0338"_ustr },
+ { u"nleqslant"_ustr, u"\u2A7D\u0338"_ustr },
+ { u"nles"_ustr, u"\u2A7D\u0338"_ustr },
+ { u"nless"_ustr, u"\u226E"_ustr },
+ { u"nlsim"_ustr, u"\u2274"_ustr },
+ { u"nlt"_ustr, u"\u226E"_ustr },
+ { u"nltri"_ustr, u"\u22EA"_ustr },
+ { u"nltrie"_ustr, u"\u22EC"_ustr },
+ { u"nmid"_ustr, u"\u2224"_ustr },
+ { u"nopf"_ustr, u"\U0001D55F"_ustr },
+ { u"not"_ustr, u"\u00AC"_ustr },
+ { u"notin"_ustr, u"\u2209"_ustr },
+ { u"notinE"_ustr, u"\u22F9\u0338"_ustr },
+ { u"notindot"_ustr, u"\u22F5\u0338"_ustr },
+ { u"notinva"_ustr, u"\u2209"_ustr },
+ { u"notinvb"_ustr, u"\u22F7"_ustr },
+ { u"notinvc"_ustr, u"\u22F6"_ustr },
+ { u"notni"_ustr, u"\u220C"_ustr },
+ { u"notniva"_ustr, u"\u220C"_ustr },
+ { u"notnivb"_ustr, u"\u22FE"_ustr },
+ { u"notnivc"_ustr, u"\u22FD"_ustr },
+ { u"npar"_ustr, u"\u2226"_ustr },
+ { u"nparallel"_ustr, u"\u2226"_ustr },
+ { u"nparsl"_ustr, u"\u2AFD\u20E5"_ustr },
+ { u"npart"_ustr, u"\u2202\u0338"_ustr },
+ { u"npolint"_ustr, u"\u2A14"_ustr },
+ { u"npr"_ustr, u"\u2280"_ustr },
+ { u"nprcue"_ustr, u"\u22E0"_ustr },
+ { u"npre"_ustr, u"\u2AAF\u0338"_ustr },
+ { u"nprec"_ustr, u"\u2280"_ustr },
+ { u"npreceq"_ustr, u"\u2AAF\u0338"_ustr },
+ { u"nrArr"_ustr, u"\u21CF"_ustr },
+ { u"nrarr"_ustr, u"\u219B"_ustr },
+ { u"nrarrc"_ustr, u"\u2933\u0338"_ustr },
+ { u"nrarrw"_ustr, u"\u219D\u0338"_ustr },
+ { u"nrightarrow"_ustr, u"\u219B"_ustr },
+ { u"nrtri"_ustr, u"\u22EB"_ustr },
+ { u"nrtrie"_ustr, u"\u22ED"_ustr },
+ { u"nsc"_ustr, u"\u2281"_ustr },
+ { u"nsccue"_ustr, u"\u22E1"_ustr },
+ { u"nsce"_ustr, u"\u2AB0\u0338"_ustr },
+ { u"nscr"_ustr, u"\U0001D4C3"_ustr },
+ { u"nshortmid"_ustr, u"\u2224"_ustr },
+ { u"nshortparallel"_ustr, u"\u2226"_ustr },
+ { u"nsim"_ustr, u"\u2241"_ustr },
+ { u"nsime"_ustr, u"\u2244"_ustr },
+ { u"nsimeq"_ustr, u"\u2244"_ustr },
+ { u"nsmid"_ustr, u"\u2224"_ustr },
+ { u"nspar"_ustr, u"\u2226"_ustr },
+ { u"nsqsube"_ustr, u"\u22E2"_ustr },
+ { u"nsqsupe"_ustr, u"\u22E3"_ustr },
+ { u"nsub"_ustr, u"\u2284"_ustr },
+ { u"nsubE"_ustr, u"\u2AC5\u0338"_ustr },
+ { u"nsube"_ustr, u"\u2288"_ustr },
+ { u"nsubset"_ustr, u"\u2282\u20D2"_ustr },
+ { u"nsubseteq"_ustr, u"\u2288"_ustr },
+ { u"nsubseteqq"_ustr, u"\u2AC5\u0338"_ustr },
+ { u"nsucc"_ustr, u"\u2281"_ustr },
+ { u"nsucceq"_ustr, u"\u2AB0\u0338"_ustr },
+ { u"nsup"_ustr, u"\u2285"_ustr },
+ { u"nsupE"_ustr, u"\u2AC6\u0338"_ustr },
+ { u"nsupe"_ustr, u"\u2289"_ustr },
+ { u"nsupset"_ustr, u"\u2283\u20D2"_ustr },
+ { u"nsupseteq"_ustr, u"\u2289"_ustr },
+ { u"nsupseteqq"_ustr, u"\u2AC6\u0338"_ustr },
+ { u"ntgl"_ustr, u"\u2279"_ustr },
+ { u"ntilde"_ustr, u"\u00F1"_ustr },
+ { u"ntlg"_ustr, u"\u2278"_ustr },
+ { u"ntriangleleft"_ustr, u"\u22EA"_ustr },
+ { u"ntrianglelefteq"_ustr, u"\u22EC"_ustr },
+ { u"ntriangleright"_ustr, u"\u22EB"_ustr },
+ { u"ntrianglerighteq"_ustr, u"\u22ED"_ustr },
+ { u"nu"_ustr, u"\u03BD"_ustr },
+ { u"num"_ustr, u"\u0023"_ustr },
+ { u"numero"_ustr, u"\u2116"_ustr },
+ { u"numsp"_ustr, u"\u2007"_ustr },
+ { u"nvDash"_ustr, u"\u22AD"_ustr },
+ { u"nvHarr"_ustr, u"\u2904"_ustr },
+ { u"nvap"_ustr, u"\u224D\u20D2"_ustr },
+ { u"nvdash"_ustr, u"\u22AC"_ustr },
+ { u"nvge"_ustr, u"\u2265\u20D2"_ustr },
+ { u"nvgt"_ustr, u"\u003E\u20D2"_ustr },
+ { u"nvinfin"_ustr, u"\u29DE"_ustr },
+ { u"nvlArr"_ustr, u"\u2902"_ustr },
+ { u"nvle"_ustr, u"\u2264\u20D2"_ustr },
+ { u"nvlt"_ustr, u"\u003C\u20D2"_ustr },
+ { u"nvltrie"_ustr, u"\u22B4\u20D2"_ustr },
+ { u"nvrArr"_ustr, u"\u2903"_ustr },
+ { u"nvrtrie"_ustr, u"\u22B5\u20D2"_ustr },
+ { u"nvsim"_ustr, u"\u223C\u20D2"_ustr },
+ { u"nwArr"_ustr, u"\u21D6"_ustr },
+ { u"nwarhk"_ustr, u"\u2923"_ustr },
+ { u"nwarr"_ustr, u"\u2196"_ustr },
+ { u"nwarrow"_ustr, u"\u2196"_ustr },
+ { u"nwnear"_ustr, u"\u2927"_ustr },
+ { u"oS"_ustr, u"\u24C8"_ustr },
+ { u"oacute"_ustr, u"\u00F3"_ustr },
+ { u"oast"_ustr, u"\u229B"_ustr },
+ { u"ocir"_ustr, u"\u229A"_ustr },
+ { u"ocirc"_ustr, u"\u00F4"_ustr },
+ { u"ocy"_ustr, u"\u043E"_ustr },
+ { u"odash"_ustr, u"\u229D"_ustr },
+ { u"odblac"_ustr, u"\u0151"_ustr },
+ { u"odiv"_ustr, u"\u2A38"_ustr },
+ { u"odot"_ustr, u"\u2299"_ustr },
+ { u"odsold"_ustr, u"\u29BC"_ustr },
+ { u"oelig"_ustr, u"\u0153"_ustr },
+ { u"ofcir"_ustr, u"\u29BF"_ustr },
+ { u"ofr"_ustr, u"\U0001D52C"_ustr },
+ { u"ogon"_ustr, u"\u02DB"_ustr },
+ { u"ograve"_ustr, u"\u00F2"_ustr },
+ { u"ogt"_ustr, u"\u29C1"_ustr },
+ { u"ohbar"_ustr, u"\u29B5"_ustr },
+ { u"ohm"_ustr, u"\u03A9"_ustr },
+ { u"oint"_ustr, u"\u222E"_ustr },
+ { u"olarr"_ustr, u"\u21BA"_ustr },
+ { u"olcir"_ustr, u"\u29BE"_ustr },
+ { u"olcross"_ustr, u"\u29BB"_ustr },
+ { u"oline"_ustr, u"\u203E"_ustr },
+ { u"olt"_ustr, u"\u29C0"_ustr },
+ { u"omacr"_ustr, u"\u014D"_ustr },
+ { u"omega"_ustr, u"\u03C9"_ustr },
+ { u"omicron"_ustr, u"\u03BF"_ustr },
+ { u"omid"_ustr, u"\u29B6"_ustr },
+ { u"ominus"_ustr, u"\u2296"_ustr },
+ { u"oopf"_ustr, u"\U0001D560"_ustr },
+ { u"opar"_ustr, u"\u29B7"_ustr },
+ { u"operp"_ustr, u"\u29B9"_ustr },
+ { u"oplus"_ustr, u"\u2295"_ustr },
+ { u"or"_ustr, u"\u2228"_ustr },
+ { u"orarr"_ustr, u"\u21BB"_ustr },
+ { u"ord"_ustr, u"\u2A5D"_ustr },
+ { u"order"_ustr, u"\u2134"_ustr },
+ { u"orderof"_ustr, u"\u2134"_ustr },
+ { u"ordf"_ustr, u"\u00AA"_ustr },
+ { u"ordm"_ustr, u"\u00BA"_ustr },
+ { u"origof"_ustr, u"\u22B6"_ustr },
+ { u"oror"_ustr, u"\u2A56"_ustr },
+ { u"orslope"_ustr, u"\u2A57"_ustr },
+ { u"orv"_ustr, u"\u2A5B"_ustr },
+ { u"oscr"_ustr, u"\u2134"_ustr },
+ { u"oslash"_ustr, u"\u00F8"_ustr },
+ { u"osol"_ustr, u"\u2298"_ustr },
+ { u"otilde"_ustr, u"\u00F5"_ustr },
+ { u"otimes"_ustr, u"\u2297"_ustr },
+ { u"otimesas"_ustr, u"\u2A36"_ustr },
+ { u"ouml"_ustr, u"\u00F6"_ustr },
+ { u"ovbar"_ustr, u"\u233D"_ustr },
+ { u"par"_ustr, u"\u2225"_ustr },
+ { u"para"_ustr, u"\u00B6"_ustr },
+ { u"parallel"_ustr, u"\u2225"_ustr },
+ { u"parsim"_ustr, u"\u2AF3"_ustr },
+ { u"parsl"_ustr, u"\u2AFD"_ustr },
+ { u"part"_ustr, u"\u2202"_ustr },
+ { u"pcy"_ustr, u"\u043F"_ustr },
+ { u"percnt"_ustr, u"\u0025"_ustr },
+ { u"period"_ustr, u"\u002E"_ustr },
+ { u"permil"_ustr, u"\u2030"_ustr },
+ { u"perp"_ustr, u"\u22A5"_ustr },
+ { u"pertenk"_ustr, u"\u2031"_ustr },
+ { u"pfr"_ustr, u"\U0001D52D"_ustr },
+ { u"phi"_ustr, u"\u03C6"_ustr },
+ { u"phiv"_ustr, u"\u03D5"_ustr },
+ { u"phmmat"_ustr, u"\u2133"_ustr },
+ { u"phone"_ustr, u"\u260E"_ustr },
+ { u"pi"_ustr, u"\u03C0"_ustr },
+ { u"pitchfork"_ustr, u"\u22D4"_ustr },
+ { u"piv"_ustr, u"\u03D6"_ustr },
+ { u"planck"_ustr, u"\u210F"_ustr },
+ { u"planckh"_ustr, u"\u210E"_ustr },
+ { u"plankv"_ustr, u"\u210F"_ustr },
+ { u"plus"_ustr, u"\u002B"_ustr },
+ { u"plusacir"_ustr, u"\u2A23"_ustr },
+ { u"plusb"_ustr, u"\u229E"_ustr },
+ { u"pluscir"_ustr, u"\u2A22"_ustr },
+ { u"plusdo"_ustr, u"\u2214"_ustr },
+ { u"plusdu"_ustr, u"\u2A25"_ustr },
+ { u"pluse"_ustr, u"\u2A72"_ustr },
+ { u"plusmn"_ustr, u"\u00B1"_ustr },
+ { u"plussim"_ustr, u"\u2A26"_ustr },
+ { u"plustwo"_ustr, u"\u2A27"_ustr },
+ { u"pm"_ustr, u"\u00B1"_ustr },
+ { u"pointint"_ustr, u"\u2A15"_ustr },
+ { u"popf"_ustr, u"\U0001D561"_ustr },
+ { u"pound"_ustr, u"\u00A3"_ustr },
+ { u"pr"_ustr, u"\u227A"_ustr },
+ { u"prE"_ustr, u"\u2AB3"_ustr },
+ { u"prap"_ustr, u"\u2AB7"_ustr },
+ { u"prcue"_ustr, u"\u227C"_ustr },
+ { u"pre"_ustr, u"\u2AAF"_ustr },
+ { u"prec"_ustr, u"\u227A"_ustr },
+ { u"precapprox"_ustr, u"\u2AB7"_ustr },
+ { u"preccurlyeq"_ustr, u"\u227C"_ustr },
+ { u"preceq"_ustr, u"\u2AAF"_ustr },
+ { u"precnapprox"_ustr, u"\u2AB9"_ustr },
+ { u"precneqq"_ustr, u"\u2AB5"_ustr },
+ { u"precnsim"_ustr, u"\u22E8"_ustr },
+ { u"precsim"_ustr, u"\u227E"_ustr },
+ { u"prime"_ustr, u"\u2032"_ustr },
+ { u"primes"_ustr, u"\u2119"_ustr },
+ { u"prnE"_ustr, u"\u2AB5"_ustr },
+ { u"prnap"_ustr, u"\u2AB9"_ustr },
+ { u"prnsim"_ustr, u"\u22E8"_ustr },
+ { u"prod"_ustr, u"\u220F"_ustr },
+ { u"profalar"_ustr, u"\u232E"_ustr },
+ { u"profline"_ustr, u"\u2312"_ustr },
+ { u"profsurf"_ustr, u"\u2313"_ustr },
+ { u"prop"_ustr, u"\u221D"_ustr },
+ { u"propto"_ustr, u"\u221D"_ustr },
+ { u"prsim"_ustr, u"\u227E"_ustr },
+ { u"prurel"_ustr, u"\u22B0"_ustr },
+ { u"pscr"_ustr, u"\U0001D4C5"_ustr },
+ { u"psi"_ustr, u"\u03C8"_ustr },
+ { u"puncsp"_ustr, u"\u2008"_ustr },
+ { u"qfr"_ustr, u"\U0001D52E"_ustr },
+ { u"qint"_ustr, u"\u2A0C"_ustr },
+ { u"qopf"_ustr, u"\U0001D562"_ustr },
+ { u"qprime"_ustr, u"\u2057"_ustr },
+ { u"qscr"_ustr, u"\U0001D4C6"_ustr },
+ { u"quaternions"_ustr, u"\u210D"_ustr },
+ { u"quatint"_ustr, u"\u2A16"_ustr },
+ { u"quest"_ustr, u"\u003F"_ustr },
+ { u"questeq"_ustr, u"\u225F"_ustr },
+ { u"quot"_ustr, u"\u0022"_ustr },
+ { u"rAarr"_ustr, u"\u21DB"_ustr },
+ { u"rArr"_ustr, u"\u21D2"_ustr },
+ { u"rAtail"_ustr, u"\u291C"_ustr },
+ { u"rBarr"_ustr, u"\u290F"_ustr },
+ { u"rHar"_ustr, u"\u2964"_ustr },
+ { u"race"_ustr, u"\u223D\u0331"_ustr },
+ { u"racute"_ustr, u"\u0155"_ustr },
+ { u"radic"_ustr, u"\u221A"_ustr },
+ { u"raemptyv"_ustr, u"\u29B3"_ustr },
+ { u"rang"_ustr, u"\u27E9"_ustr },
+ { u"rangd"_ustr, u"\u2992"_ustr },
+ { u"range"_ustr, u"\u29A5"_ustr },
+ { u"rangle"_ustr, u"\u27E9"_ustr },
+ { u"raquo"_ustr, u"\u00BB"_ustr },
+ { u"rarr"_ustr, u"\u2192"_ustr },
+ { u"rarrap"_ustr, u"\u2975"_ustr },
+ { u"rarrb"_ustr, u"\u21E5"_ustr },
+ { u"rarrbfs"_ustr, u"\u2920"_ustr },
+ { u"rarrc"_ustr, u"\u2933"_ustr },
+ { u"rarrfs"_ustr, u"\u291E"_ustr },
+ { u"rarrhk"_ustr, u"\u21AA"_ustr },
+ { u"rarrlp"_ustr, u"\u21AC"_ustr },
+ { u"rarrpl"_ustr, u"\u2945"_ustr },
+ { u"rarrsim"_ustr, u"\u2974"_ustr },
+ { u"rarrtl"_ustr, u"\u21A3"_ustr },
+ { u"rarrw"_ustr, u"\u219D"_ustr },
+ { u"ratail"_ustr, u"\u291A"_ustr },
+ { u"ratio"_ustr, u"\u2236"_ustr },
+ { u"rationals"_ustr, u"\u211A"_ustr },
+ { u"rbarr"_ustr, u"\u290D"_ustr },
+ { u"rbbrk"_ustr, u"\u2773"_ustr },
+ { u"rbrace"_ustr, u"\u007D"_ustr },
+ { u"rbrack"_ustr, u"\u005D"_ustr },
+ { u"rbrke"_ustr, u"\u298C"_ustr },
+ { u"rbrksld"_ustr, u"\u298E"_ustr },
+ { u"rbrkslu"_ustr, u"\u2990"_ustr },
+ { u"rcaron"_ustr, u"\u0159"_ustr },
+ { u"rcedil"_ustr, u"\u0157"_ustr },
+ { u"rceil"_ustr, u"\u2309"_ustr },
+ { u"rcub"_ustr, u"\u007D"_ustr },
+ { u"rcy"_ustr, u"\u0440"_ustr },
+ { u"rdca"_ustr, u"\u2937"_ustr },
+ { u"rdldhar"_ustr, u"\u2969"_ustr },
+ { u"rdquo"_ustr, u"\u201D"_ustr },
+ { u"rdquor"_ustr, u"\u201D"_ustr },
+ { u"rdsh"_ustr, u"\u21B3"_ustr },
+ { u"real"_ustr, u"\u211C"_ustr },
+ { u"realine"_ustr, u"\u211B"_ustr },
+ { u"realpart"_ustr, u"\u211C"_ustr },
+ { u"reals"_ustr, u"\u211D"_ustr },
+ { u"rect"_ustr, u"\u25AD"_ustr },
+ { u"reg"_ustr, u"\u00AE"_ustr },
+ { u"rfisht"_ustr, u"\u297D"_ustr },
+ { u"rfloor"_ustr, u"\u230B"_ustr },
+ { u"rfr"_ustr, u"\U0001D52F"_ustr },
+ { u"rhard"_ustr, u"\u21C1"_ustr },
+ { u"rharu"_ustr, u"\u21C0"_ustr },
+ { u"rharul"_ustr, u"\u296C"_ustr },
+ { u"rho"_ustr, u"\u03C1"_ustr },
+ { u"rhov"_ustr, u"\u03F1"_ustr },
+ { u"rightarrow"_ustr, u"\u2192"_ustr },
+ { u"rightarrowtail"_ustr, u"\u21A3"_ustr },
+ { u"rightharpoondown"_ustr, u"\u21C1"_ustr },
+ { u"rightharpoonup"_ustr, u"\u21C0"_ustr },
+ { u"rightleftarrows"_ustr, u"\u21C4"_ustr },
+ { u"rightleftharpoons"_ustr, u"\u21CC"_ustr },
+ { u"rightrightarrows"_ustr, u"\u21C9"_ustr },
+ { u"rightsquigarrow"_ustr, u"\u219D"_ustr },
+ { u"rightthreetimes"_ustr, u"\u22CC"_ustr },
+ { u"ring"_ustr, u"\u02DA"_ustr },
+ { u"risingdotseq"_ustr, u"\u2253"_ustr },
+ { u"rlarr"_ustr, u"\u21C4"_ustr },
+ { u"rlhar"_ustr, u"\u21CC"_ustr },
+ { u"rlm"_ustr, u"\u200F"_ustr },
+ { u"rmoust"_ustr, u"\u23B1"_ustr },
+ { u"rmoustache"_ustr, u"\u23B1"_ustr },
+ { u"rnmid"_ustr, u"\u2AEE"_ustr },
+ { u"roang"_ustr, u"\u27ED"_ustr },
+ { u"roarr"_ustr, u"\u21FE"_ustr },
+ { u"robrk"_ustr, u"\u27E7"_ustr },
+ { u"ropar"_ustr, u"\u2986"_ustr },
+ { u"ropf"_ustr, u"\U0001D563"_ustr },
+ { u"roplus"_ustr, u"\u2A2E"_ustr },
+ { u"rotimes"_ustr, u"\u2A35"_ustr },
+ { u"rpar"_ustr, u"\u0029"_ustr },
+ { u"rpargt"_ustr, u"\u2994"_ustr },
+ { u"rppolint"_ustr, u"\u2A12"_ustr },
+ { u"rrarr"_ustr, u"\u21C9"_ustr },
+ { u"rsaquo"_ustr, u"\u203A"_ustr },
+ { u"rscr"_ustr, u"\U0001D4C7"_ustr },
+ { u"rsh"_ustr, u"\u21B1"_ustr },
+ { u"rsqb"_ustr, u"\u005D"_ustr },
+ { u"rsquo"_ustr, u"\u2019"_ustr },
+ { u"rsquor"_ustr, u"\u2019"_ustr },
+ { u"rthree"_ustr, u"\u22CC"_ustr },
+ { u"rtimes"_ustr, u"\u22CA"_ustr },
+ { u"rtri"_ustr, u"\u25B9"_ustr },
+ { u"rtrie"_ustr, u"\u22B5"_ustr },
+ { u"rtrif"_ustr, u"\u25B8"_ustr },
+ { u"rtriltri"_ustr, u"\u29CE"_ustr },
+ { u"ruluhar"_ustr, u"\u2968"_ustr },
+ { u"rx"_ustr, u"\u211E"_ustr },
+ { u"sacute"_ustr, u"\u015B"_ustr },
+ { u"sbquo"_ustr, u"\u201A"_ustr },
+ { u"sc"_ustr, u"\u227B"_ustr },
+ { u"scE"_ustr, u"\u2AB4"_ustr },
+ { u"scap"_ustr, u"\u2AB8"_ustr },
+ { u"scaron"_ustr, u"\u0161"_ustr },
+ { u"sccue"_ustr, u"\u227D"_ustr },
+ { u"sce"_ustr, u"\u2AB0"_ustr },
+ { u"scedil"_ustr, u"\u015F"_ustr },
+ { u"scirc"_ustr, u"\u015D"_ustr },
+ { u"scnE"_ustr, u"\u2AB6"_ustr },
+ { u"scnap"_ustr, u"\u2ABA"_ustr },
+ { u"scnsim"_ustr, u"\u22E9"_ustr },
+ { u"scpolint"_ustr, u"\u2A13"_ustr },
+ { u"scsim"_ustr, u"\u227F"_ustr },
+ { u"scy"_ustr, u"\u0441"_ustr },
+ { u"sdot"_ustr, u"\u22C5"_ustr },
+ { u"sdotb"_ustr, u"\u22A1"_ustr },
+ { u"sdote"_ustr, u"\u2A66"_ustr },
+ { u"seArr"_ustr, u"\u21D8"_ustr },
+ { u"searhk"_ustr, u"\u2925"_ustr },
+ { u"searr"_ustr, u"\u2198"_ustr },
+ { u"searrow"_ustr, u"\u2198"_ustr },
+ { u"sect"_ustr, u"\u00A7"_ustr },
+ { u"semi"_ustr, u"\u003B"_ustr },
+ { u"seswar"_ustr, u"\u2929"_ustr },
+ { u"setminus"_ustr, u"\u2216"_ustr },
+ { u"setmn"_ustr, u"\u2216"_ustr },
+ { u"sext"_ustr, u"\u2736"_ustr },
+ { u"sfr"_ustr, u"\U0001D530"_ustr },
+ { u"sfrown"_ustr, u"\u2322"_ustr },
+ { u"sharp"_ustr, u"\u266F"_ustr },
+ { u"shchcy"_ustr, u"\u0449"_ustr },
+ { u"shcy"_ustr, u"\u0448"_ustr },
+ { u"shortmid"_ustr, u"\u2223"_ustr },
+ { u"shortparallel"_ustr, u"\u2225"_ustr },
+ { u"shy"_ustr, u"\u00AD"_ustr },
+ { u"sigma"_ustr, u"\u03C3"_ustr },
+ { u"sigmaf"_ustr, u"\u03C2"_ustr },
+ { u"sigmav"_ustr, u"\u03C2"_ustr },
+ { u"sim"_ustr, u"\u223C"_ustr },
+ { u"simdot"_ustr, u"\u2A6A"_ustr },
+ { u"sime"_ustr, u"\u2243"_ustr },
+ { u"simeq"_ustr, u"\u2243"_ustr },
+ { u"simg"_ustr, u"\u2A9E"_ustr },
+ { u"simgE"_ustr, u"\u2AA0"_ustr },
+ { u"siml"_ustr, u"\u2A9D"_ustr },
+ { u"simlE"_ustr, u"\u2A9F"_ustr },
+ { u"simne"_ustr, u"\u2246"_ustr },
+ { u"simplus"_ustr, u"\u2A24"_ustr },
+ { u"simrarr"_ustr, u"\u2972"_ustr },
+ { u"slarr"_ustr, u"\u2190"_ustr },
+ { u"smallsetminus"_ustr, u"\u2216"_ustr },
+ { u"smashp"_ustr, u"\u2A33"_ustr },
+ { u"smeparsl"_ustr, u"\u29E4"_ustr },
+ { u"smid"_ustr, u"\u2223"_ustr },
+ { u"smile"_ustr, u"\u2323"_ustr },
+ { u"smt"_ustr, u"\u2AAA"_ustr },
+ { u"smte"_ustr, u"\u2AAC"_ustr },
+ { u"smtes"_ustr, u"\u2AAC\uFE00"_ustr },
+ { u"softcy"_ustr, u"\u044C"_ustr },
+ { u"sol"_ustr, u"\u002F"_ustr },
+ { u"solb"_ustr, u"\u29C4"_ustr },
+ { u"solbar"_ustr, u"\u233F"_ustr },
+ { u"sopf"_ustr, u"\U0001D564"_ustr },
+ { u"spades"_ustr, u"\u2660"_ustr },
+ { u"spadesuit"_ustr, u"\u2660"_ustr },
+ { u"spar"_ustr, u"\u2225"_ustr },
+ { u"sqcap"_ustr, u"\u2293"_ustr },
+ { u"sqcaps"_ustr, u"\u2293\uFE00"_ustr },
+ { u"sqcup"_ustr, u"\u2294"_ustr },
+ { u"sqcups"_ustr, u"\u2294\uFE00"_ustr },
+ { u"sqsub"_ustr, u"\u228F"_ustr },
+ { u"sqsube"_ustr, u"\u2291"_ustr },
+ { u"sqsubset"_ustr, u"\u228F"_ustr },
+ { u"sqsubseteq"_ustr, u"\u2291"_ustr },
+ { u"sqsup"_ustr, u"\u2290"_ustr },
+ { u"sqsupe"_ustr, u"\u2292"_ustr },
+ { u"sqsupset"_ustr, u"\u2290"_ustr },
+ { u"sqsupseteq"_ustr, u"\u2292"_ustr },
+ { u"squ"_ustr, u"\u25A1"_ustr },
+ { u"square"_ustr, u"\u25A1"_ustr },
+ { u"squarf"_ustr, u"\u25AA"_ustr },
+ { u"squf"_ustr, u"\u25AA"_ustr },
+ { u"srarr"_ustr, u"\u2192"_ustr },
+ { u"sscr"_ustr, u"\U0001D4C8"_ustr },
+ { u"ssetmn"_ustr, u"\u2216"_ustr },
+ { u"ssmile"_ustr, u"\u2323"_ustr },
+ { u"sstarf"_ustr, u"\u22C6"_ustr },
+ { u"star"_ustr, u"\u2606"_ustr },
+ { u"starf"_ustr, u"\u2605"_ustr },
+ { u"straightepsilon"_ustr, u"\u03F5"_ustr },
+ { u"straightphi"_ustr, u"\u03D5"_ustr },
+ { u"strns"_ustr, u"\u00AF"_ustr },
+ { u"sub"_ustr, u"\u2282"_ustr },
+ { u"subE"_ustr, u"\u2AC5"_ustr },
+ { u"subdot"_ustr, u"\u2ABD"_ustr },
+ { u"sube"_ustr, u"\u2286"_ustr },
+ { u"subedot"_ustr, u"\u2AC3"_ustr },
+ { u"submult"_ustr, u"\u2AC1"_ustr },
+ { u"subnE"_ustr, u"\u2ACB"_ustr },
+ { u"subne"_ustr, u"\u228A"_ustr },
+ { u"subplus"_ustr, u"\u2ABF"_ustr },
+ { u"subrarr"_ustr, u"\u2979"_ustr },
+ { u"subset"_ustr, u"\u2282"_ustr },
+ { u"subseteq"_ustr, u"\u2286"_ustr },
+ { u"subseteqq"_ustr, u"\u2AC5"_ustr },
+ { u"subsetneq"_ustr, u"\u228A"_ustr },
+ { u"subsetneqq"_ustr, u"\u2ACB"_ustr },
+ { u"subsim"_ustr, u"\u2AC7"_ustr },
+ { u"subsub"_ustr, u"\u2AD5"_ustr },
+ { u"subsup"_ustr, u"\u2AD3"_ustr },
+ { u"succ"_ustr, u"\u227B"_ustr },
+ { u"succapprox"_ustr, u"\u2AB8"_ustr },
+ { u"succcurlyeq"_ustr, u"\u227D"_ustr },
+ { u"succeq"_ustr, u"\u2AB0"_ustr },
+ { u"succnapprox"_ustr, u"\u2ABA"_ustr },
+ { u"succneqq"_ustr, u"\u2AB6"_ustr },
+ { u"succnsim"_ustr, u"\u22E9"_ustr },
+ { u"succsim"_ustr, u"\u227F"_ustr },
+ { u"sum"_ustr, u"\u2211"_ustr },
+ { u"sung"_ustr, u"\u266A"_ustr },
+ { u"sup"_ustr, u"\u2283"_ustr },
+ { u"sup1"_ustr, u"\u00B9"_ustr },
+ { u"sup2"_ustr, u"\u00B2"_ustr },
+ { u"sup3"_ustr, u"\u00B3"_ustr },
+ { u"supE"_ustr, u"\u2AC6"_ustr },
+ { u"supdot"_ustr, u"\u2ABE"_ustr },
+ { u"supdsub"_ustr, u"\u2AD8"_ustr },
+ { u"supe"_ustr, u"\u2287"_ustr },
+ { u"supedot"_ustr, u"\u2AC4"_ustr },
+ { u"suphsol"_ustr, u"\u27C9"_ustr },
+ { u"suphsub"_ustr, u"\u2AD7"_ustr },
+ { u"suplarr"_ustr, u"\u297B"_ustr },
+ { u"supmult"_ustr, u"\u2AC2"_ustr },
+ { u"supnE"_ustr, u"\u2ACC"_ustr },
+ { u"supne"_ustr, u"\u228B"_ustr },
+ { u"supplus"_ustr, u"\u2AC0"_ustr },
+ { u"supset"_ustr, u"\u2283"_ustr },
+ { u"supseteq"_ustr, u"\u2287"_ustr },
+ { u"supseteqq"_ustr, u"\u2AC6"_ustr },
+ { u"supsetneq"_ustr, u"\u228B"_ustr },
+ { u"supsetneqq"_ustr, u"\u2ACC"_ustr },
+ { u"supsim"_ustr, u"\u2AC8"_ustr },
+ { u"supsub"_ustr, u"\u2AD4"_ustr },
+ { u"supsup"_ustr, u"\u2AD6"_ustr },
+ { u"swArr"_ustr, u"\u21D9"_ustr },
+ { u"swarhk"_ustr, u"\u2926"_ustr },
+ { u"swarr"_ustr, u"\u2199"_ustr },
+ { u"swarrow"_ustr, u"\u2199"_ustr },
+ { u"swnwar"_ustr, u"\u292A"_ustr },
+ { u"szlig"_ustr, u"\u00DF"_ustr },
+ { u"target"_ustr, u"\u2316"_ustr },
+ { u"tau"_ustr, u"\u03C4"_ustr },
+ { u"tbrk"_ustr, u"\u23B4"_ustr },
+ { u"tcaron"_ustr, u"\u0165"_ustr },
+ { u"tcedil"_ustr, u"\u0163"_ustr },
+ { u"tcy"_ustr, u"\u0442"_ustr },
+ { u"tdot"_ustr, u"\u20DB"_ustr },
+ { u"telrec"_ustr, u"\u2315"_ustr },
+ { u"tfr"_ustr, u"\U0001D531"_ustr },
+ { u"there4"_ustr, u"\u2234"_ustr },
+ { u"therefore"_ustr, u"\u2234"_ustr },
+ { u"theta"_ustr, u"\u03B8"_ustr },
+ { u"thetasym"_ustr, u"\u03D1"_ustr },
+ { u"thetav"_ustr, u"\u03D1"_ustr },
+ { u"thickapprox"_ustr, u"\u2248"_ustr },
+ { u"thicksim"_ustr, u"\u223C"_ustr },
+ { u"thinsp"_ustr, u"\u2009"_ustr },
+ { u"thkap"_ustr, u"\u2248"_ustr },
+ { u"thksim"_ustr, u"\u223C"_ustr },
+ { u"thorn"_ustr, u"\u00FE"_ustr },
+ { u"tilde"_ustr, u"\u02DC"_ustr },
+ { u"times"_ustr, u"\u00D7"_ustr },
+ { u"timesb"_ustr, u"\u22A0"_ustr },
+ { u"timesbar"_ustr, u"\u2A31"_ustr },
+ { u"timesd"_ustr, u"\u2A30"_ustr },
+ { u"tint"_ustr, u"\u222D"_ustr },
+ { u"toea"_ustr, u"\u2928"_ustr },
+ { u"top"_ustr, u"\u22A4"_ustr },
+ { u"topbot"_ustr, u"\u2336"_ustr },
+ { u"topcir"_ustr, u"\u2AF1"_ustr },
+ { u"topf"_ustr, u"\U0001D565"_ustr },
+ { u"topfork"_ustr, u"\u2ADA"_ustr },
+ { u"tosa"_ustr, u"\u2929"_ustr },
+ { u"tprime"_ustr, u"\u2034"_ustr },
+ { u"trade"_ustr, u"\u2122"_ustr },
+ { u"triangle"_ustr, u"\u25B5"_ustr },
+ { u"triangledown"_ustr, u"\u25BF"_ustr },
+ { u"triangleleft"_ustr, u"\u25C3"_ustr },
+ { u"trianglelefteq"_ustr, u"\u22B4"_ustr },
+ { u"triangleq"_ustr, u"\u225C"_ustr },
+ { u"triangleright"_ustr, u"\u25B9"_ustr },
+ { u"trianglerighteq"_ustr, u"\u22B5"_ustr },
+ { u"tridot"_ustr, u"\u25EC"_ustr },
+ { u"trie"_ustr, u"\u225C"_ustr },
+ { u"triminus"_ustr, u"\u2A3A"_ustr },
+ { u"triplus"_ustr, u"\u2A39"_ustr },
+ { u"trisb"_ustr, u"\u29CD"_ustr },
+ { u"tritime"_ustr, u"\u2A3B"_ustr },
+ { u"trpezium"_ustr, u"\u23E2"_ustr },
+ { u"tscr"_ustr, u"\U0001D4C9"_ustr },
+ { u"tscy"_ustr, u"\u0446"_ustr },
+ { u"tshcy"_ustr, u"\u045B"_ustr },
+ { u"tstrok"_ustr, u"\u0167"_ustr },
+ { u"twixt"_ustr, u"\u226C"_ustr },
+ { u"twoheadleftarrow"_ustr, u"\u219E"_ustr },
+ { u"twoheadrightarrow"_ustr, u"\u21A0"_ustr },
+ { u"uArr"_ustr, u"\u21D1"_ustr },
+ { u"uHar"_ustr, u"\u2963"_ustr },
+ { u"uacute"_ustr, u"\u00FA"_ustr },
+ { u"uarr"_ustr, u"\u2191"_ustr },
+ { u"ubrcy"_ustr, u"\u045E"_ustr },
+ { u"ubreve"_ustr, u"\u016D"_ustr },
+ { u"ucirc"_ustr, u"\u00FB"_ustr },
+ { u"ucy"_ustr, u"\u0443"_ustr },
+ { u"udarr"_ustr, u"\u21C5"_ustr },
+ { u"udblac"_ustr, u"\u0171"_ustr },
+ { u"udhar"_ustr, u"\u296E"_ustr },
+ { u"ufisht"_ustr, u"\u297E"_ustr },
+ { u"ufr"_ustr, u"\U0001D532"_ustr },
+ { u"ugrave"_ustr, u"\u00F9"_ustr },
+ { u"uharl"_ustr, u"\u21BF"_ustr },
+ { u"uharr"_ustr, u"\u21BE"_ustr },
+ { u"uhblk"_ustr, u"\u2580"_ustr },
+ { u"ulcorn"_ustr, u"\u231C"_ustr },
+ { u"ulcorner"_ustr, u"\u231C"_ustr },
+ { u"ulcrop"_ustr, u"\u230F"_ustr },
+ { u"ultri"_ustr, u"\u25F8"_ustr },
+ { u"umacr"_ustr, u"\u016B"_ustr },
+ { u"uml"_ustr, u"\u00A8"_ustr },
+ { u"uogon"_ustr, u"\u0173"_ustr },
+ { u"uopf"_ustr, u"\U0001D566"_ustr },
+ { u"uparrow"_ustr, u"\u2191"_ustr },
+ { u"updownarrow"_ustr, u"\u2195"_ustr },
+ { u"upharpoonleft"_ustr, u"\u21BF"_ustr },
+ { u"upharpoonright"_ustr, u"\u21BE"_ustr },
+ { u"uplus"_ustr, u"\u228E"_ustr },
+ { u"upsi"_ustr, u"\u03C5"_ustr },
+ { u"upsih"_ustr, u"\u03D2"_ustr },
+ { u"upsilon"_ustr, u"\u03C5"_ustr },
+ { u"upuparrows"_ustr, u"\u21C8"_ustr },
+ { u"urcorn"_ustr, u"\u231D"_ustr },
+ { u"urcorner"_ustr, u"\u231D"_ustr },
+ { u"urcrop"_ustr, u"\u230E"_ustr },
+ { u"uring"_ustr, u"\u016F"_ustr },
+ { u"urtri"_ustr, u"\u25F9"_ustr },
+ { u"uscr"_ustr, u"\U0001D4CA"_ustr },
+ { u"utdot"_ustr, u"\u22F0"_ustr },
+ { u"utilde"_ustr, u"\u0169"_ustr },
+ { u"utri"_ustr, u"\u25B5"_ustr },
+ { u"utrif"_ustr, u"\u25B4"_ustr },
+ { u"uuarr"_ustr, u"\u21C8"_ustr },
+ { u"uuml"_ustr, u"\u00FC"_ustr },
+ { u"uwangle"_ustr, u"\u29A7"_ustr },
+ { u"vArr"_ustr, u"\u21D5"_ustr },
+ { u"vBar"_ustr, u"\u2AE8"_ustr },
+ { u"vBarv"_ustr, u"\u2AE9"_ustr },
+ { u"vDash"_ustr, u"\u22A8"_ustr },
+ { u"vangrt"_ustr, u"\u299C"_ustr },
+ { u"varepsilon"_ustr, u"\u03F5"_ustr },
+ { u"varkappa"_ustr, u"\u03F0"_ustr },
+ { u"varnothing"_ustr, u"\u2205"_ustr },
+ { u"varphi"_ustr, u"\u03D5"_ustr },
+ { u"varpi"_ustr, u"\u03D6"_ustr },
+ { u"varpropto"_ustr, u"\u221D"_ustr },
+ { u"varr"_ustr, u"\u2195"_ustr },
+ { u"varrho"_ustr, u"\u03F1"_ustr },
+ { u"varsigma"_ustr, u"\u03C2"_ustr },
+ { u"varsubsetneq"_ustr, u"\u228A\uFE00"_ustr },
+ { u"varsubsetneqq"_ustr, u"\u2ACB\uFE00"_ustr },
+ { u"varsupsetneq"_ustr, u"\u228B\uFE00"_ustr },
+ { u"varsupsetneqq"_ustr, u"\u2ACC\uFE00"_ustr },
+ { u"vartheta"_ustr, u"\u03D1"_ustr },
+ { u"vartriangleleft"_ustr, u"\u22B2"_ustr },
+ { u"vartriangleright"_ustr, u"\u22B3"_ustr },
+ { u"vcy"_ustr, u"\u0432"_ustr },
+ { u"vdash"_ustr, u"\u22A2"_ustr },
+ { u"vee"_ustr, u"\u2228"_ustr },
+ { u"veebar"_ustr, u"\u22BB"_ustr },
+ { u"veeeq"_ustr, u"\u225A"_ustr },
+ { u"vellip"_ustr, u"\u22EE"_ustr },
+ { u"verbar"_ustr, u"\u007C"_ustr },
+ { u"vert"_ustr, u"\u007C"_ustr },
+ { u"vfr"_ustr, u"\U0001D533"_ustr },
+ { u"vltri"_ustr, u"\u22B2"_ustr },
+ { u"vnsub"_ustr, u"\u2282\u20D2"_ustr },
+ { u"vnsup"_ustr, u"\u2283\u20D2"_ustr },
+ { u"vopf"_ustr, u"\U0001D567"_ustr },
+ { u"vprop"_ustr, u"\u221D"_ustr },
+ { u"vrtri"_ustr, u"\u22B3"_ustr },
+ { u"vscr"_ustr, u"\U0001D4CB"_ustr },
+ { u"vsubnE"_ustr, u"\u2ACB\uFE00"_ustr },
+ { u"vsubne"_ustr, u"\u228A\uFE00"_ustr },
+ { u"vsupnE"_ustr, u"\u2ACC\uFE00"_ustr },
+ { u"vsupne"_ustr, u"\u228B\uFE00"_ustr },
+ { u"vzigzag"_ustr, u"\u299A"_ustr },
+ { u"wcirc"_ustr, u"\u0175"_ustr },
+ { u"wedbar"_ustr, u"\u2A5F"_ustr },
+ { u"wedge"_ustr, u"\u2227"_ustr },
+ { u"wedgeq"_ustr, u"\u2259"_ustr },
+ { u"weierp"_ustr, u"\u2118"_ustr },
+ { u"wfr"_ustr, u"\U0001D534"_ustr },
+ { u"wopf"_ustr, u"\U0001D568"_ustr },
+ { u"wp"_ustr, u"\u2118"_ustr },
+ { u"wr"_ustr, u"\u2240"_ustr },
+ { u"wreath"_ustr, u"\u2240"_ustr },
+ { u"wscr"_ustr, u"\U0001D4CC"_ustr },
+ { u"xcap"_ustr, u"\u22C2"_ustr },
+ { u"xcirc"_ustr, u"\u25EF"_ustr },
+ { u"xcup"_ustr, u"\u22C3"_ustr },
+ { u"xdtri"_ustr, u"\u25BD"_ustr },
+ { u"xfr"_ustr, u"\U0001D535"_ustr },
+ { u"xhArr"_ustr, u"\u27FA"_ustr },
+ { u"xharr"_ustr, u"\u27F7"_ustr },
+ { u"xi"_ustr, u"\u03BE"_ustr },
+ { u"xlArr"_ustr, u"\u27F8"_ustr },
+ { u"xlarr"_ustr, u"\u27F5"_ustr },
+ { u"xmap"_ustr, u"\u27FC"_ustr },
+ { u"xnis"_ustr, u"\u22FB"_ustr },
+ { u"xodot"_ustr, u"\u2A00"_ustr },
+ { u"xopf"_ustr, u"\U0001D569"_ustr },
+ { u"xoplus"_ustr, u"\u2A01"_ustr },
+ { u"xotime"_ustr, u"\u2A02"_ustr },
+ { u"xrArr"_ustr, u"\u27F9"_ustr },
+ { u"xrarr"_ustr, u"\u27F6"_ustr },
+ { u"xscr"_ustr, u"\U0001D4CD"_ustr },
+ { u"xsqcup"_ustr, u"\u2A06"_ustr },
+ { u"xuplus"_ustr, u"\u2A04"_ustr },
+ { u"xutri"_ustr, u"\u25B3"_ustr },
+ { u"xvee"_ustr, u"\u22C1"_ustr },
+ { u"xwedge"_ustr, u"\u22C0"_ustr },
+ { u"yacute"_ustr, u"\u00FD"_ustr },
+ { u"yacy"_ustr, u"\u044F"_ustr },
+ { u"ycirc"_ustr, u"\u0177"_ustr },
+ { u"ycy"_ustr, u"\u044B"_ustr },
+ { u"yen"_ustr, u"\u00A5"_ustr },
+ { u"yfr"_ustr, u"\U0001D536"_ustr },
+ { u"yicy"_ustr, u"\u0457"_ustr },
+ { u"yopf"_ustr, u"\U0001D56A"_ustr },
+ { u"yscr"_ustr, u"\U0001D4CE"_ustr },
+ { u"yucy"_ustr, u"\u044E"_ustr },
+ { u"yuml"_ustr, u"\u00FF"_ustr },
+ { u"zacute"_ustr, u"\u017A"_ustr },
+ { u"zcaron"_ustr, u"\u017E"_ustr },
+ { u"zcy"_ustr, u"\u0437"_ustr },
+ { u"zdot"_ustr, u"\u017C"_ustr },
+ { u"zeetrf"_ustr, u"\u2128"_ustr },
+ { u"zeta"_ustr, u"\u03B6"_ustr },
+ { u"zfr"_ustr, u"\U0001D537"_ustr },
+ { u"zhcy"_ustr, u"\u0436"_ustr },
+ { u"zigrarr"_ustr, u"\u21DD"_ustr },
+ { u"zopf"_ustr, u"\U0001D56B"_ustr },
+ { u"zscr"_ustr, u"\U0001D4CF"_ustr },
+ { u"zwj"_ustr, u"\u200D"_ustr },
+ { u"zwnj"_ustr, u"\u200C"_ustr }
+ // 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;"_ustr, u"\u03C3"_ustr},
+ { u"&infin;"_ustr, u"\u221E"_ustr}
+ // 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: */