diff options
Diffstat (limited to 'starmath/source/mathml')
-rw-r--r-- | starmath/source/mathml/attribute.cxx | 479 | ||||
-rw-r--r-- | starmath/source/mathml/def.cxx | 124 | ||||
-rw-r--r-- | starmath/source/mathml/element.cxx | 136 | ||||
-rw-r--r-- | starmath/source/mathml/export.cxx | 1090 | ||||
-rw-r--r-- | starmath/source/mathml/import.cxx | 1405 | ||||
-rw-r--r-- | starmath/source/mathml/iterator.cxx | 77 | ||||
-rw-r--r-- | starmath/source/mathml/mathmlMo.cxx | 1128 | ||||
-rw-r--r-- | starmath/source/mathml/mathmlattr.cxx | 165 | ||||
-rw-r--r-- | starmath/source/mathml/mathmlexport.cxx | 1443 | ||||
-rw-r--r-- | starmath/source/mathml/mathmlimport.cxx | 2673 | ||||
-rw-r--r-- | starmath/source/mathml/starmathdatabase.cxx | 794 | ||||
-rw-r--r-- | starmath/source/mathml/xparsmlbase.cxx | 2166 |
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"<"_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"σ"_ustr, u"\u03C3"_ustr}, + { u"∞"_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: */ |