/* -*- 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*/
// 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(u"BaseURI"_ustr, 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(u"dummyObjName"_ustr); const SfxStringItem* pDocHierarchItem
= rMedium.GetItemSet().GetItem(SID_DOC_HIERARCHICALNAME); if (pDocHierarchItem)
aName = pDocHierarchItem->GetValue();
if (!aName.isEmpty())
{
xInfoSet->setPropertyValue(u"StreamRelPath"_ustr, Any(aName));
}
}
bool bOASIS = (SotStorage::GetVersion(rMedium.GetStorage()) > SOFFICE_FILEFORMAT_60); if (xStatusIndicator.is())
xStatusIndicator->setValue(nSteps++);
// determine if stream is encrypted or not
uno::Reference<beans::XPropertySet> xProps(xEventsStream, uno::UNO_QUERY);
Any aAny = xProps->getPropertyValue(u"Encrypted"_ustr); bool bEncrypted = false; if (aAny.getValueType() == cppu::UnoType<bool>::get())
aAny >>= bEncrypted;
// set Base URL if (rPropSet.is())
{
rPropSet->setPropertyValue(u"StreamName"_ustr, Any(sStreamName));
}
void SmXMLImport::endDocument()
{ //Set the resulted tree into the SmDocShell where it belongs
std::unique_ptr<SmNode> pTree = popOrZero(aNodeStack); if (pTree && pTree->GetType() == SmNodeType::Table)
{
uno::Reference<frame::XModel> xModel = GetModel();
SmModel* pModel = dynamic_cast<SmModel*>(xModel.get());
if (pModel)
{
SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell()); auto pTreeTmp = pTree.get();
pDocShell->SetFormulaTree(static_cast<SmTableNode*>(pTree.release())); if (aText.isEmpty()) //If we picked up no annotation text
{ // Get text from imported formula
SmNodeToTextVisitor tmpvisitor(pTreeTmp, aText);
}
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 aChars2 = rChars.trim(); if (!aChars2.isEmpty())
TCharacters(aChars2 /*.collapse()*/);
}
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: 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;
}
}
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; elseif (sFontFamily.equalsIgnoreAsciiCase("sans"))
aToken.eType = TSANS; elseif (sFontFamily.equalsIgnoreAsciiCase("serif"))
aToken.eType = TSERIF; else//Just give up, we need to extend our font mechanism to be //more general return;
std::vector<SmTokenType> vVariant;
MathMLMathvariantValue eMv = mbMvFound ? meMv : eDefaultMv; switch (eMv)
{ case MathMLMathvariantValue::Normal:
vVariant.push_back(TNITALIC); break; case MathMLMathvariantValue::Bold: case MathMLMathvariantValue::BoldFraktur: // TODO: Fraktur case MathMLMathvariantValue::BoldScript: // TODO: Script
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::Script: // TODO break; case MathMLMathvariantValue::Fraktur: // TODO break; case MathMLMathvariantValue::SansSerif:
vVariant.push_back(TSANS); break; case MathMLMathvariantValue::BoldSansSerif:
vVariant.push_back(TSANS);
vVariant.push_back(TBOLD); break; case MathMLMathvariantValue::SansSerifItalic:
vVariant.push_back(TITALIC);
vVariant.push_back(TSANS); break; case MathMLMathvariantValue::SansSerifBoldItalic:
vVariant.push_back(TITALIC);
vVariant.push_back(TBOLD);
vVariant.push_back(TSANS); break; case MathMLMathvariantValue::Monospace:
vVariant.push_back(TFIXED); break; case MathMLMathvariantValue::Initial: case MathMLMathvariantValue::Tailed: case MathMLMathvariantValue::Looped: case MathMLMathvariantValue::Stretched: // TODO break;
} if (vVariant.empty()) return;
SmNodeStack& rNodeStack = mrContext.GetSmImport().GetNodeStack(); for (auto eType : vVariant)
{
SmToken aToken;
aToken.eType = eType;
aToken.cMathChar = u""_ustr;
aToken.nLevel = 5;
std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
rNodeStack.push_front(std::move(pFontNode));
}
}
namespace
{ class SmXMLDocContext_Impl : public SmXMLImportContext
{ public:
SmXMLDocContext_Impl(SmXMLImport& rImport)
: SmXMLImportContext(rImport)
{
}
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 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)
{
}
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 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 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 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);
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 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;
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 \"".
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);
}
bool lcl_CountBlanks(const MathMLAttributeLengthValue& rLV, sal_Int32* pWide, sal_Int32* pNarrow)
{
assert(pWide);
assert(pNarrow); if (rLV.aNumber.GetNumerator() == 0)
{
*pWide = *pNarrow = 0; returntrue;
} // TODO: honor other units than em if (rLV.eUnit != MathMLLengthUnit::Em) returnfalse; if (rLV.aNumber.GetNumerator() < 0) returnfalse; const Fraction aTwo(2, 1); auto aWide = rLV.aNumber / aTwo; auto nWide = static_cast<sal_Int32>(static_cast<tools::Long>(aWide)); if (nWide < 0) returnfalse; 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) returnfalse;
*pWide = nWide;
*pNarrow = nNarrow; returntrue;
}
}
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;
void SmXMLUnderContext_Impl::HandleAccent()
{ constbool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
OSL_ENSURE(bNodeCheck, "Sub has not two arguments"); if (!bNodeCheck) return;
/*Just one special case for the underline thing*/
SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
std::unique_ptr<SmNode> pTest = popOrZero(rNodeStack);
SmToken aToken;
aToken.cMathChar = u""_ustr;
aToken.eType = TUNDERLINE;
void SmXMLOverContext_Impl::endFastElement(sal_Int32)
{ if (!nAttrCount)
GenericEndElement(TCSUP, CSUP); else
HandleAccent();
}
void SmXMLOverContext_Impl::HandleAccent()
{ constbool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
OSL_ENSURE(bNodeCheck, "Sub has not two arguments"); if (!bNodeCheck) return;
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?");
} elseif (nElement == XML_ELEMENT(OFFICE, XML_SETTINGS))
{ returnnew 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);
switch (nElement)
{ //Consider semantics a dummy except for any starmath annotations case XML_ELEMENT(MATH, XML_SEMANTICS): /*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()));
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));
}
//If the first or last element is an operator with stretchyness //set then we must create a brace node here from those elements, //removing the stretchness from the operators and applying it to //ourselves, and creating the appropriate dummy StarMath none bracket //to balance the arrangement if (((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height)
&& (aRelationArray[0]->GetType() == SmNodeType::Math))
|| ((aRelationArray[nSize - 1]->GetScaleMode() == SmScaleMode::Height)
&& (aRelationArray[nSize - 1]->GetType() == SmNodeType::Math)))
{
SmToken aToken;
aToken.cMathChar = u""_ustr;
aToken.nLevel = 5;
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);
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;
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;
}
/*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();
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
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));
}
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;
}
//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);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.