diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /starmath/source/mathml | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | starmath/source/mathml/attribute.cxx | 475 | ||||
-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 | 1110 | ||||
-rw-r--r-- | starmath/source/mathml/import.cxx | 1430 | ||||
-rw-r--r-- | starmath/source/mathml/iterator.cxx | 77 | ||||
-rw-r--r-- | starmath/source/mathml/mathmlMo.cxx | 1127 | ||||
-rw-r--r-- | starmath/source/mathml/mathmlattr.cxx | 165 | ||||
-rw-r--r-- | starmath/source/mathml/mathmlexport.cxx | 1457 | ||||
-rw-r--r-- | starmath/source/mathml/mathmlimport.cxx | 2696 | ||||
-rw-r--r-- | starmath/source/mathml/starmathdatabase.cxx | 794 | ||||
-rw-r--r-- | starmath/source/mathml/xparsmlbase.cxx | 2166 |
12 files changed, 11757 insertions, 0 deletions
diff --git a/starmath/source/mathml/attribute.cxx b/starmath/source/mathml/attribute.cxx new file mode 100644 index 000000000..a1be708ae --- /dev/null +++ b/starmath/source/mathml/attribute.cxx @@ -0,0 +1,475 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <mathml/attribute.hxx> + +void SmMlAttribute::clearPreviousAttributeValue() +{ + switch (m_aSmMlAttributeValueType) + { + case SmMlAttributeValueType::NMlEmpty: + break; + case SmMlAttributeValueType::MlHref: + if (m_aAttributeValue.m_aHref.m_aLnk) + delete m_aAttributeValue.m_aHref.m_aLnk; + break; + case SmMlAttributeValueType::MlLspace: + if (m_aAttributeValue.m_aLspace.m_aLengthValue.m_aOriginalText) + delete m_aAttributeValue.m_aLspace.m_aLengthValue.m_aOriginalText; + break; + case SmMlAttributeValueType::MlMathsize: + if (m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aOriginalText) + delete m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aOriginalText; + break; + case SmMlAttributeValueType::MlMaxsize: + if (m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aOriginalText) + delete m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aOriginalText; + break; + case SmMlAttributeValueType::MlMinsize: + if (m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aOriginalText) + delete m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aOriginalText; + break; + case SmMlAttributeValueType::MlRspace: + if (m_aAttributeValue.m_aRspace.m_aLengthValue.m_aOriginalText) + delete m_aAttributeValue.m_aRspace.m_aLengthValue.m_aOriginalText; + break; + default: + break; + } +} + +void SmMlAttribute::setDefaultAttributeValue() +{ + switch (m_aSmMlAttributeValueType) + { + case SmMlAttributeValueType::NMlEmpty: + break; + case SmMlAttributeValueType::MlAccent: + m_aAttributeValue.m_aAccent.m_aAccent = SmMlAttributeValueAccent::MlFalse; + break; + case SmMlAttributeValueType::MlDir: + m_aAttributeValue.m_aDir.m_aDir = SmMlAttributeValueDir::MlLtr; + break; + case SmMlAttributeValueType::MlDisplaystyle: + m_aAttributeValue.m_aDisplaystyle.m_aDisplaystyle + = SmMlAttributeValueDisplaystyle::MlFalse; + break; + case SmMlAttributeValueType::MlFence: + m_aAttributeValue.m_aFence.m_aFence = SmMlAttributeValueFence::MlFalse; + break; + case SmMlAttributeValueType::MlForm: + m_aAttributeValue.m_aForm.m_aForm = SmMlAttributeValueForm::MlInfix; + break; + case SmMlAttributeValueType::MlHref: + m_aAttributeValue.m_aHref.m_aHref = SmMlAttributeValueHref::NMlEmpty; + m_aAttributeValue.m_aHref.m_aLnk = new OUString(u""); + break; + case SmMlAttributeValueType::MlLspace: + m_aAttributeValue.m_aLspace.m_aLengthValue.m_aLengthUnit = SmLengthUnit::MlEm; + m_aAttributeValue.m_aLspace.m_aLengthValue.m_aLengthValue = 5.0 / 18; + m_aAttributeValue.m_aLspace.m_aLengthValue.m_aOriginalText = new OUString(u"5/18em"); + break; + case SmMlAttributeValueType::MlMathbackground: + m_aAttributeValue.m_aMathbackground.m_aMathbackground + = SmMlAttributeValueMathbackground::MlTransparent; + break; + case SmMlAttributeValueType::MlMathcolor: + m_aAttributeValue.m_aMathcolor.m_aMathcolor = SmMlAttributeValueMathcolor::MlDefault; + break; + case SmMlAttributeValueType::MlMathsize: + m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aLengthUnit = SmLengthUnit::MlP; + m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aLengthValue = 100; + m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aOriginalText = new OUString(u"100%"); + break; + case SmMlAttributeValueType::MlMathvariant: + m_aAttributeValue.m_aMathvariant.m_aMathvariant = SmMlAttributeValueMathvariant::normal; + break; + case SmMlAttributeValueType::MlMaxsize: + m_aAttributeValue.m_aMaxsize.m_aMaxsize = SmMlAttributeValueMaxsize::MlInfinity; + m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aLengthUnit = SmLengthUnit::MlP; + m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aLengthValue = 10000; + m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aOriginalText = new OUString(u"10000%"); + break; + case SmMlAttributeValueType::MlMinsize: + m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aLengthUnit = SmLengthUnit::MlP; + m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aLengthValue = 1; + m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aOriginalText = new OUString(u"1%"); + break; + case SmMlAttributeValueType::MlMovablelimits: + m_aAttributeValue.m_aMovablelimits.m_aMovablelimits + = SmMlAttributeValueMovablelimits::MlFalse; + break; + case SmMlAttributeValueType::MlRspace: + m_aAttributeValue.m_aRspace.m_aLengthValue.m_aLengthUnit = SmLengthUnit::MlEm; + m_aAttributeValue.m_aRspace.m_aLengthValue.m_aLengthValue = 5.0 / 18; + m_aAttributeValue.m_aRspace.m_aLengthValue.m_aOriginalText = new OUString(u"5/18em"); + break; + case SmMlAttributeValueType::MlSeparator: + m_aAttributeValue.m_aSeparator.m_aSeparator = SmMlAttributeValueSeparator::MlFalse; + break; + case SmMlAttributeValueType::MlStretchy: + m_aAttributeValue.m_aStretchy.m_aStretchy = SmMlAttributeValueStretchy::MlFalse; + break; + case SmMlAttributeValueType::MlSymmetric: + m_aAttributeValue.m_aSymmetric.m_aSymmetric = SmMlAttributeValueSymmetric::MlFalse; + break; + } +} + +void SmMlAttribute::setAttributeValue(const SmMlAttribute* aAttribute) +{ + switch (aAttribute->getMlAttributeValueType()) + { + case SmMlAttributeValueType::NMlEmpty: + clearPreviousAttributeValue(); + m_aSmMlAttributeValueType = SmMlAttributeValueType::NMlEmpty; + break; + case SmMlAttributeValueType::MlAccent: + setMlAccent(aAttribute->getMlAccent()); + break; + case SmMlAttributeValueType::MlDir: + setMlDir(aAttribute->getMlDir()); + break; + case SmMlAttributeValueType::MlDisplaystyle: + setMlDisplaystyle(aAttribute->getMlDisplaystyle()); + break; + case SmMlAttributeValueType::MlFence: + setMlFence(aAttribute->getMlFence()); + break; + case SmMlAttributeValueType::MlForm: + setMlForm(aAttribute->getMlForm()); + break; + case SmMlAttributeValueType::MlHref: + setMlHref(aAttribute->getMlHref()); + break; + case SmMlAttributeValueType::MlLspace: + setMlLspace(aAttribute->getMlLspace()); + break; + case SmMlAttributeValueType::MlMathbackground: + setMlMathbackground(aAttribute->getMlMathbackground()); + break; + case SmMlAttributeValueType::MlMathcolor: + setMlMathcolor(aAttribute->getMlMathcolor()); + break; + case SmMlAttributeValueType::MlMathsize: + setMlMathsize(aAttribute->getMlMathsize()); + break; + case SmMlAttributeValueType::MlMathvariant: + setMlMathvariant(aAttribute->getMlMathvariant()); + break; + case SmMlAttributeValueType::MlMaxsize: + setMlMaxsize(aAttribute->getMlMaxsize()); + break; + case SmMlAttributeValueType::MlMinsize: + setMlMinsize(aAttribute->getMlMinsize()); + break; + case SmMlAttributeValueType::MlMovablelimits: + setMlMovablelimits(aAttribute->getMlMovablelimits()); + break; + case SmMlAttributeValueType::MlRspace: + setMlRspace(aAttribute->getMlRspace()); + break; + case SmMlAttributeValueType::MlSeparator: + setMlSeparator(aAttribute->getMlSeparator()); + break; + case SmMlAttributeValueType::MlStretchy: + setMlStretchy(aAttribute->getMlStretchy()); + break; + case SmMlAttributeValueType::MlSymmetric: + setMlSymmetric(aAttribute->getMlSymmetric()); + break; + } +} + +/* get values */ +/*************************************************************************************************/ + +const struct SmMlAccent* SmMlAttribute::getMlAccent() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlAccent) + return &m_aAttributeValue.m_aAccent; + return nullptr; +} + +const struct SmMlDir* SmMlAttribute::getMlDir() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlDir) + return &m_aAttributeValue.m_aDir; + return nullptr; +} + +const struct SmMlDisplaystyle* SmMlAttribute::getMlDisplaystyle() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlDisplaystyle) + return &m_aAttributeValue.m_aDisplaystyle; + return nullptr; +} + +const struct SmMlFence* SmMlAttribute::getMlFence() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlFence) + return &m_aAttributeValue.m_aFence; + return nullptr; +} + +const struct SmMlForm* SmMlAttribute::getMlForm() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlForm) + return &m_aAttributeValue.m_aForm; + return nullptr; +} + +const struct SmMlHref* SmMlAttribute::getMlHref() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlHref) + return &m_aAttributeValue.m_aHref; + return nullptr; +} + +const struct SmMlLspace* SmMlAttribute::getMlLspace() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlLspace) + return &m_aAttributeValue.m_aLspace; + return nullptr; +} + +const struct SmMlMathbackground* SmMlAttribute::getMlMathbackground() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlMathbackground) + return &m_aAttributeValue.m_aMathbackground; + return nullptr; +} + +const struct SmMlMathcolor* SmMlAttribute::getMlMathcolor() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlMathcolor) + return &m_aAttributeValue.m_aMathcolor; + return nullptr; +} + +const struct SmMlMathsize* SmMlAttribute::getMlMathsize() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlAccent) + return &m_aAttributeValue.m_aMathsize; + return nullptr; +} + +const struct SmMlMathvariant* SmMlAttribute::getMlMathvariant() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlMathvariant) + return &m_aAttributeValue.m_aMathvariant; + return nullptr; +} + +const struct SmMlMaxsize* SmMlAttribute::getMlMaxsize() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlMaxsize) + return &m_aAttributeValue.m_aMaxsize; + return nullptr; +} + +const struct SmMlMinsize* SmMlAttribute::getMlMinsize() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlMinsize) + return &m_aAttributeValue.m_aMinsize; + return nullptr; +} + +const struct SmMlMovablelimits* SmMlAttribute::getMlMovablelimits() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlMovablelimits) + return &m_aAttributeValue.m_aMovablelimits; + return nullptr; +} + +const struct SmMlRspace* SmMlAttribute::getMlRspace() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlRspace) + return &m_aAttributeValue.m_aRspace; + return nullptr; +} + +const struct SmMlSeparator* SmMlAttribute::getMlSeparator() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlSeparator) + return &m_aAttributeValue.m_aSeparator; + return nullptr; +} + +const struct SmMlStretchy* SmMlAttribute::getMlStretchy() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlStretchy) + return &m_aAttributeValue.m_aStretchy; + return nullptr; +} + +const struct SmMlSymmetric* SmMlAttribute::getMlSymmetric() const +{ + if (m_aSmMlAttributeValueType == SmMlAttributeValueType::MlSymmetric) + return &m_aAttributeValue.m_aSymmetric; + return nullptr; +} + +/* set values */ +/*************************************************************************************************/ + +void SmMlAttribute::setMlAccent(const SmMlAccent* aAccent) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aAccent.m_aAccent = aAccent->m_aAccent; +} + +void SmMlAttribute::setMlDir(const SmMlDir* aDir) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aDir.m_aDir = aDir->m_aDir; +} + +void SmMlAttribute::setMlDisplaystyle(const SmMlDisplaystyle* aDisplaystyle) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aDisplaystyle.m_aDisplaystyle = aDisplaystyle->m_aDisplaystyle; +} + +void SmMlAttribute::setMlFence(const SmMlFence* aFence) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aFence.m_aFence = aFence->m_aFence; +} + +void SmMlAttribute::setMlForm(const SmMlForm* aForm) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aForm.m_aForm = aForm->m_aForm; +} + +void SmMlAttribute::setMlHref(const SmMlHref* aHref) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aHref.m_aHref = aHref->m_aHref; + m_aAttributeValue.m_aHref.m_aLnk = new OUString(*aHref->m_aLnk); +} + +void SmMlAttribute::setMlLspace(const SmMlLspace* aLspace) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aLspace.m_aLengthValue.m_aLengthUnit + = aLspace->m_aLengthValue.m_aLengthUnit; + m_aAttributeValue.m_aLspace.m_aLengthValue.m_aLengthValue + = aLspace->m_aLengthValue.m_aLengthValue; + m_aAttributeValue.m_aLspace.m_aLengthValue.m_aOriginalText + = new OUString(*aLspace->m_aLengthValue.m_aOriginalText); +} + +void SmMlAttribute::setMlMathbackground(const SmMlMathbackground* aMathbackground) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aMathbackground.m_aMathbackground = aMathbackground->m_aMathbackground; +} + +void SmMlAttribute::setMlMathcolor(const SmMlMathcolor* aMathcolor) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aMathcolor.m_aMathcolor = aMathcolor->m_aMathcolor; +} + +void SmMlAttribute::setMlMathsize(const SmMlMathsize* aMathsize) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aLengthUnit + = aMathsize->m_aLengthValue.m_aLengthUnit; + m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aLengthValue + = aMathsize->m_aLengthValue.m_aLengthValue; + m_aAttributeValue.m_aMathsize.m_aLengthValue.m_aOriginalText + = new OUString(*aMathsize->m_aLengthValue.m_aOriginalText); +} + +void SmMlAttribute::setMlMathvariant(const SmMlMathvariant* aMathvariant) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aMathvariant.m_aMathvariant = aMathvariant->m_aMathvariant; +} + +void SmMlAttribute::setMlMaxsize(const SmMlMaxsize* aMaxsize) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aMaxsize.m_aMaxsize = aMaxsize->m_aMaxsize; + m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aLengthUnit + = aMaxsize->m_aLengthValue.m_aLengthUnit; + m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aLengthValue + = aMaxsize->m_aLengthValue.m_aLengthValue; + m_aAttributeValue.m_aMaxsize.m_aLengthValue.m_aOriginalText + = new OUString(*aMaxsize->m_aLengthValue.m_aOriginalText); +} + +void SmMlAttribute::setMlMinsize(const SmMlMinsize* aMinsize) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aLengthUnit + = aMinsize->m_aLengthValue.m_aLengthUnit; + m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aLengthValue + = aMinsize->m_aLengthValue.m_aLengthValue; + m_aAttributeValue.m_aMinsize.m_aLengthValue.m_aOriginalText + = new OUString(*aMinsize->m_aLengthValue.m_aOriginalText); +} + +void SmMlAttribute::setMlMovablelimits(const SmMlMovablelimits* aMovablelimits) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aMovablelimits.m_aMovablelimits = aMovablelimits->m_aMovablelimits; +} + +void SmMlAttribute::setMlRspace(const SmMlRspace* aRspace) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aRspace.m_aLengthValue.m_aLengthUnit + = aRspace->m_aLengthValue.m_aLengthUnit; + m_aAttributeValue.m_aRspace.m_aLengthValue.m_aLengthValue + = aRspace->m_aLengthValue.m_aLengthValue; + m_aAttributeValue.m_aRspace.m_aLengthValue.m_aOriginalText + = new OUString(*aRspace->m_aLengthValue.m_aOriginalText); +} + +void SmMlAttribute::setMlSeparator(const SmMlSeparator* aSeparator) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aSeparator.m_aSeparator = aSeparator->m_aSeparator; +} + +void SmMlAttribute::setMlStretchy(const SmMlStretchy* aStretchy) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aStretchy.m_aStretchy = aStretchy->m_aStretchy; +} + +void SmMlAttribute::setMlSymmetric(const SmMlSymmetric* aSymmetric) +{ + m_bSet = true; + clearPreviousAttributeValue(); + m_aAttributeValue.m_aSymmetric.m_aSymmetric = aSymmetric->m_aSymmetric; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/starmath/source/mathml/def.cxx b/starmath/source/mathml/def.cxx new file mode 100644 index 000000000..484dcd665 --- /dev/null +++ b/starmath/source/mathml/def.cxx @@ -0,0 +1,124 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <mathml/attribute.hxx> + +SmMlAttributePos starmathdatabase::MlAttributeListEmpty[] = { + // clang-format off + { SmMlAttributeValueType::NMlEmpty, 0 } + // clang-format on +}; + +SmMlAttributePos starmathdatabase::MlAttributeListMath[] = { + // clang-format off + { SmMlAttributeValueType::NMlEmpty, 0 } + // clang-format on +}; + +SmMlAttributePos starmathdatabase::MlAttributeListMi[] = { + // clang-format off + { SmMlAttributeValueType::MlHref, 0 }, + { SmMlAttributeValueType::MlDir, 1 }, + { SmMlAttributeValueType::MlMathbackground, 2 }, + { SmMlAttributeValueType::MlMathcolor, 3 }, + { SmMlAttributeValueType::MlDisplaystyle, 4 }, + { SmMlAttributeValueType::MlMathsize, 5 }, + { SmMlAttributeValueType::MlMathvariant, 6 } + // clang-format on +}; + +SmMlAttributePos starmathdatabase::MlAttributeListMerror[] = { + // clang-format off + { SmMlAttributeValueType::MlHref, 0 }, + { SmMlAttributeValueType::MlMathbackground, 1 }, + { SmMlAttributeValueType::MlMathcolor, 2 }, + { SmMlAttributeValueType::MlDisplaystyle, 3 } + // clang-format on +}; + +SmMlAttributePos starmathdatabase::MlAttributeListMn[] = { + // clang-format off + { SmMlAttributeValueType::MlHref, 0 }, + { SmMlAttributeValueType::MlDir, 1 }, + { SmMlAttributeValueType::MlMathbackground, 2 }, + { SmMlAttributeValueType::MlMathcolor, 3 }, + { SmMlAttributeValueType::MlDisplaystyle, 4 }, + { SmMlAttributeValueType::MlMathsize, 5 }, + { SmMlAttributeValueType::MlMathvariant, 6 } + // clang-format on +}; + +SmMlAttributePos starmathdatabase::MlAttributeListMo[] = { + // clang-format off + { SmMlAttributeValueType::MlHref, 0 }, + { SmMlAttributeValueType::MlDir, 1 }, + { SmMlAttributeValueType::MlMathbackground, 2 }, + { SmMlAttributeValueType::MlMathcolor, 3 }, + { SmMlAttributeValueType::MlDisplaystyle, 4 }, + { SmMlAttributeValueType::MlMathsize, 5 }, + { SmMlAttributeValueType::MlMathvariant, 6 }, + { SmMlAttributeValueType::MlFence, 7 }, + { SmMlAttributeValueType::MlForm, 8 }, + { SmMlAttributeValueType::MlMaxsize, 9 }, + { SmMlAttributeValueType::MlMinsize, 10 }, + { SmMlAttributeValueType::MlMovablelimits, 11 }, + { SmMlAttributeValueType::MlLspace, 12 }, + { SmMlAttributeValueType::MlRspace, 13 }, + { SmMlAttributeValueType::MlAccent, 14 }, + { SmMlAttributeValueType::MlStretchy, 15 }, + { SmMlAttributeValueType::MlSeparator, 16 }, + { SmMlAttributeValueType::MlSymmetric, 17 } + // clang-format on +}; + +SmMlAttributePos starmathdatabase::MlAttributeListMrow[] = { + // clang-format off + { SmMlAttributeValueType::MlHref, 0 }, + { SmMlAttributeValueType::MlDir, 1 }, + { SmMlAttributeValueType::MlMathbackground, 2 }, + { SmMlAttributeValueType::MlMathcolor, 3 } + // clang-format on +}; + +SmMlAttributePos starmathdatabase::MlAttributeListMtext[] = { + // clang-format off + { SmMlAttributeValueType::MlHref, 0 }, + { SmMlAttributeValueType::MlDir, 1 }, + { SmMlAttributeValueType::MlMathbackground, 2 }, + { SmMlAttributeValueType::MlMathcolor, 3 }, + { SmMlAttributeValueType::MlDisplaystyle, 4 }, + { SmMlAttributeValueType::MlMathsize, 5 }, + { SmMlAttributeValueType::MlMathvariant, 6 } + // clang-format on +}; + +SmMlAttributePos starmathdatabase::MlAttributeListMstyle[] = { + // clang-format off + { SmMlAttributeValueType::MlHref, 0 }, + { SmMlAttributeValueType::MlDir, 1 }, + { SmMlAttributeValueType::MlMathbackground, 2 }, + { SmMlAttributeValueType::MlMathcolor, 3 }, + { SmMlAttributeValueType::MlDisplaystyle, 4 }, + { SmMlAttributeValueType::MlMathsize, 5 }, + { SmMlAttributeValueType::MlMathvariant, 6 }, + { SmMlAttributeValueType::MlFence, 7 }, + { SmMlAttributeValueType::MlForm, 8 }, + { SmMlAttributeValueType::MlMaxsize, 9 }, + { SmMlAttributeValueType::MlMinsize, 10 }, + { SmMlAttributeValueType::MlMovablelimits, 11 }, + { SmMlAttributeValueType::MlLspace, 12 }, + { SmMlAttributeValueType::MlRspace, 13 }, + { SmMlAttributeValueType::MlAccent, 14 }, + { SmMlAttributeValueType::MlStretchy, 15 }, + { SmMlAttributeValueType::MlSeparator, 16 }, + { SmMlAttributeValueType::MlSymmetric, 17 } + // clang-format on +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/starmath/source/mathml/element.cxx b/starmath/source/mathml/element.cxx new file mode 100644 index 000000000..4f8f2a64f --- /dev/null +++ b/starmath/source/mathml/element.cxx @@ -0,0 +1,136 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <mathml/element.hxx> + +void SmMlElement::SmImplAttributeType() +{ + switch (m_aElementType) + { + case SmMlElementType::NMlEmpty: + m_aAttributePosList = std::vector<SmMlAttributePos>(0); + break; + case SmMlElementType::NMlStructural: + m_aAttributePosList = std::vector<SmMlAttributePos>(0); + break; + case SmMlElementType::NMlSmNode: + m_aAttributePosList = std::vector<SmMlAttributePos>(0); + break; + case SmMlElementType::MlMath: + m_aAttributePosList = std::vector<SmMlAttributePos>(0); + //m_aAttributePosList = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMath), std::end(starmathdatabase::MlAttributeListMath)); + break; + case SmMlElementType::MlMi: + m_aAttributePosList + = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMi), + std::end(starmathdatabase::MlAttributeListMi)); + break; + case SmMlElementType::MlMerror: + m_aAttributePosList + = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMerror), + std::end(starmathdatabase::MlAttributeListMerror)); + break; + case SmMlElementType::MlMn: + m_aAttributePosList + = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMn), + std::end(starmathdatabase::MlAttributeListMn)); + break; + case SmMlElementType::MlMo: + m_aAttributePosList + = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMo), + std::end(starmathdatabase::MlAttributeListMo)); + break; + case SmMlElementType::MlMrow: + m_aAttributePosList + = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMrow), + std::end(starmathdatabase::MlAttributeListMrow)); + break; + case SmMlElementType::MlMtext: + m_aAttributePosList + = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMtext), + std::end(starmathdatabase::MlAttributeListMtext)); + break; + case SmMlElementType::MlMstyle: + m_aAttributePosList + = std::vector<SmMlAttributePos>(std::begin(starmathdatabase::MlAttributeListMstyle), + std::end(starmathdatabase::MlAttributeListMstyle)); + break; + default: + break; + } + // Create attribute vector with given pattern + m_aAttributeList = starmathdatabase::makeMlAttributeList(m_aAttributePosList); +} + +SmMlAttribute SmMlElement::getAttribute(SmMlAttributeValueType aAttributeType) const +{ + // Look for the attribute position and return if exists + for (size_t i = 0; i < m_aAttributePosList.size(); ++i) + { + if (m_aAttributePosList[i].m_aAttributeValueType == aAttributeType) + return m_aAttributeList[m_aAttributePosList[i].m_nPos]; + } + return SmMlAttribute(); +} + +bool SmMlElement::isAttributeSet(SmMlAttributeValueType aAttributeType) const +{ + // Look for the attribute position and return if exists + for (size_t i = 0; i < m_aAttributePosList.size(); ++i) + { + if (m_aAttributePosList[i].m_aAttributeValueType == aAttributeType) + return m_aAttributeList[m_aAttributePosList[i].m_nPos].isSet(); + } + return false; +} + +void SmMlElement::setAttribute(const SmMlAttribute* aAttribute) +{ + // Look for the attribute position and assign if exists + for (size_t i = 0; i < m_aAttributePosList.size(); ++i) + { + if (m_aAttributePosList[i].m_aAttributeValueType == aAttribute->getMlAttributeValueType()) + { + m_aAttributeList[m_aAttributePosList[i].m_nPos].setMlAttributeValue(aAttribute); + break; + } + } +} + +void SmMlElement::setSubElement(size_t nPos, SmMlElement* aElement) +{ + // This is the new parent element + aElement->setParentElement(this); + aElement->setSubElementId(nPos); + // Check if the vector is long enough + // Careful nOldSize can be 0 and -1 will underflow + // We must put something on the empty locations + size_t nOldSize = m_aSubElements.size(); + if (nPos + 1 > nOldSize) + { + m_aSubElements.resize(nPos + 1); + for (; nOldSize < nPos; ++nOldSize) + m_aSubElements[nOldSize] = nullptr; + } + // Assign value + m_aSubElements[nPos] = aElement; +} + +std::vector<SmMlAttribute> +starmathdatabase::makeMlAttributeList(std::vector<SmMlAttributePos> aAttributePosList) +{ + std::vector<SmMlAttribute> aAttributeList(aAttributePosList.size()); + for (size_t i = 0; i < aAttributePosList.size(); ++i) + { + aAttributeList[i].setMlAttributeValueType(aAttributePosList[i].m_aAttributeValueType); + } + return aAttributeList; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/starmath/source/mathml/export.cxx b/starmath/source/mathml/export.cxx new file mode 100644 index 000000000..b55be5092 --- /dev/null +++ b/starmath/source/mathml/export.cxx @@ -0,0 +1,1110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +// Our mathml +#include <mathml/export.hxx> +#include <mathml/iterator.hxx> + +// LO tools to use +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/uno/Any.h> +#include <com/sun/star/util/MeasureUnit.hpp> +#include <com/sun/star/xml/sax/Writer.hpp> + +// Extra LO tools +#include <comphelper/genericpropertyset.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/propertysetinfo.hxx> +#include <sfx2/frame.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/sfxsids.hrc> +#include <svl/itemset.hxx> +#include <svl/stritem.hxx> +#include <unotools/streamwrap.hxx> +#include <xmloff/namespacemap.hxx> + +// Our starmath tools +#include <document.hxx> +#include <smmod.hxx> +#include <strings.hrc> +#include <unomodel.hxx> +#include <xparsmlbase.hxx> +#include <starmathdatabase.hxx> + +// Old parser +#include <mathmlexport.hxx> + +using namespace ::com::sun::star; +using namespace xmloff::token; + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star; +using namespace ::xmloff::token; + +// SmMLExportWrapper +/*************************************************************************************************/ + +bool SmMLExportWrapper::Export(SfxMedium& rMedium) +{ + bool bRet = true; + uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext()); + + // Check all fine + SAL_WARN_IF(m_xModel == nullptr, "starmath", "Missing model"); + SAL_WARN_IF(xContext == nullptr, "starmath", "Missing context"); + if (m_xModel == nullptr || xContext == nullptr) + return false; + + //Get model + uno::Reference<lang::XComponent> xModelComp = m_xModel; + SAL_WARN_IF(xModelComp == nullptr, "starmath", "Missing model component"); + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(m_xModel); + SAL_WARN_IF(pModel == nullptr, "starmath", "Failed to get threw uno tunnel"); + if (xModelComp == nullptr || pModel == nullptr) + return false; + + // Get doc shell + SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell()); + if (pDocShell == nullptr) + { + SAL_WARN("starmath", "Failed to fetch sm document"); + return false; + } + + // Check if it is a standalone window or embed object + bool bEmbedded = SfxObjectCreateMode::EMBEDDED == pDocShell->GetCreateMode(); + + // Medium item set + SfxItemSet* pMediumItemSet = rMedium.GetItemSet(); + if (pDocShell == nullptr) + { + SAL_WARN("starmath", "Failed to get medium item set"); + return false; + } + + // Progress bar ~ + uno::Reference<task::XStatusIndicator> xStatusIndicator; + + if (!bEmbedded) + { + // Extra check to ensure everything is fine + if (pDocShell->GetMedium() != &rMedium) + { + SAL_WARN("starmath", "Input medium and sm document medium do not match"); + //return false; + } + + // Fetch progress bar + const SfxUnoAnyItem* pItem = pMediumItemSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL); + if (pItem) + { + // set progress range and start status indicator + pItem->GetValue() >>= xStatusIndicator; + xStatusIndicator->start(SmResId(STR_STATSTR_WRITING), 3); + xStatusIndicator->setValue(0); + } + } + + // create XPropertySet with three properties for status indicator + static const comphelper::PropertyMapEntry aInfoMap[]{ + { OUString("UsePrettyPrinting"), 0, cppu::UnoType<bool>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 } + }; + uno::Reference<beans::XPropertySet> xInfoSet( + comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap))); + + // Always print pretty + xInfoSet->setPropertyValue("UsePrettyPrinting", Any(true)); + + // Set base URI + xInfoSet->setPropertyValue(u"BaseURI", Any(rMedium.GetBaseURL(true))); + + if (!m_bFlat) //Storage (Package) of Stream + { + // Fetch the output storage + uno::Reference<embed::XStorage> xStg = rMedium.GetOutputStorage(); + if (xStg == nullptr) + { + SAL_WARN("starmath", "Failed to fetch output storage"); + return false; + } + + // TODO/LATER: handle the case of embedded links gracefully + if (bEmbedded) //&& !pStg->IsRoot() ) + { + const SfxStringItem* pDocHierarchItem + = pMediumItemSet->GetItem(SID_DOC_HIERARCHICALNAME); + if (pDocHierarchItem != nullptr) + { + OUString aName = pDocHierarchItem->GetValue(); + if (!aName.isEmpty()) + xInfoSet->setPropertyValue("StreamRelPath", Any(aName)); + } + } + else + { + // Write file metadata ( data, LO version ... ) + // Note: export through an XML exporter component (storage version) + if (xStatusIndicator.is()) + xStatusIndicator->setValue(1); + + bRet = WriteThroughComponentS(xStg, xModelComp, u"meta.xml", xContext, xInfoSet, + u"com.sun.star.comp.Math.MLOasisMetaExporter", 6); + } + + // Write starmath formula + // Note: export through an XML exporter component (storage version) + if (bRet) + { + if (xStatusIndicator.is()) + xStatusIndicator->setValue(2); + + if (pDocShell->GetSmSyntaxVersion() == 5) + bRet = WriteThroughComponentS(xStg, xModelComp, u"content.xml", xContext, xInfoSet, + u"com.sun.star.comp.Math.XMLContentExporter", 5); + else + bRet = WriteThroughComponentS(xStg, xModelComp, u"content.xml", xContext, xInfoSet, + u"com.sun.star.comp.Math.MLContentExporter", 6); + } + + // Write starmath settings + // Note: export through an XML exporter component (storage version) + if (bRet) + { + if (xStatusIndicator.is()) + xStatusIndicator->setValue(3); + + bRet = WriteThroughComponentS(xStg, xModelComp, u"settings.xml", xContext, xInfoSet, + u"com.sun.star.comp.Math.MLOasisSettingsExporter", 6); + } + } + else + { + // Fetch the output stream + SvStream* pStream = rMedium.GetOutStream(); + if (pStream == nullptr) + { + SAL_WARN("starmath", "Missing output stream"); + return false; + } + uno::Reference<io::XOutputStream> xOut(new utl::OOutputStreamWrapper(*pStream)); + + if (xStatusIndicator.is()) + xStatusIndicator->setValue(1); + + // Write everything in the same place + // Note: export through an XML exporter component (output stream version) + if (pDocShell->GetSmSyntaxVersion() == 5) + bRet = WriteThroughComponentOS(xOut, xModelComp, xContext, xInfoSet, + u"com.sun.star.comp.Math.XMLContentExporter", 5); + else + bRet = WriteThroughComponentOS(xOut, xModelComp, xContext, xInfoSet, + u"com.sun.star.comp.Math.MLContentExporter", 6); + } + + if (xStatusIndicator.is()) + xStatusIndicator->end(); + return bRet; +} + +OUString SmMLExportWrapper::Export(SmMlElement* pElementTree) +{ + uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext()); + + // Check all fine + m_pElementTree = nullptr; + SAL_WARN_IF(m_xModel == nullptr, "starmath", "Missing model"); + SAL_WARN_IF(xContext == nullptr, "starmath", "Missing context"); + if (m_xModel == nullptr || xContext == nullptr) + return u""; + + //Get model + uno::Reference<lang::XComponent> xModelComp = m_xModel; + SAL_WARN_IF(xModelComp == nullptr, "starmath", "Missing model component"); + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(m_xModel); + SAL_WARN_IF(pModel == nullptr, "starmath", "Failed to get threw uno tunnel"); + if (xModelComp == nullptr || pModel == nullptr) + return u""; + + // Get doc shell + SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell()); + if (pDocShell == nullptr) + { + SAL_WARN("starmath", "Failed to fetch sm document"); + return u""; + } + + // create XPropertySet with three properties for status indicator + static const comphelper::PropertyMapEntry aInfoMap[]{ + { OUString("UsePrettyPrinting"), 0, cppu::UnoType<bool>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 } + }; + uno::Reference<beans::XPropertySet> xInfoSet( + comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap))); + + // Always print pretty + xInfoSet->setPropertyValue("UsePrettyPrinting", Any(true)); + + // Fetch mathml tree + m_pElementTree = pElementTree; + + // Write stuff + // Note: export through an XML exporter component (memory stream version) + return WriteThroughComponentMS(xModelComp, xContext, xInfoSet); +} + +// export through an XML exporter component (output stream version) +bool SmMLExportWrapper::WriteThroughComponentOS(const Reference<io::XOutputStream>& xOutputStream, + const Reference<XComponent>& xComponent, + Reference<uno::XComponentContext> const& rxContext, + Reference<beans::XPropertySet> const& rPropSet, + const char16_t* pComponentName, + int_fast16_t nSyntaxVersion) +{ + // We need a output stream but it is already checked by caller + // We need a component but it is already checked by caller + // We need a context but it is already checked by caller + // We need a property set but it is already checked by caller + // We need a component name but it is already checked by caller + + // get sax writer + Reference<xml::sax::XWriter> xSaxWriter = xml::sax::Writer::create(rxContext); + + // connect XML writer to output stream + xSaxWriter->setOutputStream(xOutputStream); + if (m_bUseHTMLMLEntities) + xSaxWriter->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntitiesExport); + + // prepare arguments (prepend doc handler to given arguments) + Sequence<Any> aArgs{ Any(xSaxWriter), Any(rPropSet) }; + + // get filter component + auto xExporterData = rxContext->getServiceManager()->createInstanceWithArgumentsAndContext( + OUString(pComponentName), aArgs, rxContext); + Reference<document::XExporter> xExporter(xExporterData, UNO_QUERY); + + // Check everything is fine + if (!xExporter.is()) + { + SAL_WARN("starmath", "can't instantiate export filter component"); + return false; + } + + // connect model and filter + xExporter->setSourceDocument(xComponent); + Reference<XFilter> xFilter(xExporter, UNO_QUERY); + uno::Sequence<PropertyValue> aProps(0); + + // filter + if (nSyntaxVersion == 5) + { + SmXMLExport* pFilter = comphelper::getFromUnoTunnel<SmXMLExport>(xFilter); + if (pFilter == nullptr) + { + SAL_WARN("starmath", "Failed to fetch SmMLExport"); + return false; + } + xFilter->filter(aProps); + return pFilter->GetSuccess(); + } + + // filter + SmMLExport* pFilter = comphelper::getFromUnoTunnel<SmMLExport>(xFilter); + + // Setup filter + if (pFilter == nullptr) + { + SAL_WARN("starmath", "Failed to fetch SmMLExport"); + return false; + } + pFilter->setUseExportTag(m_bUseExportTag); + pFilter->setElementTree(m_pElementTree); + + // Execute operation + xFilter->filter(aProps); + return pFilter->getSuccess(); +} + +// export through an XML exporter component (storage version) +bool SmMLExportWrapper::WriteThroughComponentS(const Reference<embed::XStorage>& xStorage, + const Reference<XComponent>& xComponent, + const char16_t* pStreamName, + Reference<uno::XComponentContext> const& rxContext, + Reference<beans::XPropertySet> const& rPropSet, + const char16_t* pComponentName, + int_fast16_t nSyntaxVersion) +{ + // We need a storage name but it is already checked by caller + // We need a component name but it is already checked by caller + // We need a stream name but it is already checked by caller + // We need a context but it is already checked by caller + // We need a property set but it is already checked by caller + // We need a component but it is already checked by caller + + // open stream + Reference<io::XStream> xStream; + try + { + xStream = xStorage->openStreamElement( + OUString(pStreamName), embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE); + } + catch (const uno::Exception&) + { + SAL_WARN("starmath", "Can't create output stream in package"); + return false; + } + + // Set stream as text / xml + uno::Reference<beans::XPropertySet> xSet(xStream, uno::UNO_QUERY); + xSet->setPropertyValue("MediaType", Any(OUString(u"text/xml"))); + + // all streams must be encrypted in encrypted document + xSet->setPropertyValue("UseCommonStoragePasswordEncryption", Any(true)); + + // set Base URL + rPropSet->setPropertyValue("StreamName", Any(OUString(pStreamName))); + + // write the stuff + // Note: export through an XML exporter component (output stream version) + return WriteThroughComponentOS(xStream->getOutputStream(), xComponent, rxContext, rPropSet, + pComponentName, nSyntaxVersion); +} + +// export through an XML exporter component (memory stream version) +OUString +SmMLExportWrapper::WriteThroughComponentMS(const Reference<XComponent>& xComponent, + Reference<uno::XComponentContext> const& rxContext, + Reference<beans::XPropertySet> const& rPropSet) +{ + // We need a component but it is already checked by caller + // We need a context but it is already checked by caller + // We need a property set it is already checked by caller + + // open stream + SvMemoryStream aMemoryStream(8192, 1024); + uno::Reference<io::XOutputStream> xStream(new utl::OOutputStreamWrapper(aMemoryStream)); + + // Set the stream as text + uno::Reference<beans::XPropertySet> xSet(xStream, uno::UNO_QUERY); + xSet->setPropertyValue("MediaType", Any(OUString("text/xml"))); + + // write the stuff + // Note: export through an XML exporter component (output stream version) + bool bOk = WriteThroughComponentOS(xStream, xComponent, rxContext, rPropSet, + u"com.sun.star.comp.Mathml.MLContentExporter", 6); + + // We don't want to read uninitialized data + if (!bOk) + return u""; + + // Recover data and generate string + OString aString(static_cast<const char*>(aMemoryStream.GetData()), + aMemoryStream.GetSize() / sizeof(char)); + return OStringToOUString(aString, RTL_TEXTENCODING_UTF8); +} + +// SmMLExport technical +/*************************************************************************************************/ + +sal_Int64 SAL_CALL SmMLExport::getSomething(const uno::Sequence<sal_Int8>& rId) +{ + return comphelper::getSomethingImpl(rId, this, + comphelper::FallbackToGetSomethingOf<SvXMLExport>{}); +} + +const uno::Sequence<sal_Int8>& SmMLExport::getUnoTunnelId() noexcept +{ + static const comphelper::UnoIdInit theSmMLExportUnoTunnelId; + return theSmMLExportUnoTunnelId.getSeq(); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +Math_MLExporter_get_implementation(css::uno::XComponentContext* context, + css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new SmMLExport(context, "com.sun.star.comp.Math.XMLExporter", + SvXMLExportFlags::OASIS | SvXMLExportFlags::ALL)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +Math_MLOasisMetaExporter_get_implementation(css::uno::XComponentContext* context, + css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new SmMLExport(context, "com.sun.star.comp.Math.XMLOasisMetaExporter", + SvXMLExportFlags::OASIS | SvXMLExportFlags::META)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +Math_MLOasisSettingsExporter_get_implementation(css::uno::XComponentContext* context, + css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new SmMLExport(context, "com.sun.star.comp.Math.XMLOasisSettingsExporter", + SvXMLExportFlags::OASIS | SvXMLExportFlags::SETTINGS)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +Math_MLContentExporter_get_implementation(css::uno::XComponentContext* context, + css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new SmMLExport(context, "com.sun.star.comp.Math.XMLContentExporter", + SvXMLExportFlags::OASIS | SvXMLExportFlags::CONTENT)); +} + +SmDocShell* SmMLExport::getSmDocShell() +{ + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(GetModel()); + if (pModel != nullptr) + return static_cast<SmDocShell*>(pModel->GetObjectShell()); + return nullptr; +} + +ErrCode SmMLExport::exportDoc(enum XMLTokenEnum eClass) +{ + if (!(getExportFlags() & SvXMLExportFlags::CONTENT)) + { + // Everything that isn't the formula itself get's default export + SvXMLExport::exportDoc(eClass); + return ERRCODE_NONE; + } + + // Checks if it has to export a particular tree + if (m_pElementTree == nullptr) + { + // Set element tree + SmDocShell* pDocShell = getSmDocShell(); + if (pDocShell != nullptr) + m_pElementTree = pDocShell->GetMlElementTree(); + else + { + m_bSuccess = false; + return SVSTREAM_INVALID_PARAMETER; + } + } + + // Start document and encrypt if necessary + GetDocHandler()->startDocument(); + addChaffWhenEncryptedStorage(); + + // make use of a default namespace + // Math doesn't need namespaces from xmloff, since it now uses default namespaces + // Because that is common with current MathML usage in the web -> ResetNamespaceMap(); + GetNamespaceMap_().Add(OUString(u""), GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH); + + // Add xmlns line + if (m_bUseExportTag) + { + GetAttrList().AddAttribute(GetNamespaceMap().GetAttrNameByKey(XML_NAMESPACE_MATH), + GetNamespaceMap().GetNameByKey(XML_NAMESPACE_MATH)); + } + + // Export and close document + ExportContent_(); + GetDocHandler()->endDocument(); + + return ERRCODE_NONE; +} + +void SmMLExport::GetViewSettings(Sequence<PropertyValue>& aProps) +{ + // Get the document shell + SmDocShell* pDocShell = getSmDocShell(); + if (pDocShell == nullptr) + { + SAL_WARN("starmath", "Missing document shell so no view settings"); + return; + } + + // Allocate enough memory + aProps.realloc(4); + PropertyValue* pValue = aProps.getArray(); + + // The view settings are the formula display settings + tools::Rectangle aRect(pDocShell->GetVisArea()); + + pValue[0].Name = "ViewAreaTop"; + pValue[0].Value <<= aRect.Top(); + + pValue[1].Name = "ViewAreaLeft"; + pValue[1].Value <<= aRect.Left(); + + pValue[2].Name = "ViewAreaWidth"; + pValue[2].Value <<= aRect.GetWidth(); + + pValue[3].Name = "ViewAreaHeight"; + pValue[3].Value <<= aRect.GetHeight(); +} + +void SmMLExport::GetConfigurationSettings(Sequence<PropertyValue>& rProps) +{ + // Get model property set (settings) + Reference<XPropertySet> xProps(GetModel(), UNO_QUERY); + if (!xProps.is()) + { + SAL_WARN("starmath", "Missing model properties so no configuration settings"); + return; + } + + // Get model property set info (settings values) + Reference<XPropertySetInfo> xPropertySetInfo = xProps->getPropertySetInfo(); + if (!xPropertySetInfo.is()) + { + SAL_WARN("starmath", "Missing model properties info so no configuration settings"); + return; + } + + // Allocate to store the properties + Sequence<Property> aProps = xPropertySetInfo->getProperties(); + const sal_Int32 nCount = aProps.getLength(); + rProps.realloc(nCount); + auto pProps = rProps.getArray(); + + // Copy properties + // This needs further revision + // Based in code mathmlexport.cxx::GetConfigurationSettings + for (sal_Int32 i = 0; i < nCount; ++i) + { + if (aProps[i].Name != "Formula" && aProps[i].Name != "BasicLibraries" + && aProps[i].Name != "DialogLibraries" && aProps[i].Name != "RuntimeUID") + { + pProps[i].Name = aProps[i].Name; + pProps[i].Value = xProps->getPropertyValue(aProps[i].Name); + } + } +} + +SmMLExport::SmMLExport(const css::uno::Reference<css::uno::XComponentContext>& rContext, + OUString const& implementationName, SvXMLExportFlags nExportFlags) + : SvXMLExport(rContext, implementationName, util::MeasureUnit::INCH, XML_MATH, nExportFlags) + , m_pElementTree(nullptr) + , m_bSuccess(true) + , m_bUseExportTag(true) +{ +} + +// SmMLExport +/*************************************************************************************************/ + +void SmMLExport::declareMlError() +{ + SAL_WARN("starmath", "Invalid use of mathml."); + m_bSuccess = false; +} + +void SmMLExport::exportMlAttributeLength(xmloff::token::XMLTokenEnum pAttribute, + const SmLengthValue& aLengthValue) +{ + if (!aLengthValue.m_aOriginalText->isEmpty()) + { + addAttribute(pAttribute, *aLengthValue.m_aOriginalText); + } + else + { + OUStringBuffer aSizeBuffer(64); + aSizeBuffer.append(aLengthValue.m_aLengthValue); + switch (aLengthValue.m_aLengthUnit) + { + case SmLengthUnit::MlEm: + aSizeBuffer.append(u"em"); + break; + case SmLengthUnit::MlEx: + aSizeBuffer.append(u"ex"); + break; + case SmLengthUnit::MlPx: + aSizeBuffer.append(u"px"); + break; + case SmLengthUnit::MlIn: + aSizeBuffer.append(u"in"); + break; + case SmLengthUnit::MlCm: + aSizeBuffer.append(u"cm"); + break; + case SmLengthUnit::MlMm: + aSizeBuffer.append(u"mm"); + break; + case SmLengthUnit::MlPt: + aSizeBuffer.append(u"pt"); + break; + case SmLengthUnit::MlPc: + aSizeBuffer.append(u"pc"); + break; + case SmLengthUnit::MlP: + aSizeBuffer.append(u"%"); + break; + case SmLengthUnit::MlM: + break; + default: + declareMlError(); + break; + } + addAttribute(pAttribute, aSizeBuffer.makeStringAndClear()); + } +} + +void SmMLExport::exportMlAttributes(const SmMlElement* pMlElement) +{ + size_t nAttributeCount = pMlElement->getAttributeCount(); + for (size_t i = 0; i < nAttributeCount; ++i) + { + SmMlAttribute aAttribute = pMlElement->getAttribute(i); + if (!aAttribute.isSet()) + continue; + + switch (aAttribute.getMlAttributeValueType()) + { + case SmMlAttributeValueType::MlAccent: + { + auto aAttributeValue = aAttribute.getMlAccent(); + switch (aAttributeValue->m_aAccent) + { + case SmMlAttributeValueAccent::MlFalse: + addAttribute(XML_ACCENT, XML_FALSE); + break; + case SmMlAttributeValueAccent::MlTrue: + addAttribute(XML_ACCENT, XML_TRUE); + break; + default: + declareMlError(); + break; + } + break; + } + case SmMlAttributeValueType::MlDir: + { + auto aAttributeValue = aAttribute.getMlDir(); + switch (aAttributeValue->m_aDir) + { + case SmMlAttributeValueDir::MlLtr: + addAttribute(XML_DIR, XML_LTR); + break; + case SmMlAttributeValueDir::MlRtl: + addAttribute(XML_DIR, XML_RTL); + break; + default: + declareMlError(); + break; + } + break; + } + case SmMlAttributeValueType::MlDisplaystyle: + { + auto aAttributeValue = aAttribute.getMlDisplaystyle(); + switch (aAttributeValue->m_aDisplaystyle) + { + case SmMlAttributeValueDisplaystyle::MlTrue: + addAttribute(XML_DISPLAYSTYLE, XML_FALSE); + break; + case SmMlAttributeValueDisplaystyle::MlFalse: + addAttribute(XML_DISPLAYSTYLE, XML_TRUE); + break; + default: + declareMlError(); + break; + } + break; + } + case SmMlAttributeValueType::MlFence: + { + auto aAttributeValue = aAttribute.getMlFence(); + switch (aAttributeValue->m_aFence) + { + case SmMlAttributeValueFence::MlTrue: + addAttribute(XML_FENCE, XML_FALSE); + break; + case SmMlAttributeValueFence::MlFalse: + addAttribute(XML_FENCE, XML_TRUE); + break; + default: + declareMlError(); + break; + } + break; + } + case SmMlAttributeValueType::MlHref: + { + auto aAttributeValue = aAttribute.getMlHref(); + switch (aAttributeValue->m_aHref) + { + case SmMlAttributeValueHref::NMlEmpty: + break; + case SmMlAttributeValueHref::NMlValid: + addAttribute(XML_HREF, *aAttributeValue->m_aLnk); + break; + default: + declareMlError(); + break; + } + break; + } + case SmMlAttributeValueType::MlLspace: + { + auto aSizeData = aAttribute.getMlLspace(); + auto aLengthData = aSizeData->m_aLengthValue; + exportMlAttributeLength(XML_LSPACE, aLengthData); + break; + } + case SmMlAttributeValueType::MlMathbackground: + { + auto aAttributeValue = aAttribute.getMlMathbackground(); + switch (aAttributeValue->m_aMathbackground) + { + case SmMlAttributeValueMathbackground::MlTransparent: + addAttribute(XML_MATHBACKGROUND, "transparent"); + break; + case SmMlAttributeValueMathbackground::MlRgb: + { + const OUString& rTextColor = starmathdatabase::Identify_Color_MATHML( + sal_uInt32(aAttributeValue->m_aCol)) + .aIdent; + addAttribute(XML_MATHBACKGROUND, rTextColor); + break; + } + default: + declareMlError(); + break; + } + break; + } + case SmMlAttributeValueType::MlMathcolor: + { + auto aAttributeValue = aAttribute.getMlMathcolor(); + switch (aAttributeValue->m_aMathcolor) + { + case SmMlAttributeValueMathcolor::MlDefault: + break; + case SmMlAttributeValueMathcolor::MlRgb: + { + const OUString& rTextColor = starmathdatabase::Identify_Color_MATHML( + sal_uInt32(aAttributeValue->m_aCol)) + .aIdent; + addAttribute(XML_MATHCOLOR, rTextColor); + break; + } + default: + declareMlError(); + break; + } + break; + } + case SmMlAttributeValueType::MlMathsize: + { + auto aSizeData = aAttribute.getMlMathsize(); + auto aLengthData = aSizeData->m_aLengthValue; + exportMlAttributeLength(XML_MATHSIZE, aLengthData); + break; + } + case SmMlAttributeValueType::MlMathvariant: + { + auto aAttributeValue = aAttribute.getMlMathvariant(); + switch (aAttributeValue->m_aMathvariant) + { + case SmMlAttributeValueMathvariant::normal: + addAttribute(XML_MATHVARIANT, "normal"); + break; + case SmMlAttributeValueMathvariant::bold: + addAttribute(XML_MATHVARIANT, "bold"); + break; + case SmMlAttributeValueMathvariant::italic: + addAttribute(XML_MATHVARIANT, "italic"); + break; + case SmMlAttributeValueMathvariant::double_struck: + addAttribute(XML_MATHVARIANT, "double-struck"); + break; + case SmMlAttributeValueMathvariant::script: + addAttribute(XML_MATHVARIANT, "script"); + break; + case SmMlAttributeValueMathvariant::fraktur: + addAttribute(XML_MATHVARIANT, "fraktur"); + break; + case SmMlAttributeValueMathvariant::sans_serif: + addAttribute(XML_MATHVARIANT, "sans-serif"); + break; + case SmMlAttributeValueMathvariant::monospace: + addAttribute(XML_MATHVARIANT, "monospace"); + break; + case SmMlAttributeValueMathvariant::bold_italic: + addAttribute(XML_MATHVARIANT, "bold-italic"); + break; + case SmMlAttributeValueMathvariant::bold_fraktur: + addAttribute(XML_MATHVARIANT, "bold-fracktur"); + break; + case SmMlAttributeValueMathvariant::bold_script: + addAttribute(XML_MATHVARIANT, "bold-script"); + break; + case SmMlAttributeValueMathvariant::bold_sans_serif: + addAttribute(XML_MATHVARIANT, "bold-sans-serif"); + break; + case SmMlAttributeValueMathvariant::sans_serif_italic: + addAttribute(XML_MATHVARIANT, "sans-serif-italic"); + break; + case SmMlAttributeValueMathvariant::sans_serif_bold_italic: + addAttribute(XML_MATHVARIANT, "sans-serif-bold-italic"); + break; + case SmMlAttributeValueMathvariant::initial: + addAttribute(XML_MATHVARIANT, "initial"); + break; + case SmMlAttributeValueMathvariant::tailed: + addAttribute(XML_MATHVARIANT, "tailed"); + break; + case SmMlAttributeValueMathvariant::looped: + addAttribute(XML_MATHVARIANT, "looped"); + break; + case SmMlAttributeValueMathvariant::stretched: + addAttribute(XML_MATHVARIANT, "stretched"); + break; + default: + declareMlError(); + break; + } + break; + } + case SmMlAttributeValueType::MlMaxsize: + { + auto aSizeData = aAttribute.getMlMaxsize(); + auto aLengthData = aSizeData->m_aLengthValue; + switch (aSizeData->m_aMaxsize) + { + case SmMlAttributeValueMaxsize::MlInfinity: + { + addAttribute(XML_MAXSIZE, XML_INFINITY); + break; + } + case SmMlAttributeValueMaxsize::MlFinite: + { + exportMlAttributeLength(XML_MAXSIZE, aLengthData); + break; + } + } + break; + } + case SmMlAttributeValueType::MlMinsize: + { + auto aSizeData = aAttribute.getMlMinsize(); + auto aLengthData = aSizeData->m_aLengthValue; + exportMlAttributeLength(XML_MINSIZE, aLengthData); + break; + } + case SmMlAttributeValueType::MlMovablelimits: + { + auto aAttributeValue = aAttribute.getMlMovablelimits(); + switch (aAttributeValue->m_aMovablelimits) + { + case SmMlAttributeValueMovablelimits::MlFalse: + addAttribute(XML_MOVABLELIMITS, XML_FALSE); + break; + case SmMlAttributeValueMovablelimits::MlTrue: + addAttribute(XML_MOVABLELIMITS, XML_TRUE); + break; + default: + declareMlError(); + break; + } + break; + } + case SmMlAttributeValueType::MlRspace: + { + auto aSizeData = aAttribute.getMlRspace(); + auto aLengthData = aSizeData->m_aLengthValue; + exportMlAttributeLength(XML_RSPACE, aLengthData); + break; + } + case SmMlAttributeValueType::MlSeparator: + { + auto aAttributeValue = aAttribute.getMlSeparator(); + switch (aAttributeValue->m_aSeparator) + { + case SmMlAttributeValueSeparator::MlFalse: + addAttribute(XML_SEPARATOR, XML_FALSE); + break; + case SmMlAttributeValueSeparator::MlTrue: + addAttribute(XML_SEPARATOR, XML_TRUE); + break; + default: + declareMlError(); + break; + } + break; + } + case SmMlAttributeValueType::MlStretchy: + { + auto aAttributeValue = aAttribute.getMlStretchy(); + switch (aAttributeValue->m_aStretchy) + { + case SmMlAttributeValueStretchy::MlFalse: + addAttribute(XML_STRETCHY, XML_FALSE); + break; + case SmMlAttributeValueStretchy::MlTrue: + addAttribute(XML_STRETCHY, XML_TRUE); + break; + default: + declareMlError(); + break; + } + break; + } + case SmMlAttributeValueType::MlSymmetric: + { + auto aAttributeValue = aAttribute.getMlSymmetric(); + switch (aAttributeValue->m_aSymmetric) + { + case SmMlAttributeValueSymmetric::MlFalse: + addAttribute(XML_SYMMETRIC, XML_FALSE); + break; + case SmMlAttributeValueSymmetric::MlTrue: + addAttribute(XML_SYMMETRIC, XML_TRUE); + break; + default: + declareMlError(); + break; + } + break; + } + default: + declareMlError(); + break; + } + } +} + +SvXMLElementExport* SmMLExport::exportMlElement(const SmMlElement* pMlElement) +{ + SvXMLElementExport* pElementExport; + switch (pMlElement->getMlElementType()) + { + case SmMlElementType::MlMath: + pElementExport = createElementExport(XML_MATH); + break; + case SmMlElementType::MlMi: + pElementExport = createElementExport(XML_MI); + break; + case SmMlElementType::MlMerror: + pElementExport = createElementExport(XML_MERROR); + break; + case SmMlElementType::MlMn: + pElementExport = createElementExport(XML_MN); + break; + case SmMlElementType::MlMo: + pElementExport = createElementExport(XML_MO); + break; + case SmMlElementType::MlMrow: + pElementExport = createElementExport(XML_MROW); + break; + case SmMlElementType::MlMtext: + pElementExport = createElementExport(XML_MTEXT); + break; + case SmMlElementType::MlMstyle: + pElementExport = createElementExport(XML_MSTYLE); + break; + default: + pElementExport = nullptr; + } + const OUString& aElementText = pMlElement->getText(); + exportMlAttributes(pMlElement); + if (aElementText.isEmpty()) + GetDocHandler()->characters(aElementText); + return pElementExport; +} + +namespace +{ +struct exportMlElementTreeExecData +{ +private: + SmMLExport* m_pSmMLExport; + std::vector<SvXMLElementExport*> m_aSvXMLElementExportList; + size_t m_nDepth; + +public: + inline exportMlElementTreeExecData(SmMLExport* pSmMLExport) + : m_pSmMLExport(pSmMLExport) + , m_aSvXMLElementExportList(1024) + , m_nDepth(0) + { + } + + inline void deleteDepthData() + { + delete m_aSvXMLElementExportList[m_nDepth]; + --m_nDepth; + } + + inline void setDepthData(SvXMLElementExport* aSvXMLElementExportList) + { + if (m_nDepth == m_aSvXMLElementExportList.size()) + m_aSvXMLElementExportList.resize(m_aSvXMLElementExportList.size() + 1024); + m_aSvXMLElementExportList[m_nDepth] = aSvXMLElementExportList; + } + + inline void incrementDepth() { ++m_nDepth; } + + inline SmMLExport* getSmMLExport() { return m_pSmMLExport; }; +}; + +} // end unnamed namespace + +static inline void exportMlElementTreeExec(SmMlElement* aSmMlElement, void* aData) +{ + // Prepare data + exportMlElementTreeExecData* pData = static_cast<exportMlElementTreeExecData*>(aData); + pData->setDepthData(pData->getSmMLExport()->exportMlElement(aSmMlElement)); + + // Prepare for following + // If it has sub elements, then it will be the next + if (aSmMlElement->getSubElementsCount() != 0) + pData->incrementDepth(); + else // Otherwise remounts up to where it should be + { + while (aSmMlElement->getParentElement() != nullptr) + { + // get parent + SmMlElement* pParent = aSmMlElement->getParentElement(); + pData->deleteDepthData(); + // was this the last branch ? + if (aSmMlElement->getSubElementId() + 1 != pParent->getSubElementsCount()) // yes -> up + break; // no -> stop going up + // Prepare for next round + aSmMlElement = pParent; + } + } +} + +void SmMLExport::exportMlElementTree() +{ + exportMlElementTreeExecData* aData = new exportMlElementTreeExecData(this); + mathml::SmMlIteratorTopToBottom(m_pElementTree, exportMlElementTreeExec, aData); + delete aData; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/mathml/import.cxx b/starmath/source/mathml/import.cxx new file mode 100644 index 000000000..52d47028e --- /dev/null +++ b/starmath/source/mathml/import.cxx @@ -0,0 +1,1430 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Our mathml +#include <mathml/import.hxx> + +// LO tools to use +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/packages/WrongPasswordException.hpp> +#include <com/sun/star/packages/zip/ZipIOException.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/xml/sax/FastParser.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/Parser.hpp> +#include <com/sun/star/xml/sax/SAXParseException.hpp> + +// Extra LO tools +#include <comphelper/fileformat.h> +#include <comphelper/genericpropertyset.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/propertysetinfo.hxx> +#include <comphelper/servicehelper.hxx> +#include <rtl/character.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/frame.hxx> +#include <sfx2/sfxsids.hrc> +#include <sot/storage.hxx> +#include <svtools/sfxecode.hxx> +#include <svl/itemset.hxx> +#include <svl/stritem.hxx> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <unotools/streamwrap.hxx> +#include <xmloff/DocumentSettingsContext.hxx> +#include <xmloff/xmlmetai.hxx> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmltoken.hxx> +#include <o3tl/string_view.hxx> + +// Our starmath tools +#include <cfgitem.hxx> +#include <document.hxx> +#include <xparsmlbase.hxx> +#include <smmod.hxx> +#include <starmathdatabase.hxx> +#include <unomodel.hxx> + +// Old parser +#include <mathmlimport.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace com::sun::star::xml::sax; +using namespace ::xmloff::token; + +// SmMLImportContext +/*************************************************************************************************/ + +SmMlElement* SmMLImportWrapper::getElementTree() +{ + return m_pMlImport == nullptr ? nullptr : m_pMlImport->getElementTree(); +} + +ErrCode SmMLImportWrapper::Import(SfxMedium& rMedium) +{ + // Fetch context + uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext()); + if (!xContext.is()) + { + SAL_WARN("starmath", "Failed to fetch model while file input"); + return ERRCODE_SFX_DOLOADFAILED; + } + + // Check model + if (!m_xModel.is()) + { + SAL_WARN("starmath", "Failed to fetch model while file input"); + return ERRCODE_SFX_DOLOADFAILED; + } + + // Make a model component from our SmModel + uno::Reference<lang::XComponent> xModelComp = m_xModel; + if (!xModelComp.is()) + { + SAL_WARN("starmath", "Failed to make model while file input"); + return ERRCODE_SFX_DOLOADFAILED; + } + + // Try to get an XStatusIndicator from the Medium + uno::Reference<task::XStatusIndicator> xStatusIndicator; + + // Get model via uno + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(m_xModel); + if (pModel == nullptr) + { + SAL_WARN("starmath", "Failed to fetch sm model while file input"); + return ERRCODE_SFX_DOLOADFAILED; + } + + // Get doc shell + m_pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell()); + if (m_pDocShell == nullptr) + { + SAL_WARN("starmath", "Failed to fetch smdoc shell while file input"); + return ERRCODE_SFX_DOLOADFAILED; + } + + // Check if it is an embed object + bool bEmbedded = m_pDocShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED; + + if (!bEmbedded) + { + // Extra check to ensure everything is fine + if (m_pDocShell->GetMedium() != &rMedium) + { + SAL_WARN("starmath", "Given medium and doc shell medium differ while file input"); + return ERRCODE_SFX_DOLOADFAILED; + } + + // Fetch the item set + SfxItemSet* pSet = rMedium.GetItemSet(); + if (pSet) + { + const SfxUnoAnyItem* pItem = pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL); + if (pItem != nullptr) + pItem->GetValue() >>= xStatusIndicator; + } + } + + // Create property list + static const comphelper::PropertyMapEntry aInfoMap[] + = { { u"PrivateData", 0, cppu::UnoType<XInterface>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { u"BaseURI", 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, + 0 }, + { u"StreamRelPath", 0, ::cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { u"StreamName", 0, ::cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 } }; + uno::Reference<beans::XPropertySet> xInfoSet( + comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap))); + + // Set base URI + // needed for relative URLs; but it's OK to import e.g. MathML from the clipboard without one + SAL_INFO_IF(rMedium.GetBaseURL().isEmpty(), "starmath", "SmMLImportWrapper: no base URL"); + xInfoSet->setPropertyValue("BaseURI", Any(rMedium.GetBaseURL())); + + // Fetch progress range + sal_Int32 nProgressRange(rMedium.IsStorage() ? 3 : 1); + if (xStatusIndicator.is()) + { + xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange); + xStatusIndicator->setValue(0); + } + + // Get storage + if (rMedium.IsStorage()) + { + // TODO/LATER: handle the case of embedded links gracefully + if (bEmbedded) // && !rMedium.GetStorage()->IsRoot() ) + { + OUString aName(u"dummyObjName"); + if (rMedium.GetItemSet()) + { + const SfxStringItem* pDocHierarchItem + = rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME); + if (pDocHierarchItem != nullptr) + aName = pDocHierarchItem->GetValue(); + } + + if (!aName.isEmpty()) + xInfoSet->setPropertyValue("StreamRelPath", Any(aName)); + } + + // Check if use OASIS ( new document format ) + bool bOASIS = SotStorage::GetVersion(rMedium.GetStorage()) > SOFFICE_FILEFORMAT_60; + if (xStatusIndicator.is()) + xStatusIndicator->setValue(1); + + // Error code in case of needed + ErrCode nWarn = ERRCODE_NONE; + + // Read metadata + // read a component from storage + if (!bEmbedded) + { + if (bOASIS) + nWarn = ReadThroughComponentS(rMedium.GetStorage(), xModelComp, u"meta.xml", + xContext, xInfoSet, + u"com.sun.star.comp.Math.MLOasisMetaImporter", 6); + else + nWarn + = ReadThroughComponentS(rMedium.GetStorage(), xModelComp, u"meta.xml", xContext, + xInfoSet, u"com.sun.star.comp.Math.XMLMetaImporter", 5); + } + + // Check if successful + if (nWarn != ERRCODE_NONE) + { + if (xStatusIndicator.is()) + xStatusIndicator->end(); + SAL_WARN("starmath", "Failed to read file"); + return nWarn; + } + + // Increase success indicator + if (xStatusIndicator.is()) + xStatusIndicator->setValue(2); + + // Read settings + // read a component from storage + if (bOASIS) + nWarn = ReadThroughComponentS(rMedium.GetStorage(), xModelComp, u"settings.xml", + xContext, xInfoSet, + u"com.sun.star.comp.Math.MLOasisSettingsImporter", 6); + else + nWarn + = ReadThroughComponentS(rMedium.GetStorage(), xModelComp, u"settings.xml", xContext, + xInfoSet, u"com.sun.star.comp.Math.XMLSettingsImporter", 5); + + // Check if successful + if (nWarn == ERRCODE_IO_BROKENPACKAGE) + { + if (xStatusIndicator.is()) + xStatusIndicator->end(); + SAL_WARN("starmath", "Failed to read file"); + return nWarn; + } + + // Increase success indicator + if (xStatusIndicator.is()) + xStatusIndicator->setValue(3); + + // Read document + // read a component from storage + if (m_pDocShell->GetSmSyntaxVersion() == 5) + nWarn + = ReadThroughComponentS(rMedium.GetStorage(), xModelComp, u"content.xml", xContext, + xInfoSet, u"com.sun.star.comp.Math.XMLImporter", 5); + else + nWarn + = ReadThroughComponentS(rMedium.GetStorage(), xModelComp, u"content.xml", xContext, + xInfoSet, u"com.sun.star.comp.Math.MLImporter", 6); + // Check if successful + if (nWarn != ERRCODE_NONE) + { + if (xStatusIndicator.is()) + xStatusIndicator->end(); + SAL_WARN("starmath", "Failed to read file"); + return nWarn; + } + + // Finish + if (xStatusIndicator.is()) + xStatusIndicator->end(); + return ERRCODE_NONE; + } + else + { + // Create input stream + Reference<io::XInputStream> xInputStream + = new utl::OInputStreamWrapper(rMedium.GetInStream()); + + // Increase success indicator + if (xStatusIndicator.is()) + xStatusIndicator->setValue(1); + + // Read data + // read a component from input stream + ErrCode nError = ERRCODE_NONE; + if (m_pDocShell->GetSmSyntaxVersion() == 5) + nError = ReadThroughComponentIS(xInputStream, xModelComp, xContext, xInfoSet, + u"com.sun.star.comp.Math.XMLImporter", false, 5); + else + nError = ReadThroughComponentIS(xInputStream, xModelComp, xContext, xInfoSet, + u"com.sun.star.comp.Math.MLImporter", false, 6); + + // Finish + if (xStatusIndicator.is()) + xStatusIndicator->end(); + + // Declare any error + if (nError != ERRCODE_NONE) + SAL_WARN("starmath", "Failed to read file"); + + return nError; + } +} + +ErrCode SmMLImportWrapper::Import(std::u16string_view aSource) +{ + // Fetch context + uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext()); + if (!xContext.is()) + { + SAL_WARN("starmath", "Failed to fetch model while file input"); + return ERRCODE_SFX_DOLOADFAILED; + } + + // Check model + if (!m_xModel.is()) + { + SAL_WARN("starmath", "Failed to fetch model while file input"); + return ERRCODE_SFX_DOLOADFAILED; + } + + // Make a model component from our SmModel + uno::Reference<lang::XComponent> xModelComp = m_xModel; + if (!xModelComp.is()) + { + SAL_WARN("starmath", "Failed to make model while file input"); + return ERRCODE_SFX_DOLOADFAILED; + } + + // Get model via uno + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(m_xModel); + if (pModel == nullptr) + { + SAL_WARN("starmath", "Failed to fetch sm model while file input"); + return ERRCODE_SFX_DOLOADFAILED; + } + + // Get doc shell + m_pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell()); + if (m_pDocShell == nullptr) + { + SAL_WARN("starmath", "Failed to fetch smdoc shell while file input"); + return ERRCODE_SFX_DOLOADFAILED; + } + + // Create property list + static const comphelper::PropertyMapEntry aInfoMap[] + = { { u"PrivateData", 0, cppu::UnoType<XInterface>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { u"BaseURI", 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, + 0 }, + { u"StreamRelPath", 0, ::cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { u"StreamName", 0, ::cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 } }; + uno::Reference<beans::XPropertySet> xInfoSet( + comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap))); + + // Read data + // read a component from text + ErrCode nError = ReadThroughComponentMS(aSource, xModelComp, xContext, xInfoSet); + + // Declare any error + if (nError != ERRCODE_NONE) + { + SAL_WARN("starmath", "Failed to read file"); + return nError; + } + + return ERRCODE_NONE; +} + +// read a component from input stream +ErrCode SmMLImportWrapper::ReadThroughComponentIS( + const Reference<io::XInputStream>& xInputStream, const Reference<XComponent>& xModelComponent, + Reference<uno::XComponentContext> const& rxContext, + Reference<beans::XPropertySet> const& rPropSet, const char16_t* pFilterName, bool bEncrypted, + int_fast16_t nSyntaxVersion) +{ + // Needs an input stream but checked by caller + // Needs a context but checked by caller + // Needs property set but checked by caller + // Needs a filter name but checked by caller + + // Prepare ParserInputSource + xml::sax::InputSource aParserInput; + aParserInput.aInputStream = xInputStream; + + // Prepare property list + Sequence<Any> aArgs{ Any(rPropSet) }; + + // Get filter + Reference<XInterface> xFilter + = rxContext->getServiceManager()->createInstanceWithArgumentsAndContext( + OUString(pFilterName), aArgs, rxContext); + if (!xFilter.is()) + { + SAL_WARN("starmath", "Can't instantiate filter component " << OUString(pFilterName)); + return ERRCODE_SFX_DOLOADFAILED; + } + + // Connect model and filter + Reference<XImporter> xImporter(xFilter, UNO_QUERY); + xImporter->setTargetDocument(xModelComponent); + + // Finally, parser the stream + try + { + Reference<css::xml::sax::XFastParser> xFastParser(xFilter, UNO_QUERY); + Reference<css::xml::sax::XFastDocumentHandler> xFastDocHandler(xFilter, UNO_QUERY); + if (xFastParser) + { + xFastParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities); + xFastParser->parseStream(aParserInput); + } + else if (xFastDocHandler) + { + Reference<css::xml::sax::XFastParser> xParser + = css::xml::sax::FastParser::create(rxContext); + xParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities); + xParser->setFastDocumentHandler(xFastDocHandler); + xParser->parseStream(aParserInput); + } + else + { + Reference<css::xml::sax::XDocumentHandler> xDocHandler(xFilter, UNO_QUERY); + assert(xDocHandler); + Reference<css::xml::sax::XParser> xParser = css::xml::sax::Parser::create(rxContext); + xParser->setDocumentHandler(xDocHandler); + xParser->parseStream(aParserInput); + } + + if (nSyntaxVersion == 5) + { + SmXMLImport* pXMlImport = comphelper::getFromUnoTunnel<SmXMLImport>(xFilter); + if (pXMlImport != nullptr && pXMlImport->GetSuccess()) + return ERRCODE_NONE; + else + { + SAL_WARN("starmath", "Filter failed on file input"); + return ERRCODE_SFX_DOLOADFAILED; + } + } + + m_pMlImport = comphelper::getFromUnoTunnel<SmMLImport>(xFilter); + if (m_pMlImport != nullptr && m_pMlImport->getSuccess()) + return ERRCODE_NONE; + else + { + SAL_WARN("starmath", "Filter failed on file input"); + return ERRCODE_SFX_DOLOADFAILED; + } + } + catch (const xml::sax::SAXParseException& r) + { + // Sax parser sends wrapped exceptions, try to find the original one + xml::sax::SAXException aTmp; + xml::sax::SAXException aSaxEx = *static_cast<const xml::sax::SAXException*>(&r); + while (aSaxEx.WrappedException >>= aTmp) + aSaxEx = aTmp; + + packages::zip::ZipIOException aBrokenPackage; + if (aSaxEx.WrappedException >>= aBrokenPackage) + { + SAL_WARN("starmath", "Failed to read file SAXParseException"); + return ERRCODE_IO_BROKENPACKAGE; + } + + if (bEncrypted) + { + SAL_WARN("starmath", "Wrong file password SAXParseException"); + return ERRCODE_SFX_WRONGPASSWORD; + } + } + catch (const xml::sax::SAXException& r) + { + packages::zip::ZipIOException aBrokenPackage; + if (r.WrappedException >>= aBrokenPackage) + { + SAL_WARN("starmath", "Failed to read file SAXException"); + return ERRCODE_IO_BROKENPACKAGE; + } + + if (bEncrypted) + { + SAL_WARN("starmath", "Wrong file password SAXException"); + return ERRCODE_SFX_WRONGPASSWORD; + } + } + catch (const packages::zip::ZipIOException&) + { + SAL_WARN("starmath", "Failed to unzip file ZipIOException"); + return ERRCODE_IO_BROKENPACKAGE; + } + catch (const io::IOException&) + { + SAL_WARN("starmath", "Failed to read file ZipIOException"); + return ERRCODE_IO_UNKNOWN; + } + catch (const std::range_error&) + { + SAL_WARN("starmath", "Failed to read file"); + return ERRCODE_ABORT; + } + + return ERRCODE_ABORT; +} + +// read a component from storage +ErrCode SmMLImportWrapper::ReadThroughComponentS(const uno::Reference<embed::XStorage>& xStorage, + const Reference<XComponent>& xModelComponent, + const char16_t* pStreamName, + Reference<uno::XComponentContext> const& rxContext, + Reference<beans::XPropertySet> const& rPropSet, + const char16_t* pFilterName, + int_fast16_t nSyntaxVersion) +{ + // Needs a storage but checked by caller + // Needs a model but checked by caller + // Needs a stream name but checked by caller + // Needs a context but checked by caller + // Needs a property set but checked by caller + // Needs a filter name but checked by caller + + // Get the input stream + try + { + // Create the stream for the event read + uno::Reference<io::XStream> xEventsStream + = xStorage->openStreamElement(OUString(pStreamName), embed::ElementModes::READ); + + // Determine if stream is encrypted or not + uno::Reference<beans::XPropertySet> xProps(xEventsStream, uno::UNO_QUERY); + Any aAny = xProps->getPropertyValue("Encrypted"); + bool bEncrypted = false; + aAny >>= bEncrypted; + + // Set base URL and open stream + rPropSet->setPropertyValue("StreamName", Any(OUString(pStreamName))); + Reference<io::XInputStream> xStream = xEventsStream->getInputStream(); + + // Execute read + return ReadThroughComponentIS(xStream, xModelComponent, rxContext, rPropSet, pFilterName, + bEncrypted, nSyntaxVersion); + } + catch (packages::WrongPasswordException&) + { + SAL_WARN("starmath", "Wrong file password"); + return ERRCODE_SFX_WRONGPASSWORD; + } + catch (packages::zip::ZipIOException&) + { + SAL_WARN("starmath", "Failed to unzip file"); + return ERRCODE_IO_BROKENPACKAGE; + } + catch (uno::Exception&) + { + } + + return ERRCODE_SFX_DOLOADFAILED; +} + +// read a component from text +ErrCode SmMLImportWrapper::ReadThroughComponentMS( + std::u16string_view aText, const css::uno::Reference<css::lang::XComponent>& xModelComponent, + css::uno::Reference<css::uno::XComponentContext> const& rxContext, + css::uno::Reference<css::beans::XPropertySet> const& rPropSet) +{ + // Needs a storage but checked by caller + // Needs a model but checked by caller + // Needs a stream name but checked by caller + // Needs a context but checked by caller + // Needs a property set but checked by caller + // Needs a filter name but checked by caller + + // Get the input stream + try + { + // Generate input memory stream + SvMemoryStream aMemoryStream; + aMemoryStream.WriteOString(OUStringToOString(aText, RTL_TEXTENCODING_UTF8)); + uno::Reference<io::XInputStream> xStream(new utl::OInputStreamWrapper(aMemoryStream)); + + // Execute read + return ReadThroughComponentIS(xStream, xModelComponent, rxContext, rPropSet, + u"com.sun.star.comp.Math.MLImporter", false, 6); + } + catch (packages::WrongPasswordException&) + { + SAL_WARN("starmath", "Wrong file password"); + return ERRCODE_SFX_WRONGPASSWORD; + } + catch (packages::zip::ZipIOException&) + { + SAL_WARN("starmath", "Failed to unzip file"); + return ERRCODE_IO_BROKENPACKAGE; + } + catch (uno::Exception&) + { + } + + return ERRCODE_SFX_DOLOADFAILED; +} + +// SmMLImport technical +/*************************************************************************************************/ + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +Math_MLImporter_get_implementation(uno::XComponentContext* pCtx, + uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire( + new SmMLImport(pCtx, "com.sun.star.comp.Math.XMLImporter", SvXMLImportFlags::ALL)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +Math_MLOasisMetaImporter_get_implementation(uno::XComponentContext* pCtx, + uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new SmMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisMetaImporter", + SvXMLImportFlags::META)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +Math_MLOasisSettingsImporter_get_implementation(uno::XComponentContext* pCtx, + uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new SmMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisSettingsImporter", + SvXMLImportFlags::SETTINGS)); +} + +// SmMLImportContext +/*************************************************************************************************/ + +namespace +{ +class SmMLImportContext : public SvXMLImportContext +{ +private: + SmMlElement** m_pParent; + SmMlElement* m_pElement; + SmMlElement* m_pStyle; + +public: + SmMLImportContext(SmMLImport& rImport, SmMlElement** pParent) + : SvXMLImportContext(rImport) + , m_pParent(pParent) + , m_pElement(nullptr) + , m_pStyle(nullptr) + { + } + +private: + void declareMlError(); + +public: + /** Handles characters (text) + */ + virtual void SAL_CALL characters(const OUString& aChars) override; + + /** Starts the mathml element + */ + virtual void SAL_CALL startFastElement( + sal_Int32 nElement, const Reference<XFastAttributeList>& aAttributeList) override; + + /** Ends the mathml element + */ + virtual void SAL_CALL endFastElement(sal_Int32 Element) override; + + /** Creates child element + */ + virtual uno::Reference<XFastContextHandler> + SAL_CALL createFastChildContext(sal_Int32 nElement, + const uno::Reference<XFastAttributeList>& Attribs) override; + + /** Inherits the style from it's parents + */ + void inheritStyle(); + + /** Inherits the style from it's parents on end + */ + void inheritStyleEnd(); + + /** Handle mathml attributes + */ + void handleAttributes(const Reference<XFastAttributeList>& aAttributeList); + + /** Handle mathml length attributes + */ + SmLengthValue handleLengthAttribute(const OUString& aAttribute); +}; + +uno::Reference<XFastContextHandler> SAL_CALL +SmMLImportContext::createFastChildContext(sal_Int32, const uno::Reference<XFastAttributeList>&) +{ + uno::Reference<xml::sax::XFastContextHandler> xContext; + xContext = new SmMLImportContext(static_cast<SmMLImport&>(GetImport()), &m_pElement); + return xContext; +} + +void SmMLImportContext::declareMlError() +{ + SmMLImport& aSmMLImport = static_cast<SmMLImport&>(GetImport()); + aSmMLImport.declareMlError(); +} + +void SmMLImportContext::inheritStyle() +{ + while ((m_pStyle = m_pStyle->getParentElement()) != nullptr) + { + if (m_pStyle->getParentElement()->getMlElementType() == SmMlElementType::MlMstyle + || m_pStyle->getParentElement()->getMlElementType() == SmMlElementType::MlMath) + break; + } + + // Parent inheritation + // Mathcolor, mathsize, dir and displaystyle are inherited from parent + SmMlElement* pParent = *m_pParent; + m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlMathcolor)); + m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlMathsize)); + m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlDir)); + m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlDisplaystyle)); + + // Inherit operator dictionary overwrites + if (m_pStyle != nullptr + && (m_pElement->getMlElementType() == SmMlElementType::MlMo + || m_pElement->getMlElementType() == SmMlElementType::MlMstyle + || m_pElement->getMlElementType() == SmMlElementType::MlMath)) + { + // TODO fetch operator dictionary first and then overwrite + if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlAccent)) + m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlAccent)); + if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlFence)) + m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlFence)); + if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlLspace)) + m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlLspace)); + if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMaxsize)) + m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlMaxsize)); + if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMinsize)) + m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlMinsize)); + if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMovablelimits)) + m_pElement->setAttribute( + m_pStyle->getAttribute(SmMlAttributeValueType::MlMovablelimits)); + if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlRspace)) + m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlRspace)); + if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlSeparator)) + m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlSeparator)); + if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlStretchy)) + m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlStretchy)); + if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlSymmetric)) + m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlSymmetric)); + + if (m_pElement->getMlElementType() == SmMlElementType::MlMo) + { + // Set form based in position + SmMlAttribute aAttribute(SmMlAttributeValueType::MlForm); + SmMlForm aForm; + if (m_pElement->getSubElementId() == 0) + aForm = { SmMlAttributeValueForm::MlPrefix }; + else + aForm = { SmMlAttributeValueForm::MlInfix }; + aAttribute.setMlForm(&aForm); + m_pElement->setAttribute(aAttribute); + } + } + + // Inherit mathvariant + if (m_pStyle && m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMathvariant)) + m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlMathvariant)); +} + +void SmMLImportContext::inheritStyleEnd() +{ + // Mo: check it is the end: postfix + if (m_pElement->getMlElementType() == SmMlElementType::MlMo) + { + if ((*m_pParent)->getSubElementsCount() == m_pElement->getSubElementId()) + { + // Set form based in position + SmMlAttribute aAttribute(SmMlAttributeValueType::MlForm); + SmMlForm aForm = { SmMlAttributeValueForm::MlPosfix }; + aAttribute.setMlForm(&aForm); + m_pElement->setAttribute(aAttribute); + } + } + + // Mi: 1 char -> italic + if (m_pElement->getMlElementType() != SmMlElementType::MlMi) + return; + + // Inherit mathvariant + if (!m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMathvariant)) + { + sal_Int32 nIndexUtf16 = 0; + // Check if there is only one code point + m_pElement->getText().iterateCodePoints(&nIndexUtf16, 1); + // Mathml says that 1 code point -> italic + if (nIndexUtf16 == m_pElement->getText().getLength()) + { + SmMlAttribute aAttribute(SmMlAttributeValueType::MlMathvariant); + SmMlMathvariant aMathvariant = { SmMlAttributeValueMathvariant::italic }; + aAttribute.setMlMathvariant(&aMathvariant); + aAttribute.setSet(false); + m_pElement->setAttribute(aAttribute); + } + } +} + +SmLengthValue SmMLImportContext::handleLengthAttribute(const OUString& aAttribute) +{ + // Locate unit indication + int32_t nUnitPos; + for (nUnitPos = 0; + nUnitPos < aAttribute.getLength() + && (rtl::isAsciiHexDigit(aAttribute[nUnitPos]) || aAttribute[nUnitPos] == '.'); + ++nUnitPos) + ; + + // Find unit + SmLengthUnit nUnit = SmLengthUnit::MlM; + if (nUnitPos != aAttribute.getLength()) + { + OUString aUnit = aAttribute.copy(nUnitPos); + if (aUnit.compareToIgnoreAsciiCaseAscii("ex")) + nUnit = SmLengthUnit::MlEx; + if (aUnit.compareToIgnoreAsciiCaseAscii("px")) + nUnit = SmLengthUnit::MlPx; + if (aUnit.compareToIgnoreAsciiCaseAscii("in")) + nUnit = SmLengthUnit::MlIn; + if (aUnit.compareToIgnoreAsciiCaseAscii("cm")) + nUnit = SmLengthUnit::MlCm; + if (aUnit.compareToIgnoreAsciiCaseAscii("mm")) + nUnit = SmLengthUnit::MlMm; + if (aUnit.compareToIgnoreAsciiCaseAscii("pt")) + nUnit = SmLengthUnit::MlPt; + if (aUnit.compareToIgnoreAsciiCaseAscii("pc")) + nUnit = SmLengthUnit::MlPc; + if (aUnit.compareToIgnoreAsciiCaseAscii("%")) + nUnit = SmLengthUnit::MlP; + else + declareMlError(); + } + + // Get value + std::u16string_view aValue = aAttribute.subView(0, nUnitPos); + double nValue = o3tl::toDouble(aValue); + if (nValue == 0) + { + nUnit = SmLengthUnit::MlM; + nValue = 1.0; + declareMlError(); + } + + // Return + SmLengthValue aLengthValue = { nUnit, nValue, new OUString(aAttribute) }; + return aLengthValue; +} + +void SmMLImportContext::handleAttributes(const Reference<XFastAttributeList>& aAttributeList) +{ + for (auto& aIter : sax_fastparser::castToFastAttributeList(aAttributeList)) + { + SmMlAttribute aAttribute(SmMlAttributeValueType::NMlEmpty); + switch (aIter.getToken() & TOKEN_MASK) + { + case XML_ACCENT: + { + if (IsXMLToken(aIter, XML_TRUE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlAccent); + SmMlAccent aAccent = { SmMlAttributeValueAccent::MlTrue }; + aAttribute.setMlAccent(&aAccent); + } + else if (IsXMLToken(aIter, XML_FALSE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlAccent); + SmMlAccent aAccent = { SmMlAttributeValueAccent::MlFalse }; + aAttribute.setMlAccent(&aAccent); + } + else + { + declareMlError(); + } + break; + } + case XML_DIR: + { + if (IsXMLToken(aIter, XML_RTL)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDir); + SmMlDir aDir = { SmMlAttributeValueDir::MlRtl }; + aAttribute.setMlDir(&aDir); + } + else if (IsXMLToken(aIter, XML_LTR)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDir); + SmMlDir aDir = { SmMlAttributeValueDir::MlLtr }; + aAttribute.setMlDir(&aDir); + } + else + { + declareMlError(); + } + break; + } + case XML_DISPLAYSTYLE: + if (IsXMLToken(aIter, XML_TRUE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDisplaystyle); + SmMlDisplaystyle aDisplaystyle = { SmMlAttributeValueDisplaystyle::MlTrue }; + aAttribute.setMlDisplaystyle(&aDisplaystyle); + } + else if (IsXMLToken(aIter, XML_FALSE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDisplaystyle); + SmMlDisplaystyle aDisplaystyle = { SmMlAttributeValueDisplaystyle::MlFalse }; + aAttribute.setMlDisplaystyle(&aDisplaystyle); + } + else + { + declareMlError(); + } + break; + case XML_FENCE: + if (IsXMLToken(aIter, XML_TRUE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlFence); + SmMlFence aFence = { SmMlAttributeValueFence::MlTrue }; + aAttribute.setMlFence(&aFence); + } + else if (IsXMLToken(aIter, XML_FALSE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlFence); + SmMlFence aFence = { SmMlAttributeValueFence::MlFalse }; + aAttribute.setMlFence(&aFence); + } + else + { + declareMlError(); + } + break; + case XML_HREF: + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlHref); + OUString* aRef = new OUString(aIter.toString()); + SmMlHref aHref = { SmMlAttributeValueHref::NMlValid, aRef }; + aAttribute.setMlHref(&aHref); + break; + } + case XML_LSPACE: + { + SmMlLspace aLspace; + aLspace.m_aLengthValue = handleLengthAttribute(aIter.toString()); + aAttribute.setMlLspace(&aLspace); + break; + } + case XML_MATHBACKGROUND: + { + if (IsXMLToken(aIter, XML_TRANSPARENT)) + { + SmMlMathbackground aMathbackground + = { SmMlAttributeValueMathbackground::MlTransparent, COL_TRANSPARENT }; + aAttribute.setMlMathbackground(&aMathbackground); + } + else + { + Color aColor + = starmathdatabase::Identify_ColorName_HTML(aIter.toString()).cColor; + SmMlMathbackground aMathbackground + = { SmMlAttributeValueMathbackground::MlRgb, aColor }; + aAttribute.setMlMathbackground(&aMathbackground); + } + break; + } + case XML_MATHCOLOR: + { + if (IsXMLToken(aIter, XML_DEFAULT)) + { + SmMlMathcolor aMathcolor + = { SmMlAttributeValueMathcolor::MlDefault, COL_BLACK }; + aAttribute.setMlMathcolor(&aMathcolor); + } + else + { + Color aColor + = starmathdatabase::Identify_ColorName_HTML(aIter.toString()).cColor; + SmMlMathcolor aMathcolor = { SmMlAttributeValueMathcolor::MlRgb, aColor }; + aAttribute.setMlMathcolor(&aMathcolor); + } + break; + } + case XML_MATHSIZE: + { + SmMlMathsize aMathsize; + aMathsize.m_aLengthValue = handleLengthAttribute(aIter.toString()); + aAttribute.setMlMathsize(&aMathsize); + break; + } + case XML_MATHVARIANT: + { + OUString aVariant = aIter.toString(); + SmMlAttributeValueMathvariant nVariant = SmMlAttributeValueMathvariant::normal; + if (aVariant.compareTo(u"normal")) + nVariant = SmMlAttributeValueMathvariant::normal; + else if (aVariant.compareTo(u"bold")) + nVariant = SmMlAttributeValueMathvariant::bold; + else if (aVariant.compareTo(u"italic")) + nVariant = SmMlAttributeValueMathvariant::italic; + else if (aVariant.compareTo(u"double-struck")) + nVariant = SmMlAttributeValueMathvariant::double_struck; + else if (aVariant.compareTo(u"script")) + nVariant = SmMlAttributeValueMathvariant::script; + else if (aVariant.compareTo(u"fraktur")) + nVariant = SmMlAttributeValueMathvariant::fraktur; + else if (aVariant.compareTo(u"sans-serif")) + nVariant = SmMlAttributeValueMathvariant::sans_serif; + else if (aVariant.compareTo(u"monospace")) + nVariant = SmMlAttributeValueMathvariant::monospace; + else if (aVariant.compareTo(u"bold-italic")) + nVariant = SmMlAttributeValueMathvariant::bold_italic; + else if (aVariant.compareTo(u"bold-fracktur")) + nVariant = SmMlAttributeValueMathvariant::bold_fraktur; + else if (aVariant.compareTo(u"bold-script")) + nVariant = SmMlAttributeValueMathvariant::bold_script; + else if (aVariant.compareTo(u"bold-sans-serif")) + nVariant = SmMlAttributeValueMathvariant::bold_sans_serif; + else if (aVariant.compareTo(u"sans-serif-italic")) + nVariant = SmMlAttributeValueMathvariant::sans_serif_italic; + else if (aVariant.compareTo(u"sans-serif-bold-italic")) + nVariant = SmMlAttributeValueMathvariant::sans_serif_bold_italic; + else if (aVariant.compareTo(u"initial")) + nVariant = SmMlAttributeValueMathvariant::initial; + else if (aVariant.compareTo(u"tailed")) + nVariant = SmMlAttributeValueMathvariant::tailed; + else if (aVariant.compareTo(u"looped")) + nVariant = SmMlAttributeValueMathvariant::looped; + else if (aVariant.compareTo(u"stretched")) + nVariant = SmMlAttributeValueMathvariant::stretched; + else + declareMlError(); + SmMlMathvariant aMathvariant = { nVariant }; + aAttribute.setMlMathvariant(&aMathvariant); + break; + } + case XML_MAXSIZE: + { + SmMlMaxsize aMaxsize; + if (IsXMLToken(aIter, XML_INFINITY)) + { + aMaxsize.m_aMaxsize = SmMlAttributeValueMaxsize::MlInfinity; + aMaxsize.m_aLengthValue = { SmLengthUnit::MlP, 10000, new OUString(u"10000%") }; + } + else + { + aMaxsize.m_aMaxsize = SmMlAttributeValueMaxsize::MlFinite; + aMaxsize.m_aLengthValue = handleLengthAttribute(aIter.toString()); + } + aAttribute.setMlMaxsize(&aMaxsize); + break; + } + case XML_MINSIZE: + { + SmMlMinsize aMinsize; + aMinsize.m_aLengthValue = handleLengthAttribute(aIter.toString()); + aAttribute.setMlMinsize(&aMinsize); + break; + } + case XML_MOVABLELIMITS: + if (IsXMLToken(aIter, XML_TRUE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlMovablelimits); + SmMlMovablelimits aMovablelimits = { SmMlAttributeValueMovablelimits::MlTrue }; + aAttribute.setMlMovablelimits(&aMovablelimits); + } + else if (IsXMLToken(aIter, XML_FALSE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlMovablelimits); + SmMlMovablelimits aMovablelimits = { SmMlAttributeValueMovablelimits::MlFalse }; + aAttribute.setMlMovablelimits(&aMovablelimits); + } + else + { + declareMlError(); + } + break; + case XML_RSPACE: + { + SmMlRspace aRspace; + aRspace.m_aLengthValue = handleLengthAttribute(aIter.toString()); + aAttribute.setMlRspace(&aRspace); + break; + } + case XML_SEPARATOR: + if (IsXMLToken(aIter, XML_TRUE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSeparator); + SmMlSeparator aSeparator = { SmMlAttributeValueSeparator::MlTrue }; + aAttribute.setMlSeparator(&aSeparator); + } + else if (IsXMLToken(aIter, XML_FALSE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSeparator); + SmMlSeparator aSeparator = { SmMlAttributeValueSeparator::MlFalse }; + aAttribute.setMlSeparator(&aSeparator); + } + else + { + declareMlError(); + } + break; + case XML_STRETCHY: + if (IsXMLToken(aIter, XML_TRUE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlStretchy); + SmMlStretchy aStretchy = { SmMlAttributeValueStretchy::MlTrue }; + aAttribute.setMlStretchy(&aStretchy); + } + else if (IsXMLToken(aIter, XML_FALSE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlStretchy); + SmMlStretchy aStretchy = { SmMlAttributeValueStretchy::MlFalse }; + aAttribute.setMlStretchy(&aStretchy); + } + else + { + declareMlError(); + } + break; + case XML_SYMMETRIC: + if (IsXMLToken(aIter, XML_TRUE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSymmetric); + SmMlSymmetric aSymmetric = { SmMlAttributeValueSymmetric::MlTrue }; + aAttribute.setMlSymmetric(&aSymmetric); + } + else if (IsXMLToken(aIter, XML_FALSE)) + { + aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSymmetric); + SmMlSymmetric aSymmetric = { SmMlAttributeValueSymmetric::MlFalse }; + aAttribute.setMlSymmetric(&aSymmetric); + } + else + { + declareMlError(); + } + break; + default: + declareMlError(); + break; + } + if (aAttribute.isNullAttribute()) + declareMlError(); + else + m_pElement->setAttribute(aAttribute); + } +} + +void SmMLImportContext::characters(const OUString& aChars) { m_pElement->setText(aChars); } + +void SmMLImportContext::startFastElement(sal_Int32 nElement, + const Reference<XFastAttributeList>& aAttributeList) +{ + switch (nElement) + { + case XML_ELEMENT(MATH, XML_MATH): + m_pElement = new SmMlElement(SmMlElementType::MlMath); + break; + case XML_ELEMENT(MATH, XML_MI): + m_pElement = new SmMlElement(SmMlElementType::MlMi); + break; + case XML_ELEMENT(MATH, XML_MERROR): + m_pElement = new SmMlElement(SmMlElementType::MlMerror); + break; + case XML_ELEMENT(MATH, XML_MN): + m_pElement = new SmMlElement(SmMlElementType::MlMn); + break; + case XML_ELEMENT(MATH, XML_MO): + m_pElement = new SmMlElement(SmMlElementType::MlMo); + break; + case XML_ELEMENT(MATH, XML_MROW): + m_pElement = new SmMlElement(SmMlElementType::MlMrow); + break; + case XML_ELEMENT(MATH, XML_MTEXT): + m_pElement = new SmMlElement(SmMlElementType::MlMtext); + break; + case XML_ELEMENT(MATH, XML_MSTYLE): + m_pElement = new SmMlElement(SmMlElementType::MlMstyle); + break; + default: + m_pElement = new SmMlElement(SmMlElementType::NMlEmpty); + declareMlError(); + break; + } + SmMlElement* pParent = *m_pParent; + pParent->setSubElement(pParent->getSubElementsCount(), m_pElement); + inheritStyle(); + handleAttributes(aAttributeList); +} + +void SmMLImportContext::endFastElement(sal_Int32) { inheritStyleEnd(); } +} + +// SmMLImport +/*************************************************************************************************/ + +const uno::Sequence<sal_Int8>& SmMLImport::getUnoTunnelId() noexcept +{ + static const comphelper::UnoIdInit theSmMLImportUnoTunnelId; + return theSmMLImportUnoTunnelId.getSeq(); +} + +sal_Int64 SAL_CALL SmMLImport::getSomething(const uno::Sequence<sal_Int8>& rId) +{ + return comphelper::getSomethingImpl(rId, this, + comphelper::FallbackToGetSomethingOf<SvXMLImport>{}); +} + +SvXMLImportContext* +SmMLImport::CreateFastContext(sal_Int32 nElement, + const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/) +{ + SvXMLImportContext* pContext = nullptr; + + switch (nElement) + { + case XML_ELEMENT(OFFICE, XML_DOCUMENT): + { + if (m_pElementTree == nullptr) + m_pElementTree = new SmMlElement(SmMlElementType::NMlEmpty); + uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(), + uno::UNO_QUERY_THROW); + pContext = new SmMLImportContext(*this, &m_pElementTree); + break; + } + case XML_ELEMENT(OFFICE, XML_DOCUMENT_META): + { + uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(), + uno::UNO_QUERY_THROW); + pContext = new SvXMLMetaDocumentContext(*this, xDPS->getDocumentProperties()); + break; + } + case XML_ELEMENT(OFFICE, XML_DOCUMENT_SETTINGS): + { + uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(), + uno::UNO_QUERY_THROW); + pContext = new XMLDocumentSettingsContext(*this); + break; + } + default: + declareMlError(); + break; + } + return pContext; +} + +void SmMLImport::endDocument() +{ + uno::Reference<frame::XModel> xModel = GetModel(); + if (!xModel.is()) + { + SAL_WARN("starmath", "Failed to set view settings because missing model"); + SvXMLImport::endDocument(); + return; + } + + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel); + if (!pModel) + { + SAL_WARN("starmath", "Failed to set view settings because missing sm model"); + SvXMLImport::endDocument(); + return; + } + + SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell()); + if (!pDocShell) + { + SAL_WARN("starmath", "Failed to set view settings because missing sm doc shell"); + SvXMLImport::endDocument(); + return; + } + + // Check if there is element tree + if (m_pElementTree == nullptr) + { + m_bSuccess = true; + SvXMLImport::endDocument(); + return; + } + + // Get element tree and setup + + if (m_pElementTree->getSubElementsCount() == 0) + { + delete m_pElementTree; + m_pElementTree = nullptr; + } + else + { + SmMlElement* pTmpElememt = m_pElementTree->getSubElement(0); + delete m_pElementTree; + m_pElementTree = pTmpElememt; + } + pDocShell->SetMlElementTree(m_pElementTree); + + m_bSuccess = true; + SvXMLImport::endDocument(); +} + +void SmMLImport::SetViewSettings(const Sequence<PropertyValue>& aViewProps) +{ + uno::Reference<frame::XModel> xModel = GetModel(); + if (!xModel.is()) + { + SAL_WARN("starmath", "Failed to set view settings because missing model"); + return; + } + + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel); + if (!pModel) + { + SAL_WARN("starmath", "Failed to set view settings because missing sm model"); + return; + } + + SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell()); + if (!pDocShell) + { + SAL_WARN("starmath", "Failed to set view settings because missing sm doc shell"); + return; + } + + tools::Rectangle aRect(pDocShell->GetVisArea()); + + tools::Long nTmp = 0; + + for (const PropertyValue& rValue : aViewProps) + { + if (rValue.Name == "ViewAreaTop") + { + rValue.Value >>= nTmp; + aRect.SaturatingSetPosY(nTmp); + } + else if (rValue.Name == "ViewAreaLeft") + { + rValue.Value >>= nTmp; + aRect.SaturatingSetPosX(nTmp); + } + else if (rValue.Name == "ViewAreaWidth") + { + rValue.Value >>= nTmp; + Size aSize(aRect.GetSize()); + aSize.setWidth(nTmp); + aRect.SaturatingSetSize(aSize); + } + else if (rValue.Name == "ViewAreaHeight") + { + rValue.Value >>= nTmp; + Size aSize(aRect.GetSize()); + aSize.setHeight(nTmp); + aRect.SaturatingSetSize(aSize); + } + } + + pDocShell->SetVisArea(aRect); +} + +void SmMLImport::SetConfigurationSettings(const Sequence<PropertyValue>& aConfProps) +{ + uno::Reference<frame::XModel> xModel = GetModel(); + if (!xModel.is()) + { + SAL_WARN("starmath", "Failed to set view settings because missing model"); + return; + } + + uno::Reference<XPropertySet> xProps(xModel, UNO_QUERY); + if (!xProps.is()) + { + SAL_WARN("starmath", "Failed to set view settings because missing model properties"); + return; + } + + Reference<XPropertySetInfo> xInfo(xProps->getPropertySetInfo()); + if (!xInfo.is()) + { + SAL_WARN("starmath", + "Failed to set view settings because missing model properties information"); + return; + } + + static const OUStringLiteral sFormula(u"Formula"); + static const OUStringLiteral sBasicLibraries(u"BasicLibraries"); + static const OUStringLiteral sDialogLibraries(u"DialogLibraries"); + for (const PropertyValue& rValue : aConfProps) + { + if (rValue.Name != sFormula && rValue.Name != sBasicLibraries + && rValue.Name != sDialogLibraries) + { + try + { + if (xInfo->hasPropertyByName(rValue.Name)) + xProps->setPropertyValue(rValue.Name, rValue.Value); + } + catch (const beans::PropertyVetoException&) + { + // dealing with read-only properties here. Nothing to do... + } + catch (const Exception&) + { + SAL_WARN("starmath", "Unexpected issue while loading document properties"); + } + } + } +} + +SmMLImport::SmMLImport(const css::uno::Reference<css::uno::XComponentContext>& rContext, + OUString const& implementationName, SvXMLImportFlags nImportFlags) + : SvXMLImport(rContext, implementationName, nImportFlags) + , m_pElementTree(nullptr) + , m_bSuccess(false) + , m_nSmSyntaxVersion(SM_MOD()->GetConfig()->GetDefaultSmSyntaxVersion()) +{ +} + +/** Handles an error on the mathml structure + */ +void SmMLImport::declareMlError() +{ + m_bSuccess = false; + SAL_WARN("starmath", "MathML error"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/starmath/source/mathml/iterator.cxx b/starmath/source/mathml/iterator.cxx new file mode 100644 index 000000000..24de35c18 --- /dev/null +++ b/starmath/source/mathml/iterator.cxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <mathml/iterator.hxx> + +/** The purpose of this iterator is to be able to iterate threw an infinite element tree + * infinite -> as much as your memory can hold + * No call-backs that will end up in out of stack + */ + +namespace mathml +{ +static inline void deleteElement(SmMlElement* aSmMlElement, void*) { delete aSmMlElement; } + +static inline void cloneElement(SmMlElement* aSmMlElement, void* aData) +{ + // Prepare data + SmMlElement* aNewSmMlElement = new SmMlElement(*aSmMlElement); + SmMlElement* aCopyTree = *static_cast<SmMlElement**>(aData); + + // Append data + aCopyTree->setSubElement(aCopyTree->getSubElementsCount(), aNewSmMlElement); + + // Prepare for following + // If it has sub elements, then it will be the next + if (aSmMlElement->getSubElementsCount() != 0) + aCopyTree = aNewSmMlElement; + else // Otherwise remounts up to where it should be + { + while (aSmMlElement->getParentElement() != nullptr) + { + // get parent + SmMlElement* pParent = aSmMlElement->getParentElement(); + aCopyTree = aCopyTree->getParentElement(); + // was this the last branch ? + if (aSmMlElement->getSubElementId() + 1 != pParent->getSubElementsCount()) + break; // no -> stop going up + // Prepare for next round + aSmMlElement = pParent; + } + } + + // Closing extras + *static_cast<SmMlElement**>(aData) = aCopyTree; +} + +void SmMlIteratorFree(SmMlElement* pMlElementTree) +{ + if (pMlElementTree == nullptr) + return; + for (size_t i = 0; i < pMlElementTree->getSubElementsCount(); ++i) + { + SmMlIteratorFree(pMlElementTree->getSubElement(i)); + } + deleteElement(pMlElementTree, nullptr); +} + +SmMlElement* SmMlIteratorCopy(SmMlElement* pMlElementTree) +{ + if (pMlElementTree == nullptr) + return nullptr; + SmMlElement* aDummyElement = new SmMlElement(); + SmMlIteratorTopToBottom(pMlElementTree, cloneElement, &aDummyElement); + SmMlElement* aResultElement = aDummyElement->getSubElement(0); + delete aDummyElement; + return aResultElement; +} + +} // end namespace mathml + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/starmath/source/mathml/mathmlMo.cxx b/starmath/source/mathml/mathmlMo.cxx new file mode 100644 index 000000000..fb76b070e --- /dev/null +++ b/starmath/source/mathml/mathmlMo.cxx @@ -0,0 +1,1127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <mathmlMo.hxx> + +static moOperatorData moOperatorDataDictionaryData[starmathdatabase::MATHML_MO_COUNT] + = { { u"\u2018", moOpDF::prefix, 10, 0, 0, moOpDP::fence | moOpDP::nonedp }, + { u"\u2019", moOpDF::postfix, 10, 0, 0, moOpDP::fence | moOpDP::nonedp }, + { u"\u201C", moOpDF::prefix, 10, 0, 0, moOpDP::fence | moOpDP::nonedp }, + { u"\u201D", moOpDF::postfix, 10, 0, 0, moOpDP::fence | moOpDP::nonedp }, + { u"(", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u")", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"[", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"]", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"{", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"|", moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"||", moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"|||", moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"}", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2016", moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence }, + { u"\u2308", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2309", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u230A", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u230B", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2329", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u232A", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2772", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2773", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u27E6", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u27E7", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u27E8", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u27E9", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u27EA", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u27EB", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u27EC", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u27ED", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u27EE", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u27EF", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2980", moOpDF::prepostfix, 20, 0, 0, moOpDP::stretchyfence }, + { u"\u2983", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2984", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2985", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2986", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2987", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2988", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2989", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u298A", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u298B", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u298C", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u298D", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u298E", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u298F", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2990", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2991", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2992", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2993", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2994", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2995", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2996", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2997", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2998", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u29FC", moOpDF::prefix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u29FD", moOpDF::postfix, 20, 0, 0, moOpDP::stretchyfence | moOpDP::symmetric }, + { u";", moOpDF::infix, 30, 0, 3, moOpDP::separator | moOpDP::linebreakstyleAfter }, + { u",", moOpDF::infix, 40, 0, 3, moOpDP::separator | moOpDP::linebreakstyleAfter }, + { u"\u2063", moOpDF::infix, 40, 0, 0, moOpDP::separator | moOpDP::linebreakstyleAfter }, + { u"\u2234", moOpDF::infix, 70, 5, 5, moOpDP::nonedp }, + { u"\u2235", moOpDF::infix, 70, 5, 5, moOpDP::nonedp }, + { u"->", moOpDF::infix, 90, 5, 5, moOpDP::nonedp }, + { u"..", moOpDF::postfix, 100, 0, 0, moOpDP::nonedp }, + { u"...", moOpDF::postfix, 100, 0, 0, moOpDP::nonedp }, + { u":", moOpDF::infix, 100, 1, 2, moOpDP::nonedp }, + { u"\u03F6", moOpDF::infix, 110, 5, 5, moOpDP::nonedp }, + { u"\u2026", moOpDF::infix, 150, 0, 0, moOpDP::nonedp }, + { u"\u22EE", moOpDF::infix, 150, 5, 5, moOpDP::nonedp }, + { u"\u22EF", moOpDF::infix, 150, 0, 0, moOpDP::nonedp }, + { u"\u22F1", moOpDF::infix, 150, 5, 5, moOpDP::nonedp }, + { u"\u220B", moOpDF::infix, 160, 5, 5, moOpDP::nonedp }, + { u"\u22A2", moOpDF::infix, 170, 5, 5, moOpDP::nonedp }, + { u"\u22A3", moOpDF::infix, 170, 5, 5, moOpDP::nonedp }, + { u"\u22A4", moOpDF::infix, 170, 5, 5, moOpDP::nonedp }, + { u"\u22A8", moOpDF::infix, 170, 5, 5, moOpDP::nonedp }, + { u"\u22A9", moOpDF::infix, 170, 5, 5, moOpDP::nonedp }, + { u"\u22AC", moOpDF::infix, 170, 5, 5, moOpDP::nonedp }, + { u"\u22AD", moOpDF::infix, 170, 5, 5, moOpDP::nonedp }, + { u"\u22AE", moOpDF::infix, 170, 5, 5, moOpDP::nonedp }, + { u"\u22AF", moOpDF::infix, 170, 5, 5, moOpDP::nonedp }, + { u"\u2228", moOpDF::infix, 190, 4, 4, moOpDP::nonedp }, + { u"&&", moOpDF::infix, 200, 4, 4, moOpDP::nonedp }, + { u"\u2227", moOpDF::infix, 200, 4, 4, moOpDP::nonedp }, + { u"\u2200", moOpDF::prefix, 230, 2, 1, moOpDP::nonedp }, + { u"\u2203", moOpDF::prefix, 230, 2, 1, moOpDP::nonedp }, + { u"\u2204", moOpDF::prefix, 230, 2, 1, moOpDP::nonedp }, + { u"\u2201", moOpDF::infix, 240, 1, 2, moOpDP::nonedp }, + { u"\u2208", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u2209", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u220C", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u2282", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u2282\u20D2", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u2283", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u2283\u20D2", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u2284", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u2285", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u2286", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u2287", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u2288", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u2289", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u228A", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"\u228B", moOpDF::infix, 240, 5, 5, moOpDP::nonedp }, + { u"<=", moOpDF::infix, 241, 5, 5, moOpDP::nonedp }, + { u"\u2264", moOpDF::infix, 241, 5, 5, moOpDP::nonedp }, + { u"\u2265", moOpDF::infix, 242, 5, 5, moOpDP::nonedp }, + { u">", moOpDF::infix, 243, 5, 5, moOpDP::nonedp }, + { u">=", moOpDF::infix, 243, 5, 5, moOpDP::nonedp }, + { u"\u226F", moOpDF::infix, 244, 5, 5, moOpDP::nonedp }, + { u"<", moOpDF::infix, 245, 5, 5, moOpDP::nonedp }, + { u"\u226E", moOpDF::infix, 246, 5, 5, moOpDP::nonedp }, + { u"\u2248", moOpDF::infix, 247, 5, 5, moOpDP::nonedp }, + { u"\u223C", moOpDF::infix, 250, 5, 5, moOpDP::nonedp }, + { u"\u2249", moOpDF::infix, 250, 5, 5, moOpDP::nonedp }, + { u"\u2262", moOpDF::infix, 252, 5, 5, moOpDP::nonedp }, + { u"\u2260", moOpDF::infix, 255, 5, 5, moOpDP::nonedp }, + { u"!=", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"*=", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"+=", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"-=", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"/=", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u":=", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"=", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"==", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u221D", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2224", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2225", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2226", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2241", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2243", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2244", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2245", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2246", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2247", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u224D", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2254", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2257", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2259", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u225A", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u225B", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u225C", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u225F", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2261", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2268", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2269", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u226A", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u226A\u0338", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u226B", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u226B\u0338", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u226D", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2270", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2271", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u227A", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u227B", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u227C", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u227D", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2280", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2281", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u22A5", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u22B4", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u22B5", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u22C9", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u22CA", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u22CB", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u22CC", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u22D4", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u22D6", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u22D7", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u22D8", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u22D9", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u22EA", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u22EB", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u22EC", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u22ED", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u25A0", moOpDF::infix, 260, 3, 3, moOpDP::nonedp }, + { u"\u25A1", moOpDF::infix, 260, 3, 3, moOpDP::nonedp }, + { u"\u25AA", moOpDF::infix, 260, 3, 3, moOpDP::nonedp }, + { u"\u25AB", moOpDF::infix, 260, 3, 3, moOpDP::nonedp }, + { u"\u25AD", moOpDF::infix, 260, 3, 3, moOpDP::nonedp }, + { u"\u25AE", moOpDF::infix, 260, 3, 3, moOpDP::nonedp }, + { u"\u25AF", moOpDF::infix, 260, 3, 3, moOpDP::nonedp }, + { u"\u25B0", moOpDF::infix, 260, 3, 3, moOpDP::nonedp }, + { u"\u25B1", moOpDF::infix, 260, 3, 3, moOpDP::nonedp }, + { u"\u25B3", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25B4", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25B5", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25B6", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25B7", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25B8", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25B9", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25BC", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25BD", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25BE", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25BF", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25C0", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25C1", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25C2", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25C3", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25C4", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25C5", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25C6", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25C7", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25C8", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25C9", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25CC", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25CD", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25CE", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25CF", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25D6", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25D7", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u25E6", moOpDF::infix, 260, 4, 4, moOpDP::nonedp }, + { u"\u29C0", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u29C1", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u29E3", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u29E4", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u29E5", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u29E6", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u29F3", moOpDF::infix, 260, 3, 3, moOpDP::nonedp }, + { u"\u2A87", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2A88", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2AAF", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2AAF\u0338", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2AB0", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2AB0\u0338", moOpDF::infix, 260, 5, 5, moOpDP::nonedp }, + { u"\u2044", moOpDF::infix, 265, 4, 4, moOpDP::stretchy }, + { u"\u2206", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u220A", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u220D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u220E", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u2215", moOpDF::infix, 265, 4, 4, moOpDP::stretchy }, + { u"\u2217", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2218", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2219", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u221F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2223", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2236", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2237", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2238", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2239", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u223A", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u223B", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u223D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u223D\u0331", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u223E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u223F", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u2242", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2242\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u224A", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u224B", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u224C", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u224E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u224E\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u224F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u224F\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2250", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2251", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2252", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2253", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2255", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2256", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2258", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u225D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u225E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2263", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2266", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2266\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2267", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u226C", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2272", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2273", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2274", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2275", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2276", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2277", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2278", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2279", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u227E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u227F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u227F\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u228C", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u228D", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u228E", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u228F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u228F\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2290", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2290\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2291", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2292", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2293", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2294", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u229A", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u229B", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u229C", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u229D", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u22A6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22A7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22AA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22AB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22B0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22B1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22B2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22B3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22B6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22B7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22B9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22BA", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u22BB", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u22BC", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u22BD", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u22BE", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u22BF", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u22C4", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u22C6", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u22C7", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u22C8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22CD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22CE", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u22CF", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u22D0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22D1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22D2", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u22D3", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u22D5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22DA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22DB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22DC", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22DD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22DE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22DF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22E0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22E1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22E2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22E3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22E4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22E5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22E6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22E7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22E8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22E9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22F0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22F2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22F3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22F4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22F5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22F6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22F7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22F8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22F9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22FA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22FB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22FC", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22FD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22FE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u22FF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u25B2", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2758", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2981", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u2982", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29A0", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29A1", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29A2", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29A3", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29A4", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29A5", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29A6", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29A7", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29A8", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29A9", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29AA", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29AB", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29AC", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29AD", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29AE", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29AF", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29B0", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29B1", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29B2", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29B3", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29B4", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29B5", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29B6", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29B7", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29B8", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29B9", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29BA", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29BB", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29BC", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29BD", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29BE", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29BF", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29C2", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29C3", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29C4", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29C5", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29C6", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29C7", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29C8", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29C9", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29CA", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29CB", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29CC", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29CD", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29CE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u29CF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u29CF\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u29D0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u29D0\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u29D1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u29D2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u29D3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u29D4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u29D5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u29D6", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29D7", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29D8", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29D9", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29DB", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29DC", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29DD", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29DE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u29E0", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29E1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u29E2", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29E7", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29E8", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29E9", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29EA", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29EB", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29EC", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29ED", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29EE", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29F0", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29F1", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29F2", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29F5", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29F6", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29F7", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29F8", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29F9", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29FA", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29FB", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u29FE", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u29FF", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A1D", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u2A1E", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u2A1F", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u2A20", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u2A21", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"\u2A22", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A23", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A24", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A25", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A26", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A27", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A28", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A29", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A2A", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A2B", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A2C", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A2D", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A2E", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A30", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A31", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A32", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A33", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A34", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A35", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A36", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A37", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A38", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A39", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A3A", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A3B", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A3C", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A3D", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A3E", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A40", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A41", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A42", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A43", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A44", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A45", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A46", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A47", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A48", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A49", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A4A", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A4B", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A4C", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A4D", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A4E", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A4F", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A50", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A51", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A52", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A53", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A54", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A55", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A56", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A57", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A58", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A59", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A5A", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A5B", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A5C", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A5D", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A5E", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A5F", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A60", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A61", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A62", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A63", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A64", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A65", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A66", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A67", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A68", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A69", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A6A", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A6B", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A6C", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A6D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A6E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A6F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A70", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A71", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A72", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2A73", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A74", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A75", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A76", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A77", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A78", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A79", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A7A", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A7B", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A7C", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A7D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A7D\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A7E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A7E\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A7F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A80", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A81", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A82", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A83", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A84", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A85", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A86", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A89", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A8A", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A8B", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A8C", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A8D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A8E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A8F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A90", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A91", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A92", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A93", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A94", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A95", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A96", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A97", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A98", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A99", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A9A", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A9B", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A9C", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A9D", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A9E", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2A9F", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AA0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AA1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AA1\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AA2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AA2\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AA3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AA4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AA5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AA6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AA7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AA8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AA9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AAA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AAB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AAC", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AAD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AAE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AB1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AB2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AB3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AB4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AB5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AB6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AB7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AB8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AB9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ABA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ABB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ABC", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ABD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ABE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ABF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AC0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AC1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AC2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AC3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AC4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AC5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AC6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AC7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AC8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AC9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ACA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ACB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ACC", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ACD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ACE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ACF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AD0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AD1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AD2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AD3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AD4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AD5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AD6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AD7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AD8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AD9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ADA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ADB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ADD", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ADD\u0338", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ADE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2ADF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AE0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AE1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AE2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AE3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AE4", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AE5", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AE6", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AE7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AE8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AE9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AEA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AEB", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AEC", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AED", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AEE", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AEF", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AF0", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AF1", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AF2", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AF3", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AF4", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2AF5", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2AF6", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2AF7", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AF8", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AF9", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AFA", moOpDF::infix, 265, 5, 5, moOpDP::nonedp }, + { u"\u2AFB", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2AFD", moOpDF::infix, 265, 4, 4, moOpDP::nonedp }, + { u"\u2AFE", moOpDF::infix, 265, 3, 3, moOpDP::nonedp }, + { u"|", moOpDF::infix, 270, 2, 2, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"||", moOpDF::infix, 270, 2, 2, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"|||", moOpDF::infix, 270, 2, 2, moOpDP::stretchyfence | moOpDP::symmetric }, + { u"\u2190", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u2191", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2192", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u2193", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2194", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u2195", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2196", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2197", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2198", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2199", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u219A", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u219B", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u219C", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u219D", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u219E", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u219F", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21A0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21A1", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21A2", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21A3", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21A4", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21A5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21A6", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21A7", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21A8", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21A9", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21AA", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21AB", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21AC", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21AD", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21AE", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u21AF", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21B0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21B1", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21B2", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21B3", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21B4", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21B5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21B6", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u21B7", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u21B8", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u21B9", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21BA", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u21BB", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u21BC", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21BD", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21BE", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21BF", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21C0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21C1", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21C2", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21C3", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21C4", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21C5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21C6", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21C7", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21C8", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21C9", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21CA", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21CB", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21CC", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21CD", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u21CE", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u21CF", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u21D0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21D1", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21D2", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21D3", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21D4", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21D5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21D6", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21D7", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21D8", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21D9", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21DA", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21DB", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21DC", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21DD", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21DE", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u21DF", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u21E0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21E1", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21E2", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21E3", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21E4", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21E5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21E6", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21E7", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21E8", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21E9", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21EA", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21EB", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21EC", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21ED", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21EE", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21EF", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21F0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21F1", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u21F2", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u21F3", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21F4", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u21F5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u21F6", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21F7", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u21F8", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u21F9", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u21FA", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u21FB", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u21FC", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u21FD", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21FE", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u21FF", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u22B8", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u27F0", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u27F1", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u27F5", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u27F6", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u27F7", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u27F8", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u27F9", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u27FA", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u27FB", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u27FC", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u27FD", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u27FE", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u27FF", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u2900", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2901", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2902", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2903", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2904", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2905", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2906", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2907", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2908", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2909", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u290A", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u290B", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u290C", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u290D", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u290E", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u290F", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u2910", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u2911", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2912", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2913", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2914", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2915", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2916", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2917", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2918", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2919", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u291A", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u291B", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u291C", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u291D", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u291E", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u291F", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2920", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2921", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2922", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2923", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2924", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2925", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2926", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2927", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2928", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2929", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u292A", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u292B", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u292C", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u292D", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u292E", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u292F", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2930", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2931", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2932", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2933", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2934", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2935", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2936", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2937", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2938", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2939", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u293A", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u293B", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u293C", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u293D", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u293E", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u293F", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2940", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2941", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2942", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2943", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2944", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2945", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2946", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2947", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2948", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2949", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u294A", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u294B", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u294C", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u294D", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u294E", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u294F", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2950", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u2951", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2952", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u2953", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u2954", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2955", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2956", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2957", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2958", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2959", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u295A", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u295B", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u295C", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u295D", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u295E", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u295F", moOpDF::infix, 270, 5, 5, moOpDP::stretchy | moOpDP::accent }, + { u"\u2960", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2961", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2962", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2963", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2964", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2965", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2966", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2967", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2968", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2969", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u296A", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u296B", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u296C", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u296D", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u296E", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u296F", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2970", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2971", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2972", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2973", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2974", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2975", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2976", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2977", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2978", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u2979", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u297A", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u297B", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u297C", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u297D", moOpDF::infix, 270, 5, 5, moOpDP::accent }, + { u"\u297E", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u297F", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2999", moOpDF::infix, 270, 3, 3, moOpDP::nonedp }, + { u"\u299A", moOpDF::infix, 270, 3, 3, moOpDP::nonedp }, + { u"\u299B", moOpDF::infix, 270, 3, 3, moOpDP::nonedp }, + { u"\u299C", moOpDF::infix, 270, 3, 3, moOpDP::nonedp }, + { u"\u299D", moOpDF::infix, 270, 3, 3, moOpDP::nonedp }, + { u"\u299E", moOpDF::infix, 270, 3, 3, moOpDP::nonedp }, + { u"\u299F", moOpDF::infix, 270, 3, 3, moOpDP::nonedp }, + { u"\u29DF", moOpDF::infix, 270, 3, 3, moOpDP::nonedp }, + { u"\u29EF", moOpDF::infix, 270, 3, 3, moOpDP::nonedp }, + { u"\u29F4", moOpDF::infix, 270, 5, 5, moOpDP::nonedp }, + { u"\u2B45", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"\u2B46", moOpDF::infix, 270, 5, 5, moOpDP::stretchy }, + { u"+", moOpDF::infix, 275, 4, 4, moOpDP::nonedp }, + { u"+", moOpDF::prefix, 275, 0, 1, moOpDP::nonedp }, + { u"-", moOpDF::infix, 275, 4, 4, moOpDP::nonedp }, + { u"-", moOpDF::prefix, 275, 0, 1, moOpDP::nonedp }, + { u"\u00B1", moOpDF::infix, 275, 4, 4, moOpDP::nonedp }, + { u"\u00B1", moOpDF::prefix, 275, 0, 1, moOpDP::nonedp }, + { u"\u2212", moOpDF::infix, 275, 4, 4, moOpDP::nonedp }, + { u"\u2212", moOpDF::prefix, 275, 0, 1, moOpDP::nonedp }, + { u"\u2213", moOpDF::infix, 275, 4, 4, moOpDP::nonedp }, + { u"\u2213", moOpDF::prefix, 275, 0, 1, moOpDP::nonedp }, + { u"\u2214", moOpDF::infix, 275, 4, 4, moOpDP::nonedp }, + { u"\u229E", moOpDF::infix, 275, 4, 4, moOpDP::nonedp }, + { u"\u229F", moOpDF::infix, 275, 4, 4, moOpDP::nonedp }, + { u"\u2211", moOpDF::prefix, 290, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A0A", moOpDF::prefix, 290, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A0B", moOpDF::prefix, 290, 1, 2, moOpDP::largeop | moOpDP::symmetric }, + { u"\u222C", moOpDF::prefix, 300, 0, 1, moOpDP::largeop | moOpDP::symmetric }, + { u"\u222D", moOpDF::prefix, 300, 0, 1, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2295", moOpDF::infix, 300, 4, 4, moOpDP::nonedp }, + { u"\u2296", moOpDF::infix, 300, 4, 4, moOpDP::nonedp }, + { u"\u2298", moOpDF::infix, 300, 4, 4, moOpDP::nonedp }, + { u"\u2A01", moOpDF::prefix, 300, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u222B", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric }, + { u"\u222E", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric }, + { u"\u222F", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2230", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2231", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2232", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2233", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2A0C", moOpDF::prefix, 310, 0, 1, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2A0D", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2A0E", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2A0F", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2A10", moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A11", moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A12", moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A13", moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A14", moOpDF::prefix, 310, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A15", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2A16", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2A17", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2A18", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2A19", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2A1A", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2A1B", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric }, + { u"\u2A1C", moOpDF::prefix, 310, 1, 2, moOpDP::largeop | moOpDP::symmetric }, + { u"\u22C3", moOpDF::prefix, 320, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A03", moOpDF::prefix, 320, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A04", moOpDF::prefix, 320, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u22C0", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u22C1", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u22C2", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A00", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A02", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A05", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A06", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A07", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A08", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2A09", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2AFC", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2AFF", moOpDF::prefix, 330, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2240", moOpDF::infix, 340, 4, 4, moOpDP::nonedp }, + { u"\u220F", moOpDF::prefix, 350, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2210", moOpDF::prefix, 350, 1, 2, moOpDP::movablelargeop | moOpDP::symmetric }, + { u"\u2229", moOpDF::infix, 350, 4, 4, moOpDP::nonedp }, + { u"\u222A", moOpDF::infix, 350, 4, 4, moOpDP::nonedp }, + { u"*", moOpDF::infix, 390, 3, 3, moOpDP::nonedp }, + { u".", moOpDF::infix, 390, 3, 3, moOpDP::nonedp }, + { u"\u00D7", moOpDF::infix, 390, 4, 4, moOpDP::nonedp }, + { u"\u2022", moOpDF::infix, 390, 4, 4, moOpDP::nonedp }, + { u"\u2043", moOpDF::infix, 390, 4, 4, moOpDP::nonedp }, + { u"\u2062", moOpDF::infix, 390, 0, 0, moOpDP::nonedp }, + { u"\u22A0", moOpDF::infix, 390, 4, 4, moOpDP::nonedp }, + { u"\u22A1", moOpDF::infix, 390, 4, 4, moOpDP::nonedp }, + { u"\u22C5", moOpDF::infix, 390, 4, 4, moOpDP::nonedp }, + { u"\u2A2F", moOpDF::infix, 390, 4, 4, moOpDP::nonedp }, + { u"\u2A3F", moOpDF::infix, 390, 4, 4, moOpDP::nonedp }, + { u"\u00B7", moOpDF::infix, 400, 4, 4, moOpDP::nonedp }, + { u"\u2297", moOpDF::infix, 410, 4, 4, moOpDP::nonedp }, + { u"%", moOpDF::infix, 640, 3, 3, moOpDP::nonedp }, + { u"\\", moOpDF::infix, 650, 0, 0, moOpDP::nonedp }, + { u"\u2216", moOpDF::infix, 650, 4, 4, moOpDP::nonedp }, + { u"/", moOpDF::infix, 660, 1, 1, moOpDP::nonedp }, + { u"\u00F7", moOpDF::infix, 660, 4, 4, moOpDP::nonedp }, + { u"\u2220", moOpDF::prefix, 670, 0, 0, moOpDP::nonedp }, + { u"\u2221", moOpDF::prefix, 670, 0, 0, moOpDP::nonedp }, + { u"\u2222", moOpDF::prefix, 670, 0, 0, moOpDP::nonedp }, + { u"\u00AC", moOpDF::prefix, 680, 2, 1, moOpDP::nonedp }, + { u"\u2299", moOpDF::infix, 710, 4, 4, moOpDP::nonedp }, + { u"\u2202", moOpDF::prefix, 740, 2, 1, moOpDP::nonedp }, + { u"\u2207", moOpDF::prefix, 740, 2, 1, moOpDP::nonedp }, + { u"**", moOpDF::infix, 780, 1, 1, moOpDP::nonedp }, + { u"<>", moOpDF::infix, 780, 1, 1, moOpDP::nonedp }, + { u"^", moOpDF::infix, 780, 1, 1, moOpDP::nonedp }, + { u"\u2032", moOpDF::postfix, 800, 0, 0, moOpDP::nonedp }, + { u"\u266D", moOpDF::postfix, 800, 0, 2, moOpDP::nonedp }, + { u"\u266E", moOpDF::postfix, 800, 0, 2, moOpDP::nonedp }, + { u"\u266F", moOpDF::postfix, 800, 0, 2, moOpDP::nonedp }, + { u"!", moOpDF::postfix, 810, 1, 0, moOpDP::nonedp }, + { u"!!", moOpDF::postfix, 810, 1, 0, moOpDP::nonedp }, + { u"//", moOpDF::infix, 820, 1, 1, moOpDP::nonedp }, + { u"@", moOpDF::infix, 825, 1, 1, moOpDP::nonedp }, + { u"?", moOpDF::infix, 835, 1, 1, moOpDP::nonedp }, + { u"\u2145", moOpDF::prefix, 845, 2, 1, moOpDP::nonedp }, + { u"\u2146", moOpDF::prefix, 845, 2, 0, moOpDP::nonedp }, + { u"\u221A", moOpDF::prefix, 845, 1, 1, moOpDP::stretchy }, + { u"\u221B", moOpDF::prefix, 845, 1, 1, moOpDP::nonedp }, + { u"\u221C", moOpDF::prefix, 845, 1, 1, moOpDP::nonedp }, + { u"\u2061", moOpDF::infix, 850, 0, 0, moOpDP::nonedp }, + { u"\"", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"&", moOpDF::postfix, 880, 0, 0, moOpDP::nonedp }, + { u"\'", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"++", moOpDF::postfix, 880, 0, 0, moOpDP::nonedp }, + { u"--", moOpDF::postfix, 880, 0, 0, moOpDP::nonedp }, + { u"^", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"_", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"`", moOpDF::postfix, 880, 0, 00, moOpDP::accent }, + { u"~", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u00A8", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u00AA", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u00AF", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u00B0", moOpDF::postfix, 880, 0, 0, moOpDP::nonedp }, + { u"\u00B2", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u00B3", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u00B4", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u00B8", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u00B9", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u00BA", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u02C6", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u02C7", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u02C9", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u02CA", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u02CB", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u02CD", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u02D8", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u02D9", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u02DA", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u02DC", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u02DD", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u02F7", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u0302", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u0311", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u201A", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u201B", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u201E", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u201F", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u2033", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u2034", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u2035", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u2036", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u2037", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u203E", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u2057", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u2064", moOpDF::infix, 880, 0, 0, moOpDP::nonedp }, + { u"\u20DB", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u20DC", moOpDF::postfix, 880, 0, 0, moOpDP::accent }, + { u"\u23B4", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u23B5", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u23DC", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u23DD", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u23DE", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u23DF", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u23E0", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"\u23E1", moOpDF::postfix, 880, 0, 0, moOpDP::stretchy | moOpDP::accent }, + { u"_", moOpDF::infix, 900, 1, 1, moOpDP::nonedp } }; + +std::vector<moOperatorData> starmathdatabase::moOperatorDataDictionary( + moOperatorDataDictionaryData, moOperatorDataDictionaryData + starmathdatabase::MATHML_MO_COUNT); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/mathml/mathmlattr.cxx b/starmath/source/mathml/mathmlattr.cxx new file mode 100644 index 000000000..5e54f0d92 --- /dev/null +++ b/starmath/source/mathml/mathmlattr.cxx @@ -0,0 +1,165 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <mathmlattr.hxx> + +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> +#include <rtl/math.h> + +#include <cstddef> +#include <string_view> +#include <unordered_map> + +static std::size_t ParseMathMLUnsignedNumber(std::u16string_view rStr, Fraction& rUN) +{ + auto nLen = rStr.length(); + std::size_t nDecimalPoint = std::u16string_view::npos; + std::size_t nIdx; + sal_Int64 nom = 0; + sal_Int64 den = 1; + bool validNomDen = true; + for (nIdx = 0; nIdx < nLen; nIdx++) + { + auto cD = rStr[nIdx]; + if (cD == u'.') + { + if (nDecimalPoint != std::u16string_view::npos) + return std::u16string_view::npos; + nDecimalPoint = nIdx; + continue; + } + if (cD < u'0' || u'9' < cD) + break; + if (validNomDen + && (o3tl::checked_multiply(nom, sal_Int64(10), nom) + || o3tl::checked_add(nom, sal_Int64(cD - u'0'), nom) + || nom >= std::numeric_limits<sal_Int32>::max() + || (nDecimalPoint != std::u16string_view::npos + && o3tl::checked_multiply(den, sal_Int64(10), den)))) + { + validNomDen = false; + } + } + if (nIdx == 0 || (nIdx == 1 && nDecimalPoint == 0)) + return std::u16string_view::npos; + + // If the input "xx.yyy" can be represented with nom = xx*10^n + yyy and den = 10^n in sal_Int64 + // (where n is the length of "yyy"), then use that to create an accurate Fraction (and TODO: we + // could even ignore trailing "0" characters in "yyy", for a smaller n and thus a greater chance + // of validNomDen); if not, use the less accurate approach of creating a Fraction from double: + if (validNomDen) + { + rUN = Fraction(nom, den); + } + else + { + rUN = Fraction( + rtl_math_uStringToDouble(rStr.data(), rStr.data() + nIdx, '.', 0, nullptr, nullptr)); + } + + return nIdx; +} + +static std::size_t ParseMathMLNumber(std::u16string_view rStr, Fraction& rN) +{ + if (rStr.empty()) + return std::u16string_view::npos; + bool bNegative = (rStr[0] == '-'); + std::size_t nOffset = bNegative ? 1 : 0; + auto nIdx = ParseMathMLUnsignedNumber(rStr.substr(nOffset), rN); + if (nIdx == std::u16string_view::npos || !rN.IsValid()) + return std::u16string_view::npos; + if (bNegative) + rN *= -1; + return nOffset + nIdx; +} + +bool ParseMathMLAttributeLengthValue(std::u16string_view rStr, MathMLAttributeLengthValue& rV) +{ + auto nIdx = ParseMathMLNumber(rStr, rV.aNumber); + if (nIdx == std::u16string_view::npos) + return false; + std::u16string_view sRest = rStr.substr(nIdx); + if (sRest.empty()) + { + rV.eUnit = MathMLLengthUnit::None; + } + if (o3tl::starts_with(sRest, u"em")) + { + rV.eUnit = MathMLLengthUnit::Em; + } + if (o3tl::starts_with(sRest, u"ex")) + { + rV.eUnit = MathMLLengthUnit::Ex; + } + if (o3tl::starts_with(sRest, u"px")) + { + rV.eUnit = MathMLLengthUnit::Px; + } + if (o3tl::starts_with(sRest, u"in")) + { + rV.eUnit = MathMLLengthUnit::In; + } + if (o3tl::starts_with(sRest, u"cm")) + { + rV.eUnit = MathMLLengthUnit::Cm; + } + if (o3tl::starts_with(sRest, u"mm")) + { + rV.eUnit = MathMLLengthUnit::Mm; + } + if (o3tl::starts_with(sRest, u"pt")) + { + rV.eUnit = MathMLLengthUnit::Pt; + } + if (o3tl::starts_with(sRest, u"pc")) + { + rV.eUnit = MathMLLengthUnit::Pc; + } + if (sRest[0] == u'%') + { + rV.eUnit = MathMLLengthUnit::Percent; + } + return true; +} + +bool GetMathMLMathvariantValue(const OUString& rStr, MathMLMathvariantValue& rV) +{ + static const std::unordered_map<OUString, MathMLMathvariantValue> aMap{ + { "normal", MathMLMathvariantValue::Normal }, + { "bold", MathMLMathvariantValue::Bold }, + { "italic", MathMLMathvariantValue::Italic }, + { "bold-italic", MathMLMathvariantValue::BoldItalic }, + { "double-struck", MathMLMathvariantValue::DoubleStruck }, + { "bold-fraktur", MathMLMathvariantValue::BoldFraktur }, + { "script", MathMLMathvariantValue::Script }, + { "bold-script", MathMLMathvariantValue::BoldScript }, + { "fraktur", MathMLMathvariantValue::Fraktur }, + { "sans-serif", MathMLMathvariantValue::SansSerif }, + { "bold-sans-serif", MathMLMathvariantValue::BoldSansSerif }, + { "sans-serif-italic", MathMLMathvariantValue::SansSerifItalic }, + { "sans-serif-bold-italic", MathMLMathvariantValue::SansSerifBoldItalic }, + { "monospace", MathMLMathvariantValue::Monospace }, + { "initial", MathMLMathvariantValue::Initial }, + { "tailed", MathMLMathvariantValue::Tailed }, + { "looped", MathMLMathvariantValue::Looped }, + { "stretched", MathMLMathvariantValue::Stretched } + }; + + auto it = aMap.find(rStr); + if (it != aMap.end()) + { + rV = it->second; + return true; + } + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/starmath/source/mathml/mathmlexport.cxx b/starmath/source/mathml/mathmlexport.cxx new file mode 100644 index 000000000..187dd1953 --- /dev/null +++ b/starmath/source/mathml/mathmlexport.cxx @@ -0,0 +1,1457 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +/* + Warning: The SvXMLElementExport helper class creates the beginning and + closing tags of xml elements in its constructor and destructor, so there's + hidden stuff going on, on occasion the ordering of these classes declarations + may be significant +*/ + +#include <com/sun/star/xml/sax/Writer.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/util/MeasureUnit.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/uno/Any.h> + +#include <officecfg/Office/Common.hxx> +#include <rtl/math.hxx> +#include <sfx2/frame.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/sfxsids.hrc> +#include <osl/diagnose.h> +#include <sot/storage.hxx> +#include <svl/itemset.hxx> +#include <svl/stritem.hxx> +#include <comphelper/fileformat.h> +#include <comphelper/processfactory.hxx> +#include <unotools/streamwrap.hxx> +#include <sax/tools/converter.hxx> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/namespacemap.hxx> +#include <xmloff/attrlist.hxx> +#include <comphelper/genericpropertyset.hxx> +#include <comphelper/servicehelper.hxx> +#include <comphelper/propertysetinfo.hxx> +#include <tools/diagnose_ex.h> +#include <sal/log.hxx> + +#include <stack> + +#include <mathmlexport.hxx> +#include <xparsmlbase.hxx> +#include <strings.hrc> +#include <smmod.hxx> +#include <unomodel.hxx> +#include <document.hxx> +#include <utility.hxx> +#include <cfgitem.hxx> +#include <starmathdatabase.hxx> + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star; +using namespace ::xmloff::token; + +namespace +{ +bool IsInPrivateUseArea(sal_Unicode cChar) { return 0xE000 <= cChar && cChar <= 0xF8FF; } + +sal_Unicode ConvertMathToMathML(sal_Unicode cChar) +{ + sal_Unicode cRes = cChar; + if (IsInPrivateUseArea(cChar)) + { + SAL_WARN("starmath", "Error: private use area characters should no longer be in use!"); + cRes = u'@'; // just some character that should easily be notice as odd in the context + } + return cRes; +} +} + +bool SmXMLExportWrapper::Export(SfxMedium& rMedium) +{ + bool bRet = true; + uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext()); + + //Get model + uno::Reference<lang::XComponent> xModelComp = xModel; + + bool bEmbedded = false; + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel); + + SmDocShell* pDocShell = pModel ? static_cast<SmDocShell*>(pModel->GetObjectShell()) : nullptr; + if (pDocShell && SfxObjectCreateMode::EMBEDDED == pDocShell->GetCreateMode()) + bEmbedded = true; + + uno::Reference<task::XStatusIndicator> xStatusIndicator; + if (!bEmbedded) + { + if (pDocShell /*&& pDocShell->GetMedium()*/) + { + OSL_ENSURE(pDocShell->GetMedium() == &rMedium, "different SfxMedium found"); + + SfxItemSet* pSet = rMedium.GetItemSet(); + if (pSet) + { + const SfxUnoAnyItem* pItem = pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL); + if (pItem) + pItem->GetValue() >>= xStatusIndicator; + } + } + + // set progress range and start status indicator + if (xStatusIndicator.is()) + { + sal_Int32 nProgressRange = bFlat ? 1 : 3; + xStatusIndicator->start(SmResId(STR_STATSTR_WRITING), nProgressRange); + } + } + + static constexpr OUStringLiteral sUsePrettyPrinting(u"UsePrettyPrinting"); + static constexpr OUStringLiteral sBaseURI(u"BaseURI"); + static constexpr OUStringLiteral sStreamRelPath(u"StreamRelPath"); + static constexpr OUStringLiteral sStreamName(u"StreamName"); + + // create XPropertySet with three properties for status indicator + static const comphelper::PropertyMapEntry aInfoMap[] = { + { sUsePrettyPrinting, 0, cppu::UnoType<bool>::get(), beans::PropertyAttribute::MAYBEVOID, + 0 }, + { sBaseURI, 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 }, + { sStreamRelPath, 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, + 0 }, + { sStreamName, 0, ::cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID, 0 } + }; + uno::Reference<beans::XPropertySet> xInfoSet( + comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap))); + + bool bUsePrettyPrinting + = bFlat || officecfg::Office::Common::Save::Document::PrettyPrinting::get(); + xInfoSet->setPropertyValue(sUsePrettyPrinting, Any(bUsePrettyPrinting)); + + // Set base URI + xInfoSet->setPropertyValue(sBaseURI, Any(rMedium.GetBaseURL(true))); + + sal_Int32 nSteps = 0; + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + if (!bFlat) //Storage (Package) of Stream + { + uno::Reference<embed::XStorage> xStg = rMedium.GetOutputStorage(); + bool bOASIS = (SotStorage::GetVersion(xStg) > SOFFICE_FILEFORMAT_60); + + // TODO/LATER: handle the case of embedded links gracefully + if (bEmbedded) //&& !pStg->IsRoot() ) + { + OUString aName; + if (rMedium.GetItemSet()) + { + const SfxStringItem* pDocHierarchItem + = rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME); + if (pDocHierarchItem) + aName = pDocHierarchItem->GetValue(); + } + + if (!aName.isEmpty()) + { + xInfoSet->setPropertyValue(sStreamRelPath, Any(aName)); + } + } + + if (!bEmbedded) + { + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + bRet = WriteThroughComponent(xStg, xModelComp, "meta.xml", xContext, xInfoSet, + (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaExporter" + : "com.sun.star.comp.Math.XMLMetaExporter")); + } + if (bRet) + { + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + bRet = WriteThroughComponent(xStg, xModelComp, "content.xml", xContext, xInfoSet, + "com.sun.star.comp.Math.XMLContentExporter"); + } + + if (bRet) + { + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + bRet = WriteThroughComponent(xStg, xModelComp, "settings.xml", xContext, xInfoSet, + (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsExporter" + : "com.sun.star.comp.Math.XMLSettingsExporter")); + } + } + else + { + SvStream* pStream = rMedium.GetOutStream(); + uno::Reference<io::XOutputStream> xOut(new utl::OOutputStreamWrapper(*pStream)); + + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + bRet = WriteThroughComponent(xOut, xModelComp, xContext, xInfoSet, + "com.sun.star.comp.Math.XMLContentExporter"); + } + + if (xStatusIndicator.is()) + xStatusIndicator->end(); + + return bRet; +} + +/// export through an XML exporter component (output stream version) +bool SmXMLExportWrapper::WriteThroughComponent(const Reference<io::XOutputStream>& xOutputStream, + const Reference<XComponent>& xComponent, + Reference<uno::XComponentContext> const& rxContext, + Reference<beans::XPropertySet> const& rPropSet, + const char* pComponentName) +{ + OSL_ENSURE(xOutputStream.is(), "I really need an output stream!"); + OSL_ENSURE(xComponent.is(), "Need component!"); + OSL_ENSURE(nullptr != pComponentName, "Need component name!"); + + // get component + Reference<xml::sax::XWriter> xSaxWriter = xml::sax::Writer::create(rxContext); + + // connect XML writer to output stream + xSaxWriter->setOutputStream(xOutputStream); + if (m_bUseHTMLMLEntities) + xSaxWriter->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntitiesExport); + + // prepare arguments (prepend doc handler to given arguments) + Sequence<Any> aArgs{ Any(xSaxWriter), Any(rPropSet) }; + + // get filter component + Reference<document::XExporter> xExporter( + rxContext->getServiceManager()->createInstanceWithArgumentsAndContext( + OUString::createFromAscii(pComponentName), aArgs, rxContext), + UNO_QUERY); + OSL_ENSURE(xExporter.is(), "can't instantiate export filter component"); + if (!xExporter.is()) + return false; + + // connect model and filter + xExporter->setSourceDocument(xComponent); + + // filter! + Reference<XFilter> xFilter(xExporter, UNO_QUERY); + uno::Sequence<PropertyValue> aProps(0); + xFilter->filter(aProps); + + auto pFilter = comphelper::getFromUnoTunnel<SmXMLExport>(xFilter); + return pFilter == nullptr || pFilter->GetSuccess(); +} + +/// export through an XML exporter component (storage version) +bool SmXMLExportWrapper::WriteThroughComponent(const Reference<embed::XStorage>& xStorage, + const Reference<XComponent>& xComponent, + const char* pStreamName, + Reference<uno::XComponentContext> const& rxContext, + Reference<beans::XPropertySet> const& rPropSet, + const char* pComponentName) +{ + OSL_ENSURE(xStorage.is(), "Need storage!"); + OSL_ENSURE(nullptr != pStreamName, "Need stream name!"); + + // open stream + Reference<io::XStream> xStream; + OUString sStreamName = OUString::createFromAscii(pStreamName); + try + { + xStream = xStorage->openStreamElement(sStreamName, embed::ElementModes::READWRITE + | embed::ElementModes::TRUNCATE); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("starmath", "Can't create output stream in package"); + return false; + } + + uno::Reference<beans::XPropertySet> xSet(xStream, uno::UNO_QUERY); + static const OUStringLiteral sMediaType = u"MediaType"; + static const OUStringLiteral sTextXml = u"text/xml"; + xSet->setPropertyValue(sMediaType, Any(OUString(sTextXml))); + + // all streams must be encrypted in encrypted document + static const OUStringLiteral sUseCommonStoragePasswordEncryption + = u"UseCommonStoragePasswordEncryption"; + xSet->setPropertyValue(sUseCommonStoragePasswordEncryption, Any(true)); + + // set Base URL + if (rPropSet.is()) + { + rPropSet->setPropertyValue("StreamName", Any(sStreamName)); + } + + // write the stuff + bool bRet = WriteThroughComponent(xStream->getOutputStream(), xComponent, rxContext, rPropSet, + pComponentName); + + return bRet; +} + +SmXMLExport::SmXMLExport(const css::uno::Reference<css::uno::XComponentContext>& rContext, + OUString const& implementationName, SvXMLExportFlags nExportFlags) + : SvXMLExport(rContext, implementationName, util::MeasureUnit::INCH, XML_MATH, nExportFlags) + , pTree(nullptr) + , bSuccess(false) +{ +} + +sal_Int64 SAL_CALL SmXMLExport::getSomething(const uno::Sequence<sal_Int8>& rId) +{ + return comphelper::getSomethingImpl(rId, this, + comphelper::FallbackToGetSomethingOf<SvXMLExport>{}); +} + +const uno::Sequence<sal_Int8>& SmXMLExport::getUnoTunnelId() noexcept +{ + static const comphelper::UnoIdInit theSmXMLExportUnoTunnelId; + return theSmXMLExportUnoTunnelId.getSeq(); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +Math_XMLExporter_get_implementation(css::uno::XComponentContext* context, + css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new SmXMLExport(context, "com.sun.star.comp.Math.XMLExporter", + SvXMLExportFlags::OASIS | SvXMLExportFlags::ALL)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +Math_XMLMetaExporter_get_implementation(css::uno::XComponentContext* context, + css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire( + new SmXMLExport(context, "com.sun.star.comp.Math.XMLMetaExporter", SvXMLExportFlags::META)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +Math_XMLOasisMetaExporter_get_implementation(css::uno::XComponentContext* context, + css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new SmXMLExport(context, "com.sun.star.comp.Math.XMLOasisMetaExporter", + SvXMLExportFlags::OASIS | SvXMLExportFlags::META)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +Math_XMLSettingsExporter_get_implementation(css::uno::XComponentContext* context, + css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new SmXMLExport(context, "com.sun.star.comp.Math.XMLSettingsExporter", + SvXMLExportFlags::SETTINGS)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +Math_XMLOasisSettingsExporter_get_implementation(css::uno::XComponentContext* context, + css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new SmXMLExport(context, "com.sun.star.comp.Math.XMLOasisSettingsExporter", + SvXMLExportFlags::OASIS | SvXMLExportFlags::SETTINGS)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +Math_XMLContentExporter_get_implementation(css::uno::XComponentContext* context, + css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new SmXMLExport(context, "com.sun.star.comp.Math.XMLContentExporter", + SvXMLExportFlags::OASIS | SvXMLExportFlags::CONTENT)); +} + +ErrCode SmXMLExport::exportDoc(enum XMLTokenEnum eClass) +{ + if (!(getExportFlags() & SvXMLExportFlags::CONTENT)) + { + SvXMLExport::exportDoc(eClass); + } + else + { + uno::Reference<frame::XModel> xModel = GetModel(); + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel); + + if (pModel) + { + SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell()); + pTree = pDocShell->GetFormulaTree(); + aText = pDocShell->GetText(); + } + + GetDocHandler()->startDocument(); + + addChaffWhenEncryptedStorage(); + + /*Add xmlns line*/ + SvXMLAttributeList& rList = GetAttrList(); + + // make use of a default namespace + ResetNamespaceMap(); // Math doesn't need namespaces from xmloff, since it now uses default namespaces (because that is common with current MathML usage in the web) + GetNamespaceMap_().Add(OUString(), GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH); + + rList.AddAttribute(GetNamespaceMap().GetAttrNameByKey(XML_NAMESPACE_MATH), + GetNamespaceMap().GetNameByKey(XML_NAMESPACE_MATH)); + + //I think we need something like ImplExportEntities(); + ExportContent_(); + GetDocHandler()->endDocument(); + } + + bSuccess = true; + return ERRCODE_NONE; +} + +void SmXMLExport::ExportContent_() +{ + uno::Reference<frame::XModel> xModel = GetModel(); + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel); + SmDocShell* pDocShell = pModel ? static_cast<SmDocShell*>(pModel->GetObjectShell()) : nullptr; + OSL_ENSURE(pDocShell, "doc shell missing"); + + if (pDocShell && !pDocShell->GetFormat().IsTextmode()) + { + // If the Math equation is not in text mode, we attach a display="block" + // attribute on the <math> root. We don't do anything if it is in + // text mode, the default display="inline" value will be used. + AddAttribute(XML_NAMESPACE_MATH, XML_DISPLAY, XML_BLOCK); + } + SvXMLElementExport aEquation(*this, XML_NAMESPACE_MATH, XML_MATH, true, true); + std::unique_ptr<SvXMLElementExport> pSemantics; + + if (!aText.isEmpty()) + { + pSemantics.reset( + new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_SEMANTICS, true, true)); + } + + ExportNodes(pTree, 0); + + if (aText.isEmpty()) + return; + + SmModule* pMod = SM_MOD(); + sal_uInt16 nSmSyntaxVersion = pMod->GetConfig()->GetDefaultSmSyntaxVersion(); + + // Convert symbol names + if (pDocShell) + { + nSmSyntaxVersion = pDocShell->GetSmSyntaxVersion(); + AbstractSmParser* rParser = pDocShell->GetParser(); + bool bVal = rParser->IsExportSymbolNames(); + rParser->SetExportSymbolNames(true); + auto pTmpTree = rParser->Parse(aText); + aText = rParser->GetText(); + pTmpTree.reset(); + rParser->SetExportSymbolNames(bVal); + } + + OUStringBuffer sStrBuf(12); + sStrBuf.append(u"StarMath "); + if (nSmSyntaxVersion == 5) + sStrBuf.append(u"5.0"); + else + sStrBuf.append(static_cast<sal_Int32>(nSmSyntaxVersion)); + + AddAttribute(XML_NAMESPACE_MATH, XML_ENCODING, sStrBuf.makeStringAndClear()); + SvXMLElementExport aAnnotation(*this, XML_NAMESPACE_MATH, XML_ANNOTATION, true, false); + GetDocHandler()->characters(aText); +} + +void SmXMLExport::GetViewSettings(Sequence<PropertyValue>& aProps) +{ + uno::Reference<frame::XModel> xModel = GetModel(); + if (!xModel.is()) + return; + + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel); + + if (!pModel) + return; + + SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell()); + if (!pDocShell) + return; + + aProps.realloc(4); + PropertyValue* pValue = aProps.getArray(); + sal_Int32 nIndex = 0; + + tools::Rectangle aRect(pDocShell->GetVisArea()); + + pValue[nIndex].Name = "ViewAreaTop"; + pValue[nIndex++].Value <<= aRect.Top(); + + pValue[nIndex].Name = "ViewAreaLeft"; + pValue[nIndex++].Value <<= aRect.Left(); + + pValue[nIndex].Name = "ViewAreaWidth"; + pValue[nIndex++].Value <<= aRect.GetWidth(); + + pValue[nIndex].Name = "ViewAreaHeight"; + pValue[nIndex++].Value <<= aRect.GetHeight(); +} + +void SmXMLExport::GetConfigurationSettings(Sequence<PropertyValue>& rProps) +{ + Reference<XPropertySet> xProps(GetModel(), UNO_QUERY); + if (!xProps.is()) + return; + + Reference<XPropertySetInfo> xPropertySetInfo = xProps->getPropertySetInfo(); + if (!xPropertySetInfo.is()) + return; + + const Sequence<Property> aProps = xPropertySetInfo->getProperties(); + const sal_Int32 nCount = aProps.getLength(); + if (!nCount) + return; + + rProps.realloc(nCount); + SmMathConfig* pConfig = SM_MOD()->GetConfig(); + const bool bUsedSymbolsOnly = pConfig && pConfig->IsSaveOnlyUsedSymbols(); + + std::transform(aProps.begin(), aProps.end(), rProps.getArray(), + [bUsedSymbolsOnly, &xProps](const Property& prop) { + PropertyValue aRet; + if (prop.Name != "Formula" && prop.Name != "BasicLibraries" + && prop.Name != "DialogLibraries" && prop.Name != "RuntimeUID") + { + aRet.Name = prop.Name; + OUString aActualName(prop.Name); + // handle 'save used symbols only' + static constexpr OUStringLiteral sUserDefinedSymbolsInUse + = u"UserDefinedSymbolsInUse"; + if (bUsedSymbolsOnly && prop.Name == "Symbols") + aActualName = sUserDefinedSymbolsInUse; + aRet.Value = xProps->getPropertyValue(aActualName); + } + return aRet; + }); +} + +void SmXMLExport::ExportLine(const SmNode* pNode, int nLevel) { ExportExpression(pNode, nLevel); } + +void SmXMLExport::ExportBinaryHorizontal(const SmNode* pNode, int nLevel) +{ + TG nGroup = pNode->GetToken().nGroup; + + SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MROW, true, true); + + // Unfold the binary tree structure as long as the nodes are SmBinHorNode + // with the same nGroup. This will reduce the number of nested <mrow> + // elements e.g. we only need three <mrow> levels to export + + // "a*b*c*d+e*f*g*h+i*j*k*l = a*b*c*d+e*f*g*h+i*j*k*l = + // a*b*c*d+e*f*g*h+i*j*k*l = a*b*c*d+e*f*g*h+i*j*k*l" + + // See https://www.libreoffice.org/bugzilla/show_bug.cgi?id=66081 + ::std::stack<const SmNode*> s; + s.push(pNode); + while (!s.empty()) + { + const SmNode* node = s.top(); + s.pop(); + if (node->GetType() != SmNodeType::BinHor || node->GetToken().nGroup != nGroup) + { + ExportNodes(node, nLevel + 1); + continue; + } + const SmBinHorNode* binNode = static_cast<const SmBinHorNode*>(node); + s.push(binNode->RightOperand()); + s.push(binNode->Symbol()); + s.push(binNode->LeftOperand()); + } +} + +void SmXMLExport::ExportUnaryHorizontal(const SmNode* pNode, int nLevel) +{ + ExportExpression(pNode, nLevel); +} + +void SmXMLExport::ExportExpression(const SmNode* pNode, int nLevel, + bool bNoMrowContainer /*=false*/) +{ + std::unique_ptr<SvXMLElementExport> pRow; + size_t nSize = pNode->GetNumSubNodes(); + + // #i115443: nodes of type expression always need to be grouped with mrow statement + if (!bNoMrowContainer && (nSize > 1 || pNode->GetType() == SmNodeType::Expression)) + pRow.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW, true, true)); + + for (size_t i = 0; i < nSize; ++i) + { + if (const SmNode* pTemp = pNode->GetSubNode(i)) + ExportNodes(pTemp, nLevel + 1); + } +} + +void SmXMLExport::ExportBinaryVertical(const SmNode* pNode, int nLevel) +{ + assert(pNode->GetNumSubNodes() == 3); + const SmNode* pNum = pNode->GetSubNode(0); + const SmNode* pDenom = pNode->GetSubNode(2); + if (pNum->GetType() == SmNodeType::Align && pNum->GetToken().eType != TALIGNC) + { + // A left or right alignment is specified on the numerator: + // attach the corresponding numalign attribute. + AddAttribute(XML_NAMESPACE_MATH, XML_NUMALIGN, + pNum->GetToken().eType == TALIGNL ? XML_LEFT : XML_RIGHT); + } + if (pDenom->GetType() == SmNodeType::Align && pDenom->GetToken().eType != TALIGNC) + { + // A left or right alignment is specified on the denominator: + // attach the corresponding denomalign attribute. + AddAttribute(XML_NAMESPACE_MATH, XML_DENOMALIGN, + pDenom->GetToken().eType == TALIGNL ? XML_LEFT : XML_RIGHT); + } + SvXMLElementExport aFraction(*this, XML_NAMESPACE_MATH, XML_MFRAC, true, true); + ExportNodes(pNum, nLevel); + ExportNodes(pDenom, nLevel); +} + +void SmXMLExport::ExportBinaryDiagonal(const SmNode* pNode, int nLevel) +{ + assert(pNode->GetNumSubNodes() == 3); + + if (pNode->GetToken().eType == TWIDESLASH) + { + // wideslash + // export the node as <mfrac bevelled="true"> + AddAttribute(XML_NAMESPACE_MATH, XML_BEVELLED, XML_TRUE); + SvXMLElementExport aFraction(*this, XML_NAMESPACE_MATH, XML_MFRAC, true, true); + ExportNodes(pNode->GetSubNode(0), nLevel); + ExportNodes(pNode->GetSubNode(1), nLevel); + } + else + { + // widebslash + // We can not use <mfrac> to a backslash, so just use <mo>\</mo> + SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MROW, true, true); + + ExportNodes(pNode->GetSubNode(0), nLevel); + + { // Scoping for <mo> creation + SvXMLElementExport aMo(*this, XML_NAMESPACE_MATH, XML_MO, true, true); + GetDocHandler()->characters(OUStringChar(MS_BACKSLASH)); + } + + ExportNodes(pNode->GetSubNode(1), nLevel); + } +} + +void SmXMLExport::ExportTable(const SmNode* pNode, int nLevel) +{ + std::unique_ptr<SvXMLElementExport> pTable; + + size_t nSize = pNode->GetNumSubNodes(); + + //If the list ends in newline then the last entry has + //no subnodes, the newline is superfluous so we just drop + //the last node, inclusion would create a bad MathML + //table + if (nSize >= 1) + { + const SmNode* pLine = pNode->GetSubNode(nSize - 1); + if (pLine->GetType() == SmNodeType::Line && pLine->GetNumSubNodes() == 1 + && pLine->GetSubNode(0) != nullptr + && pLine->GetSubNode(0)->GetToken().eType == TNEWLINE) + --nSize; + } + + // try to avoid creating a mtable element when the formula consists only + // of a single output line + if (nLevel || (nSize > 1)) + pTable.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTABLE, true, true)); + + for (size_t i = 0; i < nSize; ++i) + { + if (const SmNode* pTemp = pNode->GetSubNode(i)) + { + std::unique_ptr<SvXMLElementExport> pRow; + std::unique_ptr<SvXMLElementExport> pCell; + if (pTable) + { + pRow.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTR, true, true)); + SmTokenType eAlign = TALIGNC; + if (pTemp->GetType() == SmNodeType::Align) + { + // For Binom() and Stack() constructions, the SmNodeType::Align nodes + // are direct children. + // binom{alignl ...}{alignr ...} and + // stack{alignl ... ## alignr ... ## ...} + eAlign = pTemp->GetToken().eType; + } + else if (pTemp->GetType() == SmNodeType::Line && pTemp->GetNumSubNodes() == 1 + && pTemp->GetSubNode(0) + && pTemp->GetSubNode(0)->GetType() == SmNodeType::Align) + { + // For the Table() construction, the SmNodeType::Align node is a child + // of an SmNodeType::Line node. + // alignl ... newline alignr ... newline ... + eAlign = pTemp->GetSubNode(0)->GetToken().eType; + } + if (eAlign != TALIGNC) + { + // If a left or right alignment is specified on this line, + // attach the corresponding columnalign attribute. + AddAttribute(XML_NAMESPACE_MATH, XML_COLUMNALIGN, + eAlign == TALIGNL ? XML_LEFT : XML_RIGHT); + } + pCell.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTD, true, true)); + } + ExportNodes(pTemp, nLevel + 1); + } + } +} + +void SmXMLExport::ExportMath(const SmNode* pNode) +{ + const SmTextNode* pTemp = static_cast<const SmTextNode*>(pNode); + std::unique_ptr<SvXMLElementExport> pMath; + + if (pNode->GetType() == SmNodeType::Math || pNode->GetType() == SmNodeType::GlyphSpecial) + { + // Export SmNodeType::Math and SmNodeType::GlyphSpecial symbols as <mo> elements + pMath.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MO, true, false)); + } + else if (pNode->GetType() == SmNodeType::Special) + { + bool bIsItalic = IsItalic(pNode->GetFont()); + if (!bIsItalic) + AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_NORMAL); + pMath.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI, true, false)); + } + else + { + // Export SmNodeType::MathIdent and SmNodeType::Place symbols as <mi> elements: + // - These math symbols should not be drawn slanted. Hence we should + // attach a mathvariant="normal" attribute to single-char <mi> elements + // that are not mathematical alphanumeric symbol. For simplicity and to + // work around browser limitations, we always attach such an attribute. + // - The MathML specification suggests to use empty <mi> elements as + // placeholders but they won't be visible in most MathML rendering + // engines so let's use an empty square for SmNodeType::Place instead. + AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_NORMAL); + pMath.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI, true, false)); + } + sal_Unicode nArse = pTemp->GetText()[0]; + sal_Unicode cTmp = ConvertMathToMathML(nArse); + if (cTmp != 0) + nArse = cTmp; + OSL_ENSURE(nArse != 0xffff, "Non existent symbol"); + GetDocHandler()->characters(OUString(nArse)); +} + +void SmXMLExport::ExportText(const SmNode* pNode) +{ + std::unique_ptr<SvXMLElementExport> pText; + const SmTextNode* pTemp = static_cast<const SmTextNode*>(pNode); + switch (pNode->GetToken().eType) + { + default: + case TIDENT: + { + //Note that we change the fontstyle to italic for strings that + //are italic and longer than a single character. + bool bIsItalic = IsItalic(pTemp->GetFont()); + if ((pTemp->GetText().getLength() > 1) && bIsItalic) + AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_ITALIC); + else if ((pTemp->GetText().getLength() == 1) && !bIsItalic) + AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_NORMAL); + pText.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI, true, false)); + break; + } + case TNUMBER: + pText.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MN, true, false)); + break; + case TTEXT: + pText.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTEXT, true, false)); + break; + } + GetDocHandler()->characters(pTemp->GetText()); +} + +void SmXMLExport::ExportBlank(const SmNode* pNode) +{ + const SmBlankNode* pTemp = static_cast<const SmBlankNode*>(pNode); + //!! exports an <mspace> element. Note that for example "~_~" is allowed in + //!! Math (so it has no sense at all) but must not result in an empty + //!! <msub> tag in MathML !! + + if (pTemp->GetBlankNum() != 0) + { + // Attach a width attribute. We choose the (somewhat arbitrary) values + // ".5em" for a small gap '`' and "2em" for a large gap '~'. + // (see SmBlankNode::IncreaseBy for how pTemp->mnNum is set). + OUStringBuffer sStrBuf; + ::sax::Converter::convertDouble(sStrBuf, pTemp->GetBlankNum() * .5); + sStrBuf.append("em"); + AddAttribute(XML_NAMESPACE_MATH, XML_WIDTH, sStrBuf.makeStringAndClear()); + } + + SvXMLElementExport aTextExport(*this, XML_NAMESPACE_MATH, XML_MSPACE, true, false); + + GetDocHandler()->characters(OUString()); +} + +void SmXMLExport::ExportSubSupScript(const SmNode* pNode, int nLevel) +{ + const SmNode* pSub = nullptr; + const SmNode* pSup = nullptr; + const SmNode* pCSub = nullptr; + const SmNode* pCSup = nullptr; + const SmNode* pLSub = nullptr; + const SmNode* pLSup = nullptr; + std::unique_ptr<SvXMLElementExport> pThing2; + + //if we have prescripts at all then we must use the tensor notation + + //This is one of those excellent locations where scope is vital to + //arrange the construction and destruction of the element helper + //classes correctly + pLSub = pNode->GetSubNode(LSUB + 1); + pLSup = pNode->GetSubNode(LSUP + 1); + if (pLSub || pLSup) + { + SvXMLElementExport aMultiScripts(*this, XML_NAMESPACE_MATH, XML_MMULTISCRIPTS, true, true); + + if (nullptr != (pCSub = pNode->GetSubNode(CSUB + 1)) + && nullptr != (pCSup = pNode->GetSubNode(CSUP + 1))) + { + pThing2.reset( + new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDEROVER, true, true)); + } + else if (nullptr != (pCSub = pNode->GetSubNode(CSUB + 1))) + { + pThing2.reset( + new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDER, true, true)); + } + else if (nullptr != (pCSup = pNode->GetSubNode(CSUP + 1))) + { + pThing2.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MOVER, true, true)); + } + + ExportNodes(pNode->GetSubNode(0), nLevel + 1); //Main Term + + if (pCSub) + ExportNodes(pCSub, nLevel + 1); + if (pCSup) + ExportNodes(pCSup, nLevel + 1); + pThing2.reset(); + + pSub = pNode->GetSubNode(RSUB + 1); + pSup = pNode->GetSubNode(RSUP + 1); + if (pSub || pSup) + { + if (pSub) + ExportNodes(pSub, nLevel + 1); + else + { + SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE, true, true); + } + if (pSup) + ExportNodes(pSup, nLevel + 1); + else + { + SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE, true, true); + } + } + + //Separator element between suffix and prefix sub/sup pairs + { + SvXMLElementExport aPrescripts(*this, XML_NAMESPACE_MATH, XML_MPRESCRIPTS, true, true); + } + + if (pLSub) + ExportNodes(pLSub, nLevel + 1); + else + { + SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE, true, true); + } + if (pLSup) + ExportNodes(pLSup, nLevel + 1); + else + { + SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE, true, true); + } + } + else + { + std::unique_ptr<SvXMLElementExport> pThing; + if (nullptr != (pSub = pNode->GetSubNode(RSUB + 1)) + && nullptr != (pSup = pNode->GetSubNode(RSUP + 1))) + { + pThing.reset( + new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUBSUP, true, true)); + } + else if (nullptr != (pSub = pNode->GetSubNode(RSUB + 1))) + { + pThing.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUB, true, true)); + } + else if (nullptr != (pSup = pNode->GetSubNode(RSUP + 1))) + { + pThing.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUP, true, true)); + } + + if (nullptr != (pCSub = pNode->GetSubNode(CSUB + 1)) + && nullptr != (pCSup = pNode->GetSubNode(CSUP + 1))) + { + pThing2.reset( + new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDEROVER, true, true)); + } + else if (nullptr != (pCSub = pNode->GetSubNode(CSUB + 1))) + { + pThing2.reset( + new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDER, true, true)); + } + else if (nullptr != (pCSup = pNode->GetSubNode(CSUP + 1))) + { + pThing2.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MOVER, true, true)); + } + ExportNodes(pNode->GetSubNode(0), nLevel + 1); //Main Term + + if (pCSub) + ExportNodes(pCSub, nLevel + 1); + if (pCSup) + ExportNodes(pCSup, nLevel + 1); + pThing2.reset(); + + if (pSub) + ExportNodes(pSub, nLevel + 1); + if (pSup) + ExportNodes(pSup, nLevel + 1); + pThing.reset(); + } +} + +void SmXMLExport::ExportBrace(const SmNode* pNode, int nLevel) +{ + const SmNode* pTemp; + const SmNode* pLeft = pNode->GetSubNode(0); + const SmNode* pRight = pNode->GetSubNode(2); + + // This used to generate <mfenced> or <mrow>+<mo> elements according to + // the stretchiness of fences. The MathML recommendation defines an + // <mrow>+<mo> construction that is equivalent to the <mfenced> element: + // http://www.w3.org/TR/MathML3/chapter3.html#presm.mfenced + // To simplify our code and avoid issues with mfenced implementations in + // MathML rendering engines, we now always generate <mrow>+<mo> elements. + // See #fdo 66282. + + // <mrow> + SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MROW, true, true); + + // <mo fence="true"> opening-fence </mo> + if (pLeft && (pLeft->GetToken().eType != TNONE)) + { + AddAttribute(XML_NAMESPACE_MATH, XML_FENCE, XML_TRUE); + AddAttribute(XML_NAMESPACE_MATH, XML_FORM, XML_PREFIX); + if (pNode->GetScaleMode() == SmScaleMode::Height) + AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE); + else + AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE); + ExportNodes(pLeft, nLevel + 1); + } + + if (nullptr != (pTemp = pNode->GetSubNode(1))) + { + // <mrow> + SvXMLElementExport aRowExport(*this, XML_NAMESPACE_MATH, XML_MROW, true, true); + ExportNodes(pTemp, nLevel + 1); + // </mrow> + } + + // <mo fence="true"> closing-fence </mo> + if (pRight && (pRight->GetToken().eType != TNONE)) + { + AddAttribute(XML_NAMESPACE_MATH, XML_FENCE, XML_TRUE); + AddAttribute(XML_NAMESPACE_MATH, XML_FORM, XML_POSTFIX); + if (pNode->GetScaleMode() == SmScaleMode::Height) + AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE); + else + AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE); + ExportNodes(pRight, nLevel + 1); + } + + // </mrow> +} + +void SmXMLExport::ExportRoot(const SmNode* pNode, int nLevel) +{ + if (pNode->GetSubNode(0)) + { + SvXMLElementExport aRoot(*this, XML_NAMESPACE_MATH, XML_MROOT, true, true); + ExportNodes(pNode->GetSubNode(2), nLevel + 1); + ExportNodes(pNode->GetSubNode(0), nLevel + 1); + } + else + { + SvXMLElementExport aSqrt(*this, XML_NAMESPACE_MATH, XML_MSQRT, true, true); + ExportNodes(pNode->GetSubNode(2), nLevel + 1); + } +} + +void SmXMLExport::ExportOperator(const SmNode* pNode, int nLevel) +{ + /*we need to either use content or font and size attributes + *here*/ + SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MROW, true, true); + ExportNodes(pNode->GetSubNode(0), nLevel + 1); + ExportNodes(pNode->GetSubNode(1), nLevel + 1); +} + +void SmXMLExport::ExportAttributes(const SmNode* pNode, int nLevel) +{ + std::unique_ptr<SvXMLElementExport> pElement; + + if (pNode->GetToken().eType == TUNDERLINE) + { + AddAttribute(XML_NAMESPACE_MATH, XML_ACCENTUNDER, XML_TRUE); + pElement.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDER, true, true)); + } + else if (pNode->GetToken().eType == TOVERSTRIKE) + { + // export as <menclose notation="horizontalstrike"> + AddAttribute(XML_NAMESPACE_MATH, XML_NOTATION, XML_HORIZONTALSTRIKE); + pElement.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MENCLOSE, true, true)); + } + else + { + AddAttribute(XML_NAMESPACE_MATH, XML_ACCENT, XML_TRUE); + pElement.reset(new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MOVER, true, true)); + } + + ExportNodes(pNode->GetSubNode(1), nLevel + 1); + switch (pNode->GetToken().eType) + { + case TOVERLINE: + { + //proper entity support required + SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO, true, true); + static constexpr OUStringLiteral nArse = u"\u00AF"; + GetDocHandler()->characters(nArse); + } + break; + case TUNDERLINE: + { + //proper entity support required + SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO, true, true); + static constexpr OUStringLiteral nArse = u"\u0332"; + GetDocHandler()->characters(nArse); + } + break; + case TOVERSTRIKE: + break; + case TWIDETILDE: + case TWIDEHAT: + case TWIDEVEC: + case TWIDEHARPOON: + { + // make these wide accents stretchy + AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE); + ExportNodes(pNode->GetSubNode(0), nLevel + 1); + } + break; + default: + ExportNodes(pNode->GetSubNode(0), nLevel + 1); + break; + } +} + +static bool lcl_HasEffectOnMathvariant(const SmTokenType eType) +{ + return eType == TBOLD || eType == TNBOLD || eType == TITALIC || eType == TNITALIC + || eType == TSANS || eType == TSERIF || eType == TFIXED; +} + +void SmXMLExport::ExportFont(const SmNode* pNode, int nLevel) +{ + // gather the mathvariant attribute relevant data from all + // successively following SmFontNodes... + + int nBold = -1; // for the following variables: -1 = yet undefined; 0 = false; 1 = true; + int nItalic = -1; // for the following variables: -1 = yet undefined; 0 = false; 1 = true; + int nSansSerifFixed = -1; + SmTokenType eNodeType = TUNKNOWN; + + for (;;) + { + eNodeType = pNode->GetToken().eType; + if (!lcl_HasEffectOnMathvariant(eNodeType)) + break; + switch (eNodeType) + { + case TBOLD: + nBold = 1; + break; + case TNBOLD: + nBold = 0; + break; + case TITALIC: + nItalic = 1; + break; + case TNITALIC: + nItalic = 0; + break; + case TSANS: + nSansSerifFixed = 0; + break; + case TSERIF: + nSansSerifFixed = 1; + break; + case TFIXED: + nSansSerifFixed = 2; + break; + default: + SAL_WARN("starmath", "unexpected case"); + } + // According to the parser every node that is to be evaluated here + // has a single non-zero subnode at index 1!! Thus we only need to check + // that single node for follow-up nodes that have an effect on the attribute. + if (pNode->GetNumSubNodes() > 1 && pNode->GetSubNode(1) + && lcl_HasEffectOnMathvariant(pNode->GetSubNode(1)->GetToken().eType)) + { + pNode = pNode->GetSubNode(1); + } + else + break; + } + + sal_uInt32 nc; + switch (pNode->GetToken().eType) + { + case TPHANTOM: + // No attribute needed. An <mphantom> element will be used below. + break; + case TMATHMLCOL: + { + nc = pNode->GetToken().cMathChar.toUInt32(16); + const OUString& sssStr = starmathdatabase::Identify_Color_MATHML(nc).aIdent; + AddAttribute(XML_NAMESPACE_MATH, XML_MATHCOLOR, sssStr); + } + break; + case TRGB: + case TRGBA: + case THEX: + case THTMLCOL: + case TDVIPSNAMESCOL: + case TICONICCOL: + { + nc = pNode->GetToken().cMathChar.toUInt32(16); + OUString ssStr("#" + Color(ColorTransparency, nc).AsRGBHEXString()); + AddAttribute(XML_NAMESPACE_MATH, XML_MATHCOLOR, ssStr); + } + break; + case TSIZE: + { + const SmFontNode* pFontNode = static_cast<const SmFontNode*>(pNode); + const Fraction& aFrac = pFontNode->GetSizeParameter(); + + OUStringBuffer sStrBuf; + switch (pFontNode->GetSizeType()) + { + case FontSizeType::MULTIPLY: + ::sax::Converter::convertDouble(sStrBuf, + static_cast<double>(aFrac * Fraction(100.00))); + sStrBuf.append('%'); + break; + case FontSizeType::DIVIDE: + ::sax::Converter::convertDouble(sStrBuf, + static_cast<double>(Fraction(100.00) / aFrac)); + sStrBuf.append('%'); + break; + case FontSizeType::ABSOLUT: + ::sax::Converter::convertDouble(sStrBuf, static_cast<double>(aFrac)); + sStrBuf.append(GetXMLToken(XML_UNIT_PT)); + break; + default: + { + //The problem here is that the wheels fall off because + //font size is stored in 100th's of a mm not pts, and + //rounding errors take their toll on the original + //value specified in points. + + //Must fix StarMath to retain the original pt values + Fraction aTemp = Sm100th_mmToPts(pFontNode->GetFont().GetFontSize().Height()); + + if (pFontNode->GetSizeType() == FontSizeType::MINUS) + aTemp -= aFrac; + else + aTemp += aFrac; + + double mytest = static_cast<double>(aTemp); + + mytest = ::rtl::math::round(mytest, 1); + ::sax::Converter::convertDouble(sStrBuf, mytest); + sStrBuf.append(GetXMLToken(XML_UNIT_PT)); + } + break; + } + + OUString sStr(sStrBuf.makeStringAndClear()); + AddAttribute(XML_NAMESPACE_MATH, XML_MATHSIZE, sStr); + } + break; + case TBOLD: + case TITALIC: + case TNBOLD: + case TNITALIC: + case TFIXED: + case TSANS: + case TSERIF: + { + // nBold: -1 = yet undefined; 0 = false; 1 = true; + // nItalic: -1 = yet undefined; 0 = false; 1 = true; + // nSansSerifFixed: -1 = undefined; 0 = sans; 1 = serif; 2 = fixed; + const char* pText = "normal"; + if (nSansSerifFixed == -1 || nSansSerifFixed == 1) + { + pText = "normal"; + if (nBold == 1 && nItalic != 1) + pText = "bold"; + else if (nBold != 1 && nItalic == 1) + pText = "italic"; + else if (nBold == 1 && nItalic == 1) + pText = "bold-italic"; + } + else if (nSansSerifFixed == 0) + { + pText = "sans-serif"; + if (nBold == 1 && nItalic != 1) + pText = "bold-sans-serif"; + else if (nBold != 1 && nItalic == 1) + pText = "sans-serif-italic"; + else if (nBold == 1 && nItalic == 1) + pText = "sans-serif-bold-italic"; + } + else if (nSansSerifFixed == 2) + pText = "monospace"; // no modifiers allowed for monospace ... + else + { + SAL_WARN("starmath", "unexpected case"); + } + AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, OUString::createFromAscii(pText)); + } + break; + default: + break; + } + { + // Wrap everything in an <mphantom> or <mstyle> element. These elements + // are mrow-like, so ExportExpression doesn't need to add an explicit + // <mrow> element. See #fdo 66283. + SvXMLElementExport aElement(*this, XML_NAMESPACE_MATH, + pNode->GetToken().eType == TPHANTOM ? XML_MPHANTOM : XML_MSTYLE, + true, true); + ExportExpression(pNode, nLevel, true); + } +} + +void SmXMLExport::ExportVerticalBrace(const SmVerticalBraceNode* pNode, int nLevel) +{ + // "[body] overbrace [script]" + + // Position body, overbrace and script vertically. First place the overbrace + // OVER the body and then the script OVER this expression. + + // [script] + // --[overbrace]-- + // XXXXXX[body]XXXXXXX + + // Similarly for the underbrace construction. + + XMLTokenEnum which; + + switch (pNode->GetToken().eType) + { + case TOVERBRACE: + default: + which = XML_MOVER; + break; + case TUNDERBRACE: + which = XML_MUNDER; + break; + } + + SvXMLElementExport aOver1(*this, XML_NAMESPACE_MATH, which, true, true); + { //Scoping + // using accents will draw the over-/underbraces too close to the base + // see http://www.w3.org/TR/MathML2/chapter3.html#id.3.4.5.2 + // also XML_ACCENT is illegal with XML_MUNDER. Thus no XML_ACCENT attribute here! + SvXMLElementExport aOver2(*this, XML_NAMESPACE_MATH, which, true, true); + ExportNodes(pNode->Body(), nLevel); + AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE); + ExportNodes(pNode->Brace(), nLevel); + } + ExportNodes(pNode->Script(), nLevel); +} + +void SmXMLExport::ExportMatrix(const SmNode* pNode, int nLevel) +{ + SvXMLElementExport aTable(*this, XML_NAMESPACE_MATH, XML_MTABLE, true, true); + const SmMatrixNode* pMatrix = static_cast<const SmMatrixNode*>(pNode); + size_t i = 0; + for (sal_uInt16 y = 0; y < pMatrix->GetNumRows(); y++) + { + SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MTR, true, true); + for (sal_uInt16 x = 0; x < pMatrix->GetNumCols(); x++) + { + if (const SmNode* pTemp = pNode->GetSubNode(i++)) + { + if (pTemp->GetType() == SmNodeType::Align && pTemp->GetToken().eType != TALIGNC) + { + // A left or right alignment is specified on this cell, + // attach the corresponding columnalign attribute. + AddAttribute(XML_NAMESPACE_MATH, XML_COLUMNALIGN, + pTemp->GetToken().eType == TALIGNL ? XML_LEFT : XML_RIGHT); + } + SvXMLElementExport aCell(*this, XML_NAMESPACE_MATH, XML_MTD, true, true); + ExportNodes(pTemp, nLevel + 1); + } + } + } +} + +void SmXMLExport::ExportNodes(const SmNode* pNode, int nLevel) +{ + if (!pNode) + return; + switch (pNode->GetType()) + { + case SmNodeType::Table: + ExportTable(pNode, nLevel); + break; + case SmNodeType::Align: + case SmNodeType::Bracebody: + case SmNodeType::Expression: + ExportExpression(pNode, nLevel); + break; + case SmNodeType::Line: + ExportLine(pNode, nLevel); + break; + case SmNodeType::Text: + ExportText(pNode); + break; + case SmNodeType::GlyphSpecial: + case SmNodeType::Math: + { + sal_Unicode cTmp = 0; + const SmTextNode* pTemp = static_cast<const SmTextNode*>(pNode); + if (!pTemp->GetText().isEmpty()) + cTmp = ConvertMathToMathML(pTemp->GetText()[0]); + if (cTmp == 0) + { + // no conversion to MathML implemented -> export it as text + // thus at least it will not vanish into nothing + ExportText(pNode); + } + else + { + switch (pNode->GetToken().eType) + { + case TINTD: + AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE); + break; + default: + break; + } + //To fully handle generic MathML we need to implement the full + //operator dictionary, we will generate MathML with explicit + //stretchiness for now. + sal_Int16 nLength = GetAttrList().getLength(); + bool bAddStretch = true; + for (sal_Int16 i = 0; i < nLength; i++) + { + OUString sLocalName; + sal_uInt16 nPrefix = GetNamespaceMap().GetKeyByAttrName( + GetAttrList().getNameByIndex(i), &sLocalName); + + if ((XML_NAMESPACE_MATH == nPrefix) && IsXMLToken(sLocalName, XML_STRETCHY)) + { + bAddStretch = false; + break; + } + } + if (bAddStretch) + { + AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE); + } + ExportMath(pNode); + } + } + break; + case SmNodeType:: + Special: //SmNodeType::Special requires some sort of Entity preservation in the XML engine. + case SmNodeType::MathIdent: + case SmNodeType::Place: + ExportMath(pNode); + break; + case SmNodeType::BinHor: + ExportBinaryHorizontal(pNode, nLevel); + break; + case SmNodeType::UnHor: + ExportUnaryHorizontal(pNode, nLevel); + break; + case SmNodeType::Brace: + ExportBrace(pNode, nLevel); + break; + case SmNodeType::BinVer: + ExportBinaryVertical(pNode, nLevel); + break; + case SmNodeType::BinDiagonal: + ExportBinaryDiagonal(pNode, nLevel); + break; + case SmNodeType::SubSup: + ExportSubSupScript(pNode, nLevel); + break; + case SmNodeType::Root: + ExportRoot(pNode, nLevel); + break; + case SmNodeType::Oper: + ExportOperator(pNode, nLevel); + break; + case SmNodeType::Attribute: + ExportAttributes(pNode, nLevel); + break; + case SmNodeType::Font: + ExportFont(pNode, nLevel); + break; + case SmNodeType::VerticalBrace: + ExportVerticalBrace(static_cast<const SmVerticalBraceNode*>(pNode), nLevel); + break; + case SmNodeType::Matrix: + ExportMatrix(pNode, nLevel); + break; + case SmNodeType::Blank: + ExportBlank(pNode); + break; + default: + SAL_WARN("starmath", "Warning: failed to export a node?"); + break; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/mathml/mathmlimport.cxx b/starmath/source/mathml/mathmlimport.cxx new file mode 100644 index 000000000..44d8cc1e3 --- /dev/null +++ b/starmath/source/mathml/mathmlimport.cxx @@ -0,0 +1,2696 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +/*todo: Change characters and tcharacters to accumulate the characters together +into one string, xml parser hands them to us line by line rather than all in +one go*/ + +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/FastParser.hpp> +#include <com/sun/star/xml/sax/Parser.hpp> +#include <com/sun/star/xml/sax/SAXParseException.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/packages/WrongPasswordException.hpp> +#include <com/sun/star/packages/zip/ZipIOException.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/uno/Any.h> +#include <com/sun/star/task/XStatusIndicator.hpp> + +#include <comphelper/fileformat.h> +#include <comphelper/genericpropertyset.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/servicehelper.hxx> +#include <comphelper/propertysetinfo.hxx> +#include <rtl/character.hxx> +#include <sal/log.hxx> +#include <sfx2/frame.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/sfxsids.hrc> +#include <sfx2/sfxmodelfactory.hxx> +#include <osl/diagnose.h> +#include <sot/storage.hxx> +#include <svtools/sfxecode.hxx> +#include <svl/itemset.hxx> +#include <svl/stritem.hxx> +#include <unotools/streamwrap.hxx> +#include <sax/tools/converter.hxx> +#include <xmloff/DocumentSettingsContext.hxx> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/xmluconv.hxx> +#include <xmloff/xmlmetai.hxx> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <tools/diagnose_ex.h> +#include <o3tl/string_view.hxx> + +#include <mathmlattr.hxx> +#include <xparsmlbase.hxx> +#include <mathmlimport.hxx> +#include <document.hxx> +#include <smdll.hxx> +#include <unomodel.hxx> +#include <utility.hxx> +#include <visitors.hxx> +#include <starmathdatabase.hxx> +#include <smmod.hxx> +#include <cfgitem.hxx> + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star; +using namespace ::xmloff::token; + +namespace +{ +std::unique_ptr<SmNode> popOrZero(SmNodeStack& rStack) +{ + if (rStack.empty()) + return nullptr; + auto pTmp = std::move(rStack.front()); + rStack.pop_front(); + return pTmp; +} +} + +ErrCode SmXMLImportWrapper::Import(SfxMedium& rMedium) +{ + ErrCode nError = ERRCODE_SFX_DOLOADFAILED; + + uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext()); + + //Make a model component from our SmModel + uno::Reference<lang::XComponent> xModelComp = xModel; + OSL_ENSURE(xModelComp.is(), "XMLReader::Read: got no model"); + + // try to get an XStatusIndicator from the Medium + uno::Reference<task::XStatusIndicator> xStatusIndicator; + + bool bEmbedded = false; + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel); + + SmDocShell* pDocShell = pModel ? static_cast<SmDocShell*>(pModel->GetObjectShell()) : nullptr; + if (pDocShell) + { + OSL_ENSURE(pDocShell->GetMedium() == &rMedium, "different SfxMedium found"); + + SfxItemSet* pSet = rMedium.GetItemSet(); + if (pSet) + { + const SfxUnoAnyItem* pItem = pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL); + if (pItem) + pItem->GetValue() >>= xStatusIndicator; + } + + if (SfxObjectCreateMode::EMBEDDED == pDocShell->GetCreateMode()) + bEmbedded = true; + } + + static const comphelper::PropertyMapEntry aInfoMap[] + = { { OUString("PrivateData"), 0, cppu::UnoType<XInterface>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), + beans::PropertyAttribute::MAYBEVOID, 0 } }; + uno::Reference<beans::XPropertySet> xInfoSet( + comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap))); + + // Set base URI + OUString const baseURI(rMedium.GetBaseURL()); + // needed for relative URLs; but it's OK to import e.g. MathML from the + // clipboard without one + SAL_INFO_IF(baseURI.isEmpty(), "starmath", "SmXMLImportWrapper: no base URL"); + xInfoSet->setPropertyValue("BaseURI", Any(baseURI)); + + sal_Int32 nSteps = 3; + if (!(rMedium.IsStorage())) + nSteps = 1; + + sal_Int32 nProgressRange(nSteps); + if (xStatusIndicator.is()) + { + xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange); + } + + nSteps = 0; + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + if (rMedium.IsStorage()) + { + // TODO/LATER: handle the case of embedded links gracefully + if (bEmbedded) // && !rMedium.GetStorage()->IsRoot() ) + { + OUString aName("dummyObjName"); + if (rMedium.GetItemSet()) + { + const SfxStringItem* pDocHierarchItem + = rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME); + if (pDocHierarchItem) + aName = pDocHierarchItem->GetValue(); + } + + if (!aName.isEmpty()) + { + xInfoSet->setPropertyValue("StreamRelPath", Any(aName)); + } + } + + bool bOASIS = (SotStorage::GetVersion(rMedium.GetStorage()) > SOFFICE_FILEFORMAT_60); + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + auto nWarn + = ReadThroughComponent(rMedium.GetStorage(), xModelComp, "meta.xml", xContext, xInfoSet, + (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaImporter" + : "com.sun.star.comp.Math.XMLMetaImporter"), + m_bUseHTMLMLEntities); + + if (nWarn != ERRCODE_IO_BROKENPACKAGE) + { + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + nWarn = ReadThroughComponent(rMedium.GetStorage(), xModelComp, "settings.xml", xContext, + xInfoSet, + (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsImporter" + : "com.sun.star.comp.Math.XMLSettingsImporter"), + m_bUseHTMLMLEntities); + + if (nWarn != ERRCODE_IO_BROKENPACKAGE) + { + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + nError = ReadThroughComponent( + rMedium.GetStorage(), xModelComp, "content.xml", xContext, xInfoSet, + "com.sun.star.comp.Math.XMLImporter", m_bUseHTMLMLEntities); + } + else + nError = ERRCODE_IO_BROKENPACKAGE; + } + else + nError = ERRCODE_IO_BROKENPACKAGE; + } + else + { + Reference<io::XInputStream> xInputStream + = new utl::OInputStreamWrapper(rMedium.GetInStream()); + + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + nError = ReadThroughComponent(xInputStream, xModelComp, xContext, xInfoSet, + "com.sun.star.comp.Math.XMLImporter", false, + m_bUseHTMLMLEntities); + } + + if (xStatusIndicator.is()) + xStatusIndicator->end(); + return nError; +} + +/// read a component (file + filter version) +ErrCode SmXMLImportWrapper::ReadThroughComponent(const Reference<io::XInputStream>& xInputStream, + const Reference<XComponent>& xModelComponent, + Reference<uno::XComponentContext> const& rxContext, + Reference<beans::XPropertySet> const& rPropSet, + const char* pFilterName, bool bEncrypted, + bool bUseHTMLMLEntities) +{ + ErrCode nError = ERRCODE_SFX_DOLOADFAILED; + OSL_ENSURE(xInputStream.is(), "input stream missing"); + OSL_ENSURE(xModelComponent.is(), "document missing"); + OSL_ENSURE(rxContext.is(), "factory missing"); + OSL_ENSURE(nullptr != pFilterName, "I need a service name for the component!"); + + // prepare ParserInputSource + xml::sax::InputSource aParserInput; + aParserInput.aInputStream = xInputStream; + + Sequence<Any> aArgs{ Any(rPropSet) }; + + // get filter + Reference<XInterface> xFilter + = rxContext->getServiceManager()->createInstanceWithArgumentsAndContext( + OUString::createFromAscii(pFilterName), aArgs, rxContext); + SAL_WARN_IF(!xFilter, "starmath", "Can't instantiate filter component " << pFilterName); + if (!xFilter.is()) + return nError; + + // connect model and filter + Reference<XImporter> xImporter(xFilter, UNO_QUERY); + xImporter->setTargetDocument(xModelComponent); + + // finally, parser the stream + try + { + Reference<css::xml::sax::XFastParser> xFastParser(xFilter, UNO_QUERY); + Reference<css::xml::sax::XFastDocumentHandler> xFastDocHandler(xFilter, UNO_QUERY); + if (xFastParser) + { + if (bUseHTMLMLEntities) + xFastParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities); + xFastParser->parseStream(aParserInput); + } + else if (xFastDocHandler) + { + Reference<css::xml::sax::XFastParser> xParser + = css::xml::sax::FastParser::create(rxContext); + if (bUseHTMLMLEntities) + xParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities); + xParser->setFastDocumentHandler(xFastDocHandler); + xParser->parseStream(aParserInput); + } + else + { + Reference<css::xml::sax::XDocumentHandler> xDocHandler(xFilter, UNO_QUERY); + assert(xDocHandler); + Reference<css::xml::sax::XParser> xParser = css::xml::sax::Parser::create(rxContext); + xParser->setDocumentHandler(xDocHandler); + xParser->parseStream(aParserInput); + } + + auto pFilter = comphelper::getFromUnoTunnel<SmXMLImport>(xFilter); + if (pFilter && pFilter->GetSuccess()) + nError = ERRCODE_NONE; + } + catch (const xml::sax::SAXParseException& r) + { + // sax parser sends wrapped exceptions, + // try to find the original one + xml::sax::SAXException aSaxEx = *static_cast<const xml::sax::SAXException*>(&r); + bool bTryChild = true; + + while (bTryChild) + { + xml::sax::SAXException aTmp; + if (aSaxEx.WrappedException >>= aTmp) + aSaxEx = aTmp; + else + bTryChild = false; + } + + packages::zip::ZipIOException aBrokenPackage; + if (aSaxEx.WrappedException >>= aBrokenPackage) + return ERRCODE_IO_BROKENPACKAGE; + + if (bEncrypted) + nError = ERRCODE_SFX_WRONGPASSWORD; + } + catch (const xml::sax::SAXException& r) + { + packages::zip::ZipIOException aBrokenPackage; + if (r.WrappedException >>= aBrokenPackage) + return ERRCODE_IO_BROKENPACKAGE; + + if (bEncrypted) + nError = ERRCODE_SFX_WRONGPASSWORD; + } + catch (const packages::zip::ZipIOException&) + { + nError = ERRCODE_IO_BROKENPACKAGE; + } + catch (const io::IOException&) + { + } + catch (const std::range_error&) + { + } + + return nError; +} + +ErrCode SmXMLImportWrapper::ReadThroughComponent(const uno::Reference<embed::XStorage>& xStorage, + const Reference<XComponent>& xModelComponent, + const char* pStreamName, + Reference<uno::XComponentContext> const& rxContext, + Reference<beans::XPropertySet> const& rPropSet, + const char* pFilterName, bool bUseHTMLMLEntities) +{ + OSL_ENSURE(xStorage.is(), "Need storage!"); + OSL_ENSURE(nullptr != pStreamName, "Please, please, give me a name!"); + + // open stream (and set parser input) + OUString sStreamName = OUString::createFromAscii(pStreamName); + + // get input stream + try + { + uno::Reference<io::XStream> xEventsStream + = xStorage->openStreamElement(sStreamName, embed::ElementModes::READ); + + // determine if stream is encrypted or not + uno::Reference<beans::XPropertySet> xProps(xEventsStream, uno::UNO_QUERY); + Any aAny = xProps->getPropertyValue("Encrypted"); + bool bEncrypted = false; + if (aAny.getValueType() == cppu::UnoType<bool>::get()) + aAny >>= bEncrypted; + + // set Base URL + if (rPropSet.is()) + { + rPropSet->setPropertyValue("StreamName", Any(sStreamName)); + } + + Reference<io::XInputStream> xStream = xEventsStream->getInputStream(); + return ReadThroughComponent(xStream, xModelComponent, rxContext, rPropSet, pFilterName, + bEncrypted, bUseHTMLMLEntities); + } + catch (packages::WrongPasswordException&) + { + return ERRCODE_SFX_WRONGPASSWORD; + } + catch (packages::zip::ZipIOException&) + { + return ERRCODE_IO_BROKENPACKAGE; + } + catch (uno::Exception&) + { + } + + return ERRCODE_SFX_DOLOADFAILED; +} + +SmXMLImport::SmXMLImport(const css::uno::Reference<css::uno::XComponentContext>& rContext, + OUString const& implementationName, SvXMLImportFlags nImportFlags) + : SvXMLImport(rContext, implementationName, nImportFlags) + , bSuccess(false) + , nParseDepth(0) + , mnSmSyntaxVersion(SM_MOD()->GetConfig()->GetDefaultSmSyntaxVersion()) +{ +} + +const uno::Sequence<sal_Int8>& SmXMLImport::getUnoTunnelId() noexcept +{ + static const comphelper::UnoIdInit theSmXMLImportUnoTunnelId; + return theSmXMLImportUnoTunnelId.getSeq(); +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +Math_XMLImporter_get_implementation(uno::XComponentContext* pCtx, + uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire( + new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLImporter", SvXMLImportFlags::ALL)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +Math_XMLOasisMetaImporter_get_implementation(uno::XComponentContext* pCtx, + uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisMetaImporter", + SvXMLImportFlags::META)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +Math_XMLOasisSettingsImporter_get_implementation(uno::XComponentContext* pCtx, + uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisSettingsImporter", + SvXMLImportFlags::SETTINGS)); +} + +sal_Int64 SAL_CALL SmXMLImport::getSomething(const uno::Sequence<sal_Int8>& rId) +{ + return comphelper::getSomethingImpl(rId, this, + comphelper::FallbackToGetSomethingOf<SvXMLImport>{}); +} + +void SmXMLImport::endDocument() +{ + //Set the resulted tree into the SmDocShell where it belongs + std::unique_ptr<SmNode> pTree = popOrZero(aNodeStack); + if (pTree && pTree->GetType() == SmNodeType::Table) + { + uno::Reference<frame::XModel> xModel = GetModel(); + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel); + + if (pModel) + { + SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell()); + auto pTreeTmp = pTree.get(); + pDocShell->SetFormulaTree(static_cast<SmTableNode*>(pTree.release())); + if (aText.isEmpty()) //If we picked up no annotation text + { + // Get text from imported formula + SmNodeToTextVisitor tmpvisitor(pTreeTmp, aText); + } + + // Convert symbol names + AbstractSmParser* rParser = pDocShell->GetParser(); + bool bVal = rParser->IsImportSymbolNames(); + rParser->SetImportSymbolNames(true); + auto pTmpTree = rParser->Parse(aText); + aText = rParser->GetText(); + pTmpTree.reset(); + rParser->SetImportSymbolNames(bVal); + + pDocShell->SetText(aText); + pDocShell->SetSmSyntaxVersion(mnSmSyntaxVersion); + } + OSL_ENSURE(pModel, "So there *was* a UNO problem after all"); + + bSuccess = true; + } + + SvXMLImport::endDocument(); +} + +namespace +{ +class SmXMLImportContext : public SvXMLImportContext +{ +public: + SmXMLImportContext(SmXMLImport& rImport) + : SvXMLImportContext(rImport) + { + GetSmImport().IncParseDepth(); + } + + virtual ~SmXMLImportContext() override { GetSmImport().DecParseDepth(); } + + SmXMLImport& GetSmImport() { return static_cast<SmXMLImport&>(GetImport()); } + + virtual void TCharacters(const OUString& /*rChars*/); + virtual void SAL_CALL characters(const OUString& rChars) override; + virtual void SAL_CALL startFastElement( + sal_Int32 /*nElement*/, + const css::uno::Reference<css::xml::sax::XFastAttributeList>& /*rAttrList*/) override + { + if (GetSmImport().TooDeep()) + throw std::range_error("too deep"); + } +}; +} + +void SmXMLImportContext::TCharacters(const OUString& /*rChars*/) {} + +void SmXMLImportContext::characters(const OUString& rChars) +{ + /* + Whitespace occurring within the content of token elements is "trimmed" + from the ends (i.e. all whitespace at the beginning and end of the + content is removed), and "collapsed" internally (i.e. each sequence of + 1 or more whitespace characters is replaced with one blank character). + */ + //collapsing not done yet! + const OUString& rChars2 = rChars.trim(); + if (!rChars2.isEmpty()) + TCharacters(rChars2 /*.collapse()*/); +} + +namespace +{ +struct SmXMLContext_Helper +{ + sal_Int8 nIsBold; + sal_Int8 nIsItalic; + double nFontSize; + OUString sFontFamily; + OUString sColor; + + SmXMLImportContext& rContext; + + explicit SmXMLContext_Helper(SmXMLImportContext& rImport) + : nIsBold(-1) + , nIsItalic(-1) + , nFontSize(0.0) + , rContext(rImport) + { + } + + bool IsFontNodeNeeded() const; + void RetrieveAttrs(const uno::Reference<xml::sax::XFastAttributeList>& xAttrList); + void ApplyAttrs(); +}; +} + +bool SmXMLContext_Helper::IsFontNodeNeeded() const +{ + return nIsBold != -1 || nIsItalic != -1 || nFontSize != 0.0 || !sFontFamily.isEmpty() + || !sColor.isEmpty(); +} + +void SmXMLContext_Helper::RetrieveAttrs( + const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + bool bMvFound = false; + for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList)) + { + // sometimes they have namespace, sometimes not? + switch (aIter.getToken() & TOKEN_MASK) + { + case XML_FONTWEIGHT: + nIsBold = sal_Int8(IsXMLToken(aIter, XML_BOLD)); + break; + case XML_FONTSTYLE: + nIsItalic = sal_Int8(IsXMLToken(aIter, XML_ITALIC)); + break; + case XML_FONTSIZE: + case XML_MATHSIZE: + { + OUString sValue = aIter.toString(); + ::sax::Converter::convertDouble(nFontSize, sValue); + rContext.GetSmImport().GetMM100UnitConverter().SetXMLMeasureUnit( + util::MeasureUnit::POINT); + if (-1 == sValue.indexOf(GetXMLToken(XML_UNIT_PT))) + { + if (-1 == sValue.indexOf('%')) + nFontSize = 0.0; + else + { + rContext.GetSmImport().GetMM100UnitConverter().SetXMLMeasureUnit( + util::MeasureUnit::PERCENT); + } + } + break; + } + case XML_FONTFAMILY: + sFontFamily = aIter.toString(); + break; + case XML_COLOR: + sColor = aIter.toString(); + break; + case XML_MATHCOLOR: + sColor = aIter.toString(); + break; + case XML_MATHVARIANT: + bMvFound = true; + break; + default: + XMLOFF_WARN_UNKNOWN("starmath", aIter); + break; + } + } + + if (bMvFound) + { + // Ignore deprecated attributes fontfamily, fontweight, and fontstyle + // in favor of mathvariant, as specified in + // <https://www.w3.org/TR/MathML3/chapter3.html#presm.deprecatt>. + sFontFamily.clear(); + nIsBold = -1; + nIsItalic = -1; + } +} + +void SmXMLContext_Helper::ApplyAttrs() +{ + SmNodeStack& rNodeStack = rContext.GetSmImport().GetNodeStack(); + + if (!IsFontNodeNeeded()) + return; + + SmToken aToken; + aToken.cMathChar = u""; + aToken.nLevel = 5; + + if (nIsBold != -1) + { + if (nIsBold) + aToken.eType = TBOLD; + else + aToken.eType = TNBOLD; + std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken)); + pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack)); + rNodeStack.push_front(std::move(pFontNode)); + } + if (nIsItalic != -1) + { + if (nIsItalic) + aToken.eType = TITALIC; + else + aToken.eType = TNITALIC; + std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken)); + pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack)); + rNodeStack.push_front(std::move(pFontNode)); + } + if (nFontSize != 0.0) + { + aToken.eType = TSIZE; + std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken)); + + if (util::MeasureUnit::PERCENT + == rContext.GetSmImport().GetMM100UnitConverter().GetXMLMeasureUnit()) + { + if (nFontSize < 100.00) + pFontNode->SetSizeParameter(Fraction(100.00 / nFontSize), FontSizeType::DIVIDE); + else + pFontNode->SetSizeParameter(Fraction(nFontSize / 100.00), FontSizeType::MULTIPLY); + } + else + pFontNode->SetSizeParameter(Fraction(nFontSize), FontSizeType::ABSOLUT); + + pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack)); + rNodeStack.push_front(std::move(pFontNode)); + } + if (!sColor.isEmpty()) + { + SmColorTokenTableEntry aSmColorTokenTableEntry; + aSmColorTokenTableEntry = starmathdatabase::Identify_ColorName_HTML(sColor); + if (aSmColorTokenTableEntry.eType == TRGB) + aSmColorTokenTableEntry = starmathdatabase::Identify_Color_Parser( + sal_uInt32(aSmColorTokenTableEntry.cColor)); + if (aSmColorTokenTableEntry.eType != TERROR) + { + aToken = aSmColorTokenTableEntry; + std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken)); + pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack)); + rNodeStack.push_front(std::move(pFontNode)); + } + // If not known, not implemented yet. Giving up. + } + if (sFontFamily.isEmpty()) + return; + + if (sFontFamily.equalsIgnoreAsciiCase(GetXMLToken(XML_FIXED))) + aToken.eType = TFIXED; + else if (sFontFamily.equalsIgnoreAsciiCase("sans")) + aToken.eType = TSANS; + else if (sFontFamily.equalsIgnoreAsciiCase("serif")) + aToken.eType = TSERIF; + else //Just give up, we need to extend our font mechanism to be + //more general + return; + + aToken.aText = sFontFamily; + std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken)); + pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack)); + rNodeStack.push_front(std::move(pFontNode)); +} + +namespace +{ +class SmXMLTokenAttrHelper +{ + SmXMLImportContext& mrContext; + MathMLMathvariantValue meMv; + bool mbMvFound; + +public: + SmXMLTokenAttrHelper(SmXMLImportContext& rContext) + : mrContext(rContext) + , meMv(MathMLMathvariantValue::Normal) + , mbMvFound(false) + { + } + + void RetrieveAttrs(const uno::Reference<xml::sax::XFastAttributeList>& xAttrList); + void ApplyAttrs(MathMLMathvariantValue eDefaultMv); +}; +} + +void SmXMLTokenAttrHelper::RetrieveAttrs( + const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList)) + { + OUString sValue = aIter.toString(); + switch (aIter.getToken()) + { + case XML_MATHVARIANT: + if (!GetMathMLMathvariantValue(sValue, meMv)) + SAL_WARN("starmath", "failed to recognize mathvariant: " << sValue); + mbMvFound = true; + break; + default: + XMLOFF_WARN_UNKNOWN("starmath", aIter); + break; + } + } +} + +void SmXMLTokenAttrHelper::ApplyAttrs(MathMLMathvariantValue eDefaultMv) +{ + assert(eDefaultMv == MathMLMathvariantValue::Normal + || eDefaultMv == MathMLMathvariantValue::Italic); + + std::vector<SmTokenType> vVariant; + MathMLMathvariantValue eMv = mbMvFound ? meMv : eDefaultMv; + switch (eMv) + { + case MathMLMathvariantValue::Normal: + vVariant.push_back(TNITALIC); + break; + case MathMLMathvariantValue::Bold: + vVariant.push_back(TBOLD); + break; + case MathMLMathvariantValue::Italic: + // nothing to do + break; + case MathMLMathvariantValue::BoldItalic: + vVariant.push_back(TITALIC); + vVariant.push_back(TBOLD); + break; + case MathMLMathvariantValue::DoubleStruck: + // TODO + break; + case MathMLMathvariantValue::BoldFraktur: + // TODO: Fraktur + vVariant.push_back(TBOLD); + break; + case MathMLMathvariantValue::Script: + // TODO + break; + case MathMLMathvariantValue::BoldScript: + // TODO: Script + vVariant.push_back(TBOLD); + break; + case MathMLMathvariantValue::Fraktur: + // TODO + break; + case MathMLMathvariantValue::SansSerif: + vVariant.push_back(TSANS); + break; + case MathMLMathvariantValue::BoldSansSerif: + vVariant.push_back(TSANS); + vVariant.push_back(TBOLD); + break; + case MathMLMathvariantValue::SansSerifItalic: + vVariant.push_back(TITALIC); + vVariant.push_back(TSANS); + break; + case MathMLMathvariantValue::SansSerifBoldItalic: + vVariant.push_back(TITALIC); + vVariant.push_back(TBOLD); + vVariant.push_back(TSANS); + break; + case MathMLMathvariantValue::Monospace: + vVariant.push_back(TFIXED); + break; + case MathMLMathvariantValue::Initial: + case MathMLMathvariantValue::Tailed: + case MathMLMathvariantValue::Looped: + case MathMLMathvariantValue::Stretched: + // TODO + break; + } + if (vVariant.empty()) + return; + SmNodeStack& rNodeStack = mrContext.GetSmImport().GetNodeStack(); + for (auto eType : vVariant) + { + SmToken aToken; + aToken.eType = eType; + aToken.cMathChar = u""; + aToken.nLevel = 5; + std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken)); + pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack)); + rNodeStack.push_front(std::move(pFontNode)); + } +} + +namespace +{ +class SmXMLDocContext_Impl : public SmXMLImportContext +{ +public: + SmXMLDocContext_Impl(SmXMLImport& rImport) + : SmXMLImportContext(rImport) + { + } + + virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override; + + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; + +/*avert the gaze from the originator*/ +class SmXMLRowContext_Impl : public SmXMLDocContext_Impl +{ +protected: + size_t nElementCount; + +public: + SmXMLRowContext_Impl(SmXMLImport& rImport) + : SmXMLDocContext_Impl(rImport) + , nElementCount(GetSmImport().GetNodeStack().size()) + { + } + + virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override; + + uno::Reference<xml::sax::XFastContextHandler> StrictCreateChildContext(sal_Int32 nElement); + + virtual void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; + +class SmXMLEncloseContext_Impl : public SmXMLRowContext_Impl +{ +public: + // TODO/LATER: convert <menclose notation="horizontalstrike"> into + // "overstrike{}" and extend the Math syntax to support more notations + SmXMLEncloseContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + { + } + + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; +} + +void SmXMLEncloseContext_Impl::endFastElement(sal_Int32 nElement) +{ + /* + <menclose> accepts any number of arguments; if this number is not 1, its + contents are treated as a single "inferred <mrow>" containing its + arguments + */ + if (GetSmImport().GetNodeStack().size() - nElementCount != 1) + SmXMLRowContext_Impl::endFastElement(nElement); +} + +namespace +{ +class SmXMLFracContext_Impl : public SmXMLRowContext_Impl +{ +public: + // TODO/LATER: convert <mfrac bevelled="true"> into "wideslash{}{}" + SmXMLFracContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + { + } + + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; + +class SmXMLSqrtContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLSqrtContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + { + } + + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; + +class SmXMLRootContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLRootContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + { + } + + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; + +class SmXMLStyleContext_Impl : public SmXMLRowContext_Impl +{ +protected: + SmXMLContext_Helper aStyleHelper; + +public: + /*Right now the style tag is completely ignored*/ + SmXMLStyleContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + , aStyleHelper(*this) + { + } + + void SAL_CALL endFastElement(sal_Int32 nElement) override; + void SAL_CALL startFastElement( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override; +}; +} + +void SmXMLStyleContext_Impl::startFastElement( + sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + aStyleHelper.RetrieveAttrs(xAttrList); +} + +void SmXMLStyleContext_Impl::endFastElement(sal_Int32 nElement) +{ + /* + <mstyle> accepts any number of arguments; if this number is not 1, its + contents are treated as a single "inferred <mrow>" containing its + arguments + */ + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + if (rNodeStack.size() - nElementCount != 1) + SmXMLRowContext_Impl::endFastElement(nElement); + aStyleHelper.ApplyAttrs(); +} + +namespace +{ +class SmXMLPaddedContext_Impl : public SmXMLRowContext_Impl +{ +public: + /*Right now the style tag is completely ignored*/ + SmXMLPaddedContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + { + } + + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; +} + +void SmXMLPaddedContext_Impl::endFastElement(sal_Int32 nElement) +{ + /* + <mpadded> accepts any number of arguments; if this number is not 1, its + contents are treated as a single "inferred <mrow>" containing its + arguments + */ + if (GetSmImport().GetNodeStack().size() - nElementCount != 1) + SmXMLRowContext_Impl::endFastElement(nElement); +} + +namespace +{ +class SmXMLPhantomContext_Impl : public SmXMLRowContext_Impl +{ +public: + /*Right now the style tag is completely ignored*/ + SmXMLPhantomContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + { + } + + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; +} + +void SmXMLPhantomContext_Impl::endFastElement(sal_Int32 nElement) +{ + /* + <mphantom> accepts any number of arguments; if this number is not 1, its + contents are treated as a single "inferred <mrow>" containing its + arguments + */ + if (GetSmImport().GetNodeStack().size() - nElementCount != 1) + SmXMLRowContext_Impl::endFastElement(nElement); + + SmToken aToken; + aToken.cMathChar = u""; + aToken.nLevel = 5; + aToken.eType = TPHANTOM; + + std::unique_ptr<SmFontNode> pPhantom(new SmFontNode(aToken)); + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + pPhantom->SetSubNodes(nullptr, popOrZero(rNodeStack)); + rNodeStack.push_front(std::move(pPhantom)); +} + +namespace +{ +class SmXMLFencedContext_Impl : public SmXMLRowContext_Impl +{ +protected: + sal_Unicode cBegin; + sal_Unicode cEnd; + bool bIsStretchy; + +public: + SmXMLFencedContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + , cBegin('(') + , cEnd(')') + , bIsStretchy(false) + { + } + + void SAL_CALL startFastElement( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override; + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; +} + +void SmXMLFencedContext_Impl::startFastElement( + sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList)) + { + switch (aIter.getToken()) + { + //temp, starmath cannot handle multichar brackets (I think) + case XML_OPEN: + cBegin = aIter.toString()[0]; + break; + case XML_CLOSE: + cEnd = aIter.toString()[0]; + break; + case XML_STRETCHY: + bIsStretchy = IsXMLToken(aIter, XML_TRUE); + break; + default: + XMLOFF_WARN_UNKNOWN("starmath", aIter); + /*Go to superclass*/ + break; + } + } +} + +void SmXMLFencedContext_Impl::endFastElement(sal_Int32 /*nElement*/) +{ + SmToken aToken; + aToken.cMathChar = u""; + aToken.aText = ","; + aToken.nLevel = 5; + + std::unique_ptr<SmStructureNode> pSNode(new SmBraceNode(aToken)); + if (bIsStretchy) + aToken = starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl(cBegin); + else + aToken = starmathdatabase::Identify_Prefix_SmXMLOperatorContext_Impl(cBegin); + if (aToken.eType == TERROR) + aToken = SmToken(TLPARENT, MS_LPARENT, "(", TG::LBrace, 5); + std::unique_ptr<SmNode> pLeft(new SmMathSymbolNode(aToken)); + if (bIsStretchy) + aToken = starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl(cEnd); + else + aToken = starmathdatabase::Identify_Postfix_SmXMLOperatorContext_Impl(cEnd); + if (aToken.eType == TERROR) + aToken = SmToken(TRPARENT, MS_RPARENT, ")", TG::LBrace, 5); + std::unique_ptr<SmNode> pRight(new SmMathSymbolNode(aToken)); + + SmNodeArray aRelationArray; + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + aToken.cMathChar = u""; + aToken.eType = TIDENT; + + auto i = rNodeStack.size() - nElementCount; + if (rNodeStack.size() - nElementCount > 1) + i += rNodeStack.size() - 1 - nElementCount; + aRelationArray.resize(i); + while (rNodeStack.size() > nElementCount) + { + auto pNode = std::move(rNodeStack.front()); + rNodeStack.pop_front(); + aRelationArray[--i] = pNode.release(); + if (i > 1 && rNodeStack.size() > 1) + aRelationArray[--i] = new SmGlyphSpecialNode(aToken); + } + + SmToken aDummy; + std::unique_ptr<SmStructureNode> pBody(new SmExpressionNode(aDummy)); + pBody->SetSubNodes(std::move(aRelationArray)); + + pSNode->SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight)); + // mfenced is always scalable. Stretchy keyword is not official, but in case of been in there + // can be used as a hint. + pSNode->SetScaleMode(SmScaleMode::Height); + GetSmImport().GetNodeStack().push_front(std::move(pSNode)); +} + +namespace +{ +class SmXMLErrorContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLErrorContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + { + } + + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; +} + +void SmXMLErrorContext_Impl::endFastElement(sal_Int32 /*nElement*/) +{ + /*Right now the error tag is completely ignored, what + can I do with it in starmath, ?, maybe we need a + report window ourselves, do a test for validity of + the xml input, use mirrors, and then generate + the markup inside the merror with a big red colour + of something. For now just throw them all away. + */ + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + while (rNodeStack.size() > nElementCount) + { + rNodeStack.pop_front(); + } +} + +namespace +{ +class SmXMLNumberContext_Impl : public SmXMLImportContext +{ +protected: + SmToken aToken; + +public: + SmXMLNumberContext_Impl(SmXMLImport& rImport) + : SmXMLImportContext(rImport) + { + aToken.cMathChar = u""; + aToken.nLevel = 5; + aToken.eType = TNUMBER; + } + + virtual void TCharacters(const OUString& rChars) override; + + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; +} + +void SmXMLNumberContext_Impl::TCharacters(const OUString& rChars) { aToken.aText = rChars; } + +void SmXMLNumberContext_Impl::endFastElement(sal_Int32) +{ + GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_NUMBER)); +} + +namespace +{ +class SmXMLAnnotationContext_Impl : public SmXMLImportContext +{ + sal_uInt8 mnStarMathVersion; + +public: + SmXMLAnnotationContext_Impl(SmXMLImport& rImport) + : SmXMLImportContext(rImport) + , mnStarMathVersion(0) + { + } + + void SAL_CALL characters(const OUString& rChars) override; + + void SAL_CALL startFastElement( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override; +}; +} + +void SmXMLAnnotationContext_Impl::startFastElement( + sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList)) + { + // sometimes they have namespace, sometimes not? + switch (aIter.getToken() & TOKEN_MASK) + { + case XML_ENCODING: + mnStarMathVersion + = aIter.toView() == "StarMath 5.0" ? 5 : aIter.toView() == "StarMath 6" ? 6 : 0; + break; + default: + XMLOFF_WARN_UNKNOWN("starmath", aIter); + break; + } + } +} + +void SmXMLAnnotationContext_Impl::characters(const OUString& rChars) +{ + if (mnStarMathVersion) + { + GetSmImport().SetText(GetSmImport().GetText() + rChars); + GetSmImport().SetSmSyntaxVersion(mnStarMathVersion); + } +} + +namespace +{ +class SmXMLTextContext_Impl : public SmXMLImportContext +{ +protected: + SmToken aToken; + +public: + SmXMLTextContext_Impl(SmXMLImport& rImport) + : SmXMLImportContext(rImport) + { + aToken.cMathChar = u""; + aToken.nLevel = 5; + aToken.eType = TTEXT; + } + + virtual void TCharacters(const OUString& rChars) override; + + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; +} + +void SmXMLTextContext_Impl::TCharacters(const OUString& rChars) { aToken.aText = rChars; } + +void SmXMLTextContext_Impl::endFastElement(sal_Int32) +{ + GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_TEXT)); +} + +namespace +{ +class SmXMLStringContext_Impl : public SmXMLImportContext +{ +protected: + SmToken aToken; + +public: + SmXMLStringContext_Impl(SmXMLImport& rImport) + : SmXMLImportContext(rImport) + { + aToken.cMathChar = u""; + aToken.nLevel = 5; + aToken.eType = TTEXT; + } + + virtual void TCharacters(const OUString& rChars) override; + + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; +} + +void SmXMLStringContext_Impl::TCharacters(const OUString& rChars) +{ + /* + The content of <ms> elements should be rendered with visible "escaping" of + certain characters in the content, including at least "double quote" + itself, and preferably whitespace other than individual blanks. The intent + is for the viewer to see that the expression is a string literal, and to + see exactly which characters form its content. For example, <ms>double + quote is "</ms> might be rendered as "double quote is \"". + + Obviously this isn't fully done here. + */ + aToken.aText = "\"" + rChars + "\""; +} + +void SmXMLStringContext_Impl::endFastElement(sal_Int32) +{ + GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_FIXED)); +} + +namespace +{ +class SmXMLIdentifierContext_Impl : public SmXMLImportContext +{ + SmXMLTokenAttrHelper maTokenAttrHelper; + SmXMLContext_Helper aStyleHelper; + SmToken aToken; + +public: + SmXMLIdentifierContext_Impl(SmXMLImport& rImport) + : SmXMLImportContext(rImport) + , maTokenAttrHelper(*this) + , aStyleHelper(*this) + { + aToken.cMathChar = u""; + aToken.nLevel = 5; + aToken.eType = TIDENT; + } + + void TCharacters(const OUString& rChars) override; + void SAL_CALL + startFastElement(sal_Int32 /*nElement*/, + const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override + { + maTokenAttrHelper.RetrieveAttrs(xAttrList); + aStyleHelper.RetrieveAttrs(xAttrList); + }; + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; +} + +void SmXMLIdentifierContext_Impl::endFastElement(sal_Int32) +{ + std::unique_ptr<SmTextNode> pNode; + //we will handle identifier italic/normal here instead of with a standalone + //font node + if (((aStyleHelper.nIsItalic == -1) && (aToken.aText.getLength() > 1)) + || ((aStyleHelper.nIsItalic == 0) && (aToken.aText.getLength() == 1))) + { + pNode.reset(new SmTextNode(aToken, FNT_FUNCTION)); + pNode->GetFont().SetItalic(ITALIC_NONE); + aStyleHelper.nIsItalic = -1; + } + else + pNode.reset(new SmTextNode(aToken, FNT_VARIABLE)); + if (aStyleHelper.nIsItalic != -1) + { + if (aStyleHelper.nIsItalic) + pNode->GetFont().SetItalic(ITALIC_NORMAL); + else + pNode->GetFont().SetItalic(ITALIC_NONE); + aStyleHelper.nIsItalic = -1; + } + GetSmImport().GetNodeStack().push_front(std::move(pNode)); + aStyleHelper.ApplyAttrs(); + + maTokenAttrHelper.ApplyAttrs((aToken.aText.getLength() == 1) ? MathMLMathvariantValue::Italic + : MathMLMathvariantValue::Normal); +} + +void SmXMLIdentifierContext_Impl::TCharacters(const OUString& rChars) { aToken.aText = rChars; } + +namespace +{ +class SmXMLOperatorContext_Impl : public SmXMLImportContext +{ + SmXMLTokenAttrHelper maTokenAttrHelper; + bool bIsStretchy; + bool bIsFenced; + bool isPrefix; + bool isInfix; + bool isPostfix; + SmToken aToken; + +public: + SmXMLOperatorContext_Impl(SmXMLImport& rImport) + : SmXMLImportContext(rImport) + , maTokenAttrHelper(*this) + , bIsStretchy(false) + , bIsFenced(false) + , isPrefix(false) + , isInfix(false) + , isPostfix(false) + { + aToken.eType = TSPECIAL; + aToken.nLevel = 5; + } + + void TCharacters(const OUString& rChars) override; + void SAL_CALL startFastElement( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override; + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; +} + +void SmXMLOperatorContext_Impl::TCharacters(const OUString& rChars) +{ + aToken.setChar(rChars[0]); + SmToken bToken; + if (bIsFenced) + { + if (isPrefix) + bToken + = starmathdatabase::Identify_Prefix_SmXMLOperatorContext_Impl(aToken.cMathChar[0]); + else if (isInfix) + bToken = SmToken(TMLINE, MS_VERTLINE, "mline", TG::NONE, 0); + else if (isPostfix) + bToken + = starmathdatabase::Identify_Postfix_SmXMLOperatorContext_Impl(aToken.cMathChar[0]); + else + bToken = starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl( + aToken.cMathChar[0]); + } + else + bToken = starmathdatabase::Identify_SmXMLOperatorContext_Impl(aToken.cMathChar[0], + bIsStretchy); + if (bToken.eType != TERROR) + aToken = bToken; +} + +void SmXMLOperatorContext_Impl::endFastElement(sal_Int32) +{ + std::unique_ptr<SmMathSymbolNode> pNode(new SmMathSymbolNode(aToken)); + //For stretchy scaling the scaling must be retrieved from this node + //and applied to the expression itself so as to get the expression + //to scale the operator to the height of the expression itself + if (bIsStretchy) + pNode->SetScaleMode(SmScaleMode::Height); + GetSmImport().GetNodeStack().push_front(std::move(pNode)); + + // TODO: apply to non-alphabetic characters too + if (rtl::isAsciiAlpha(aToken.cMathChar[0])) + maTokenAttrHelper.ApplyAttrs(MathMLMathvariantValue::Normal); +} + +void SmXMLOperatorContext_Impl::startFastElement( + sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + maTokenAttrHelper.RetrieveAttrs(xAttrList); + + for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList)) + { + switch (aIter.getToken()) + { + case XML_STRETCHY: + bIsStretchy = IsXMLToken(aIter, XML_TRUE); + break; + case XML_FENCE: + bIsFenced = IsXMLToken(aIter, XML_TRUE); + break; + case XML_FORM: + isPrefix = IsXMLToken(aIter, XML_PREFIX); // < + isInfix = IsXMLToken(aIter, XML_INFIX); // | + isPostfix = IsXMLToken(aIter, XML_POSTFIX); // > + break; + default: + XMLOFF_WARN_UNKNOWN("starmath", aIter); + break; + } + } +} + +namespace +{ +class SmXMLSpaceContext_Impl : public SmXMLImportContext +{ +public: + SmXMLSpaceContext_Impl(SmXMLImport& rImport) + : SmXMLImportContext(rImport) + { + } + + void SAL_CALL startFastElement( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override; +}; + +bool lcl_CountBlanks(const MathMLAttributeLengthValue& rLV, sal_Int32* pWide, sal_Int32* pNarrow) +{ + assert(pWide); + assert(pNarrow); + if (rLV.aNumber.GetNumerator() == 0) + { + *pWide = *pNarrow = 0; + return true; + } + // TODO: honor other units than em + if (rLV.eUnit != MathMLLengthUnit::Em) + return false; + if (rLV.aNumber.GetNumerator() < 0) + return false; + const Fraction aTwo(2, 1); + auto aWide = rLV.aNumber / aTwo; + auto nWide = static_cast<sal_Int32>(static_cast<tools::Long>(aWide)); + if (nWide < 0) + return false; + const Fraction aPointFive(1, 2); + auto aNarrow = (rLV.aNumber - Fraction(nWide, 1) * aTwo) / aPointFive; + auto nNarrow = static_cast<sal_Int32>(static_cast<tools::Long>(aNarrow)); + if (nNarrow < 0) + return false; + *pWide = nWide; + *pNarrow = nNarrow; + return true; +} +} + +void SmXMLSpaceContext_Impl::startFastElement( + sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + // There is no syntax in Math to specify blank nodes of arbitrary size yet. + MathMLAttributeLengthValue aLV; + sal_Int32 nWide = 0, nNarrow = 0; + + for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList)) + { + OUString sValue = aIter.toString(); + switch (aIter.getToken()) + { + case XML_WIDTH: + if (!ParseMathMLAttributeLengthValue(o3tl::trim(sValue), aLV) + || !lcl_CountBlanks(aLV, &nWide, &nNarrow)) + SAL_WARN("starmath", "ignore mspace's width: " << sValue); + break; + default: + XMLOFF_WARN_UNKNOWN("starmath", aIter); + break; + } + } + SmToken aToken; + aToken.eType = TBLANK; + aToken.cMathChar = u""; + aToken.nGroup = TG::Blank; + aToken.nLevel = 5; + std::unique_ptr<SmBlankNode> pBlank(new SmBlankNode(aToken)); + if (nWide > 0) + pBlank->IncreaseBy(aToken, nWide); + if (nNarrow > 0) + { + aToken.eType = TSBLANK; + pBlank->IncreaseBy(aToken, nNarrow); + } + GetSmImport().GetNodeStack().push_front(std::move(pBlank)); +} + +namespace +{ +class SmXMLSubContext_Impl : public SmXMLRowContext_Impl +{ +protected: + void GenericEndElement(SmTokenType eType, SmSubSup aSubSup); + +public: + SmXMLSubContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + { + } + + void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TRSUB, RSUB); } +}; +} + +void SmXMLSubContext_Impl::GenericEndElement(SmTokenType eType, SmSubSup eSubSup) +{ + /*The <msub> element requires exactly 2 arguments.*/ + const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2; + OSL_ENSURE(bNodeCheck, "Sub has not two arguments"); + if (!bNodeCheck) + return; + + SmToken aToken; + aToken.cMathChar = u""; + aToken.eType = eType; + std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken)); + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + + // initialize subnodes array + SmNodeArray aSubNodes; + aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES); + for (size_t i = 1; i < aSubNodes.size(); i++) + aSubNodes[i] = nullptr; + + aSubNodes[eSubSup + 1] = popOrZero(rNodeStack).release(); + aSubNodes[0] = popOrZero(rNodeStack).release(); + pNode->SetSubNodes(std::move(aSubNodes)); + rNodeStack.push_front(std::move(pNode)); +} + +namespace +{ +class SmXMLSupContext_Impl : public SmXMLSubContext_Impl +{ +public: + SmXMLSupContext_Impl(SmXMLImport& rImport) + : SmXMLSubContext_Impl(rImport) + { + } + + void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TRSUP, RSUP); } +}; + +class SmXMLSubSupContext_Impl : public SmXMLRowContext_Impl +{ +protected: + void GenericEndElement(SmTokenType eType, SmSubSup aSub, SmSubSup aSup); + +public: + SmXMLSubSupContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + { + } + + void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TRSUB, RSUB, RSUP); } +}; +} + +void SmXMLSubSupContext_Impl::GenericEndElement(SmTokenType eType, SmSubSup aSub, SmSubSup aSup) +{ + /*The <msub> element requires exactly 3 arguments.*/ + const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 3; + OSL_ENSURE(bNodeCheck, "SubSup has not three arguments"); + if (!bNodeCheck) + return; + + SmToken aToken; + aToken.cMathChar = u""; + aToken.eType = eType; + std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken)); + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + + // initialize subnodes array + SmNodeArray aSubNodes; + aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES); + for (size_t i = 1; i < aSubNodes.size(); i++) + aSubNodes[i] = nullptr; + + aSubNodes[aSup + 1] = popOrZero(rNodeStack).release(); + aSubNodes[aSub + 1] = popOrZero(rNodeStack).release(); + aSubNodes[0] = popOrZero(rNodeStack).release(); + pNode->SetSubNodes(std::move(aSubNodes)); + rNodeStack.push_front(std::move(pNode)); +} + +namespace +{ +class SmXMLUnderContext_Impl : public SmXMLSubContext_Impl +{ +protected: + sal_Int16 nAttrCount; + +public: + SmXMLUnderContext_Impl(SmXMLImport& rImport) + : SmXMLSubContext_Impl(rImport) + , nAttrCount(0) + { + } + + void SAL_CALL startFastElement( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override; + void SAL_CALL endFastElement(sal_Int32 nElement) override; + void HandleAccent(); +}; +} + +void SmXMLUnderContext_Impl::startFastElement( + sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + sax_fastparser::FastAttributeList& rAttribList + = sax_fastparser::castToFastAttributeList(xAttrList); + nAttrCount = rAttribList.getFastAttributeTokens().size(); +} + +void SmXMLUnderContext_Impl::HandleAccent() +{ + const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2; + OSL_ENSURE(bNodeCheck, "Sub has not two arguments"); + if (!bNodeCheck) + return; + + /*Just one special case for the underline thing*/ + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + std::unique_ptr<SmNode> pTest = popOrZero(rNodeStack); + SmToken aToken; + aToken.cMathChar = u""; + aToken.eType = TUNDERLINE; + + std::unique_ptr<SmNode> pFirst; + std::unique_ptr<SmStructureNode> pNode(new SmAttributeNode(aToken)); + if ((pTest->GetToken().cMathChar[0] & 0x0FFF) == 0x0332) + { + pFirst.reset(new SmRectangleNode(aToken)); + } + else + pFirst = std::move(pTest); + + std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack); + pNode->SetSubNodes(std::move(pFirst), std::move(pSecond)); + pNode->SetScaleMode(SmScaleMode::Width); + rNodeStack.push_front(std::move(pNode)); +} + +void SmXMLUnderContext_Impl::endFastElement(sal_Int32) +{ + if (!nAttrCount) + GenericEndElement(TCSUB, CSUB); + else + HandleAccent(); +} + +namespace +{ +class SmXMLOverContext_Impl : public SmXMLSubContext_Impl +{ +protected: + sal_Int16 nAttrCount; + +public: + SmXMLOverContext_Impl(SmXMLImport& rImport) + : SmXMLSubContext_Impl(rImport) + , nAttrCount(0) + { + } + + void SAL_CALL endFastElement(sal_Int32 nElement) override; + void SAL_CALL startFastElement( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override; + void HandleAccent(); +}; +} + +void SmXMLOverContext_Impl::startFastElement( + sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + sax_fastparser::FastAttributeList& rAttribList + = sax_fastparser::castToFastAttributeList(xAttrList); + nAttrCount = rAttribList.getFastAttributeTokens().size(); +} + +void SmXMLOverContext_Impl::endFastElement(sal_Int32) +{ + if (!nAttrCount) + GenericEndElement(TCSUP, CSUP); + else + HandleAccent(); +} + +void SmXMLOverContext_Impl::HandleAccent() +{ + const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2; + OSL_ENSURE(bNodeCheck, "Sub has not two arguments"); + if (!bNodeCheck) + return; + + SmToken aToken; + aToken.cMathChar = u""; + aToken.eType = TACUTE; + + std::unique_ptr<SmAttributeNode> pNode(new SmAttributeNode(aToken)); + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + + std::unique_ptr<SmNode> pFirst = popOrZero(rNodeStack); + std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack); + pNode->SetSubNodes(std::move(pFirst), std::move(pSecond)); + pNode->SetScaleMode(SmScaleMode::Width); + rNodeStack.push_front(std::move(pNode)); +} + +namespace +{ +class SmXMLUnderOverContext_Impl : public SmXMLSubSupContext_Impl +{ +public: + SmXMLUnderOverContext_Impl(SmXMLImport& rImport) + : SmXMLSubSupContext_Impl(rImport) + { + } + + void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TCSUB, CSUB, CSUP); } +}; + +class SmXMLMultiScriptsContext_Impl : public SmXMLSubSupContext_Impl +{ + bool bHasPrescripts; + + void ProcessSubSupPairs(bool bIsPrescript); + +public: + SmXMLMultiScriptsContext_Impl(SmXMLImport& rImport) + : SmXMLSubSupContext_Impl(rImport) + , bHasPrescripts(false) + { + } + + void SAL_CALL endFastElement(sal_Int32 nElement) override; + virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override; +}; + +class SmXMLNoneContext_Impl : public SmXMLImportContext +{ +public: + SmXMLNoneContext_Impl(SmXMLImport& rImport) + : SmXMLImportContext(rImport) + { + } + + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; +} + +void SmXMLNoneContext_Impl::endFastElement(sal_Int32) +{ + SmToken aToken; + aToken.cMathChar = u""; + aToken.aText.clear(); + aToken.nLevel = 5; + aToken.eType = TIDENT; + GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_VARIABLE)); +} + +namespace +{ +class SmXMLPrescriptsContext_Impl : public SmXMLImportContext +{ +public: + SmXMLPrescriptsContext_Impl(SmXMLImport& rImport) + : SmXMLImportContext(rImport) + { + } +}; + +class SmXMLTableRowContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLTableRowContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + { + } + + virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override; +}; + +class SmXMLTableContext_Impl : public SmXMLTableRowContext_Impl +{ +public: + SmXMLTableContext_Impl(SmXMLImport& rImport) + : SmXMLTableRowContext_Impl(rImport) + { + } + + void SAL_CALL endFastElement(sal_Int32 nElement) override; + virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override; +}; + +class SmXMLTableCellContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLTableCellContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + { + } +}; + +class SmXMLAlignGroupContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLAlignGroupContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + { + } + + /*Don't do anything with alignment for now*/ +}; + +class SmXMLActionContext_Impl : public SmXMLRowContext_Impl +{ + size_t mnSelection; // 1-based + +public: + SmXMLActionContext_Impl(SmXMLImport& rImport) + : SmXMLRowContext_Impl(rImport) + , mnSelection(1) + { + } + + void SAL_CALL startFastElement( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override; + void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; + +// NB: virtually inherit so we can multiply inherit properly +// in SmXMLFlatDocContext_Impl +class SmXMLOfficeContext_Impl : public virtual SvXMLImportContext +{ +public: + SmXMLOfficeContext_Impl(SmXMLImport& rImport) + : SvXMLImportContext(rImport) + { + } + + virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList) override; +}; +} + +uno::Reference<xml::sax::XFastContextHandler> SmXMLOfficeContext_Impl::createFastChildContext( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/) +{ + if (nElement == XML_ELEMENT(OFFICE, XML_META)) + { + SAL_WARN("starmath", + "XML_TOK_DOC_META: should not have come here, maybe document is invalid?"); + } + else if (nElement == XML_ELEMENT(OFFICE, XML_SETTINGS)) + { + return new XMLDocumentSettingsContext(GetImport()); + } + return nullptr; +} + +namespace +{ +// context for flat file xml format +class SmXMLFlatDocContext_Impl : public SmXMLOfficeContext_Impl, public SvXMLMetaDocumentContext +{ +public: + SmXMLFlatDocContext_Impl(SmXMLImport& i_rImport, + const uno::Reference<document::XDocumentProperties>& i_xDocProps); + + virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList) override; +}; +} + +SmXMLFlatDocContext_Impl::SmXMLFlatDocContext_Impl( + SmXMLImport& i_rImport, const uno::Reference<document::XDocumentProperties>& i_xDocProps) + : SvXMLImportContext(i_rImport) + , SmXMLOfficeContext_Impl(i_rImport) + , SvXMLMetaDocumentContext(i_rImport, i_xDocProps) +{ +} + +uno::Reference<xml::sax::XFastContextHandler> + SAL_CALL SmXMLFlatDocContext_Impl::createFastChildContext( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + // behave like meta base class iff we encounter office:meta + if (nElement == XML_ELEMENT(OFFICE, XML_META)) + { + return SvXMLMetaDocumentContext::createFastChildContext(nElement, xAttrList); + } + else + { + return SmXMLOfficeContext_Impl::createFastChildContext(nElement, xAttrList); + } +} + +uno::Reference<xml::sax::XFastContextHandler> SmXMLDocContext_Impl::createFastChildContext( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/) +{ + uno::Reference<xml::sax::XFastContextHandler> xContext; + + switch (nElement) + { + //Consider semantics a dummy except for any starmath annotations + case XML_ELEMENT(MATH, XML_SEMANTICS): + xContext = new SmXMLRowContext_Impl(GetSmImport()); + break; + /*General Layout Schemata*/ + case XML_ELEMENT(MATH, XML_MROW): + xContext = new SmXMLRowContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MENCLOSE): + xContext = new SmXMLEncloseContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MFRAC): + xContext = new SmXMLFracContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MSQRT): + xContext = new SmXMLSqrtContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MROOT): + xContext = new SmXMLRootContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MSTYLE): + xContext = new SmXMLStyleContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MERROR): + xContext = new SmXMLErrorContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MPADDED): + xContext = new SmXMLPaddedContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MPHANTOM): + xContext = new SmXMLPhantomContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MFENCED): + xContext = new SmXMLFencedContext_Impl(GetSmImport()); + break; + /*Script and Limit Schemata*/ + case XML_ELEMENT(MATH, XML_MSUB): + xContext = new SmXMLSubContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MSUP): + xContext = new SmXMLSupContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MSUBSUP): + xContext = new SmXMLSubSupContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MUNDER): + xContext = new SmXMLUnderContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MOVER): + xContext = new SmXMLOverContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MUNDEROVER): + xContext = new SmXMLUnderOverContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MMULTISCRIPTS): + xContext = new SmXMLMultiScriptsContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MTABLE): + xContext = new SmXMLTableContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MACTION): + xContext = new SmXMLActionContext_Impl(GetSmImport()); + break; + default: + /*Basically there's an implicit mrow around certain bare + *elements, use a RowContext to see if this is one of + *those ones*/ + rtl::Reference<SmXMLRowContext_Impl> aTempContext( + new SmXMLRowContext_Impl(GetSmImport())); + + xContext = aTempContext->StrictCreateChildContext(nElement); + break; + } + return xContext; +} + +void SmXMLDocContext_Impl::endFastElement(sal_Int32) +{ + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + + std::unique_ptr<SmNode> pContextNode = popOrZero(rNodeStack); + + SmToken aDummy; + std::unique_ptr<SmStructureNode> pSNode(new SmLineNode(aDummy)); + pSNode->SetSubNodes(std::move(pContextNode), nullptr); + rNodeStack.push_front(std::move(pSNode)); + + SmNodeArray LineArray; + auto n = rNodeStack.size(); + LineArray.resize(n); + for (size_t j = 0; j < n; j++) + { + auto pNode = std::move(rNodeStack.front()); + rNodeStack.pop_front(); + LineArray[n - (j + 1)] = pNode.release(); + } + std::unique_ptr<SmStructureNode> pSNode2(new SmTableNode(aDummy)); + pSNode2->SetSubNodes(std::move(LineArray)); + rNodeStack.push_front(std::move(pSNode2)); +} + +void SmXMLFracContext_Impl::endFastElement(sal_Int32) +{ + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + const bool bNodeCheck = rNodeStack.size() - nElementCount == 2; + OSL_ENSURE(bNodeCheck, "Fraction (mfrac) tag is missing component"); + if (!bNodeCheck) + return; + + SmToken aToken; + aToken.cMathChar = u""; + aToken.eType = TFRAC; + std::unique_ptr<SmStructureNode> pSNode(new SmBinVerNode(aToken)); + std::unique_ptr<SmNode> pOper(new SmRectangleNode(aToken)); + std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack); + std::unique_ptr<SmNode> pFirst = popOrZero(rNodeStack); + pSNode->SetSubNodes(std::move(pFirst), std::move(pOper), std::move(pSecond)); + rNodeStack.push_front(std::move(pSNode)); +} + +void SmXMLRootContext_Impl::endFastElement(sal_Int32) +{ + /*The <mroot> element requires exactly 2 arguments.*/ + const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2; + OSL_ENSURE(bNodeCheck, "Root tag is missing component"); + if (!bNodeCheck) + return; + + SmToken aToken; + aToken.setChar(MS_SQRT); //Temporary: alert, based on StarSymbol font + aToken.eType = TNROOT; + std::unique_ptr<SmStructureNode> pSNode(new SmRootNode(aToken)); + std::unique_ptr<SmNode> pOper(new SmRootSymbolNode(aToken)); + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + std::unique_ptr<SmNode> pIndex = popOrZero(rNodeStack); + std::unique_ptr<SmNode> pBase = popOrZero(rNodeStack); + pSNode->SetSubNodes(std::move(pIndex), std::move(pOper), std::move(pBase)); + rNodeStack.push_front(std::move(pSNode)); +} + +void SmXMLSqrtContext_Impl::endFastElement(sal_Int32 nElement) +{ + /* + <msqrt> accepts any number of arguments; if this number is not 1, its + contents are treated as a single "inferred <mrow>" containing its + arguments + */ + if (GetSmImport().GetNodeStack().size() - nElementCount != 1) + SmXMLRowContext_Impl::endFastElement(nElement); + + SmToken aToken; + aToken.setChar(MS_SQRT); //Temporary: alert, based on StarSymbol font + aToken.eType = TSQRT; + std::unique_ptr<SmStructureNode> pSNode(new SmRootNode(aToken)); + std::unique_ptr<SmNode> pOper(new SmRootSymbolNode(aToken)); + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + pSNode->SetSubNodes(nullptr, std::move(pOper), popOrZero(rNodeStack)); + rNodeStack.push_front(std::move(pSNode)); +} + +void SmXMLRowContext_Impl::endFastElement(sal_Int32) +{ + SmNodeArray aRelationArray; + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + + if (rNodeStack.size() > nElementCount) + { + auto nSize = rNodeStack.size() - nElementCount; + + aRelationArray.resize(nSize); + for (auto j = nSize; j > 0; j--) + { + auto pNode = std::move(rNodeStack.front()); + rNodeStack.pop_front(); + aRelationArray[j - 1] = pNode.release(); + } + + //If the first or last element is an operator with stretchyness + //set then we must create a brace node here from those elements, + //removing the stretchness from the operators and applying it to + //ourselves, and creating the appropriate dummy StarMath none bracket + //to balance the arrangement + if (((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height) + && (aRelationArray[0]->GetType() == SmNodeType::Math)) + || ((aRelationArray[nSize - 1]->GetScaleMode() == SmScaleMode::Height) + && (aRelationArray[nSize - 1]->GetType() == SmNodeType::Math))) + { + SmToken aToken; + aToken.cMathChar = u""; + aToken.nLevel = 5; + + int nLeft = 0, nRight = 0; + if ((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height) + && (aRelationArray[0]->GetType() == SmNodeType::Math)) + { + aToken = aRelationArray[0]->GetToken(); + nLeft = 1; + } + else + aToken.cMathChar = u""; + + aToken.eType = TLPARENT; + std::unique_ptr<SmNode> pLeft(new SmMathSymbolNode(aToken)); + + if ((aRelationArray[nSize - 1]->GetScaleMode() == SmScaleMode::Height) + && (aRelationArray[nSize - 1]->GetType() == SmNodeType::Math)) + { + aToken = aRelationArray[nSize - 1]->GetToken(); + nRight = 1; + } + else + aToken.cMathChar = u""; + + aToken.eType = TRPARENT; + std::unique_ptr<SmNode> pRight(new SmMathSymbolNode(aToken)); + + SmNodeArray aRelationArray2; + + //!! nSize-nLeft-nRight may be < 0 !! + int nRelArrSize = nSize - nLeft - nRight; + if (nRelArrSize > 0) + { + aRelationArray2.resize(nRelArrSize); + for (int i = 0; i < nRelArrSize; i++) + { + aRelationArray2[i] = aRelationArray[i + nLeft]; + aRelationArray[i + nLeft] = nullptr; + } + } + + SmToken aDummy; + std::unique_ptr<SmStructureNode> pSNode(new SmBraceNode(aToken)); + std::unique_ptr<SmStructureNode> pBody(new SmExpressionNode(aDummy)); + pBody->SetSubNodes(std::move(aRelationArray2)); + + pSNode->SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight)); + pSNode->SetScaleMode(SmScaleMode::Height); + rNodeStack.push_front(std::move(pSNode)); + + for (auto a : aRelationArray) + delete a; + + return; + } + } + else + { + // The elements msqrt, mstyle, merror, menclose, mpadded, mphantom, mtd, and math + // treat their content as a single inferred mrow in case their content is empty. + // Here an empty group {} is used to catch those cases and transform them without error + // to StarMath. + aRelationArray.resize(2); + SmToken aToken; + aToken.setChar(MS_LBRACE); + aToken.nLevel = 5; + aToken.eType = TLGROUP; + aToken.nGroup = TG::NONE; + aToken.aText = "{"; + aRelationArray[0] = new SmLineNode(aToken); + + aToken.setChar(MS_RBRACE); + aToken.nLevel = 0; + aToken.eType = TRGROUP; + aToken.nGroup = TG::NONE; + aToken.aText = "}"; + aRelationArray[1] = new SmLineNode(aToken); + } + + SmToken aDummy; + std::unique_ptr<SmStructureNode> pSNode(new SmExpressionNode(aDummy)); + pSNode->SetSubNodes(std::move(aRelationArray)); + rNodeStack.push_front(std::move(pSNode)); +} + +uno::Reference<xml::sax::XFastContextHandler> +SmXMLRowContext_Impl::StrictCreateChildContext(sal_Int32 nElement) +{ + uno::Reference<xml::sax::XFastContextHandler> pContext; + + switch (nElement) + { + /*Note that these should accept malignmark subelements, but do not*/ + case XML_ELEMENT(MATH, XML_MN): + pContext = new SmXMLNumberContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MI): + pContext = new SmXMLIdentifierContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MO): + pContext = new SmXMLOperatorContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MTEXT): + pContext = new SmXMLTextContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MSPACE): + pContext = new SmXMLSpaceContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_MS): + pContext = new SmXMLStringContext_Impl(GetSmImport()); + break; + + /*Note: The maligngroup should only be seen when the row + * (or descendants) are in a table*/ + case XML_ELEMENT(MATH, XML_MALIGNGROUP): + pContext = new SmXMLAlignGroupContext_Impl(GetSmImport()); + break; + + case XML_ELEMENT(MATH, XML_ANNOTATION): + pContext = new SmXMLAnnotationContext_Impl(GetSmImport()); + break; + + default: + break; + } + return pContext; +} + +uno::Reference<xml::sax::XFastContextHandler> SmXMLRowContext_Impl::createFastChildContext( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + uno::Reference<xml::sax::XFastContextHandler> xContext = StrictCreateChildContext(nElement); + + if (!xContext) + { + //Hmm, unrecognized for this level, check to see if it's + //an element that can have an implicit schema around it + xContext = SmXMLDocContext_Impl::createFastChildContext(nElement, xAttrList); + } + return xContext; +} + +uno::Reference<xml::sax::XFastContextHandler> SmXMLMultiScriptsContext_Impl::createFastChildContext( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + uno::Reference<xml::sax::XFastContextHandler> xContext; + + switch (nElement) + { + case XML_ELEMENT(MATH, XML_MPRESCRIPTS): + bHasPrescripts = true; + ProcessSubSupPairs(false); + xContext = new SmXMLPrescriptsContext_Impl(GetSmImport()); + break; + case XML_ELEMENT(MATH, XML_NONE): + xContext = new SmXMLNoneContext_Impl(GetSmImport()); + break; + default: + xContext = SmXMLRowContext_Impl::createFastChildContext(nElement, xAttrList); + break; + } + return xContext; +} + +void SmXMLMultiScriptsContext_Impl::ProcessSubSupPairs(bool bIsPrescript) +{ + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + + if (rNodeStack.size() <= nElementCount) + return; + + auto nCount = rNodeStack.size() - nElementCount - 1; + if (nCount == 0) + return; + + if (nCount % 2 == 0) + { + SmToken aToken; + aToken.cMathChar = u""; + aToken.eType = bIsPrescript ? TLSUB : TRSUB; + + SmNodeStack aReverseStack; + for (size_t i = 0; i < nCount + 1; i++) + { + auto pNode = std::move(rNodeStack.front()); + rNodeStack.pop_front(); + aReverseStack.push_front(std::move(pNode)); + } + + SmSubSup eSub = bIsPrescript ? LSUB : RSUB; + SmSubSup eSup = bIsPrescript ? LSUP : RSUP; + + for (size_t i = 0; i < nCount; i += 2) + { + std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken)); + + // initialize subnodes array + SmNodeArray aSubNodes(1 + SUBSUP_NUM_ENTRIES); + + /*On each loop the base and its sub sup pair becomes the + base for the next loop to which the next sub sup pair is + attached, i.e. wheels within wheels*/ + aSubNodes[0] = popOrZero(aReverseStack).release(); + + std::unique_ptr<SmNode> pScriptNode = popOrZero(aReverseStack); + + if (pScriptNode + && ((pScriptNode->GetToken().eType != TIDENT) + || (!pScriptNode->GetToken().aText.isEmpty()))) + aSubNodes[eSub + 1] = pScriptNode.release(); + pScriptNode = popOrZero(aReverseStack); + if (pScriptNode + && ((pScriptNode->GetToken().eType != TIDENT) + || (!pScriptNode->GetToken().aText.isEmpty()))) + aSubNodes[eSup + 1] = pScriptNode.release(); + + pNode->SetSubNodes(std::move(aSubNodes)); + aReverseStack.push_front(std::move(pNode)); + } + assert(!aReverseStack.empty()); + auto pNode = std::move(aReverseStack.front()); + aReverseStack.pop_front(); + rNodeStack.push_front(std::move(pNode)); + } + else + { + // Ignore odd number of elements. + for (size_t i = 0; i < nCount; i++) + { + rNodeStack.pop_front(); + } + } +} + +void SmXMLTableContext_Impl::endFastElement(sal_Int32) +{ + SmNodeArray aExpressionArray; + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + SmNodeStack aReverseStack; + aExpressionArray.resize(rNodeStack.size() - nElementCount); + + size_t nRows = rNodeStack.size() - nElementCount; + size_t nCols = 0; + + for (size_t i = nRows; i > 0; --i) + { + SmNode* pArray = rNodeStack.front().release(); + rNodeStack.pop_front(); + if (pArray->GetNumSubNodes() == 0) + { + //This is a little tricky, it is possible that there was + //be elements that were not inside a <mtd> pair, in which + //case they will not be in a row, i.e. they will not have + //SubNodes, so we have to wait until here before we can + //resolve the situation. Implicit surrounding tags are + //surprisingly difficult to get right within this + //architecture + + SmNodeArray aRelationArray; + aRelationArray.resize(1); + aRelationArray[0] = pArray; + SmToken aDummy; + SmExpressionNode* pExprNode = new SmExpressionNode(aDummy); + pExprNode->SetSubNodes(std::move(aRelationArray)); + pArray = pExprNode; + } + + nCols = std::max(nCols, pArray->GetNumSubNodes()); + aReverseStack.push_front(std::unique_ptr<SmNode>(pArray)); + } + if (nCols > SAL_MAX_UINT16) + throw std::range_error("column limit"); + if (nRows > SAL_MAX_UINT16) + throw std::range_error("row limit"); + aExpressionArray.resize(nCols * nRows); + size_t j = 0; + for (auto& elem : aReverseStack) + { + std::unique_ptr<SmStructureNode> xArray(static_cast<SmStructureNode*>(elem.release())); + for (size_t i = 0; i < xArray->GetNumSubNodes(); ++i) + aExpressionArray[j++] = xArray->GetSubNode(i); + xArray->ClearSubNodes(); + } + aReverseStack.clear(); + + SmToken aToken; + aToken.cMathChar = u""; + aToken.eType = TMATRIX; + std::unique_ptr<SmMatrixNode> pSNode(new SmMatrixNode(aToken)); + pSNode->SetSubNodes(std::move(aExpressionArray)); + pSNode->SetRowCol(nRows, nCols); + rNodeStack.push_front(std::move(pSNode)); +} + +uno::Reference<xml::sax::XFastContextHandler> SmXMLTableRowContext_Impl::createFastChildContext( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + uno::Reference<xml::sax::XFastContextHandler> xContext; + + switch (nElement) + { + case XML_ELEMENT(MATH, XML_MTD): + xContext = new SmXMLTableCellContext_Impl(GetSmImport()); + break; + default: + xContext = SmXMLRowContext_Impl::createFastChildContext(nElement, xAttrList); + break; + } + return xContext; +} + +uno::Reference<xml::sax::XFastContextHandler> SmXMLTableContext_Impl::createFastChildContext( + sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + uno::Reference<xml::sax::XFastContextHandler> xContext; + + switch (nElement) + { + case XML_ELEMENT(MATH, XML_MTR): + xContext = new SmXMLTableRowContext_Impl(GetSmImport()); + break; + default: + xContext = SmXMLTableRowContext_Impl::createFastChildContext(nElement, xAttrList); + break; + } + return xContext; +} + +void SmXMLMultiScriptsContext_Impl::endFastElement(sal_Int32) +{ + ProcessSubSupPairs(bHasPrescripts); +} + +void SmXMLActionContext_Impl::startFastElement( + sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) +{ + for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList)) + { + switch (aIter.getToken()) + { + case XML_SELECTION: + { + sal_Int32 n = aIter.toInt32(); + if (n > 0) + mnSelection = static_cast<size_t>(n); + } + break; + default: + XMLOFF_WARN_UNKNOWN("starmath", aIter); + break; + } + } +} + +void SmXMLActionContext_Impl::endFastElement(sal_Int32) +{ + SmNodeStack& rNodeStack = GetSmImport().GetNodeStack(); + auto nSize = rNodeStack.size(); + if (nSize <= nElementCount) + { + // not compliant to maction's specification, e.g., no subexpressions + return; + } + assert(mnSelection > 0); + if (nSize < nElementCount + mnSelection) + { + // No selected subexpression exists, which is a MathML error; + // fallback to selecting the first + mnSelection = 1; + } + assert(nSize >= nElementCount + mnSelection); + for (auto i = nSize - (nElementCount + mnSelection); i > 0; i--) + { + rNodeStack.pop_front(); + } + auto pSelected = std::move(rNodeStack.front()); + rNodeStack.pop_front(); + for (auto i = rNodeStack.size() - nElementCount; i > 0; i--) + { + rNodeStack.pop_front(); + } + rNodeStack.push_front(std::move(pSelected)); +} + +SvXMLImportContext* +SmXMLImport::CreateFastContext(sal_Int32 nElement, + const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/) +{ + SvXMLImportContext* pContext = nullptr; + + switch (nElement) + { + case XML_ELEMENT(OFFICE, XML_DOCUMENT): + case XML_ELEMENT(OFFICE, XML_DOCUMENT_META): + { + uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(), + uno::UNO_QUERY_THROW); + pContext = ((nElement & TOKEN_MASK) == XML_DOCUMENT_META) + ? new SvXMLMetaDocumentContext(*this, xDPS->getDocumentProperties()) + // flat OpenDocument file format -- this has not been tested... + : new SmXMLFlatDocContext_Impl(*this, xDPS->getDocumentProperties()); + } + break; + default: + if (IsTokenInNamespace(nElement, XML_NAMESPACE_OFFICE)) + pContext = new SmXMLOfficeContext_Impl(*this); + else + pContext = new SmXMLDocContext_Impl(*this); + } + return pContext; +} + +SmXMLImport::~SmXMLImport() noexcept { cleanup(); } + +void SmXMLImport::SetViewSettings(const Sequence<PropertyValue>& aViewProps) +{ + uno::Reference<frame::XModel> xModel = GetModel(); + if (!xModel.is()) + return; + + SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel); + + if (!pModel) + return; + + SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell()); + if (!pDocShell) + return; + + tools::Rectangle aRect(pDocShell->GetVisArea()); + + tools::Long nTmp = 0; + + for (const PropertyValue& rValue : aViewProps) + { + if (rValue.Name == "ViewAreaTop") + { + rValue.Value >>= nTmp; + aRect.SaturatingSetPosY(nTmp); + } + else if (rValue.Name == "ViewAreaLeft") + { + rValue.Value >>= nTmp; + aRect.SaturatingSetPosX(nTmp); + } + else if (rValue.Name == "ViewAreaWidth") + { + rValue.Value >>= nTmp; + Size aSize(aRect.GetSize()); + aSize.setWidth(nTmp); + aRect.SaturatingSetSize(aSize); + } + else if (rValue.Name == "ViewAreaHeight") + { + rValue.Value >>= nTmp; + Size aSize(aRect.GetSize()); + aSize.setHeight(nTmp); + aRect.SaturatingSetSize(aSize); + } + } + + pDocShell->SetVisArea(aRect); +} + +void SmXMLImport::SetConfigurationSettings(const Sequence<PropertyValue>& aConfProps) +{ + uno::Reference<XPropertySet> xProps(GetModel(), UNO_QUERY); + if (!xProps.is()) + return; + + Reference<XPropertySetInfo> xInfo(xProps->getPropertySetInfo()); + if (!xInfo.is()) + return; + + static const OUStringLiteral sFormula(u"Formula"); + static const OUStringLiteral sBasicLibraries(u"BasicLibraries"); + static const OUStringLiteral sDialogLibraries(u"DialogLibraries"); + for (const PropertyValue& rValue : aConfProps) + { + if (rValue.Name != sFormula && rValue.Name != sBasicLibraries + && rValue.Name != sDialogLibraries) + { + try + { + if (xInfo->hasPropertyByName(rValue.Name)) + xProps->setPropertyValue(rValue.Name, rValue.Value); + } + catch (const beans::PropertyVetoException&) + { + // dealing with read-only properties here. Nothing to do... + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION("starmath"); + } + } + } +} + +extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportMML(SvStream& rStream) +{ + SmGlobals::ensure(); + + SfxObjectShellLock xDocSh(new SmDocShell(SfxModelFlags::EMBEDDED_OBJECT)); + xDocSh->DoInitNew(); + uno::Reference<frame::XModel> xModel(xDocSh->GetModel()); + + uno::Reference<beans::XPropertySet> xInfoSet; + uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext()); + uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream)); + + //SetLoading hack because the document properties will be re-initted + //by the xml filter and during the init, while it's considered uninitialized, + //setting a property will inform the document it's modified, which attempts + //to update the properties, which throws cause the properties are uninitialized + xDocSh->SetLoading(SfxLoadedFlags::NONE); + + ErrCode nRet = ERRCODE_SFX_DOLOADFAILED; + + try + { + nRet = SmXMLImportWrapper::ReadThroughComponent(xStream, xModel, xContext, xInfoSet, + "com.sun.star.comp.Math.XMLImporter", false, + false); + } + catch (...) + { + } + + xDocSh->SetLoading(SfxLoadedFlags::ALL); + + xDocSh->DoClose(); + + return nRet != ERRCODE_NONE; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/mathml/starmathdatabase.cxx b/starmath/source/mathml/starmathdatabase.cxx new file mode 100644 index 000000000..66bdf3f34 --- /dev/null +++ b/starmath/source/mathml/starmathdatabase.cxx @@ -0,0 +1,794 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <starmathdatabase.hxx> +#include <types.hxx> + +SmToken starmathdatabase::Identify_SmXMLOperatorContext_Impl(sal_Unicode cChar, bool bIsStretchy) +{ + switch (cChar) + { + case MS_COPROD: + return SmToken(TCOPROD, MS_COPROD, "coprod", TG::Oper, 5); + case MS_IIINT: + return SmToken(TIIINT, MS_IIINT, "iiint", TG::Oper, 5); + case MS_IINT: + return SmToken(TIINT, MS_IINT, "iint", TG::Oper, 5); + case MS_INT: + if (bIsStretchy) + return SmToken(TINTD, MS_INT, "intd", TG::Oper, 5); + else + return SmToken(TINT, MS_INT, "int", TG::Oper, 5); + case MS_LINT: + return SmToken(TLINT, MS_LINT, "lint", TG::Oper, 5); + case MS_LLINT: + return SmToken(TLLINT, MS_LLINT, "llint", TG::Oper, 5); + case MS_LLLINT: + return SmToken(TLLLINT, MS_LLLINT, "lllint", TG::Oper, 5); + case MS_PROD: + return SmToken(TPROD, MS_PROD, "prod", TG::Oper, 5); + case MS_SUM: + return SmToken(TSUM, MS_SUM, "sum", TG::Oper, 5); + case MS_FACT: + return SmToken(TFACT, MS_FACT, "!", TG::UnOper, 5); + case MS_NEG: + return SmToken(TNEG, MS_NEG, "neg", TG::UnOper, 5); + case MS_OMINUS: + return SmToken(TOMINUS, MS_OMINUS, "ominus", TG::Sum, 0); + case MS_OPLUS: + return SmToken(TOPLUS, MS_OPLUS, "oplus", TG::Sum, 0); + case MS_UNION: + return SmToken(TUNION, MS_UNION, "union", TG::Sum, 0); + case MS_OR: + return SmToken(TOR, MS_OR, "|", TG::Sum, 5); + case MS_PLUSMINUS: + return SmToken(TPLUSMINUS, MS_PLUSMINUS, "+-", TG::Sum | TG::UnOper, 5); + case MS_MINUSPLUS: + return SmToken(TMINUSPLUS, MS_MINUSPLUS, "-+", TG::Sum | TG::UnOper, 5); + case 0xe083: + case MS_PLUS: + return SmToken(TPLUS, MS_PLUS, "+", TG::Sum | TG::UnOper, 5); + case MS_MINUS: + return SmToken(TMINUS, MS_MINUS, "-", TG::Sum | TG::UnOper, 5); + case 0x2022: + case MS_CDOT: + return SmToken(TCDOT, MS_CDOT, "cdot", TG::Product, 0); + case MS_DIV: + return SmToken(TDIV, MS_DIV, "div", TG::Product, 0); + case MS_TIMES: + return SmToken(TTIMES, MS_TIMES, "times", TG::Product, 0); + case MS_INTERSECT: + return SmToken(TINTERSECT, MS_INTERSECT, "intersection", TG::Product, 0); + case MS_ODIVIDE: + return SmToken(TODIVIDE, MS_ODIVIDE, "odivide", TG::Product, 0); + case MS_ODOT: + return SmToken(TODOT, MS_ODOT, "odot", TG::Product, 0); + case MS_OTIMES: + return SmToken(TOTIMES, MS_OTIMES, "otimes", TG::Product, 0); + case MS_AND: + return SmToken(TAND, MS_AND, "&", TG::Product, 0); + case MS_MULTIPLY: + return SmToken(TMULTIPLY, MS_MULTIPLY, "*", TG::Product, 0); + case MS_SLASH: + if (bIsStretchy) + return SmToken(TWIDESLASH, MS_SLASH, "wideslash", TG::Product, 0); + else + return SmToken(TSLASH, MS_SLASH, "slash", TG::Product, 0); + case MS_BACKSLASH: + if (bIsStretchy) + return SmToken(TWIDEBACKSLASH, MS_BACKSLASH, "widebslash", TG::Product, 0); + else + return SmToken(TBACKSLASH, MS_BACKSLASH, "bslash", TG::Product, 0); + case MS_DEF: + return SmToken(TDEF, MS_DEF, "def", TG::Relation, 0); + case MS_LINE: + return SmToken(TDIVIDES, MS_LINE, "divides", TG::Relation, 0); + case MS_EQUIV: + return SmToken(TEQUIV, MS_EQUIV, "equiv", TG::Relation, 0); + case MS_GE: + return SmToken(TGE, MS_GE, ">=", TG::Relation, 0); + case MS_GESLANT: + return SmToken(TGESLANT, MS_GESLANT, "geslant", TG::Relation, 0); + case MS_GG: + return SmToken(TGG, MS_GG, ">>", TG::Relation, 0); + case MS_GT: + return SmToken(TGT, MS_GT, ">", TG::Relation, 0); + case MS_IN: + return SmToken(TIN, MS_IN, "in", TG::Relation, 0); + case MS_LE: + return SmToken(TLE, MS_LE, "<=", TG::Relation, 0); + case MS_LESLANT: + return SmToken(TLESLANT, MS_LESLANT, "leslant", TG::Relation, 0); + case MS_LL: + return SmToken(TLL, MS_LL, "<<", TG::Relation, 0); + case MS_LT: + return SmToken(TLT, MS_LT, "<", TG::Relation, 0); + case MS_NDIVIDES: + return SmToken(TNDIVIDES, MS_NDIVIDES, "ndivides", TG::Relation, 0); + case MS_NEQ: + return SmToken(TNEQ, MS_NEQ, "<>", TG::Relation, 0); + case MS_NOTIN: + return SmToken(TNOTIN, MS_NOTIN, "notin", TG::Relation, 0); + case MS_NOTPRECEDES: + return SmToken(TNOTPRECEDES, MS_NOTPRECEDES, "nprec", TG::Relation, 0); + case MS_NSUBSET: + return SmToken(TNSUBSET, MS_NSUBSET, "nsubset", TG::Relation, 0); + case MS_NSUBSETEQ: + return SmToken(TNSUBSETEQ, MS_NSUBSETEQ, "nsubseteq", TG::Relation, 0); + case MS_NOTSUCCEEDS: + return SmToken(TNOTSUCCEEDS, MS_NOTSUCCEEDS, "nsucc", TG::Relation, 0); + case MS_NSUPSET: + return SmToken(TNSUPSET, MS_NSUPSET, "nsupset", TG::Relation, 0); + case MS_NSUPSETEQ: + return SmToken(TNSUPSETEQ, MS_NSUPSETEQ, "nsupseteq", TG::Relation, 0); + case MS_ORTHO: + return SmToken(TORTHO, MS_ORTHO, "ortho", TG::Relation, 0); + case MS_NI: + return SmToken(TNI, MS_NI, "owns", TG::Relation, 0); + case MS_DLINE: + return SmToken(TPARALLEL, MS_DLINE, "parallel", TG::Relation, 0); + case MS_PRECEDES: + return SmToken(TPRECEDES, MS_PRECEDES, "prec", TG::Relation, 0); + case MS_PRECEDESEQUAL: + return SmToken(TPRECEDESEQUAL, MS_PRECEDESEQUAL, "preccurlyeq", TG::Relation, 0); + case MS_PRECEDESEQUIV: + return SmToken(TPRECEDESEQUIV, MS_PRECEDESEQUIV, "precsim", TG::Relation, 0); + case MS_PROP: + return SmToken(TPROP, MS_PROP, "prop", TG::Relation, 0); + case MS_SIM: + return SmToken(TSIM, MS_SIM, "sim", TG::Relation, 0); + case 0x2245: + case MS_SIMEQ: + return SmToken(TSIMEQ, MS_SIMEQ, "simeq", TG::Relation, 0); + case MS_SUBSET: + return SmToken(TSUBSET, MS_SUBSET, "subset", TG::Relation, 0); + case MS_SUBSETEQ: + return SmToken(TSUBSETEQ, MS_SUBSETEQ, "subseteq", TG::Relation, 0); + case MS_SUCCEEDS: + return SmToken(TSUCCEEDS, MS_SUCCEEDS, "succ", TG::Relation, 0); + case MS_SUCCEEDSEQUAL: + return SmToken(TSUCCEEDSEQUAL, MS_SUCCEEDSEQUAL, "succcurlyeq", TG::Relation, 0); + case MS_SUCCEEDSEQUIV: + return SmToken(TSUCCEEDSEQUIV, MS_SUCCEEDSEQUIV, "succsim", TG::Relation, 0); + case MS_SUPSET: + return SmToken(TSUPSET, MS_SUPSET, "supset", TG::Relation, 0); + case MS_SUPSETEQ: + return SmToken(TSUPSETEQ, MS_SUPSETEQ, "supseteq", TG::Relation, 0); + case MS_RIGHTARROW: + return SmToken(TTOWARD, MS_RIGHTARROW, "toward", TG::Relation, 0); + case MS_TRANSL: + return SmToken(TTRANSL, MS_TRANSL, "transl", TG::Relation, 0); + case MS_TRANSR: + return SmToken(TTRANSR, MS_TRANSR, "transr", TG::Relation, 0); + case MS_ASSIGN: + return SmToken(TASSIGN, MS_ASSIGN, "=", TG::Relation, 0); + case MS_LANGLE: + return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5); + case MS_LMATHANGLE: + return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5); + case MS_LBRACE: + return SmToken(TLBRACE, MS_LBRACE, "lbrace", TG::LBrace, 5); + case MS_LCEIL: + return SmToken(TLCEIL, MS_LCEIL, "lceil", TG::LBrace, 5); + case MS_LFLOOR: + return SmToken(TLFLOOR, MS_LFLOOR, "lfloor", TG::LBrace, 5); + case MS_LDBRACKET: + return SmToken(TLDBRACKET, MS_LDBRACKET, "ldbracket", TG::LBrace, 5); + case MS_LBRACKET: + return SmToken(TLBRACKET, MS_LBRACKET, "[", TG::LBrace, 5); + case MS_LPARENT: + return SmToken(TLPARENT, MS_LPARENT, "(", TG::LBrace, 5); + case MS_RANGLE: + return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5); + case MS_RMATHANGLE: + return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5); + case MS_RBRACE: + return SmToken(TRBRACE, MS_RBRACE, "rbrace", TG::RBrace, 5); + case MS_RCEIL: + return SmToken(TRCEIL, MS_RCEIL, "rceil", TG::RBrace, 5); + case MS_RFLOOR: + return SmToken(TRFLOOR, MS_RFLOOR, "rfloor", TG::RBrace, 5); + case MS_RDBRACKET: + return SmToken(TRDBRACKET, MS_RDBRACKET, "rdbracket", TG::RBrace, 5); + case MS_RBRACKET: + return SmToken(TRBRACKET, MS_RBRACKET, "]", TG::RBrace, 5); + case MS_RPARENT: + return SmToken(TRPARENT, MS_RPARENT, ")", TG::RBrace, 5); + case MS_NONE: + return SmToken(TNONE, MS_NONE, "none", TG::RBrace | TG::LBrace, 5); + default: + return SmToken(TERROR, MS_NONE, "", TG::NONE, SAL_MAX_UINT16); + } +} + +SmToken starmathdatabase::Identify_Prefix_SmXMLOperatorContext_Impl(sal_Unicode cChar) +{ + switch (cChar) + { + case MS_VERTLINE: + return SmToken(TLLINE, MS_VERTLINE, "lline", TG::LBrace, 5); + case MS_DVERTLINE: + return SmToken(TLDLINE, MS_DVERTLINE, "ldline", TG::LBrace, 5); + case MS_LANGLE: + return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5); + case MS_LMATHANGLE: + return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5); + case MS_LBRACE: + return SmToken(TLBRACE, MS_LBRACE, "lbrace", TG::LBrace, 5); + case MS_LCEIL: + return SmToken(TLCEIL, MS_LCEIL, "lceil", TG::LBrace, 5); + case MS_LFLOOR: + return SmToken(TLFLOOR, MS_LFLOOR, "lfloor", TG::LBrace, 5); + case MS_LDBRACKET: + return SmToken(TLDBRACKET, MS_LDBRACKET, "ldbracket", TG::LBrace, 5); + case MS_LBRACKET: + return SmToken(TLBRACKET, MS_LBRACKET, "[", TG::LBrace, 5); + case MS_LPARENT: + return SmToken(TLPARENT, MS_LPARENT, "(", TG::LBrace, 5); + case MS_RANGLE: + return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5); + case MS_RMATHANGLE: + return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5); + case MS_RBRACE: + return SmToken(TRBRACE, MS_RBRACE, "rbrace", TG::RBrace, 5); + case MS_RCEIL: + return SmToken(TRCEIL, MS_RCEIL, "rceil", TG::RBrace, 5); + case MS_RFLOOR: + return SmToken(TRFLOOR, MS_RFLOOR, "rfloor", TG::RBrace, 5); + case MS_RDBRACKET: + return SmToken(TRDBRACKET, MS_RDBRACKET, "rdbracket", TG::RBrace, 5); + case MS_RBRACKET: + return SmToken(TRBRACKET, MS_RBRACKET, "]", TG::RBrace, 5); + case MS_RPARENT: + return SmToken(TRPARENT, MS_RPARENT, ")", TG::RBrace, 5); + case MS_NONE: + return SmToken(TNONE, MS_NONE, "none", TG::LBrace | TG::RBrace, 5); + default: + return SmToken(TERROR, MS_NONE, "", TG::NONE, SAL_MAX_UINT16); + } +} + +SmToken starmathdatabase::Identify_Postfix_SmXMLOperatorContext_Impl(sal_Unicode cChar) +{ + switch (cChar) + { + case MS_VERTLINE: + return SmToken(TRLINE, MS_VERTLINE, "rline", TG::RBrace, 5); + case MS_DVERTLINE: + return SmToken(TRDLINE, MS_DVERTLINE, "rdline", TG::RBrace, 5); + case MS_LANGLE: + return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5); + case MS_LMATHANGLE: + return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5); + case MS_LBRACE: + return SmToken(TLBRACE, MS_LBRACE, "lbrace", TG::LBrace, 5); + case MS_LCEIL: + return SmToken(TLCEIL, MS_LCEIL, "lceil", TG::LBrace, 5); + case MS_LFLOOR: + return SmToken(TLFLOOR, MS_LFLOOR, "lfloor", TG::LBrace, 5); + case MS_LDBRACKET: + return SmToken(TLDBRACKET, MS_LDBRACKET, "ldbracket", TG::LBrace, 5); + case MS_LBRACKET: + return SmToken(TLBRACKET, MS_LBRACKET, "[", TG::LBrace, 5); + case MS_LPARENT: + return SmToken(TLPARENT, MS_LPARENT, "(", TG::LBrace, 5); + case MS_RANGLE: + return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5); + case MS_RMATHANGLE: + return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5); + case MS_RBRACE: + return SmToken(TRBRACE, MS_RBRACE, "rbrace", TG::RBrace, 5); + case MS_RCEIL: + return SmToken(TRCEIL, MS_RCEIL, "rceil", TG::RBrace, 5); + case MS_RFLOOR: + return SmToken(TRFLOOR, MS_RFLOOR, "rfloor", TG::RBrace, 5); + case MS_RDBRACKET: + return SmToken(TRDBRACKET, MS_RDBRACKET, "rdbracket", TG::RBrace, 5); + case MS_RBRACKET: + return SmToken(TRBRACKET, MS_RBRACKET, "]", TG::RBrace, 5); + case MS_RPARENT: + return SmToken(TRPARENT, MS_RPARENT, ")", TG::RBrace, 5); + case MS_NONE: + return SmToken(TNONE, MS_NONE, "none", TG::LBrace | TG::RBrace, 5); + default: + return SmToken(TERROR, MS_NONE, "", TG::NONE, SAL_MAX_UINT16); + } +} + +SmToken starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl(sal_Unicode cChar) +{ + switch (cChar) + { + case MS_VERTLINE: + return SmToken(TLRLINE, MS_VERTLINE, "lrline", TG::LBrace | TG::RBrace, 5); + case MS_DVERTLINE: + return SmToken(TLRDLINE, MS_DVERTLINE, "lrdline", TG::LBrace | TG::RBrace, 5); + case MS_LANGLE: + return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5); + case MS_LMATHANGLE: + return SmToken(TLANGLE, MS_LMATHANGLE, "langle", TG::LBrace, 5); + case MS_LBRACE: + return SmToken(TLBRACE, MS_LBRACE, "lbrace", TG::LBrace, 5); + case MS_LCEIL: + return SmToken(TLCEIL, MS_LCEIL, "lceil", TG::LBrace, 5); + case MS_LFLOOR: + return SmToken(TLFLOOR, MS_LFLOOR, "lfloor", TG::LBrace, 5); + case MS_LDBRACKET: + return SmToken(TLDBRACKET, MS_LDBRACKET, "ldbracket", TG::LBrace, 5); + case MS_LBRACKET: + return SmToken(TLBRACKET, MS_LBRACKET, "[", TG::LBrace, 5); + case MS_LPARENT: + return SmToken(TLPARENT, MS_LPARENT, "(", TG::LBrace, 5); + case MS_RANGLE: + return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5); + case MS_RMATHANGLE: + return SmToken(TRANGLE, MS_RMATHANGLE, "rangle", TG::RBrace, 5); + case MS_RBRACE: + return SmToken(TRBRACE, MS_RBRACE, "rbrace", TG::RBrace, 5); + case MS_RCEIL: + return SmToken(TRCEIL, MS_RCEIL, "rceil", TG::RBrace, 5); + case MS_RFLOOR: + return SmToken(TRFLOOR, MS_RFLOOR, "rfloor", TG::RBrace, 5); + case MS_RDBRACKET: + return SmToken(TRDBRACKET, MS_RDBRACKET, "rdbracket", TG::RBrace, 5); + case MS_RBRACKET: + return SmToken(TRBRACKET, MS_RBRACKET, "]", TG::RBrace, 5); + case MS_RPARENT: + return SmToken(TRPARENT, MS_RPARENT, ")", TG::RBrace, 5); + case MS_NONE: + return SmToken(TNONE, MS_NONE, "none", TG::LBrace | TG::RBrace, 5); + default: + return SmToken(TERROR, MS_NONE, "", TG::NONE, SAL_MAX_UINT16); + } +} + +const SmColorTokenTableEntry starmathdatabase::aColorTokenTableParse[] + = { { "aliceblue", THTMLCOL, COL_SM_ALICEBLUE }, + { "antiquewhite", THTMLCOL, COL_SM_ANTIQUEWHITE }, + { "aqua", TMATHMLCOL, COL_SM_AQUA }, + { "aquamarine", THTMLCOL, COL_SM_AQUAMARINE }, + { "azure", THTMLCOL, COL_SM_AZURE }, + { "beige", THTMLCOL, COL_SM_BEIGE }, + { "bisque", THTMLCOL, COL_SM_BISQUE }, + { "black", TMATHMLCOL, COL_SM_BLACK }, + { "blanchedalmond", THTMLCOL, COL_SM_BLANCHEDALMOND }, + { "blue", TMATHMLCOL, COL_SM_BLUE }, + { "blueviolet", THTMLCOL, COL_SM_BLUEVIOLET }, + { "brown", THTMLCOL, COL_SM_BROWN }, + { "burlywood", THTMLCOL, COL_SM_BURLYWOOD }, + { "cadetblue", THTMLCOL, COL_SM_CADETBLUE }, + { "chartreuse", THTMLCOL, COL_SM_CHARTREUSE }, + { "chocolate", THTMLCOL, COL_SM_CHOCOLATE }, + { "coral", THTMLCOL, COL_SM_CORAL }, + { "cornflowerblue", THTMLCOL, COL_SM_CORNFLOWERBLUE }, + { "cornsilk", THTMLCOL, COL_SM_CORNSILK }, + { "crimson", THTMLCOL, COL_SM_CRIMSON }, + { "cyan", TMATHMLCOL, COL_SM_CYAN }, + { "darkblue", THTMLCOL, COL_SM_DARKBLUE }, + { "darkcyan", THTMLCOL, COL_SM_DARKCYAN }, + { "darkgoldenrod", THTMLCOL, COL_SM_DARKGOLDENROD }, + { "darkgray", THTMLCOL, COL_SM_DARKGRAY }, + { "darkgreen", THTMLCOL, COL_SM_DARKGREEN }, + { "darkgrey", THTMLCOL, COL_SM_DARKGREY }, + { "darkkhaki", THTMLCOL, COL_SM_DARKKHAKI }, + { "darkmagenta", THTMLCOL, COL_SM_DARKMAGENTA }, + { "darkolivegreen", THTMLCOL, COL_SM_DARKOLIVEGREEN }, + { "darkorange", THTMLCOL, COL_SM_DARKORANGE }, + { "darkorchid", THTMLCOL, COL_SM_DARKORCHID }, + { "darkred", THTMLCOL, COL_SM_DARKRED }, + { "darksalmon", THTMLCOL, COL_SM_DARKSALMON }, + { "darkseagreen", THTMLCOL, COL_SM_DARKSEAGREEN }, + { "darkslateblue", THTMLCOL, COL_SM_DARKSLATEBLUE }, + { "darkslategray", THTMLCOL, COL_SM_DARKSLATEGRAY }, + { "darkslategrey", THTMLCOL, COL_SM_DARKSLATEGREY }, + { "darkturquoise", THTMLCOL, COL_SM_DARKTURQUOISE }, + { "darkviolet", THTMLCOL, COL_SM_DARKVIOLET }, + { "debian", TICONICCOL, COL_SM_DEBIAN_MAGENTA }, + { "deeppink", THTMLCOL, COL_SM_DEEPPINK }, + { "deepskyblue", THTMLCOL, COL_SM_DEEPSKYBLUE }, + { "dimgray", THTMLCOL, COL_SM_DIMGRAY }, + { "dimgrey", THTMLCOL, COL_SM_DIMGREY }, + { "dodgerblue", THTMLCOL, COL_SM_DODGERBLUE }, + { "dvip", TDVIPSNAMESCOL, COL_SM_BLACK }, + { "firebrick", THTMLCOL, COL_SM_FIREBRICK }, + { "floralwhite", THTMLCOL, COL_SM_FLORALWHITE }, + { "forestgreen", THTMLCOL, COL_SM_FORESTGREEN }, + { "fuchsia", TMATHMLCOL, COL_SM_FUCHSIA }, + { "gainsboro", THTMLCOL, COL_SM_GAINSBORO }, + { "ghostwhite", THTMLCOL, COL_SM_GHOSTWHITE }, + { "gold", THTMLCOL, COL_SM_GOLD }, + { "goldenrod", THTMLCOL, COL_SM_GOLDENROD }, + { "gray", TMATHMLCOL, COL_SM_GRAY }, + { "green", TMATHMLCOL, COL_SM_GREEN }, + { "greenyellow", THTMLCOL, COL_SM_GREENYELLOW }, + { "grey", THTMLCOL, COL_SM_GREY }, + { "hex", THEX, COL_SM_BLACK }, + { "honeydew", THTMLCOL, COL_SM_HONEYDEW }, + { "hotpink", THTMLCOL, COL_SM_HOTPINK }, + { "indianred", THTMLCOL, COL_SM_INDIANRED }, + { "indigo", THTMLCOL, COL_SM_INDIGO }, + { "ivory", THTMLCOL, COL_SM_IVORY }, + { "khaki", THTMLCOL, COL_SM_KHAKI }, + { "lavender", THTMLCOL, COL_SM_LAVENDER }, + { "lavenderblush", THTMLCOL, COL_SM_LAVENDERBLUSH }, + { "lawngreen", THTMLCOL, COL_SM_LAWNGREEN }, + { "lemonchiffon", THTMLCOL, COL_SM_LEMONCHIFFON }, + { "lightblue", THTMLCOL, COL_SM_LIGHTBLUE }, + { "lightcoral", THTMLCOL, COL_SM_LIGHTCORAL }, + { "lightcyan", THTMLCOL, COL_SM_LIGHTCYAN }, + { "lightgoldenrodyellow", THTMLCOL, COL_SM_LIGHTGOLDENRODYELLOW }, + { "lightgray", THTMLCOL, COL_SM_LIGHTGRAY }, + { "lightgreen", THTMLCOL, COL_SM_LIGHTGREEN }, + { "lightgrey", THTMLCOL, COL_SM_LIGHTGREY }, + { "lightpink", THTMLCOL, COL_SM_LIGHTPINK }, + { "lightsalmon", THTMLCOL, COL_SM_LIGHTSALMON }, + { "lightseagreen", THTMLCOL, COL_SM_LIGHTSEAGREEN }, + { "lightskyblue", THTMLCOL, COL_SM_LIGHTSKYBLUE }, + { "lightslategray", THTMLCOL, COL_SM_LIGHTSLATEGRAY }, + { "lightslategrey", THTMLCOL, COL_SM_LIGHTSLATEGREY }, + { "lightsteelblue", THTMLCOL, COL_SM_LIGHTSTEELBLUE }, + { "lightyellow", THTMLCOL, COL_SM_LIGHTYELLOW }, + { "lime", TMATHMLCOL, COL_SM_LIME }, + { "limegreen", THTMLCOL, COL_SM_LIMEGREEN }, + { "linen", THTMLCOL, COL_SM_LINEN }, + { "lo", TICONICCOL, COL_SM_LO_GREEN }, + { "magenta", TMATHMLCOL, COL_SM_MAGENTA }, + { "maroon", TMATHMLCOL, COL_SM_MAROON }, + { "mediumaquamarine", THTMLCOL, COL_SM_MEDIUMAQUAMARINE }, + { "mediumblue", THTMLCOL, COL_SM_MEDIUMBLUE }, + { "mediumorchid", THTMLCOL, COL_SM_MEDIUMORCHID }, + { "mediumpurple", THTMLCOL, COL_SM_MEDIUMPURPLE }, + { "mediumseagreen", THTMLCOL, COL_SM_MEDIUMSEAGREEN }, + { "mediumslateblue", THTMLCOL, COL_SM_MEDIUMSLATEBLUE }, + { "mediumspringgreen", THTMLCOL, COL_SM_MEDIUMSPRINGGREEN }, + { "mediumturquoise", THTMLCOL, COL_SM_MEDIUMTURQUOISE }, + { "mediumvioletred", THTMLCOL, COL_SM_MEDIUMVIOLETRED }, + { "midnightblue", THTMLCOL, COL_SM_MIDNIGHTBLUE }, + { "mintcream", THTMLCOL, COL_SM_MINTCREAM }, + { "mistyrose", THTMLCOL, COL_SM_MISTYROSE }, + { "moccasin", THTMLCOL, COL_SM_MOCCASIN }, + { "navajowhite", THTMLCOL, COL_SM_NAVAJOWHITE }, + { "navy", TMATHMLCOL, COL_SM_NAVY }, + { "oldlace", THTMLCOL, COL_SM_OLDLACE }, + { "olive", TMATHMLCOL, COL_SM_OLIVE }, + { "olivedrab", THTMLCOL, COL_SM_OLIVEDRAB }, + { "orange", THTMLCOL, COL_SM_ORANGE }, + { "orangered", THTMLCOL, COL_SM_ORANGERED }, + { "orchid", THTMLCOL, COL_SM_ORCHID }, + { "palegoldenrod", THTMLCOL, COL_SM_PALEGOLDENROD }, + { "palegreen", THTMLCOL, COL_SM_PALEGREEN }, + { "paleturquoise", THTMLCOL, COL_SM_PALETURQUOISE }, + { "palevioletred", THTMLCOL, COL_SM_PALEVIOLETRED }, + { "papayawhip", THTMLCOL, COL_SM_PAPAYAWHIP }, + { "peachpuff", THTMLCOL, COL_SM_PEACHPUFF }, + { "peru", THTMLCOL, COL_SM_PERU }, + { "pink", THTMLCOL, COL_SM_PINK }, + { "plum", THTMLCOL, COL_SM_PLUM }, + { "powderblue", THTMLCOL, COL_SM_POWDERBLUE }, + { "purple", TMATHMLCOL, COL_SM_PURPLE }, + { "rebeccapurple", THTMLCOL, COL_SM_REBECCAPURPLE }, + { "red", TMATHMLCOL, COL_SM_RED }, + { "rgb", TRGB, COL_AUTO }, + { "rgba", TRGBA, COL_AUTO }, + { "rosybrown", THTMLCOL, COL_SM_ROSYBROWN }, + { "royalblue", THTMLCOL, COL_SM_ROYALBLUE }, + { "saddlebrown", THTMLCOL, COL_SM_SADDLEBROWN }, + { "salmon", THTMLCOL, COL_SM_SALMON }, + { "sandybrown", THTMLCOL, COL_SM_SANDYBROWN }, + { "seagreen", THTMLCOL, COL_SM_SEAGREEN }, + { "seashell", THTMLCOL, COL_SM_SEASHELL }, + { "sienna", THTMLCOL, COL_SM_SIENNA }, + { "silver", TMATHMLCOL, COL_SM_SILVER }, + { "skyblue", THTMLCOL, COL_SM_SKYBLUE }, + { "slateblue", THTMLCOL, COL_SM_SLATEBLUE }, + { "slategray", THTMLCOL, COL_SM_SLATEGRAY }, + { "slategrey", THTMLCOL, COL_SM_SLATEGREY }, + { "snow", THTMLCOL, COL_SM_SNOW }, + { "springgreen", THTMLCOL, COL_SM_SPRINGGREEN }, + { "steelblue", THTMLCOL, COL_SM_STEELBLUE }, + { "tan", THTMLCOL, COL_SM_TAN }, + { "teal", TMATHMLCOL, COL_SM_TEAL }, + { "thistle", THTMLCOL, COL_SM_THISTLE }, + { "tomato", THTMLCOL, COL_SM_TOMATO }, + { "turquoise", THTMLCOL, COL_SM_TURQUOISE }, + { "ubuntu", TICONICCOL, COL_SM_UBUNTU_ORANGE }, + { "violet", THTMLCOL, COL_SM_VIOLET }, + { "wheat", THTMLCOL, COL_SM_WHEAT }, + { "white", TMATHMLCOL, COL_SM_WHITE }, + { "whitesmoke", THTMLCOL, COL_SM_WHITESMOKE }, + { "yellow", TMATHMLCOL, COL_SM_YELLOW }, + { "yellowgreen", THTMLCOL, COL_SM_YELLOWGREEN } }; + +const SmColorTokenTableEntry starmathdatabase::aColorTokenTableHTML[] + = { { "aliceblue", THTMLCOL, COL_SM_ALICEBLUE }, + { "antiquewhite", THTMLCOL, COL_SM_ANTIQUEWHITE }, + { "aqua", TMATHMLCOL, COL_SM_AQUA }, + { "aquamarine", THTMLCOL, COL_SM_AQUAMARINE }, + { "azure", THTMLCOL, COL_SM_AZURE }, + { "beige", THTMLCOL, COL_SM_BEIGE }, + { "bisque", THTMLCOL, COL_SM_BISQUE }, + { "black", TMATHMLCOL, COL_SM_BLACK }, + { "blanchedalmond", THTMLCOL, COL_SM_BLANCHEDALMOND }, + { "blue", TMATHMLCOL, COL_SM_BLUE }, + { "blueviolet", THTMLCOL, COL_SM_BLUEVIOLET }, + { "brown", THTMLCOL, COL_SM_BROWN }, + { "burlywood", THTMLCOL, COL_SM_BURLYWOOD }, + { "cadetblue", THTMLCOL, COL_SM_CADETBLUE }, + { "chartreuse", THTMLCOL, COL_SM_CHARTREUSE }, + { "chocolate", THTMLCOL, COL_SM_CHOCOLATE }, + { "coral", THTMLCOL, COL_SM_CORAL }, + { "cornflowerblue", THTMLCOL, COL_SM_CORNFLOWERBLUE }, + { "cornsilk", THTMLCOL, COL_SM_CORNSILK }, + { "crimson", THTMLCOL, COL_SM_CRIMSON }, + { "cyan", TMATHMLCOL, COL_SM_CYAN }, + { "darkblue", THTMLCOL, COL_SM_DARKBLUE }, + { "darkcyan", THTMLCOL, COL_SM_DARKCYAN }, + { "darkgoldenrod", THTMLCOL, COL_SM_DARKGOLDENROD }, + { "darkgray", THTMLCOL, COL_SM_DARKGRAY }, + { "darkgreen", THTMLCOL, COL_SM_DARKGREEN }, + { "darkgrey", THTMLCOL, COL_SM_DARKGREY }, + { "darkkhaki", THTMLCOL, COL_SM_DARKKHAKI }, + { "darkmagenta", THTMLCOL, COL_SM_DARKMAGENTA }, + { "darkolivegreen", THTMLCOL, COL_SM_DARKOLIVEGREEN }, + { "darkorange", THTMLCOL, COL_SM_DARKORANGE }, + { "darkorchid", THTMLCOL, COL_SM_DARKORCHID }, + { "darkred", THTMLCOL, COL_SM_DARKRED }, + { "darksalmon", THTMLCOL, COL_SM_DARKSALMON }, + { "darkseagreen", THTMLCOL, COL_SM_DARKSEAGREEN }, + { "darkslateblue", THTMLCOL, COL_SM_DARKSLATEBLUE }, + { "darkslategray", THTMLCOL, COL_SM_DARKSLATEGRAY }, + { "darkslategrey", THTMLCOL, COL_SM_DARKSLATEGREY }, + { "darkturquoise", THTMLCOL, COL_SM_DARKTURQUOISE }, + { "darkviolet", THTMLCOL, COL_SM_DARKVIOLET }, + { "deeppink", THTMLCOL, COL_SM_DEEPPINK }, + { "deepskyblue", THTMLCOL, COL_SM_DEEPSKYBLUE }, + { "dimgray", THTMLCOL, COL_SM_DIMGRAY }, + { "dimgrey", THTMLCOL, COL_SM_DIMGREY }, + { "dodgerblue", THTMLCOL, COL_SM_DODGERBLUE }, + { "firebrick", THTMLCOL, COL_SM_FIREBRICK }, + { "floralwhite", THTMLCOL, COL_SM_FLORALWHITE }, + { "forestgreen", THTMLCOL, COL_SM_FORESTGREEN }, + { "fuchsia", TMATHMLCOL, COL_SM_FUCHSIA }, + { "gainsboro", THTMLCOL, COL_SM_GAINSBORO }, + { "ghostwhite", THTMLCOL, COL_SM_GHOSTWHITE }, + { "gold", THTMLCOL, COL_SM_GOLD }, + { "goldenrod", THTMLCOL, COL_SM_GOLDENROD }, + { "gray", TMATHMLCOL, COL_SM_GRAY }, + { "green", TMATHMLCOL, COL_SM_GREEN }, + { "greenyellow", THTMLCOL, COL_SM_GREENYELLOW }, + { "grey", THTMLCOL, COL_SM_GREY }, + { "honeydew", THTMLCOL, COL_SM_HONEYDEW }, + { "hotpink", THTMLCOL, COL_SM_HOTPINK }, + { "indianred", THTMLCOL, COL_SM_INDIANRED }, + { "indigo", THTMLCOL, COL_SM_INDIGO }, + { "ivory", THTMLCOL, COL_SM_IVORY }, + { "khaki", THTMLCOL, COL_SM_KHAKI }, + { "lavender", THTMLCOL, COL_SM_LAVENDER }, + { "lavenderblush", THTMLCOL, COL_SM_LAVENDERBLUSH }, + { "lawngreen", THTMLCOL, COL_SM_LAWNGREEN }, + { "lemonchiffon", THTMLCOL, COL_SM_LEMONCHIFFON }, + { "lightblue", THTMLCOL, COL_SM_LIGHTBLUE }, + { "lightcoral", THTMLCOL, COL_SM_LIGHTCORAL }, + { "lightcyan", THTMLCOL, COL_SM_LIGHTCYAN }, + { "lightgoldenrodyellow", THTMLCOL, COL_SM_LIGHTGOLDENRODYELLOW }, + { "lightgray", THTMLCOL, COL_SM_LIGHTGRAY }, + { "lightgreen", THTMLCOL, COL_SM_LIGHTGREEN }, + { "lightgrey", THTMLCOL, COL_SM_LIGHTGREY }, + { "lightpink", THTMLCOL, COL_SM_LIGHTPINK }, + { "lightsalmon", THTMLCOL, COL_SM_LIGHTSALMON }, + { "lightseagreen", THTMLCOL, COL_SM_LIGHTSEAGREEN }, + { "lightskyblue", THTMLCOL, COL_SM_LIGHTSKYBLUE }, + { "lightslategray", THTMLCOL, COL_SM_LIGHTSLATEGRAY }, + { "lightslategrey", THTMLCOL, COL_SM_LIGHTSLATEGREY }, + { "lightsteelblue", THTMLCOL, COL_SM_LIGHTSTEELBLUE }, + { "lightyellow", THTMLCOL, COL_SM_LIGHTYELLOW }, + { "lime", TMATHMLCOL, COL_SM_LIME }, + { "limegreen", THTMLCOL, COL_SM_LIMEGREEN }, + { "linen", THTMLCOL, COL_SM_LINEN }, + { "magenta", TMATHMLCOL, COL_SM_MAGENTA }, + { "maroon", TMATHMLCOL, COL_SM_MAROON }, + { "mediumaquamarine", THTMLCOL, COL_SM_MEDIUMAQUAMARINE }, + { "mediumblue", THTMLCOL, COL_SM_MEDIUMBLUE }, + { "mediumorchid", THTMLCOL, COL_SM_MEDIUMORCHID }, + { "mediumpurple", THTMLCOL, COL_SM_MEDIUMPURPLE }, + { "mediumseagreen", THTMLCOL, COL_SM_MEDIUMSEAGREEN }, + { "mediumslateblue", THTMLCOL, COL_SM_MEDIUMSLATEBLUE }, + { "mediumspringgreen", THTMLCOL, COL_SM_MEDIUMSPRINGGREEN }, + { "mediumturquoise", THTMLCOL, COL_SM_MEDIUMTURQUOISE }, + { "mediumvioletred", THTMLCOL, COL_SM_MEDIUMVIOLETRED }, + { "midnightblue", THTMLCOL, COL_SM_MIDNIGHTBLUE }, + { "mintcream", THTMLCOL, COL_SM_MINTCREAM }, + { "mistyrose", THTMLCOL, COL_SM_MISTYROSE }, + { "moccasin", THTMLCOL, COL_SM_MOCCASIN }, + { "navajowhite", THTMLCOL, COL_SM_NAVAJOWHITE }, + { "navy", TMATHMLCOL, COL_SM_NAVY }, + { "oldlace", THTMLCOL, COL_SM_OLDLACE }, + { "olive", TMATHMLCOL, COL_SM_OLIVE }, + { "olivedrab", THTMLCOL, COL_SM_OLIVEDRAB }, + { "orange", THTMLCOL, COL_SM_ORANGE }, + { "orangered", THTMLCOL, COL_SM_ORANGERED }, + { "orchid", THTMLCOL, COL_SM_ORCHID }, + { "palegoldenrod", THTMLCOL, COL_SM_PALEGOLDENROD }, + { "palegreen", THTMLCOL, COL_SM_PALEGREEN }, + { "paleturquoise", THTMLCOL, COL_SM_PALETURQUOISE }, + { "palevioletred", THTMLCOL, COL_SM_PALEVIOLETRED }, + { "papayawhip", THTMLCOL, COL_SM_PAPAYAWHIP }, + { "peachpuff", THTMLCOL, COL_SM_PEACHPUFF }, + { "peru", THTMLCOL, COL_SM_PERU }, + { "pink", THTMLCOL, COL_SM_PINK }, + { "plum", THTMLCOL, COL_SM_PLUM }, + { "powderblue", THTMLCOL, COL_SM_POWDERBLUE }, + { "purple", TMATHMLCOL, COL_SM_PURPLE }, + { "rebeccapurple", THTMLCOL, COL_SM_REBECCAPURPLE }, + { "red", TMATHMLCOL, COL_SM_RED }, + { "rosybrown", THTMLCOL, COL_SM_ROSYBROWN }, + { "royalblue", THTMLCOL, COL_SM_ROYALBLUE }, + { "saddlebrown", THTMLCOL, COL_SM_SADDLEBROWN }, + { "salmon", THTMLCOL, COL_SM_SALMON }, + { "sandybrown", THTMLCOL, COL_SM_SANDYBROWN }, + { "seagreen", THTMLCOL, COL_SM_SEAGREEN }, + { "seashell", THTMLCOL, COL_SM_SEASHELL }, + { "sienna", THTMLCOL, COL_SM_SIENNA }, + { "silver", TMATHMLCOL, COL_SM_SILVER }, + { "skyblue", THTMLCOL, COL_SM_SKYBLUE }, + { "slateblue", THTMLCOL, COL_SM_SLATEBLUE }, + { "slategray", THTMLCOL, COL_SM_SLATEGRAY }, + { "slategrey", THTMLCOL, COL_SM_SLATEGREY }, + { "snow", THTMLCOL, COL_SM_SNOW }, + { "springgreen", THTMLCOL, COL_SM_SPRINGGREEN }, + { "steelblue", THTMLCOL, COL_SM_STEELBLUE }, + { "tan", THTMLCOL, COL_SM_TAN }, + { "teal", TMATHMLCOL, COL_SM_TEAL }, + { "thistle", THTMLCOL, COL_SM_THISTLE }, + { "tomato", THTMLCOL, COL_SM_TOMATO }, + { "turquoise", THTMLCOL, COL_SM_TURQUOISE }, + { "violet", THTMLCOL, COL_SM_VIOLET }, + { "wheat", THTMLCOL, COL_SM_WHEAT }, + { "white", TMATHMLCOL, COL_SM_WHITE }, + { "whitesmoke", THTMLCOL, COL_SM_WHITESMOKE }, + { "yellow", TMATHMLCOL, COL_SM_YELLOW }, + { "yellowgreen", THTMLCOL, COL_SM_YELLOWGREEN } }; + +const SmColorTokenTableEntry starmathdatabase::aColorTokenTableDVIPS[] + = { { "apricot", TDVIPSNAMESCOL, COL_SM_DIV_APRICOT }, + { "aquamarine", TDVIPSNAMESCOL, COL_SM_DIV_AQUAMARINE }, + { "bittersweet", TDVIPSNAMESCOL, COL_SM_DIV_BITTERSWEET }, + { "black", TDVIPSNAMESCOL, COL_SM_BLACK }, + { "blue", TDVIPSNAMESCOL, COL_SM_BLACK } }; + +const SmColorTokenTableEntry starmathdatabase::aColorTokenTableMATHML[] = { + // clang-format off + { "aqua", TMATHMLCOL, COL_SM_AQUA }, + { "black", TMATHMLCOL, COL_SM_BLACK }, + { "blue", TMATHMLCOL, COL_SM_BLUE }, + { "fuchsia", TMATHMLCOL, COL_SM_FUCHSIA }, + { "gray", TMATHMLCOL, COL_SM_GRAY }, + { "green", TMATHMLCOL, COL_SM_GREEN }, + { "lime", TMATHMLCOL, COL_SM_LIME }, + { "maroon", TMATHMLCOL, COL_SM_MAROON }, + { "navy", TMATHMLCOL, COL_SM_NAVY }, + { "olive", TMATHMLCOL, COL_SM_OLIVE }, + { "purple", TMATHMLCOL, COL_SM_PURPLE }, + { "red", TMATHMLCOL, COL_SM_RED }, + { "silver", TMATHMLCOL, COL_SM_SILVER }, + { "teal", TMATHMLCOL, COL_SM_TEAL }, + { "white", TMATHMLCOL, COL_SM_WHITE }, + { "yellow", TMATHMLCOL, COL_SM_YELLOW } + // clang-format on +}; + +const SmColorTokenTableEntry starmathdatabase::aColorTokenTableERROR[] + = { { "", TERROR, COL_SM_BLACK } }; + +SmColorTokenTableEntry starmathdatabase::Identify_Color_Parser(sal_uInt32 cColor) +{ + for (auto i = std::begin(aColorTokenTableParse); i < std::end(aColorTokenTableParse); ++i) + if (i->equals(cColor)) + return i; + for (auto i = std::begin(aColorTokenTableDVIPS); i < std::end(aColorTokenTableDVIPS); ++i) + if (i->equals(cColor)) + return i; + if ((cColor & 0x00FFFFFF) == cColor) + return SmColorTokenTableEntry("", TRGB, cColor); + else + return SmColorTokenTableEntry("", TRGBA, cColor); +} + +SmColorTokenTableEntry starmathdatabase::Identify_Color_HTML(sal_uInt32 cColor) +{ + for (auto i = std::begin(aColorTokenTableHTML); i < std::end(aColorTokenTableHTML); ++i) + if (i->equals(cColor)) + return i; + if ((cColor & 0x00FFFFFF) == cColor) + return SmColorTokenTableEntry("", TRGB, cColor); + else + return SmColorTokenTableEntry("", TRGBA, cColor); +} + +SmColorTokenTableEntry starmathdatabase::Identify_Color_MATHML(sal_uInt32 cColor) +{ + for (auto i = std::begin(aColorTokenTableMATHML); i < std::end(aColorTokenTableMATHML); ++i) + if (i->equals(cColor)) + return i; + if ((cColor & 0x00FFFFFF) == cColor) + return SmColorTokenTableEntry("", TRGB, cColor); + else + return SmColorTokenTableEntry("", TRGBA, cColor); +} + +SmColorTokenTableEntry starmathdatabase::Identify_Color_DVIPSNAMES(sal_uInt32 cColor) +{ + for (auto i = std::begin(aColorTokenTableDVIPS); i < std::end(aColorTokenTableDVIPS); ++i) + if (i->equals(cColor)) + return i; + if ((cColor & 0x00FFFFFF) == cColor) + return SmColorTokenTableEntry("", TRGB, cColor); + else + return SmColorTokenTableEntry("", TRGBA, cColor); +} + +const SmColorTokenTableEntry* +starmathdatabase::Identify_ColorName_Parser(std::u16string_view colorname) +{ + if (colorname.empty()) + return &aColorTokenTableERROR[0]; + for (auto i = std::begin(aColorTokenTableParse); i < std::end(aColorTokenTableParse); ++i) + { + sal_Int32 matches = o3tl::compareToIgnoreAsciiCase(colorname, i->aIdent); + if (matches == 0) + return i; + if (matches < 0) + break; + } + return &aColorTokenTableERROR[0]; +} +SmColorTokenTableEntry starmathdatabase::Identify_ColorName_HTML(std::u16string_view colorname) +{ + if (colorname.empty()) + return SmColorTokenTableEntry("", TERROR, COL_SM_BLACK); + if (colorname[0] == '#') + { + Color col = Color::STRtoRGB(colorname); + return SmColorTokenTableEntry("", TRGB, col); + } + for (auto i = std::begin(aColorTokenTableHTML); i < std::end(aColorTokenTableHTML); ++i) + { + sal_Int32 matches = o3tl::compareToIgnoreAsciiCase(colorname, i->aIdent); + if (matches == 0) + return i; + if (matches < 0) + break; + } + return SmColorTokenTableEntry("", TERROR, COL_SM_BLACK); +} +const SmColorTokenTableEntry* +starmathdatabase::Identify_ColorName_DVIPSNAMES(std::u16string_view colorname) +{ + if (colorname.empty()) + return &aColorTokenTableERROR[0]; + for (auto i = std::begin(aColorTokenTableDVIPS); i < std::end(aColorTokenTableDVIPS); ++i) + { + sal_Int32 matches = o3tl::compareToIgnoreAsciiCase(colorname, i->aIdent); + if (matches == 0) + return i; + if (matches < 0) + break; + } + return &aColorTokenTableERROR[0]; +} diff --git a/starmath/source/mathml/xparsmlbase.cxx b/starmath/source/mathml/xparsmlbase.cxx new file mode 100644 index 000000000..7e0e93ab7 --- /dev/null +++ b/starmath/source/mathml/xparsmlbase.cxx @@ -0,0 +1,2166 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#include <xparsmlbase.hxx> + +static ::css::beans::Pair<::rtl::OUString, ::rtl::OUString> + icustomMathmlHtmlEntitiesData[starmathdatabase::STARMATH_MATHMLHTML_ENTITY_NUMBER] = { + // clang-format off + { u"AElig", u"\u00C6" }, + { u"AMP", u"\u0026" }, + { u"Aacute", u"\u00C1" }, + { u"Abreve", u"\u0102" }, + { u"Acirc", u"\u00C2" }, + { u"Acy", u"\u0410" }, + { u"Afr", u"\U0001D504" }, + { u"Agrave", u"\u00C0" }, + { u"Alpha", u"\u0391" }, + { u"Amacr", u"\u0100" }, + { u"And", u"\u2A53" }, + { u"Aogon", u"\u0104" }, + { u"Aopf", u"\U0001D538" }, + { u"ApplyFunction", u"\u2061" }, + { u"Aring", u"\u00C5" }, + { u"Ascr", u"\U0001D49C" }, + { u"Assign", u"\u2254" }, + { u"Atilde", u"\u00C3" }, + { u"Auml", u"\u00C4" }, + { u"Backslash", u"\u2216" }, + { u"Barv", u"\u2AE7" }, + { u"Barwed", u"\u2306" }, + { u"Bcy", u"\u0411" }, + { u"Because", u"\u2235" }, + { u"Bernoullis", u"\u212C" }, + { u"Beta", u"\u0392" }, + { u"Bfr", u"\U0001D505" }, + { u"Bopf", u"\U0001D539" }, + { u"Breve", u"\u02D8" }, + { u"Bscr", u"\u212C" }, + { u"Bumpeq", u"\u224E" }, + { u"CHcy", u"\u0427" }, + { u"COPY", u"\u00A9" }, + { u"Cacute", u"\u0106" }, + { u"Cap", u"\u22D2" }, + { u"CapitalDifferentialD", u"\u2145" }, + { u"Cayleys", u"\u212D" }, + { u"Ccaron", u"\u010C" }, + { u"Ccedil", u"\u00C7" }, + { u"Ccirc", u"\u0108" }, + { u"Cconint", u"\u2230" }, + { u"Cdot", u"\u010A" }, + { u"Cedilla", u"\u00B8" }, + { u"CenterDot", u"\u00B7" }, + { u"Cfr", u"\u212D" }, + { u"Chi", u"\u03A7" }, + { u"CircleDot", u"\u2299" }, + { u"CircleMinus", u"\u2296" }, + { u"CirclePlus", u"\u2295" }, + { u"CircleTimes", u"\u2297" }, + { u"ClockwiseContourIntegral", u"\u2232" }, + { u"CloseCurlyDoubleQuote", u"\u201D" }, + { u"CloseCurlyQuote", u"\u2019" }, + { u"Colon", u"\u2237" }, + { u"Colone", u"\u2A74" }, + { u"Congruent", u"\u2261" }, + { u"Conint", u"\u222F" }, + { u"ContourIntegral", u"\u222E" }, + { u"Copf", u"\u2102" }, + { u"Coproduct", u"\u2210" }, + { u"CounterClockwiseContourIntegral", u"\u2233" }, + { u"Cross", u"\u2A2F" }, + { u"Cscr", u"\U0001D49E" }, + { u"Cup", u"\u22D3" }, + { u"CupCap", u"\u224D" }, + { u"DD", u"\u2145" }, + { u"DDotrahd", u"\u2911" }, + { u"DJcy", u"\u0402" }, + { u"DScy", u"\u0405" }, + { u"DZcy", u"\u040F" }, + { u"Dagger", u"\u2021" }, + { u"Darr", u"\u21A1" }, + { u"Dashv", u"\u2AE4" }, + { u"Dcaron", u"\u010E" }, + { u"Dcy", u"\u0414" }, + { u"Del", u"\u2207" }, + { u"Delta", u"\u0394" }, + { u"Dfr", u"\U0001D507" }, + { u"DiacriticalAcute", u"\u00B4" }, + { u"DiacriticalDot", u"\u02D9" }, + { u"DiacriticalDoubleAcute", u"\u02DD" }, + { u"DiacriticalGrave", u"\u0060" }, + { u"DiacriticalTilde", u"\u02DC" }, + { u"Diamond", u"\u22C4" }, + { u"DifferentialD", u"\u2146" }, + { u"Dopf", u"\U0001D53B" }, + { u"Dot", u"\u00A8" }, + { u"DotDot", u"\u20DC" }, + { u"DotEqual", u"\u2250" }, + { u"DoubleContourIntegral", u"\u222F" }, + { u"DoubleDot", u"\u00A8" }, + { u"DoubleDownArrow", u"\u21D3" }, + { u"DoubleLeftArrow", u"\u21D0" }, + { u"DoubleLeftRightArrow", u"\u21D4" }, + { u"DoubleLeftTee", u"\u2AE4" }, + { u"DoubleLongLeftArrow", u"\u27F8" }, + { u"DoubleLongLeftRightArrow", u"\u27FA" }, + { u"DoubleLongRightArrow", u"\u27F9" }, + { u"DoubleRightArrow", u"\u21D2" }, + { u"DoubleRightTee", u"\u22A8" }, + { u"DoubleUpArrow", u"\u21D1" }, + { u"DoubleUpDownArrow", u"\u21D5" }, + { u"DoubleVerticalBar", u"\u2225" }, + { u"DownArrow", u"\u2193" }, + { u"DownArrowBar", u"\u2913" }, + { u"DownArrowUpArrow", u"\u21F5" }, + { u"DownBreve", u"\u0311" }, + { u"DownLeftRightVector", u"\u2950" }, + { u"DownLeftTeeVector", u"\u295E" }, + { u"DownLeftVector", u"\u21BD" }, + { u"DownLeftVectorBar", u"\u2956" }, + { u"DownRightTeeVector", u"\u295F" }, + { u"DownRightVector", u"\u21C1" }, + { u"DownRightVectorBar", u"\u2957" }, + { u"DownTee", u"\u22A4" }, + { u"DownTeeArrow", u"\u21A7" }, + { u"Downarrow", u"\u21D3" }, + { u"Dscr", u"\U0001D49F" }, + { u"Dstrok", u"\u0110" }, + { u"ENG", u"\u014A" }, + { u"ETH", u"\u00D0" }, + { u"Eacute", u"\u00C9" }, + { u"Ecaron", u"\u011A" }, + { u"Ecirc", u"\u00CA" }, + { u"Ecy", u"\u042D" }, + { u"Edot", u"\u0116" }, + { u"Efr", u"\U0001D508" }, + { u"Egrave", u"\u00C8" }, + { u"Element", u"\u2208" }, + { u"Emacr", u"\u0112" }, + { u"EmptySmallSquare", u"\u25FB" }, + { u"EmptyVerySmallSquare", u"\u25AB" }, + { u"Eogon", u"\u0118" }, + { u"Eopf", u"\U0001D53C" }, + { u"Epsilon", u"\u0395" }, + { u"Equal", u"\u2A75" }, + { u"EqualTilde", u"\u2242" }, + { u"Equilibrium", u"\u21CC" }, + { u"Escr", u"\u2130" }, + { u"Esim", u"\u2A73" }, + { u"Eta", u"\u0397" }, + { u"Euml", u"\u00CB" }, + { u"Exists", u"\u2203" }, + { u"ExponentialE", u"\u2147" }, + { u"Fcy", u"\u0424" }, + { u"Ffr", u"\U0001D509" }, + { u"FilledSmallSquare", u"\u25FC" }, + { u"FilledVerySmallSquare", u"\u25AA" }, + { u"Fopf", u"\U0001D53D" }, + { u"ForAll", u"\u2200" }, + { u"Fouriertrf", u"\u2131" }, + { u"Fscr", u"\u2131" }, + { u"GJcy", u"\u0403" }, + { u"GT", u"\u003E" }, + { u"Gamma", u"\u0393" }, + { u"Gammad", u"\u03DC" }, + { u"Gbreve", u"\u011E" }, + { u"Gcedil", u"\u0122" }, + { u"Gcirc", u"\u011C" }, + { u"Gcy", u"\u0413" }, + { u"Gdot", u"\u0120" }, + { u"Gfr", u"\U0001D50A" }, + { u"Gg", u"\u22D9" }, + { u"Gopf", u"\U0001D53E" }, + { u"GreaterEqual", u"\u2265" }, + { u"GreaterEqualLess", u"\u22DB" }, + { u"GreaterFullEqual", u"\u2267" }, + { u"GreaterGreater", u"\u2AA2" }, + { u"GreaterLess", u"\u2277" }, + { u"GreaterSlantEqual", u"\u2A7E" }, + { u"GreaterTilde", u"\u2273" }, + { u"Gscr", u"\U0001D4A2" }, + { u"Gt", u"\u226B" }, + { u"HARDcy", u"\u042A" }, + { u"Hacek", u"\u02C7" }, + { u"Hat", u"\u005E" }, + { u"Hcirc", u"\u0124" }, + { u"Hfr", u"\u210C" }, + { u"HilbertSpace", u"\u210B" }, + { u"Hopf", u"\u210D" }, + { u"HorizontalLine", u"\u2500" }, + { u"Hscr", u"\u210B" }, + { u"Hstrok", u"\u0126" }, + { u"HumpDownHump", u"\u224E" }, + { u"HumpEqual", u"\u224F" }, + { u"IEcy", u"\u0415" }, + { u"IJlig", u"\u0132" }, + { u"IOcy", u"\u0401" }, + { u"Iacute", u"\u00CD" }, + { u"Icirc", u"\u00CE" }, + { u"Icy", u"\u0418" }, + { u"Idot", u"\u0130" }, + { u"Ifr", u"\u2111" }, + { u"Igrave", u"\u00CC" }, + { u"Im", u"\u2111" }, + { u"Imacr", u"\u012A" }, + { u"ImaginaryI", u"\u2148" }, + { u"Implies", u"\u21D2" }, + { u"Int", u"\u222C" }, + { u"Integral", u"\u222B" }, + { u"Intersection", u"\u22C2" }, + { u"InvisibleComma", u"\u2063" }, + { u"InvisibleTimes", u"\u2062" }, + { u"Iogon", u"\u012E" }, + { u"Iopf", u"\U0001D540" }, + { u"Iota", u"\u0399" }, + { u"Iscr", u"\u2110" }, + { u"Itilde", u"\u0128" }, + { u"Iukcy", u"\u0406" }, + { u"Iuml", u"\u00CF" }, + { u"Jcirc", u"\u0134" }, + { u"Jcy", u"\u0419" }, + { u"Jfr", u"\U0001D50D" }, + { u"Jopf", u"\U0001D541" }, + { u"Jscr", u"\U0001D4A5" }, + { u"Jsercy", u"\u0408" }, + { u"Jukcy", u"\u0404" }, + { u"KHcy", u"\u0425" }, + { u"KJcy", u"\u040C" }, + { u"Kappa", u"\u039A" }, + { u"Kcedil", u"\u0136" }, + { u"Kcy", u"\u041A" }, + { u"Kfr", u"\U0001D50E" }, + { u"Kopf", u"\U0001D542" }, + { u"Kscr", u"\U0001D4A6" }, + { u"LJcy", u"\u0409" }, + { u"LT", u"\u003C" }, + { u"Lacute", u"\u0139" }, + { u"Lambda", u"\u039B" }, + { u"Lang", u"\u27EA" }, + { u"Laplacetrf", u"\u2112" }, + { u"Larr", u"\u219E" }, + { u"Lcaron", u"\u013D" }, + { u"Lcedil", u"\u013B" }, + { u"Lcy", u"\u041B" }, + { u"LeftAngleBracket", u"\u27E8" }, + { u"LeftArrow", u"\u2190" }, + { u"LeftArrowBar", u"\u21E4" }, + { u"LeftArrowRightArrow", u"\u21C6" }, + { u"LeftCeiling", u"\u2308" }, + { u"LeftDoubleBracket", u"\u27E6" }, + { u"LeftDownTeeVector", u"\u2961" }, + { u"LeftDownVector", u"\u21C3" }, + { u"LeftDownVectorBar", u"\u2959" }, + { u"LeftFloor", u"\u230A" }, + { u"LeftRightArrow", u"\u2194" }, + { u"LeftRightVector", u"\u294E" }, + { u"LeftTee", u"\u22A3" }, + { u"LeftTeeArrow", u"\u21A4" }, + { u"LeftTeeVector", u"\u295A" }, + { u"LeftTriangle", u"\u22B2" }, + { u"LeftTriangleBar", u"\u29CF" }, + { u"LeftTriangleEqual", u"\u22B4" }, + { u"LeftUpDownVector", u"\u2951" }, + { u"LeftUpTeeVector", u"\u2960" }, + { u"LeftUpVector", u"\u21BF" }, + { u"LeftUpVectorBar", u"\u2958" }, + { u"LeftVector", u"\u21BC" }, + { u"LeftVectorBar", u"\u2952" }, + { u"Leftarrow", u"\u21D0" }, + { u"Leftrightarrow", u"\u21D4" }, + { u"LessEqualGreater", u"\u22DA" }, + { u"LessFullEqual", u"\u2266" }, + { u"LessGreater", u"\u2276" }, + { u"LessLess", u"\u2AA1" }, + { u"LessSlantEqual", u"\u2A7D" }, + { u"LessTilde", u"\u2272" }, + { u"Lfr", u"\U0001D50F" }, + { u"Ll", u"\u22D8" }, + { u"Lleftarrow", u"\u21DA" }, + { u"Lmidot", u"\u013F" }, + { u"LongLeftArrow", u"\u27F5" }, + { u"LongLeftRightArrow", u"\u27F7" }, + { u"LongRightArrow", u"\u27F6" }, + { u"Longleftarrow", u"\u27F8" }, + { u"Longleftrightarrow", u"\u27FA" }, + { u"Longrightarrow", u"\u27F9" }, + { u"Lopf", u"\U0001D543" }, + { u"LowerLeftArrow", u"\u2199" }, + { u"LowerRightArrow", u"\u2198" }, + { u"Lscr", u"\u2112" }, + { u"Lsh", u"\u21B0" }, + { u"Lstrok", u"\u0141" }, + { u"Lt", u"\u226A" }, + { u"Map", u"\u2905" }, + { u"Mcy", u"\u041C" }, + { u"MediumSpace", u"\u205F" }, + { u"Mellintrf", u"\u2133" }, + { u"Mfr", u"\U0001D510" }, + { u"MinusPlus", u"\u2213" }, + { u"Mopf", u"\U0001D544" }, + { u"Mscr", u"\u2133" }, + { u"Mu", u"\u039C" }, + { u"NJcy", u"\u040A" }, + { u"Nacute", u"\u0143" }, + { u"Ncaron", u"\u0147" }, + { u"Ncedil", u"\u0145" }, + { u"Ncy", u"\u041D" }, + { u"NegativeMediumSpace", u"\u200B" }, + { u"NegativeThickSpace", u"\u200B" }, + { u"NegativeThinSpace", u"\u200B" }, + { u"NegativeVeryThinSpace", u"\u200B" }, + { u"NestedGreaterGreater", u"\u226B" }, + { u"NestedLessLess", u"\u226A" }, + { u"NewLine", u"\u000A" }, + { u"Nfr", u"\U0001D511" }, + { u"NoBreak", u"\u2060" }, + { u"NonBreakingSpace", u"\u00A0" }, + { u"Nopf", u"\u2115" }, + { u"Not", u"\u2AEC" }, + { u"NotCongruent", u"\u2262" }, + { u"NotCupCap", u"\u226D" }, + { u"NotDoubleVerticalBar", u"\u2226" }, + { u"NotElement", u"\u2209" }, + { u"NotEqual", u"\u2260" }, + { u"NotEqualTilde", u"\u2242\u0338" }, + { u"NotExists", u"\u2204" }, + { u"NotGreater", u"\u226F" }, + { u"NotGreaterEqual", u"\u2271" }, + { u"NotGreaterFullEqual", u"\u2267\u0338" }, + { u"NotGreaterGreater", u"\u226B\u0338" }, + { u"NotGreaterLess", u"\u2279" }, + { u"NotGreaterSlantEqual", u"\u2A7E\u0338" }, + { u"NotGreaterTilde", u"\u2275" }, + { u"NotHumpDownHump", u"\u224E\u0338" }, + { u"NotHumpEqual", u"\u224F\u0338" }, + { u"NotLeftTriangle", u"\u22EA" }, + { u"NotLeftTriangleBar", u"\u29CF\u0338" }, + { u"NotLeftTriangleEqual", u"\u22EC" }, + { u"NotLess", u"\u226E" }, + { u"NotLessEqual", u"\u2270" }, + { u"NotLessGreater", u"\u2278" }, + { u"NotLessLess", u"\u226A\u0338" }, + { u"NotLessSlantEqual", u"\u2A7D\u0338" }, + { u"NotLessTilde", u"\u2274" }, + { u"NotNestedGreaterGreater", u"\u2AA2\u0338" }, + { u"NotNestedLessLess", u"\u2AA1\u0338" }, + { u"NotPrecedes", u"\u2280" }, + { u"NotPrecedesEqual", u"\u2AAF\u0338" }, + { u"NotPrecedesSlantEqual", u"\u22E0" }, + { u"NotReverseElement", u"\u220C" }, + { u"NotRightTriangle", u"\u22EB" }, + { u"NotRightTriangleBar", u"\u29D0\u0338" }, + { u"NotRightTriangleEqual", u"\u22ED" }, + { u"NotSquareSubset", u"\u228F\u0338" }, + { u"NotSquareSubsetEqual", u"\u22E2" }, + { u"NotSquareSuperset", u"\u2290\u0338" }, + { u"NotSquareSupersetEqual", u"\u22E3" }, + { u"NotSubset", u"\u2282\u20D2" }, + { u"NotSubsetEqual", u"\u2288" }, + { u"NotSucceeds", u"\u2281" }, + { u"NotSucceedsEqual", u"\u2AB0\u0338" }, + { u"NotSucceedsSlantEqual", u"\u22E1" }, + { u"NotSucceedsTilde", u"\u227F\u0338" }, + { u"NotSuperset", u"\u2283\u20D2" }, + { u"NotSupersetEqual", u"\u2289" }, + { u"NotTilde", u"\u2241" }, + { u"NotTildeEqual", u"\u2244" }, + { u"NotTildeFullEqual", u"\u2247" }, + { u"NotTildeTilde", u"\u2249" }, + { u"NotVerticalBar", u"\u2224" }, + { u"Nscr", u"\U0001D4A9" }, + { u"Ntilde", u"\u00D1" }, + { u"Nu", u"\u039D" }, + { u"OElig", u"\u0152" }, + { u"Oacute", u"\u00D3" }, + { u"Ocirc", u"\u00D4" }, + { u"Ocy", u"\u041E" }, + { u"Odblac", u"\u0150" }, + { u"Ofr", u"\U0001D512" }, + { u"Ograve", u"\u00D2" }, + { u"Omacr", u"\u014C" }, + { u"Omega", u"\u03A9" }, + { u"Omicron", u"\u039F" }, + { u"Oopf", u"\U0001D546" }, + { u"OpenCurlyDoubleQuote", u"\u201C" }, + { u"OpenCurlyQuote", u"\u2018" }, + { u"Or", u"\u2A54" }, + { u"Oscr", u"\U0001D4AA" }, + { u"Oslash", u"\u00D8" }, + { u"Otilde", u"\u00D5" }, + { u"Otimes", u"\u2A37" }, + { u"Ouml", u"\u00D6" }, + { u"OverBar", u"\u203E" }, + { u"OverBrace", u"\u23DE" }, + { u"OverBracket", u"\u23B4" }, + { u"OverParenthesis", u"\u23DC" }, + { u"PartialD", u"\u2202" }, + { u"Pcy", u"\u041F" }, + { u"Pfr", u"\U0001D513" }, + { u"Phi", u"\u03A6" }, + { u"Pi", u"\u03A0" }, + { u"PlusMinus", u"\u00B1" }, + { u"Poincareplane", u"\u210C" }, + { u"Popf", u"\u2119" }, + { u"Pr", u"\u2ABB" }, + { u"Precedes", u"\u227A" }, + { u"PrecedesEqual", u"\u2AAF" }, + { u"PrecedesSlantEqual", u"\u227C" }, + { u"PrecedesTilde", u"\u227E" }, + { u"Prime", u"\u2033" }, + { u"Product", u"\u220F" }, + { u"Proportion", u"\u2237" }, + { u"Proportional", u"\u221D" }, + { u"Pscr", u"\U0001D4AB" }, + { u"Psi", u"\u03A8" }, + { u"QUOT", u"\u0022" }, + { u"Qfr", u"\U0001D514" }, + { u"Qopf", u"\u211A" }, + { u"Qscr", u"\U0001D4AC" }, + { u"RBarr", u"\u2910" }, + { u"REG", u"\u00AE" }, + { u"Racute", u"\u0154" }, + { u"Rang", u"\u27EB" }, + { u"Rarr", u"\u21A0" }, + { u"Rarrtl", u"\u2916" }, + { u"Rcaron", u"\u0158" }, + { u"Rcedil", u"\u0156" }, + { u"Rcy", u"\u0420" }, + { u"Re", u"\u211C" }, + { u"ReverseElement", u"\u220B" }, + { u"ReverseEquilibrium", u"\u21CB" }, + { u"ReverseUpEquilibrium", u"\u296F" }, + { u"Rfr", u"\u211C" }, + { u"Rho", u"\u03A1" }, + { u"RightAngleBracket", u"\u27E9" }, + { u"RightArrow", u"\u2192" }, + { u"RightArrowBar", u"\u21E5" }, + { u"RightArrowLeftArrow", u"\u21C4" }, + { u"RightCeiling", u"\u2309" }, + { u"RightDoubleBracket", u"\u27E7" }, + { u"RightDownTeeVector", u"\u295D" }, + { u"RightDownVector", u"\u21C2" }, + { u"RightDownVectorBar", u"\u2955" }, + { u"RightFloor", u"\u230B" }, + { u"RightTee", u"\u22A2" }, + { u"RightTeeArrow", u"\u21A6" }, + { u"RightTeeVector", u"\u295B" }, + { u"RightTriangle", u"\u22B3" }, + { u"RightTriangleBar", u"\u29D0" }, + { u"RightTriangleEqual", u"\u22B5" }, + { u"RightUpDownVector", u"\u294F" }, + { u"RightUpTeeVector", u"\u295C" }, + { u"RightUpVector", u"\u21BE" }, + { u"RightUpVectorBar", u"\u2954" }, + { u"RightVector", u"\u21C0" }, + { u"RightVectorBar", u"\u2953" }, + { u"Rightarrow", u"\u21D2" }, + { u"Ropf", u"\u211D" }, + { u"RoundImplies", u"\u2970" }, + { u"Rrightarrow", u"\u21DB" }, + { u"Rscr", u"\u211B" }, + { u"Rsh", u"\u21B1" }, + { u"RuleDelayed", u"\u29F4" }, + { u"SHCHcy", u"\u0429" }, + { u"SHcy", u"\u0428" }, + { u"SOFTcy", u"\u042C" }, + { u"Sacute", u"\u015A" }, + { u"Sc", u"\u2ABC" }, + { u"Scaron", u"\u0160" }, + { u"Scedil", u"\u015E" }, + { u"Scirc", u"\u015C" }, + { u"Scy", u"\u0421" }, + { u"Sfr", u"\U0001D516" }, + { u"ShortDownArrow", u"\u2193" }, + { u"ShortLeftArrow", u"\u2190" }, + { u"ShortRightArrow", u"\u2192" }, + { u"ShortUpArrow", u"\u2191" }, + { u"Sigma", u"\u03A3" }, + { u"SmallCircle", u"\u2218" }, + { u"Sopf", u"\U0001D54A" }, + { u"Sqrt", u"\u221A" }, + { u"Square", u"\u25A1" }, + { u"SquareIntersection", u"\u2293" }, + { u"SquareSubset", u"\u228F" }, + { u"SquareSubsetEqual", u"\u2291" }, + { u"SquareSuperset", u"\u2290" }, + { u"SquareSupersetEqual", u"\u2292" }, + { u"SquareUnion", u"\u2294" }, + { u"Sscr", u"\U0001D4AE" }, + { u"Star", u"\u22C6" }, + { u"Sub", u"\u22D0" }, + { u"Subset", u"\u22D0" }, + { u"SubsetEqual", u"\u2286" }, + { u"Succeeds", u"\u227B" }, + { u"SucceedsEqual", u"\u2AB0" }, + { u"SucceedsSlantEqual", u"\u227D" }, + { u"SucceedsTilde", u"\u227F" }, + { u"SuchThat", u"\u220B" }, + { u"Sum", u"\u2211" }, + { u"Sup", u"\u22D1" }, + { u"Superset", u"\u2283" }, + { u"SupersetEqual", u"\u2287" }, + { u"Supset", u"\u22D1" }, + { u"THORN", u"\u00DE" }, + { u"TRADE", u"\u2122" }, + { u"TSHcy", u"\u040B" }, + { u"TScy", u"\u0426" }, + { u"Tab", u"\u0009" }, + { u"Tau", u"\u03A4" }, + { u"Tcaron", u"\u0164" }, + { u"Tcedil", u"\u0162" }, + { u"Tcy", u"\u0422" }, + { u"Tfr", u"\U0001D517" }, + { u"Therefore", u"\u2234" }, + { u"Theta", u"\u0398" }, + { u"ThickSpace", u"\u205F\u200A" }, + { u"ThinSpace", u"\u2009" }, + { u"Tilde", u"\u223C" }, + { u"TildeEqual", u"\u2243" }, + { u"TildeFullEqual", u"\u2245" }, + { u"TildeTilde", u"\u2248" }, + { u"Topf", u"\U0001D54B" }, + { u"TripleDot", u"\u20DB" }, + { u"Tscr", u"\U0001D4AF" }, + { u"Tstrok", u"\u0166" }, + { u"Uacute", u"\u00DA" }, + { u"Uarr", u"\u219F" }, + { u"Uarrocir", u"\u2949" }, + { u"Ubrcy", u"\u040E" }, + { u"Ubreve", u"\u016C" }, + { u"Ucirc", u"\u00DB" }, + { u"Ucy", u"\u0423" }, + { u"Udblac", u"\u0170" }, + { u"Ufr", u"\U0001D518" }, + { u"Ugrave", u"\u00D9" }, + { u"Umacr", u"\u016A" }, + { u"UnderBar", u"\u005F" }, + { u"UnderBrace", u"\u23DF" }, + { u"UnderBracket", u"\u23B5" }, + { u"UnderParenthesis", u"\u23DD" }, + { u"Union", u"\u22C3" }, + { u"UnionPlus", u"\u228E" }, + { u"Uogon", u"\u0172" }, + { u"Uopf", u"\U0001D54C" }, + { u"UpArrow", u"\u2191" }, + { u"UpArrowBar", u"\u2912" }, + { u"UpArrowDownArrow", u"\u21C5" }, + { u"UpDownArrow", u"\u2195" }, + { u"UpEquilibrium", u"\u296E" }, + { u"UpTee", u"\u22A5" }, + { u"UpTeeArrow", u"\u21A5" }, + { u"Uparrow", u"\u21D1" }, + { u"Updownarrow", u"\u21D5" }, + { u"UpperLeftArrow", u"\u2196" }, + { u"UpperRightArrow", u"\u2197" }, + { u"Upsi", u"\u03D2" }, + { u"Upsilon", u"\u03A5" }, + { u"Uring", u"\u016E" }, + { u"Uscr", u"\U0001D4B0" }, + { u"Utilde", u"\u0168" }, + { u"Uuml", u"\u00DC" }, + { u"VDash", u"\u22AB" }, + { u"Vbar", u"\u2AEB" }, + { u"Vcy", u"\u0412" }, + { u"Vdash", u"\u22A9" }, + { u"Vdashl", u"\u2AE6" }, + { u"Vee", u"\u22C1" }, + { u"Verbar", u"\u2016" }, + { u"Vert", u"\u2016" }, + { u"VerticalBar", u"\u2223" }, + { u"VerticalLine", u"\u007C" }, + { u"VerticalSeparator", u"\u2758" }, + { u"VerticalTilde", u"\u2240" }, + { u"VeryThinSpace", u"\u200A" }, + { u"Vfr", u"\U0001D519" }, + { u"Vopf", u"\U0001D54D" }, + { u"Vscr", u"\U0001D4B1" }, + { u"Vvdash", u"\u22AA" }, + { u"Wcirc", u"\u0174" }, + { u"Wedge", u"\u22C0" }, + { u"Wfr", u"\U0001D51A" }, + { u"Wopf", u"\U0001D54E" }, + { u"Wscr", u"\U0001D4B2" }, + { u"Xfr", u"\U0001D51B" }, + { u"Xi", u"\u039E" }, + { u"Xopf", u"\U0001D54F" }, + { u"Xscr", u"\U0001D4B3" }, + { u"YAcy", u"\u042F" }, + { u"YIcy", u"\u0407" }, + { u"YUcy", u"\u042E" }, + { u"Yacute", u"\u00DD" }, + { u"Ycirc", u"\u0176" }, + { u"Ycy", u"\u042B" }, + { u"Yfr", u"\U0001D51C" }, + { u"Yopf", u"\U0001D550" }, + { u"Yscr", u"\U0001D4B4" }, + { u"Yuml", u"\u0178" }, + { u"ZHcy", u"\u0416" }, + { u"Zacute", u"\u0179" }, + { u"Zcaron", u"\u017D" }, + { u"Zcy", u"\u0417" }, + { u"Zdot", u"\u017B" }, + { u"ZeroWidthSpace", u"\u200B" }, + { u"Zeta", u"\u0396" }, + { u"Zfr", u"\u2128" }, + { u"Zopf", u"\u2124" }, + { u"Zscr", u"\U0001D4B5" }, + { u"aacute", u"\u00E1" }, + { u"abreve", u"\u0103" }, + { u"ac", u"\u223E" }, + { u"acE", u"\u223E\u0333" }, + { u"acd", u"\u223F" }, + { u"acirc", u"\u00E2" }, + { u"acute", u"\u00B4" }, + { u"acy", u"\u0430" }, + { u"aelig", u"\u00E6" }, + { u"af", u"\u2061" }, + { u"afr", u"\U0001D51E" }, + { u"agrave", u"\u00E0" }, + { u"alefsym", u"\u2135" }, + { u"aleph", u"\u2135" }, + { u"alpha", u"\u03B1" }, + { u"amacr", u"\u0101" }, + { u"amalg", u"\u2A3F" }, + { u"amp", u"\u0026" }, + { u"and", u"\u2227" }, + { u"andand", u"\u2A55" }, + { u"andd", u"\u2A5C" }, + { u"andslope", u"\u2A58" }, + { u"andv", u"\u2A5A" }, + { u"ang", u"\u2220" }, + { u"ange", u"\u29A4" }, + { u"angle", u"\u2220" }, + { u"angmsd", u"\u2221" }, + { u"angmsdaa", u"\u29A8" }, + { u"angmsdab", u"\u29A9" }, + { u"angmsdac", u"\u29AA" }, + { u"angmsdad", u"\u29AB" }, + { u"angmsdae", u"\u29AC" }, + { u"angmsdaf", u"\u29AD" }, + { u"angmsdag", u"\u29AE" }, + { u"angmsdah", u"\u29AF" }, + { u"angrt", u"\u221F" }, + { u"angrtvb", u"\u22BE" }, + { u"angrtvbd", u"\u299D" }, + { u"angsph", u"\u2222" }, + { u"angst", u"\u00C5" }, + { u"angzarr", u"\u237C" }, + { u"aogon", u"\u0105" }, + { u"aopf", u"\U0001D552" }, + { u"ap", u"\u2248" }, + { u"apE", u"\u2A70" }, + { u"apacir", u"\u2A6F" }, + { u"ape", u"\u224A" }, + { u"apid", u"\u224B" }, + { u"apos", u"\u0027" }, + { u"approx", u"\u2248" }, + { u"approxeq", u"\u224A" }, + { u"aring", u"\u00E5" }, + { u"ascr", u"\U0001D4B6" }, + { u"ast", u"\u002A" }, + { u"asymp", u"\u2248" }, + { u"asympeq", u"\u224D" }, + { u"atilde", u"\u00E3" }, + { u"auml", u"\u00E4" }, + { u"awconint", u"\u2233" }, + { u"awint", u"\u2A11" }, + { u"bNot", u"\u2AED" }, + { u"backcong", u"\u224C" }, + { u"backepsilon", u"\u03F6" }, + { u"backprime", u"\u2035" }, + { u"backsim", u"\u223D" }, + { u"backsimeq", u"\u22CD" }, + { u"barvee", u"\u22BD" }, + { u"barwed", u"\u2305" }, + { u"barwedge", u"\u2305" }, + { u"bbrk", u"\u23B5" }, + { u"bbrktbrk", u"\u23B6" }, + { u"bcong", u"\u224C" }, + { u"bcy", u"\u0431" }, + { u"bdquo", u"\u201E" }, + { u"becaus", u"\u2235" }, + { u"because", u"\u2235" }, + { u"bemptyv", u"\u29B0" }, + { u"bepsi", u"\u03F6" }, + { u"bernou", u"\u212C" }, + { u"beta", u"\u03B2" }, + { u"beth", u"\u2136" }, + { u"between", u"\u226C" }, + { u"bfr", u"\U0001D51F" }, + { u"bigcap", u"\u22C2" }, + { u"bigcirc", u"\u25EF" }, + { u"bigcup", u"\u22C3" }, + { u"bigodot", u"\u2A00" }, + { u"bigoplus", u"\u2A01" }, + { u"bigotimes", u"\u2A02" }, + { u"bigsqcup", u"\u2A06" }, + { u"bigstar", u"\u2605" }, + { u"bigtriangledown", u"\u25BD" }, + { u"bigtriangleup", u"\u25B3" }, + { u"biguplus", u"\u2A04" }, + { u"bigvee", u"\u22C1" }, + { u"bigwedge", u"\u22C0" }, + { u"bkarow", u"\u290D" }, + { u"blacklozenge", u"\u29EB" }, + { u"blacksquare", u"\u25AA" }, + { u"blacktriangle", u"\u25B4" }, + { u"blacktriangledown", u"\u25BE" }, + { u"blacktriangleleft", u"\u25C2" }, + { u"blacktriangleright", u"\u25B8" }, + { u"blank", u"\u2423" }, + { u"blk12", u"\u2592" }, + { u"blk14", u"\u2591" }, + { u"blk34", u"\u2593" }, + { u"block", u"\u2588" }, + { u"bne", u"\u003D\u20E5" }, + { u"bnequiv", u"\u2261\u20E5" }, + { u"bnot", u"\u2310" }, + { u"bopf", u"\U0001D553" }, + { u"bot", u"\u22A5" }, + { u"bottom", u"\u22A5" }, + { u"bowtie", u"\u22C8" }, + { u"boxDL", u"\u2557" }, + { u"boxDR", u"\u2554" }, + { u"boxDl", u"\u2556" }, + { u"boxDr", u"\u2553" }, + { u"boxH", u"\u2550" }, + { u"boxHD", u"\u2566" }, + { u"boxHU", u"\u2569" }, + { u"boxHd", u"\u2564" }, + { u"boxHu", u"\u2567" }, + { u"boxUL", u"\u255D" }, + { u"boxUR", u"\u255A" }, + { u"boxUl", u"\u255C" }, + { u"boxUr", u"\u2559" }, + { u"boxV", u"\u2551" }, + { u"boxVH", u"\u256C" }, + { u"boxVL", u"\u2563" }, + { u"boxVR", u"\u2560" }, + { u"boxVh", u"\u256B" }, + { u"boxVl", u"\u2562" }, + { u"boxVr", u"\u255F" }, + { u"boxbox", u"\u29C9" }, + { u"boxdL", u"\u2555" }, + { u"boxdR", u"\u2552" }, + { u"boxdl", u"\u2510" }, + { u"boxdr", u"\u250C" }, + { u"boxh", u"\u2500" }, + { u"boxhD", u"\u2565" }, + { u"boxhU", u"\u2568" }, + { u"boxhd", u"\u252C" }, + { u"boxhu", u"\u2534" }, + { u"boxminus", u"\u229F" }, + { u"boxplus", u"\u229E" }, + { u"boxtimes", u"\u22A0" }, + { u"boxuL", u"\u255B" }, + { u"boxuR", u"\u2558" }, + { u"boxul", u"\u2518" }, + { u"boxur", u"\u2514" }, + { u"boxv", u"\u2502" }, + { u"boxvH", u"\u256A" }, + { u"boxvL", u"\u2561" }, + { u"boxvR", u"\u255E" }, + { u"boxvh", u"\u253C" }, + { u"boxvl", u"\u2524" }, + { u"boxvr", u"\u251C" }, + { u"bprime", u"\u2035" }, + { u"breve", u"\u02D8" }, + { u"brvbar", u"\u00A6" }, + { u"bscr", u"\U0001D4B7" }, + { u"bsemi", u"\u204F" }, + { u"bsim", u"\u223D" }, + { u"bsime", u"\u22CD" }, + { u"bsol", u"\u005C" }, + { u"bsolb", u"\u29C5" }, + { u"bsolhsub", u"\u27C8" }, + { u"bull", u"\u2022" }, + { u"bullet", u"\u2022" }, + { u"bump", u"\u224E" }, + { u"bumpE", u"\u2AAE" }, + { u"bumpe", u"\u224F" }, + { u"bumpeq", u"\u224F" }, + { u"cacute", u"\u0107" }, + { u"cap", u"\u2229" }, + { u"capand", u"\u2A44" }, + { u"capbrcup", u"\u2A49" }, + { u"capcap", u"\u2A4B" }, + { u"capcup", u"\u2A47" }, + { u"capdot", u"\u2A40" }, + { u"caps", u"\u2229\uFE00" }, + { u"caret", u"\u2041" }, + { u"caron", u"\u02C7" }, + { u"ccaps", u"\u2A4D" }, + { u"ccaron", u"\u010D" }, + { u"ccedil", u"\u00E7" }, + { u"ccirc", u"\u0109" }, + { u"ccups", u"\u2A4C" }, + { u"ccupssm", u"\u2A50" }, + { u"cdot", u"\u010B" }, + { u"cedil", u"\u00B8" }, + { u"cemptyv", u"\u29B2" }, + { u"cent", u"\u00A2" }, + { u"centerdot", u"\u00B7" }, + { u"cfr", u"\U0001D520" }, + { u"chcy", u"\u0447" }, + { u"check", u"\u2713" }, + { u"checkmark", u"\u2713" }, + { u"chi", u"\u03C7" }, + { u"cir", u"\u25CB" }, + { u"cirE", u"\u29C3" }, + { u"circ", u"\u02C6" }, + { u"circeq", u"\u2257" }, + { u"circlearrowleft", u"\u21BA" }, + { u"circlearrowright", u"\u21BB" }, + { u"circledR", u"\u00AE" }, + { u"circledS", u"\u24C8" }, + { u"circledast", u"\u229B" }, + { u"circledcirc", u"\u229A" }, + { u"circleddash", u"\u229D" }, + { u"cire", u"\u2257" }, + { u"cirfnint", u"\u2A10" }, + { u"cirmid", u"\u2AEF" }, + { u"cirscir", u"\u29C2" }, + { u"clubs", u"\u2663" }, + { u"clubsuit", u"\u2663" }, + { u"colon", u"\u003A" }, + { u"colone", u"\u2254" }, + { u"coloneq", u"\u2254" }, + { u"comma", u"\u002C" }, + { u"commat", u"\u0040" }, + { u"comp", u"\u2201" }, + { u"compfn", u"\u2218" }, + { u"complement", u"\u2201" }, + { u"complexes", u"\u2102" }, + { u"cong", u"\u2245" }, + { u"congdot", u"\u2A6D" }, + { u"conint", u"\u222E" }, + { u"copf", u"\U0001D554" }, + { u"coprod", u"\u2210" }, + { u"copy", u"\u00A9" }, + { u"copysr", u"\u2117" }, + { u"crarr", u"\u21B5" }, + { u"cross", u"\u2717" }, + { u"cscr", u"\U0001D4B8" }, + { u"csub", u"\u2ACF" }, + { u"csube", u"\u2AD1" }, + { u"csup", u"\u2AD0" }, + { u"csupe", u"\u2AD2" }, + { u"ctdot", u"\u22EF" }, + { u"cudarrl", u"\u2938" }, + { u"cudarrr", u"\u2935" }, + { u"cuepr", u"\u22DE" }, + { u"cuesc", u"\u22DF" }, + { u"cularr", u"\u21B6" }, + { u"cularrp", u"\u293D" }, + { u"cup", u"\u222A" }, + { u"cupbrcap", u"\u2A48" }, + { u"cupcap", u"\u2A46" }, + { u"cupcup", u"\u2A4A" }, + { u"cupdot", u"\u228D" }, + { u"cupor", u"\u2A45" }, + { u"cups", u"\u222A\uFE00" }, + { u"curarr", u"\u21B7" }, + { u"curarrm", u"\u293C" }, + { u"curlyeqprec", u"\u22DE" }, + { u"curlyeqsucc", u"\u22DF" }, + { u"curlyvee", u"\u22CE" }, + { u"curlywedge", u"\u22CF" }, + { u"curren", u"\u00A4" }, + { u"curvearrowleft", u"\u21B6" }, + { u"curvearrowright", u"\u21B7" }, + { u"cuvee", u"\u22CE" }, + { u"cuwed", u"\u22CF" }, + { u"cwconint", u"\u2232" }, + { u"cwint", u"\u2231" }, + { u"cylcty", u"\u232D" }, + { u"dArr", u"\u21D3" }, + { u"dHar", u"\u2965" }, + { u"dagger", u"\u2020" }, + { u"daleth", u"\u2138" }, + { u"darr", u"\u2193" }, + { u"dash", u"\u2010" }, + { u"dashv", u"\u22A3" }, + { u"dbkarow", u"\u290F" }, + { u"dblac", u"\u02DD" }, + { u"dcaron", u"\u010F" }, + { u"dcy", u"\u0434" }, + { u"dd", u"\u2146" }, + { u"ddagger", u"\u2021" }, + { u"ddarr", u"\u21CA" }, + { u"ddotseq", u"\u2A77" }, + { u"deg", u"\u00B0" }, + { u"delta", u"\u03B4" }, + { u"demptyv", u"\u29B1" }, + { u"dfisht", u"\u297F" }, + { u"dfr", u"\U0001D521" }, + { u"dharl", u"\u21C3" }, + { u"dharr", u"\u21C2" }, + { u"diam", u"\u22C4" }, + { u"diamond", u"\u22C4" }, + { u"diamondsuit", u"\u2666" }, + { u"diams", u"\u2666" }, + { u"die", u"\u00A8" }, + { u"digamma", u"\u03DD" }, + { u"disin", u"\u22F2" }, + { u"div", u"\u00F7" }, + { u"divide", u"\u00F7" }, + { u"divideontimes", u"\u22C7" }, + { u"divonx", u"\u22C7" }, + { u"djcy", u"\u0452" }, + { u"dlcorn", u"\u231E" }, + { u"dlcrop", u"\u230D" }, + { u"dollar", u"\u0024" }, + { u"dopf", u"\U0001D555" }, + { u"dot", u"\u02D9" }, + { u"doteq", u"\u2250" }, + { u"doteqdot", u"\u2251" }, + { u"dotminus", u"\u2238" }, + { u"dotplus", u"\u2214" }, + { u"dotsquare", u"\u22A1" }, + { u"doublebarwedge", u"\u2306" }, + { u"downarrow", u"\u2193" }, + { u"downdownarrows", u"\u21CA" }, + { u"downharpoonleft", u"\u21C3" }, + { u"downharpoonright", u"\u21C2" }, + { u"drbkarow", u"\u2910" }, + { u"drcorn", u"\u231F" }, + { u"drcrop", u"\u230C" }, + { u"dscr", u"\U0001D4B9" }, + { u"dscy", u"\u0455" }, + { u"dsol", u"\u29F6" }, + { u"dstrok", u"\u0111" }, + { u"dtdot", u"\u22F1" }, + { u"dtri", u"\u25BF" }, + { u"dtrif", u"\u25BE" }, + { u"duarr", u"\u21F5" }, + { u"duhar", u"\u296F" }, + { u"dwangle", u"\u29A6" }, + { u"dzcy", u"\u045F" }, + { u"dzigrarr", u"\u27FF" }, + { u"eDDot", u"\u2A77" }, + { u"eDot", u"\u2251" }, + { u"eacute", u"\u00E9" }, + { u"easter", u"\u2A6E" }, + { u"ecaron", u"\u011B" }, + { u"ecir", u"\u2256" }, + { u"ecirc", u"\u00EA" }, + { u"ecolon", u"\u2255" }, + { u"ecy", u"\u044D" }, + { u"edot", u"\u0117" }, + { u"ee", u"\u2147" }, + { u"efDot", u"\u2252" }, + { u"efr", u"\U0001D522" }, + { u"eg", u"\u2A9A" }, + { u"egrave", u"\u00E8" }, + { u"egs", u"\u2A96" }, + { u"egsdot", u"\u2A98" }, + { u"el", u"\u2A99" }, + { u"elinters", u"\u23E7" }, + { u"ell", u"\u2113" }, + { u"els", u"\u2A95" }, + { u"elsdot", u"\u2A97" }, + { u"emacr", u"\u0113" }, + { u"empty", u"\u2205" }, + { u"emptyset", u"\u2205" }, + { u"emptyv", u"\u2205" }, + { u"emsp", u"\u2003" }, + { u"emsp13", u"\u2004" }, + { u"emsp14", u"\u2005" }, + { u"eng", u"\u014B" }, + { u"ensp", u"\u2002" }, + { u"eogon", u"\u0119" }, + { u"eopf", u"\U0001D556" }, + { u"epar", u"\u22D5" }, + { u"eparsl", u"\u29E3" }, + { u"eplus", u"\u2A71" }, + { u"epsi", u"\u03B5" }, + { u"epsilon", u"\u03B5" }, + { u"epsiv", u"\u03F5" }, + { u"eqcirc", u"\u2256" }, + { u"eqcolon", u"\u2255" }, + { u"eqsim", u"\u2242" }, + { u"eqslantgtr", u"\u2A96" }, + { u"eqslantless", u"\u2A95" }, + { u"equals", u"\u003D" }, + { u"equest", u"\u225F" }, + { u"equiv", u"\u2261" }, + { u"equivDD", u"\u2A78" }, + { u"eqvparsl", u"\u29E5" }, + { u"erDot", u"\u2253" }, + { u"erarr", u"\u2971" }, + { u"escr", u"\u212F" }, + { u"esdot", u"\u2250" }, + { u"esim", u"\u2242" }, + { u"eta", u"\u03B7" }, + { u"eth", u"\u00F0" }, + { u"euml", u"\u00EB" }, + { u"euro", u"\u20AC" }, + { u"excl", u"\u0021" }, + { u"exist", u"\u2203" }, + { u"expectation", u"\u2130" }, + { u"exponentiale", u"\u2147" }, + { u"fallingdotseq", u"\u2252" }, + { u"fcy", u"\u0444" }, + { u"female", u"\u2640" }, + { u"ffilig", u"\uFB03" }, + { u"fflig", u"\uFB00" }, + { u"ffllig", u"\uFB04" }, + { u"ffr", u"\U0001D523" }, + { u"filig", u"\uFB01" }, + { u"fjlig", u"\u0066\u006A" }, + { u"flat", u"\u266D" }, + { u"fllig", u"\uFB02" }, + { u"fltns", u"\u25B1" }, + { u"fnof", u"\u0192" }, + { u"fopf", u"\U0001D557" }, + { u"forall", u"\u2200" }, + { u"fork", u"\u22D4" }, + { u"forkv", u"\u2AD9" }, + { u"fpartint", u"\u2A0D" }, + { u"frac12", u"\u00BD" }, + { u"frac13", u"\u2153" }, + { u"frac14", u"\u00BC" }, + { u"frac15", u"\u2155" }, + { u"frac16", u"\u2159" }, + { u"frac18", u"\u215B" }, + { u"frac23", u"\u2154" }, + { u"frac25", u"\u2156" }, + { u"frac34", u"\u00BE" }, + { u"frac35", u"\u2157" }, + { u"frac38", u"\u215C" }, + { u"frac45", u"\u2158" }, + { u"frac56", u"\u215A" }, + { u"frac58", u"\u215D" }, + { u"frac78", u"\u215E" }, + { u"frasl", u"\u2044" }, + { u"frown", u"\u2322" }, + { u"fscr", u"\U0001D4BB" }, + { u"gE", u"\u2267" }, + { u"gEl", u"\u2A8C" }, + { u"gacute", u"\u01F5" }, + { u"gamma", u"\u03B3" }, + { u"gammad", u"\u03DD" }, + { u"gap", u"\u2A86" }, + { u"gbreve", u"\u011F" }, + { u"gcirc", u"\u011D" }, + { u"gcy", u"\u0433" }, + { u"gdot", u"\u0121" }, + { u"ge", u"\u2265" }, + { u"gel", u"\u22DB" }, + { u"geq", u"\u2265" }, + { u"geqq", u"\u2267" }, + { u"geqslant", u"\u2A7E" }, + { u"ges", u"\u2A7E" }, + { u"gescc", u"\u2AA9" }, + { u"gesdot", u"\u2A80" }, + { u"gesdoto", u"\u2A82" }, + { u"gesdotol", u"\u2A84" }, + { u"gesl", u"\u22DB\uFE00" }, + { u"gesles", u"\u2A94" }, + { u"gfr", u"\U0001D524" }, + { u"gg", u"\u226B" }, + { u"ggg", u"\u22D9" }, + { u"gimel", u"\u2137" }, + { u"gjcy", u"\u0453" }, + { u"gl", u"\u2277" }, + { u"glE", u"\u2A92" }, + { u"gla", u"\u2AA5" }, + { u"glj", u"\u2AA4" }, + { u"gnE", u"\u2269" }, + { u"gnap", u"\u2A8A" }, + { u"gnapprox", u"\u2A8A" }, + { u"gne", u"\u2A88" }, + { u"gneq", u"\u2A88" }, + { u"gneqq", u"\u2269" }, + { u"gnsim", u"\u22E7" }, + { u"gopf", u"\U0001D558" }, + { u"grave", u"\u0060" }, + { u"gscr", u"\u210A" }, + { u"gsim", u"\u2273" }, + { u"gsime", u"\u2A8E" }, + { u"gsiml", u"\u2A90" }, + { u"gt", u"\u003E" }, + { u"gtcc", u"\u2AA7" }, + { u"gtcir", u"\u2A7A" }, + { u"gtdot", u"\u22D7" }, + { u"gtlPar", u"\u2995" }, + { u"gtquest", u"\u2A7C" }, + { u"gtrapprox", u"\u2A86" }, + { u"gtrarr", u"\u2978" }, + { u"gtrdot", u"\u22D7" }, + { u"gtreqless", u"\u22DB" }, + { u"gtreqqless", u"\u2A8C" }, + { u"gtrless", u"\u2277" }, + { u"gtrsim", u"\u2273" }, + { u"gvertneqq", u"\u2269\uFE00" }, + { u"gvnE", u"\u2269\uFE00" }, + { u"hArr", u"\u21D4" }, + { u"hairsp", u"\u200A" }, + { u"half", u"\u00BD" }, + { u"hamilt", u"\u210B" }, + { u"hardcy", u"\u044A" }, + { u"harr", u"\u2194" }, + { u"harrcir", u"\u2948" }, + { u"harrw", u"\u21AD" }, + { u"hbar", u"\u210F" }, + { u"hcirc", u"\u0125" }, + { u"hearts", u"\u2665" }, + { u"heartsuit", u"\u2665" }, + { u"hellip", u"\u2026" }, + { u"hercon", u"\u22B9" }, + { u"hfr", u"\U0001D525" }, + { u"hksearow", u"\u2925" }, + { u"hkswarow", u"\u2926" }, + { u"hoarr", u"\u21FF" }, + { u"homtht", u"\u223B" }, + { u"hookleftarrow", u"\u21A9" }, + { u"hookrightarrow", u"\u21AA" }, + { u"hopf", u"\U0001D559" }, + { u"horbar", u"\u2015" }, + { u"hscr", u"\U0001D4BD" }, + { u"hslash", u"\u210F" }, + { u"hstrok", u"\u0127" }, + { u"hybull", u"\u2043" }, + { u"hyphen", u"\u2010" }, + { u"iacute", u"\u00ED" }, + { u"ic", u"\u2063" }, + { u"icirc", u"\u00EE" }, + { u"icy", u"\u0438" }, + { u"iecy", u"\u0435" }, + { u"iexcl", u"\u00A1" }, + { u"iff", u"\u21D4" }, + { u"ifr", u"\U0001D526" }, + { u"igrave", u"\u00EC" }, + { u"ii", u"\u2148" }, + { u"iiiint", u"\u2A0C" }, + { u"iiint", u"\u222D" }, + { u"iinfin", u"\u29DC" }, + { u"iiota", u"\u2129" }, + { u"ijlig", u"\u0133" }, + { u"imacr", u"\u012B" }, + { u"image", u"\u2111" }, + { u"imagline", u"\u2110" }, + { u"imagpart", u"\u2111" }, + { u"imath", u"\u0131" }, + { u"imof", u"\u22B7" }, + { u"imped", u"\u01B5" }, + { u"in", u"\u2208" }, + { u"incare", u"\u2105" }, + { u"infin", u"\u221E" }, + { u"infintie", u"\u29DD" }, + { u"inodot", u"\u0131" }, + { u"int", u"\u222B" }, + { u"intcal", u"\u22BA" }, + { u"integers", u"\u2124" }, + { u"intercal", u"\u22BA" }, + { u"intlarhk", u"\u2A17" }, + { u"intprod", u"\u2A3C" }, + { u"iocy", u"\u0451" }, + { u"iogon", u"\u012F" }, + { u"iopf", u"\U0001D55A" }, + { u"iota", u"\u03B9" }, + { u"iprod", u"\u2A3C" }, + { u"iquest", u"\u00BF" }, + { u"iscr", u"\U0001D4BE" }, + { u"isin", u"\u2208" }, + { u"isinE", u"\u22F9" }, + { u"isindot", u"\u22F5" }, + { u"isins", u"\u22F4" }, + { u"isinsv", u"\u22F3" }, + { u"isinv", u"\u2208" }, + { u"it", u"\u2062" }, + { u"itilde", u"\u0129" }, + { u"iukcy", u"\u0456" }, + { u"iuml", u"\u00EF" }, + { u"jcirc", u"\u0135" }, + { u"jcy", u"\u0439" }, + { u"jfr", u"\U0001D527" }, + { u"jmath", u"\u0237" }, + { u"jopf", u"\U0001D55B" }, + { u"jscr", u"\U0001D4BF" }, + { u"jsercy", u"\u0458" }, + { u"jukcy", u"\u0454" }, + { u"kappa", u"\u03BA" }, + { u"kappav", u"\u03F0" }, + { u"kcedil", u"\u0137" }, + { u"kcy", u"\u043A" }, + { u"kfr", u"\U0001D528" }, + { u"kgreen", u"\u0138" }, + { u"khcy", u"\u0445" }, + { u"kjcy", u"\u045C" }, + { u"kopf", u"\U0001D55C" }, + { u"kscr", u"\U0001D4C0" }, + { u"lAarr", u"\u21DA" }, + { u"lArr", u"\u21D0" }, + { u"lAtail", u"\u291B" }, + { u"lBarr", u"\u290E" }, + { u"lE", u"\u2266" }, + { u"lEg", u"\u2A8B" }, + { u"lHar", u"\u2962" }, + { u"lacute", u"\u013A" }, + { u"laemptyv", u"\u29B4" }, + { u"lagran", u"\u2112" }, + { u"lambda", u"\u03BB" }, + { u"lang", u"\u27E8" }, + { u"langd", u"\u2991" }, + { u"langle", u"\u27E8" }, + { u"lap", u"\u2A85" }, + { u"laquo", u"\u00AB" }, + { u"larr", u"\u2190" }, + { u"larrb", u"\u21E4" }, + { u"larrbfs", u"\u291F" }, + { u"larrfs", u"\u291D" }, + { u"larrhk", u"\u21A9" }, + { u"larrlp", u"\u21AB" }, + { u"larrpl", u"\u2939" }, + { u"larrsim", u"\u2973" }, + { u"larrtl", u"\u21A2" }, + { u"lat", u"\u2AAB" }, + { u"latail", u"\u2919" }, + { u"late", u"\u2AAD" }, + { u"lates", u"\u2AAD\uFE00" }, + { u"lbarr", u"\u290C" }, + { u"lbbrk", u"\u2772" }, + { u"lbrace", u"\u007B" }, + { u"lbrack", u"\u005B" }, + { u"lbrke", u"\u298B" }, + { u"lbrksld", u"\u298F" }, + { u"lbrkslu", u"\u298D" }, + { u"lcaron", u"\u013E" }, + { u"lcedil", u"\u013C" }, + { u"lceil", u"\u2308" }, + { u"lcub", u"\u007B" }, + { u"lcy", u"\u043B" }, + { u"ldca", u"\u2936" }, + { u"ldquo", u"\u201C" }, + { u"ldquor", u"\u201E" }, + { u"ldrdhar", u"\u2967" }, + { u"ldrushar", u"\u294B" }, + { u"ldsh", u"\u21B2" }, + { u"le", u"\u2264" }, + { u"leftarrow", u"\u2190" }, + { u"leftarrowtail", u"\u21A2" }, + { u"leftharpoondown", u"\u21BD" }, + { u"leftharpoonup", u"\u21BC" }, + { u"leftleftarrows", u"\u21C7" }, + { u"leftrightarrow", u"\u2194" }, + { u"leftrightarrows", u"\u21C6" }, + { u"leftrightharpoons", u"\u21CB" }, + { u"leftrightsquigarrow", u"\u21AD" }, + { u"leftthreetimes", u"\u22CB" }, + { u"leg", u"\u22DA" }, + { u"leq", u"\u2264" }, + { u"leqq", u"\u2266" }, + { u"leqslant", u"\u2A7D" }, + { u"les", u"\u2A7D" }, + { u"lescc", u"\u2AA8" }, + { u"lesdot", u"\u2A7F" }, + { u"lesdoto", u"\u2A81" }, + { u"lesdotor", u"\u2A83" }, + { u"lesg", u"\u22DA\uFE00" }, + { u"lesges", u"\u2A93" }, + { u"lessapprox", u"\u2A85" }, + { u"lessdot", u"\u22D6" }, + { u"lesseqgtr", u"\u22DA" }, + { u"lesseqqgtr", u"\u2A8B" }, + { u"lessgtr", u"\u2276" }, + { u"lesssim", u"\u2272" }, + { u"lfisht", u"\u297C" }, + { u"lfloor", u"\u230A" }, + { u"lfr", u"\U0001D529" }, + { u"lg", u"\u2276" }, + { u"lgE", u"\u2A91" }, + { u"lhard", u"\u21BD" }, + { u"lharu", u"\u21BC" }, + { u"lharul", u"\u296A" }, + { u"lhblk", u"\u2584" }, + { u"ljcy", u"\u0459" }, + { u"ll", u"\u226A" }, + { u"llarr", u"\u21C7" }, + { u"llcorner", u"\u231E" }, + { u"llhard", u"\u296B" }, + { u"lltri", u"\u25FA" }, + { u"lmidot", u"\u0140" }, + { u"lmoust", u"\u23B0" }, + { u"lmoustache", u"\u23B0" }, + { u"lnE", u"\u2268" }, + { u"lnap", u"\u2A89" }, + { u"lnapprox", u"\u2A89" }, + { u"lne", u"\u2A87" }, + { u"lneq", u"\u2A87" }, + { u"lneqq", u"\u2268" }, + { u"lnsim", u"\u22E6" }, + { u"loang", u"\u27EC" }, + { u"loarr", u"\u21FD" }, + { u"lobrk", u"\u27E6" }, + { u"longleftarrow", u"\u27F5" }, + { u"longleftrightarrow", u"\u27F7" }, + { u"longmapsto", u"\u27FC" }, + { u"longrightarrow", u"\u27F6" }, + { u"looparrowleft", u"\u21AB" }, + { u"looparrowright", u"\u21AC" }, + { u"lopar", u"\u2985" }, + { u"lopf", u"\U0001D55D" }, + { u"loplus", u"\u2A2D" }, + { u"lotimes", u"\u2A34" }, + { u"lowast", u"\u2217" }, + { u"lowbar", u"\u005F" }, + { u"loz", u"\u25CA" }, + { u"lozenge", u"\u25CA" }, + { u"lozf", u"\u29EB" }, + { u"lpar", u"\u0028" }, + { u"lparlt", u"\u2993" }, + { u"lrarr", u"\u21C6" }, + { u"lrcorner", u"\u231F" }, + { u"lrhar", u"\u21CB" }, + { u"lrhard", u"\u296D" }, + { u"lrm", u"\u200E" }, + { u"lrtri", u"\u22BF" }, + { u"lsaquo", u"\u2039" }, + { u"lscr", u"\U0001D4C1" }, + { u"lsh", u"\u21B0" }, + { u"lsim", u"\u2272" }, + { u"lsime", u"\u2A8D" }, + { u"lsimg", u"\u2A8F" }, + { u"lsqb", u"\u005B" }, + { u"lsquo", u"\u2018" }, + { u"lsquor", u"\u201A" }, + { u"lstrok", u"\u0142" }, + { u"lt", u"\u003C" }, + { u"ltcc", u"\u2AA6" }, + { u"ltcir", u"\u2A79" }, + { u"ltdot", u"\u22D6" }, + { u"lthree", u"\u22CB" }, + { u"ltimes", u"\u22C9" }, + { u"ltlarr", u"\u2976" }, + { u"ltquest", u"\u2A7B" }, + { u"ltrPar", u"\u2996" }, + { u"ltri", u"\u25C3" }, + { u"ltrie", u"\u22B4" }, + { u"ltrif", u"\u25C2" }, + { u"lurdshar", u"\u294A" }, + { u"luruhar", u"\u2966" }, + { u"lvertneqq", u"\u2268\uFE00" }, + { u"lvnE", u"\u2268\uFE00" }, + { u"mDDot", u"\u223A" }, + { u"macr", u"\u00AF" }, + { u"male", u"\u2642" }, + { u"malt", u"\u2720" }, + { u"maltese", u"\u2720" }, + { u"map", u"\u21A6" }, + { u"mapsto", u"\u21A6" }, + { u"mapstodown", u"\u21A7" }, + { u"mapstoleft", u"\u21A4" }, + { u"mapstoup", u"\u21A5" }, + { u"marker", u"\u25AE" }, + { u"mcomma", u"\u2A29" }, + { u"mcy", u"\u043C" }, + { u"mdash", u"\u2014" }, + { u"measuredangle", u"\u2221" }, + { u"mfr", u"\U0001D52A" }, + { u"mho", u"\u2127" }, + { u"micro", u"\u00B5" }, + { u"mid", u"\u2223" }, + { u"midast", u"\u002A" }, + { u"midcir", u"\u2AF0" }, + { u"middot", u"\u00B7" }, + { u"minus", u"\u2212" }, + { u"minusb", u"\u229F" }, + { u"minusd", u"\u2238" }, + { u"minusdu", u"\u2A2A" }, + { u"mlcp", u"\u2ADB" }, + { u"mldr", u"\u2026" }, + { u"mnplus", u"\u2213" }, + { u"models", u"\u22A7" }, + { u"mopf", u"\U0001D55E" }, + { u"mp", u"\u2213" }, + { u"mscr", u"\U0001D4C2" }, + { u"mstpos", u"\u223E" }, + { u"mu", u"\u03BC" }, + { u"multimap", u"\u22B8" }, + { u"mumap", u"\u22B8" }, + { u"nGg", u"\u22D9\u0338" }, + { u"nGt", u"\u226B\u20D2" }, + { u"nGtv", u"\u226B\u0338" }, + { u"nLeftarrow", u"\u21CD" }, + { u"nLeftrightarrow", u"\u21CE" }, + { u"nLl", u"\u22D8\u0338" }, + { u"nLt", u"\u226A\u20D2" }, + { u"nLtv", u"\u226A\u0338" }, + { u"nRightarrow", u"\u21CF" }, + { u"nVDash", u"\u22AF" }, + { u"nVdash", u"\u22AE" }, + { u"nabla", u"\u2207" }, + { u"nacute", u"\u0144" }, + { u"nang", u"\u2220\u20D2" }, + { u"nap", u"\u2249" }, + { u"napE", u"\u2A70\u0338" }, + { u"napid", u"\u224B\u0338" }, + { u"napos", u"\u0149" }, + { u"napprox", u"\u2249" }, + { u"natur", u"\u266E" }, + { u"natural", u"\u266E" }, + { u"naturals", u"\u2115" }, + { u"nbsp", u"\u00A0" }, + { u"nbump", u"\u224E\u0338" }, + { u"nbumpe", u"\u224F\u0338" }, + { u"ncap", u"\u2A43" }, + { u"ncaron", u"\u0148" }, + { u"ncedil", u"\u0146" }, + { u"ncong", u"\u2247" }, + { u"ncongdot", u"\u2A6D\u0338" }, + { u"ncup", u"\u2A42" }, + { u"ncy", u"\u043D" }, + { u"ndash", u"\u2013" }, + { u"ne", u"\u2260" }, + { u"neArr", u"\u21D7" }, + { u"nearhk", u"\u2924" }, + { u"nearr", u"\u2197" }, + { u"nearrow", u"\u2197" }, + { u"nedot", u"\u2250\u0338" }, + { u"nequiv", u"\u2262" }, + { u"nesear", u"\u2928" }, + { u"nesim", u"\u2242\u0338" }, + { u"nexist", u"\u2204" }, + { u"nexists", u"\u2204" }, + { u"nfr", u"\U0001D52B" }, + { u"ngE", u"\u2267\u0338" }, + { u"nge", u"\u2271" }, + { u"ngeq", u"\u2271" }, + { u"ngeqq", u"\u2267\u0338" }, + { u"ngeqslant", u"\u2A7E\u0338" }, + { u"nges", u"\u2A7E\u0338" }, + { u"ngsim", u"\u2275" }, + { u"ngt", u"\u226F" }, + { u"ngtr", u"\u226F" }, + { u"nhArr", u"\u21CE" }, + { u"nharr", u"\u21AE" }, + { u"nhpar", u"\u2AF2" }, + { u"ni", u"\u220B" }, + { u"nis", u"\u22FC" }, + { u"nisd", u"\u22FA" }, + { u"niv", u"\u220B" }, + { u"njcy", u"\u045A" }, + { u"nlArr", u"\u21CD" }, + { u"nlE", u"\u2266\u0338" }, + { u"nlarr", u"\u219A" }, + { u"nldr", u"\u2025" }, + { u"nle", u"\u2270" }, + { u"nleftarrow", u"\u219A" }, + { u"nleftrightarrow", u"\u21AE" }, + { u"nleq", u"\u2270" }, + { u"nleqq", u"\u2266\u0338" }, + { u"nleqslant", u"\u2A7D\u0338" }, + { u"nles", u"\u2A7D\u0338" }, + { u"nless", u"\u226E" }, + { u"nlsim", u"\u2274" }, + { u"nlt", u"\u226E" }, + { u"nltri", u"\u22EA" }, + { u"nltrie", u"\u22EC" }, + { u"nmid", u"\u2224" }, + { u"nopf", u"\U0001D55F" }, + { u"not", u"\u00AC" }, + { u"notin", u"\u2209" }, + { u"notinE", u"\u22F9\u0338" }, + { u"notindot", u"\u22F5\u0338" }, + { u"notinva", u"\u2209" }, + { u"notinvb", u"\u22F7" }, + { u"notinvc", u"\u22F6" }, + { u"notni", u"\u220C" }, + { u"notniva", u"\u220C" }, + { u"notnivb", u"\u22FE" }, + { u"notnivc", u"\u22FD" }, + { u"npar", u"\u2226" }, + { u"nparallel", u"\u2226" }, + { u"nparsl", u"\u2AFD\u20E5" }, + { u"npart", u"\u2202\u0338" }, + { u"npolint", u"\u2A14" }, + { u"npr", u"\u2280" }, + { u"nprcue", u"\u22E0" }, + { u"npre", u"\u2AAF\u0338" }, + { u"nprec", u"\u2280" }, + { u"npreceq", u"\u2AAF\u0338" }, + { u"nrArr", u"\u21CF" }, + { u"nrarr", u"\u219B" }, + { u"nrarrc", u"\u2933\u0338" }, + { u"nrarrw", u"\u219D\u0338" }, + { u"nrightarrow", u"\u219B" }, + { u"nrtri", u"\u22EB" }, + { u"nrtrie", u"\u22ED" }, + { u"nsc", u"\u2281" }, + { u"nsccue", u"\u22E1" }, + { u"nsce", u"\u2AB0\u0338" }, + { u"nscr", u"\U0001D4C3" }, + { u"nshortmid", u"\u2224" }, + { u"nshortparallel", u"\u2226" }, + { u"nsim", u"\u2241" }, + { u"nsime", u"\u2244" }, + { u"nsimeq", u"\u2244" }, + { u"nsmid", u"\u2224" }, + { u"nspar", u"\u2226" }, + { u"nsqsube", u"\u22E2" }, + { u"nsqsupe", u"\u22E3" }, + { u"nsub", u"\u2284" }, + { u"nsubE", u"\u2AC5\u0338" }, + { u"nsube", u"\u2288" }, + { u"nsubset", u"\u2282\u20D2" }, + { u"nsubseteq", u"\u2288" }, + { u"nsubseteqq", u"\u2AC5\u0338" }, + { u"nsucc", u"\u2281" }, + { u"nsucceq", u"\u2AB0\u0338" }, + { u"nsup", u"\u2285" }, + { u"nsupE", u"\u2AC6\u0338" }, + { u"nsupe", u"\u2289" }, + { u"nsupset", u"\u2283\u20D2" }, + { u"nsupseteq", u"\u2289" }, + { u"nsupseteqq", u"\u2AC6\u0338" }, + { u"ntgl", u"\u2279" }, + { u"ntilde", u"\u00F1" }, + { u"ntlg", u"\u2278" }, + { u"ntriangleleft", u"\u22EA" }, + { u"ntrianglelefteq", u"\u22EC" }, + { u"ntriangleright", u"\u22EB" }, + { u"ntrianglerighteq", u"\u22ED" }, + { u"nu", u"\u03BD" }, + { u"num", u"\u0023" }, + { u"numero", u"\u2116" }, + { u"numsp", u"\u2007" }, + { u"nvDash", u"\u22AD" }, + { u"nvHarr", u"\u2904" }, + { u"nvap", u"\u224D\u20D2" }, + { u"nvdash", u"\u22AC" }, + { u"nvge", u"\u2265\u20D2" }, + { u"nvgt", u"\u003E\u20D2" }, + { u"nvinfin", u"\u29DE" }, + { u"nvlArr", u"\u2902" }, + { u"nvle", u"\u2264\u20D2" }, + { u"nvlt", u"\u003C\u20D2" }, + { u"nvltrie", u"\u22B4\u20D2" }, + { u"nvrArr", u"\u2903" }, + { u"nvrtrie", u"\u22B5\u20D2" }, + { u"nvsim", u"\u223C\u20D2" }, + { u"nwArr", u"\u21D6" }, + { u"nwarhk", u"\u2923" }, + { u"nwarr", u"\u2196" }, + { u"nwarrow", u"\u2196" }, + { u"nwnear", u"\u2927" }, + { u"oS", u"\u24C8" }, + { u"oacute", u"\u00F3" }, + { u"oast", u"\u229B" }, + { u"ocir", u"\u229A" }, + { u"ocirc", u"\u00F4" }, + { u"ocy", u"\u043E" }, + { u"odash", u"\u229D" }, + { u"odblac", u"\u0151" }, + { u"odiv", u"\u2A38" }, + { u"odot", u"\u2299" }, + { u"odsold", u"\u29BC" }, + { u"oelig", u"\u0153" }, + { u"ofcir", u"\u29BF" }, + { u"ofr", u"\U0001D52C" }, + { u"ogon", u"\u02DB" }, + { u"ograve", u"\u00F2" }, + { u"ogt", u"\u29C1" }, + { u"ohbar", u"\u29B5" }, + { u"ohm", u"\u03A9" }, + { u"oint", u"\u222E" }, + { u"olarr", u"\u21BA" }, + { u"olcir", u"\u29BE" }, + { u"olcross", u"\u29BB" }, + { u"oline", u"\u203E" }, + { u"olt", u"\u29C0" }, + { u"omacr", u"\u014D" }, + { u"omega", u"\u03C9" }, + { u"omicron", u"\u03BF" }, + { u"omid", u"\u29B6" }, + { u"ominus", u"\u2296" }, + { u"oopf", u"\U0001D560" }, + { u"opar", u"\u29B7" }, + { u"operp", u"\u29B9" }, + { u"oplus", u"\u2295" }, + { u"or", u"\u2228" }, + { u"orarr", u"\u21BB" }, + { u"ord", u"\u2A5D" }, + { u"order", u"\u2134" }, + { u"orderof", u"\u2134" }, + { u"ordf", u"\u00AA" }, + { u"ordm", u"\u00BA" }, + { u"origof", u"\u22B6" }, + { u"oror", u"\u2A56" }, + { u"orslope", u"\u2A57" }, + { u"orv", u"\u2A5B" }, + { u"oscr", u"\u2134" }, + { u"oslash", u"\u00F8" }, + { u"osol", u"\u2298" }, + { u"otilde", u"\u00F5" }, + { u"otimes", u"\u2297" }, + { u"otimesas", u"\u2A36" }, + { u"ouml", u"\u00F6" }, + { u"ovbar", u"\u233D" }, + { u"par", u"\u2225" }, + { u"para", u"\u00B6" }, + { u"parallel", u"\u2225" }, + { u"parsim", u"\u2AF3" }, + { u"parsl", u"\u2AFD" }, + { u"part", u"\u2202" }, + { u"pcy", u"\u043F" }, + { u"percnt", u"\u0025" }, + { u"period", u"\u002E" }, + { u"permil", u"\u2030" }, + { u"perp", u"\u22A5" }, + { u"pertenk", u"\u2031" }, + { u"pfr", u"\U0001D52D" }, + { u"phi", u"\u03C6" }, + { u"phiv", u"\u03D5" }, + { u"phmmat", u"\u2133" }, + { u"phone", u"\u260E" }, + { u"pi", u"\u03C0" }, + { u"pitchfork", u"\u22D4" }, + { u"piv", u"\u03D6" }, + { u"planck", u"\u210F" }, + { u"planckh", u"\u210E" }, + { u"plankv", u"\u210F" }, + { u"plus", u"\u002B" }, + { u"plusacir", u"\u2A23" }, + { u"plusb", u"\u229E" }, + { u"pluscir", u"\u2A22" }, + { u"plusdo", u"\u2214" }, + { u"plusdu", u"\u2A25" }, + { u"pluse", u"\u2A72" }, + { u"plusmn", u"\u00B1" }, + { u"plussim", u"\u2A26" }, + { u"plustwo", u"\u2A27" }, + { u"pm", u"\u00B1" }, + { u"pointint", u"\u2A15" }, + { u"popf", u"\U0001D561" }, + { u"pound", u"\u00A3" }, + { u"pr", u"\u227A" }, + { u"prE", u"\u2AB3" }, + { u"prap", u"\u2AB7" }, + { u"prcue", u"\u227C" }, + { u"pre", u"\u2AAF" }, + { u"prec", u"\u227A" }, + { u"precapprox", u"\u2AB7" }, + { u"preccurlyeq", u"\u227C" }, + { u"preceq", u"\u2AAF" }, + { u"precnapprox", u"\u2AB9" }, + { u"precneqq", u"\u2AB5" }, + { u"precnsim", u"\u22E8" }, + { u"precsim", u"\u227E" }, + { u"prime", u"\u2032" }, + { u"primes", u"\u2119" }, + { u"prnE", u"\u2AB5" }, + { u"prnap", u"\u2AB9" }, + { u"prnsim", u"\u22E8" }, + { u"prod", u"\u220F" }, + { u"profalar", u"\u232E" }, + { u"profline", u"\u2312" }, + { u"profsurf", u"\u2313" }, + { u"prop", u"\u221D" }, + { u"propto", u"\u221D" }, + { u"prsim", u"\u227E" }, + { u"prurel", u"\u22B0" }, + { u"pscr", u"\U0001D4C5" }, + { u"psi", u"\u03C8" }, + { u"puncsp", u"\u2008" }, + { u"qfr", u"\U0001D52E" }, + { u"qint", u"\u2A0C" }, + { u"qopf", u"\U0001D562" }, + { u"qprime", u"\u2057" }, + { u"qscr", u"\U0001D4C6" }, + { u"quaternions", u"\u210D" }, + { u"quatint", u"\u2A16" }, + { u"quest", u"\u003F" }, + { u"questeq", u"\u225F" }, + { u"quot", u"\u0022" }, + { u"rAarr", u"\u21DB" }, + { u"rArr", u"\u21D2" }, + { u"rAtail", u"\u291C" }, + { u"rBarr", u"\u290F" }, + { u"rHar", u"\u2964" }, + { u"race", u"\u223D\u0331" }, + { u"racute", u"\u0155" }, + { u"radic", u"\u221A" }, + { u"raemptyv", u"\u29B3" }, + { u"rang", u"\u27E9" }, + { u"rangd", u"\u2992" }, + { u"range", u"\u29A5" }, + { u"rangle", u"\u27E9" }, + { u"raquo", u"\u00BB" }, + { u"rarr", u"\u2192" }, + { u"rarrap", u"\u2975" }, + { u"rarrb", u"\u21E5" }, + { u"rarrbfs", u"\u2920" }, + { u"rarrc", u"\u2933" }, + { u"rarrfs", u"\u291E" }, + { u"rarrhk", u"\u21AA" }, + { u"rarrlp", u"\u21AC" }, + { u"rarrpl", u"\u2945" }, + { u"rarrsim", u"\u2974" }, + { u"rarrtl", u"\u21A3" }, + { u"rarrw", u"\u219D" }, + { u"ratail", u"\u291A" }, + { u"ratio", u"\u2236" }, + { u"rationals", u"\u211A" }, + { u"rbarr", u"\u290D" }, + { u"rbbrk", u"\u2773" }, + { u"rbrace", u"\u007D" }, + { u"rbrack", u"\u005D" }, + { u"rbrke", u"\u298C" }, + { u"rbrksld", u"\u298E" }, + { u"rbrkslu", u"\u2990" }, + { u"rcaron", u"\u0159" }, + { u"rcedil", u"\u0157" }, + { u"rceil", u"\u2309" }, + { u"rcub", u"\u007D" }, + { u"rcy", u"\u0440" }, + { u"rdca", u"\u2937" }, + { u"rdldhar", u"\u2969" }, + { u"rdquo", u"\u201D" }, + { u"rdquor", u"\u201D" }, + { u"rdsh", u"\u21B3" }, + { u"real", u"\u211C" }, + { u"realine", u"\u211B" }, + { u"realpart", u"\u211C" }, + { u"reals", u"\u211D" }, + { u"rect", u"\u25AD" }, + { u"reg", u"\u00AE" }, + { u"rfisht", u"\u297D" }, + { u"rfloor", u"\u230B" }, + { u"rfr", u"\U0001D52F" }, + { u"rhard", u"\u21C1" }, + { u"rharu", u"\u21C0" }, + { u"rharul", u"\u296C" }, + { u"rho", u"\u03C1" }, + { u"rhov", u"\u03F1" }, + { u"rightarrow", u"\u2192" }, + { u"rightarrowtail", u"\u21A3" }, + { u"rightharpoondown", u"\u21C1" }, + { u"rightharpoonup", u"\u21C0" }, + { u"rightleftarrows", u"\u21C4" }, + { u"rightleftharpoons", u"\u21CC" }, + { u"rightrightarrows", u"\u21C9" }, + { u"rightsquigarrow", u"\u219D" }, + { u"rightthreetimes", u"\u22CC" }, + { u"ring", u"\u02DA" }, + { u"risingdotseq", u"\u2253" }, + { u"rlarr", u"\u21C4" }, + { u"rlhar", u"\u21CC" }, + { u"rlm", u"\u200F" }, + { u"rmoust", u"\u23B1" }, + { u"rmoustache", u"\u23B1" }, + { u"rnmid", u"\u2AEE" }, + { u"roang", u"\u27ED" }, + { u"roarr", u"\u21FE" }, + { u"robrk", u"\u27E7" }, + { u"ropar", u"\u2986" }, + { u"ropf", u"\U0001D563" }, + { u"roplus", u"\u2A2E" }, + { u"rotimes", u"\u2A35" }, + { u"rpar", u"\u0029" }, + { u"rpargt", u"\u2994" }, + { u"rppolint", u"\u2A12" }, + { u"rrarr", u"\u21C9" }, + { u"rsaquo", u"\u203A" }, + { u"rscr", u"\U0001D4C7" }, + { u"rsh", u"\u21B1" }, + { u"rsqb", u"\u005D" }, + { u"rsquo", u"\u2019" }, + { u"rsquor", u"\u2019" }, + { u"rthree", u"\u22CC" }, + { u"rtimes", u"\u22CA" }, + { u"rtri", u"\u25B9" }, + { u"rtrie", u"\u22B5" }, + { u"rtrif", u"\u25B8" }, + { u"rtriltri", u"\u29CE" }, + { u"ruluhar", u"\u2968" }, + { u"rx", u"\u211E" }, + { u"sacute", u"\u015B" }, + { u"sbquo", u"\u201A" }, + { u"sc", u"\u227B" }, + { u"scE", u"\u2AB4" }, + { u"scap", u"\u2AB8" }, + { u"scaron", u"\u0161" }, + { u"sccue", u"\u227D" }, + { u"sce", u"\u2AB0" }, + { u"scedil", u"\u015F" }, + { u"scirc", u"\u015D" }, + { u"scnE", u"\u2AB6" }, + { u"scnap", u"\u2ABA" }, + { u"scnsim", u"\u22E9" }, + { u"scpolint", u"\u2A13" }, + { u"scsim", u"\u227F" }, + { u"scy", u"\u0441" }, + { u"sdot", u"\u22C5" }, + { u"sdotb", u"\u22A1" }, + { u"sdote", u"\u2A66" }, + { u"seArr", u"\u21D8" }, + { u"searhk", u"\u2925" }, + { u"searr", u"\u2198" }, + { u"searrow", u"\u2198" }, + { u"sect", u"\u00A7" }, + { u"semi", u"\u003B" }, + { u"seswar", u"\u2929" }, + { u"setminus", u"\u2216" }, + { u"setmn", u"\u2216" }, + { u"sext", u"\u2736" }, + { u"sfr", u"\U0001D530" }, + { u"sfrown", u"\u2322" }, + { u"sharp", u"\u266F" }, + { u"shchcy", u"\u0449" }, + { u"shcy", u"\u0448" }, + { u"shortmid", u"\u2223" }, + { u"shortparallel", u"\u2225" }, + { u"shy", u"\u00AD" }, + { u"sigma", u"\u03C3" }, + { u"sigmaf", u"\u03C2" }, + { u"sigmav", u"\u03C2" }, + { u"sim", u"\u223C" }, + { u"simdot", u"\u2A6A" }, + { u"sime", u"\u2243" }, + { u"simeq", u"\u2243" }, + { u"simg", u"\u2A9E" }, + { u"simgE", u"\u2AA0" }, + { u"siml", u"\u2A9D" }, + { u"simlE", u"\u2A9F" }, + { u"simne", u"\u2246" }, + { u"simplus", u"\u2A24" }, + { u"simrarr", u"\u2972" }, + { u"slarr", u"\u2190" }, + { u"smallsetminus", u"\u2216" }, + { u"smashp", u"\u2A33" }, + { u"smeparsl", u"\u29E4" }, + { u"smid", u"\u2223" }, + { u"smile", u"\u2323" }, + { u"smt", u"\u2AAA" }, + { u"smte", u"\u2AAC" }, + { u"smtes", u"\u2AAC\uFE00" }, + { u"softcy", u"\u044C" }, + { u"sol", u"\u002F" }, + { u"solb", u"\u29C4" }, + { u"solbar", u"\u233F" }, + { u"sopf", u"\U0001D564" }, + { u"spades", u"\u2660" }, + { u"spadesuit", u"\u2660" }, + { u"spar", u"\u2225" }, + { u"sqcap", u"\u2293" }, + { u"sqcaps", u"\u2293\uFE00" }, + { u"sqcup", u"\u2294" }, + { u"sqcups", u"\u2294\uFE00" }, + { u"sqsub", u"\u228F" }, + { u"sqsube", u"\u2291" }, + { u"sqsubset", u"\u228F" }, + { u"sqsubseteq", u"\u2291" }, + { u"sqsup", u"\u2290" }, + { u"sqsupe", u"\u2292" }, + { u"sqsupset", u"\u2290" }, + { u"sqsupseteq", u"\u2292" }, + { u"squ", u"\u25A1" }, + { u"square", u"\u25A1" }, + { u"squarf", u"\u25AA" }, + { u"squf", u"\u25AA" }, + { u"srarr", u"\u2192" }, + { u"sscr", u"\U0001D4C8" }, + { u"ssetmn", u"\u2216" }, + { u"ssmile", u"\u2323" }, + { u"sstarf", u"\u22C6" }, + { u"star", u"\u2606" }, + { u"starf", u"\u2605" }, + { u"straightepsilon", u"\u03F5" }, + { u"straightphi", u"\u03D5" }, + { u"strns", u"\u00AF" }, + { u"sub", u"\u2282" }, + { u"subE", u"\u2AC5" }, + { u"subdot", u"\u2ABD" }, + { u"sube", u"\u2286" }, + { u"subedot", u"\u2AC3" }, + { u"submult", u"\u2AC1" }, + { u"subnE", u"\u2ACB" }, + { u"subne", u"\u228A" }, + { u"subplus", u"\u2ABF" }, + { u"subrarr", u"\u2979" }, + { u"subset", u"\u2282" }, + { u"subseteq", u"\u2286" }, + { u"subseteqq", u"\u2AC5" }, + { u"subsetneq", u"\u228A" }, + { u"subsetneqq", u"\u2ACB" }, + { u"subsim", u"\u2AC7" }, + { u"subsub", u"\u2AD5" }, + { u"subsup", u"\u2AD3" }, + { u"succ", u"\u227B" }, + { u"succapprox", u"\u2AB8" }, + { u"succcurlyeq", u"\u227D" }, + { u"succeq", u"\u2AB0" }, + { u"succnapprox", u"\u2ABA" }, + { u"succneqq", u"\u2AB6" }, + { u"succnsim", u"\u22E9" }, + { u"succsim", u"\u227F" }, + { u"sum", u"\u2211" }, + { u"sung", u"\u266A" }, + { u"sup", u"\u2283" }, + { u"sup1", u"\u00B9" }, + { u"sup2", u"\u00B2" }, + { u"sup3", u"\u00B3" }, + { u"supE", u"\u2AC6" }, + { u"supdot", u"\u2ABE" }, + { u"supdsub", u"\u2AD8" }, + { u"supe", u"\u2287" }, + { u"supedot", u"\u2AC4" }, + { u"suphsol", u"\u27C9" }, + { u"suphsub", u"\u2AD7" }, + { u"suplarr", u"\u297B" }, + { u"supmult", u"\u2AC2" }, + { u"supnE", u"\u2ACC" }, + { u"supne", u"\u228B" }, + { u"supplus", u"\u2AC0" }, + { u"supset", u"\u2283" }, + { u"supseteq", u"\u2287" }, + { u"supseteqq", u"\u2AC6" }, + { u"supsetneq", u"\u228B" }, + { u"supsetneqq", u"\u2ACC" }, + { u"supsim", u"\u2AC8" }, + { u"supsub", u"\u2AD4" }, + { u"supsup", u"\u2AD6" }, + { u"swArr", u"\u21D9" }, + { u"swarhk", u"\u2926" }, + { u"swarr", u"\u2199" }, + { u"swarrow", u"\u2199" }, + { u"swnwar", u"\u292A" }, + { u"szlig", u"\u00DF" }, + { u"target", u"\u2316" }, + { u"tau", u"\u03C4" }, + { u"tbrk", u"\u23B4" }, + { u"tcaron", u"\u0165" }, + { u"tcedil", u"\u0163" }, + { u"tcy", u"\u0442" }, + { u"tdot", u"\u20DB" }, + { u"telrec", u"\u2315" }, + { u"tfr", u"\U0001D531" }, + { u"there4", u"\u2234" }, + { u"therefore", u"\u2234" }, + { u"theta", u"\u03B8" }, + { u"thetasym", u"\u03D1" }, + { u"thetav", u"\u03D1" }, + { u"thickapprox", u"\u2248" }, + { u"thicksim", u"\u223C" }, + { u"thinsp", u"\u2009" }, + { u"thkap", u"\u2248" }, + { u"thksim", u"\u223C" }, + { u"thorn", u"\u00FE" }, + { u"tilde", u"\u02DC" }, + { u"times", u"\u00D7" }, + { u"timesb", u"\u22A0" }, + { u"timesbar", u"\u2A31" }, + { u"timesd", u"\u2A30" }, + { u"tint", u"\u222D" }, + { u"toea", u"\u2928" }, + { u"top", u"\u22A4" }, + { u"topbot", u"\u2336" }, + { u"topcir", u"\u2AF1" }, + { u"topf", u"\U0001D565" }, + { u"topfork", u"\u2ADA" }, + { u"tosa", u"\u2929" }, + { u"tprime", u"\u2034" }, + { u"trade", u"\u2122" }, + { u"triangle", u"\u25B5" }, + { u"triangledown", u"\u25BF" }, + { u"triangleleft", u"\u25C3" }, + { u"trianglelefteq", u"\u22B4" }, + { u"triangleq", u"\u225C" }, + { u"triangleright", u"\u25B9" }, + { u"trianglerighteq", u"\u22B5" }, + { u"tridot", u"\u25EC" }, + { u"trie", u"\u225C" }, + { u"triminus", u"\u2A3A" }, + { u"triplus", u"\u2A39" }, + { u"trisb", u"\u29CD" }, + { u"tritime", u"\u2A3B" }, + { u"trpezium", u"\u23E2" }, + { u"tscr", u"\U0001D4C9" }, + { u"tscy", u"\u0446" }, + { u"tshcy", u"\u045B" }, + { u"tstrok", u"\u0167" }, + { u"twixt", u"\u226C" }, + { u"twoheadleftarrow", u"\u219E" }, + { u"twoheadrightarrow", u"\u21A0" }, + { u"uArr", u"\u21D1" }, + { u"uHar", u"\u2963" }, + { u"uacute", u"\u00FA" }, + { u"uarr", u"\u2191" }, + { u"ubrcy", u"\u045E" }, + { u"ubreve", u"\u016D" }, + { u"ucirc", u"\u00FB" }, + { u"ucy", u"\u0443" }, + { u"udarr", u"\u21C5" }, + { u"udblac", u"\u0171" }, + { u"udhar", u"\u296E" }, + { u"ufisht", u"\u297E" }, + { u"ufr", u"\U0001D532" }, + { u"ugrave", u"\u00F9" }, + { u"uharl", u"\u21BF" }, + { u"uharr", u"\u21BE" }, + { u"uhblk", u"\u2580" }, + { u"ulcorn", u"\u231C" }, + { u"ulcorner", u"\u231C" }, + { u"ulcrop", u"\u230F" }, + { u"ultri", u"\u25F8" }, + { u"umacr", u"\u016B" }, + { u"uml", u"\u00A8" }, + { u"uogon", u"\u0173" }, + { u"uopf", u"\U0001D566" }, + { u"uparrow", u"\u2191" }, + { u"updownarrow", u"\u2195" }, + { u"upharpoonleft", u"\u21BF" }, + { u"upharpoonright", u"\u21BE" }, + { u"uplus", u"\u228E" }, + { u"upsi", u"\u03C5" }, + { u"upsih", u"\u03D2" }, + { u"upsilon", u"\u03C5" }, + { u"upuparrows", u"\u21C8" }, + { u"urcorn", u"\u231D" }, + { u"urcorner", u"\u231D" }, + { u"urcrop", u"\u230E" }, + { u"uring", u"\u016F" }, + { u"urtri", u"\u25F9" }, + { u"uscr", u"\U0001D4CA" }, + { u"utdot", u"\u22F0" }, + { u"utilde", u"\u0169" }, + { u"utri", u"\u25B5" }, + { u"utrif", u"\u25B4" }, + { u"uuarr", u"\u21C8" }, + { u"uuml", u"\u00FC" }, + { u"uwangle", u"\u29A7" }, + { u"vArr", u"\u21D5" }, + { u"vBar", u"\u2AE8" }, + { u"vBarv", u"\u2AE9" }, + { u"vDash", u"\u22A8" }, + { u"vangrt", u"\u299C" }, + { u"varepsilon", u"\u03F5" }, + { u"varkappa", u"\u03F0" }, + { u"varnothing", u"\u2205" }, + { u"varphi", u"\u03D5" }, + { u"varpi", u"\u03D6" }, + { u"varpropto", u"\u221D" }, + { u"varr", u"\u2195" }, + { u"varrho", u"\u03F1" }, + { u"varsigma", u"\u03C2" }, + { u"varsubsetneq", u"\u228A\uFE00" }, + { u"varsubsetneqq", u"\u2ACB\uFE00" }, + { u"varsupsetneq", u"\u228B\uFE00" }, + { u"varsupsetneqq", u"\u2ACC\uFE00" }, + { u"vartheta", u"\u03D1" }, + { u"vartriangleleft", u"\u22B2" }, + { u"vartriangleright", u"\u22B3" }, + { u"vcy", u"\u0432" }, + { u"vdash", u"\u22A2" }, + { u"vee", u"\u2228" }, + { u"veebar", u"\u22BB" }, + { u"veeeq", u"\u225A" }, + { u"vellip", u"\u22EE" }, + { u"verbar", u"\u007C" }, + { u"vert", u"\u007C" }, + { u"vfr", u"\U0001D533" }, + { u"vltri", u"\u22B2" }, + { u"vnsub", u"\u2282\u20D2" }, + { u"vnsup", u"\u2283\u20D2" }, + { u"vopf", u"\U0001D567" }, + { u"vprop", u"\u221D" }, + { u"vrtri", u"\u22B3" }, + { u"vscr", u"\U0001D4CB" }, + { u"vsubnE", u"\u2ACB\uFE00" }, + { u"vsubne", u"\u228A\uFE00" }, + { u"vsupnE", u"\u2ACC\uFE00" }, + { u"vsupne", u"\u228B\uFE00" }, + { u"vzigzag", u"\u299A" }, + { u"wcirc", u"\u0175" }, + { u"wedbar", u"\u2A5F" }, + { u"wedge", u"\u2227" }, + { u"wedgeq", u"\u2259" }, + { u"weierp", u"\u2118" }, + { u"wfr", u"\U0001D534" }, + { u"wopf", u"\U0001D568" }, + { u"wp", u"\u2118" }, + { u"wr", u"\u2240" }, + { u"wreath", u"\u2240" }, + { u"wscr", u"\U0001D4CC" }, + { u"xcap", u"\u22C2" }, + { u"xcirc", u"\u25EF" }, + { u"xcup", u"\u22C3" }, + { u"xdtri", u"\u25BD" }, + { u"xfr", u"\U0001D535" }, + { u"xhArr", u"\u27FA" }, + { u"xharr", u"\u27F7" }, + { u"xi", u"\u03BE" }, + { u"xlArr", u"\u27F8" }, + { u"xlarr", u"\u27F5" }, + { u"xmap", u"\u27FC" }, + { u"xnis", u"\u22FB" }, + { u"xodot", u"\u2A00" }, + { u"xopf", u"\U0001D569" }, + { u"xoplus", u"\u2A01" }, + { u"xotime", u"\u2A02" }, + { u"xrArr", u"\u27F9" }, + { u"xrarr", u"\u27F6" }, + { u"xscr", u"\U0001D4CD" }, + { u"xsqcup", u"\u2A06" }, + { u"xuplus", u"\u2A04" }, + { u"xutri", u"\u25B3" }, + { u"xvee", u"\u22C1" }, + { u"xwedge", u"\u22C0" }, + { u"yacute", u"\u00FD" }, + { u"yacy", u"\u044F" }, + { u"ycirc", u"\u0177" }, + { u"ycy", u"\u044B" }, + { u"yen", u"\u00A5" }, + { u"yfr", u"\U0001D536" }, + { u"yicy", u"\u0457" }, + { u"yopf", u"\U0001D56A" }, + { u"yscr", u"\U0001D4CE" }, + { u"yucy", u"\u044E" }, + { u"yuml", u"\u00FF" }, + { u"zacute", u"\u017A" }, + { u"zcaron", u"\u017E" }, + { u"zcy", u"\u0437" }, + { u"zdot", u"\u017C" }, + { u"zeetrf", u"\u2128" }, + { u"zeta", u"\u03B6" }, + { u"zfr", u"\U0001D537" }, + { u"zhcy", u"\u0436" }, + { u"zigrarr", u"\u21DD" }, + { u"zopf", u"\U0001D56B" }, + { u"zscr", u"\U0001D4CF" }, + { u"zwj", u"\u200D" }, + { u"zwnj", u"\u200C" } + // clang-format on + }; + +const ::css::uno::Sequence<::css::beans::Pair<OUString, OUString>> + starmathdatabase::icustomMathmlHtmlEntities( + icustomMathmlHtmlEntitiesData, starmathdatabase::STARMATH_MATHMLHTML_ENTITY_NUMBER); + +static ::css::beans::Pair<::rtl::OUString, ::rtl::OUString> + icustomMathmlHtmlEntitiesNamesExportData[2] = { + // clang-format off + { u"σ", u"\u03C3"}, + { u"∞", u"\u221E"} + // clang-format on + }; +const ::css::uno::Sequence<::css::beans::Pair<::rtl::OUString, ::rtl::OUString>> + starmathdatabase::icustomMathmlHtmlEntitiesExport(icustomMathmlHtmlEntitiesNamesExportData, 2); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |