Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / starmath / source / mathml / mathmlimport.cxx
bloba33a4015846fda91d3d399db932d0ba428b81581
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 /*todo: Change characters and tcharacters to accumulate the characters together
21 into one string, xml parser hands them to us line by line rather than all in
22 one go*/
24 #include <com/sun/star/xml/sax/InputSource.hpp>
25 #include <com/sun/star/xml/sax/FastParser.hpp>
26 #include <com/sun/star/xml/sax/Parser.hpp>
27 #include <com/sun/star/xml/sax/SAXParseException.hpp>
28 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
29 #include <com/sun/star/packages/WrongPasswordException.hpp>
30 #include <com/sun/star/packages/zip/ZipIOException.hpp>
31 #include <com/sun/star/beans/PropertyAttribute.hpp>
32 #include <com/sun/star/embed/ElementModes.hpp>
33 #include <com/sun/star/uno/Any.h>
34 #include <com/sun/star/task/XStatusIndicator.hpp>
36 #include <comphelper/fileformat.h>
37 #include <comphelper/genericpropertyset.hxx>
38 #include <comphelper/processfactory.hxx>
39 #include <comphelper/servicehelper.hxx>
40 #include <comphelper/propertysetinfo.hxx>
41 #include <rtl/character.hxx>
42 #include <sal/log.hxx>
43 #include <sfx2/frame.hxx>
44 #include <sfx2/docfile.hxx>
45 #include <sfx2/sfxsids.hrc>
46 #include <sfx2/sfxmodelfactory.hxx>
47 #include <osl/diagnose.h>
48 #include <sot/storage.hxx>
49 #include <svtools/sfxecode.hxx>
50 #include <svl/itemset.hxx>
51 #include <svl/stritem.hxx>
52 #include <unotools/streamwrap.hxx>
53 #include <sax/tools/converter.hxx>
54 #include <xmloff/DocumentSettingsContext.hxx>
55 #include <xmloff/xmlnamespace.hxx>
56 #include <xmloff/xmltoken.hxx>
57 #include <xmloff/xmluconv.hxx>
58 #include <xmloff/xmlmetai.hxx>
59 #include <svx/dialmgr.hxx>
60 #include <svx/strings.hrc>
61 #include <comphelper/diagnose_ex.hxx>
62 #include <o3tl/string_view.hxx>
64 #include <mathmlattr.hxx>
65 #include <xparsmlbase.hxx>
66 #include <mathmlimport.hxx>
67 #include <document.hxx>
68 #include <smdll.hxx>
69 #include <unomodel.hxx>
70 #include <utility.hxx>
71 #include <visitors.hxx>
72 #include <starmathdatabase.hxx>
73 #include <smmod.hxx>
74 #include <cfgitem.hxx>
76 using namespace ::com::sun::star::beans;
77 using namespace ::com::sun::star::container;
78 using namespace ::com::sun::star::document;
79 using namespace ::com::sun::star::lang;
80 using namespace ::com::sun::star::uno;
81 using namespace ::com::sun::star;
82 using namespace ::xmloff::token;
84 namespace
86 std::unique_ptr<SmNode> popOrZero(SmNodeStack& rStack)
88 if (rStack.empty())
89 return nullptr;
90 auto pTmp = std::move(rStack.front());
91 rStack.pop_front();
92 return pTmp;
96 ErrCode SmXMLImportWrapper::Import(SfxMedium& rMedium)
98 ErrCode nError = ERRCODE_SFX_DOLOADFAILED;
100 uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
102 OSL_ENSURE(m_xModel.is(), "XMLReader::Read: got no model");
104 // try to get an XStatusIndicator from the Medium
105 uno::Reference<task::XStatusIndicator> xStatusIndicator;
107 bool bEmbedded = false;
108 SmModel* pModel = m_xModel.get();
110 SmDocShell* pDocShell = pModel ? static_cast<SmDocShell*>(pModel->GetObjectShell()) : nullptr;
111 if (pDocShell)
113 OSL_ENSURE(pDocShell->GetMedium() == &rMedium, "different SfxMedium found");
115 SfxItemSet* pSet = rMedium.GetItemSet();
116 if (pSet)
118 const SfxUnoAnyItem* pItem = pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL);
119 if (pItem)
120 pItem->GetValue() >>= xStatusIndicator;
123 if (SfxObjectCreateMode::EMBEDDED == pDocShell->GetCreateMode())
124 bEmbedded = true;
127 static const comphelper::PropertyMapEntry aInfoMap[]
128 = { { OUString("PrivateData"), 0, cppu::UnoType<XInterface>::get(),
129 beans::PropertyAttribute::MAYBEVOID, 0 },
130 { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(),
131 beans::PropertyAttribute::MAYBEVOID, 0 },
132 { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(),
133 beans::PropertyAttribute::MAYBEVOID, 0 },
134 { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(),
135 beans::PropertyAttribute::MAYBEVOID, 0 } };
136 uno::Reference<beans::XPropertySet> xInfoSet(
137 comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));
139 // Set base URI
140 OUString const baseURI(rMedium.GetBaseURL());
141 // needed for relative URLs; but it's OK to import e.g. MathML from the
142 // clipboard without one
143 SAL_INFO_IF(baseURI.isEmpty(), "starmath", "SmXMLImportWrapper: no base URL");
144 xInfoSet->setPropertyValue("BaseURI", Any(baseURI));
146 sal_Int32 nSteps = 3;
147 if (!(rMedium.IsStorage()))
148 nSteps = 1;
150 sal_Int32 nProgressRange(nSteps);
151 if (xStatusIndicator.is())
153 xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange);
156 nSteps = 0;
157 if (xStatusIndicator.is())
158 xStatusIndicator->setValue(nSteps++);
160 if (rMedium.IsStorage())
162 // TODO/LATER: handle the case of embedded links gracefully
163 if (bEmbedded) // && !rMedium.GetStorage()->IsRoot() )
165 OUString aName("dummyObjName");
166 if (rMedium.GetItemSet())
168 const SfxStringItem* pDocHierarchItem
169 = rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME);
170 if (pDocHierarchItem)
171 aName = pDocHierarchItem->GetValue();
174 if (!aName.isEmpty())
176 xInfoSet->setPropertyValue("StreamRelPath", Any(aName));
180 bool bOASIS = (SotStorage::GetVersion(rMedium.GetStorage()) > SOFFICE_FILEFORMAT_60);
181 if (xStatusIndicator.is())
182 xStatusIndicator->setValue(nSteps++);
184 auto nWarn
185 = ReadThroughComponent(rMedium.GetStorage(), m_xModel, "meta.xml", xContext, xInfoSet,
186 (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaImporter"
187 : "com.sun.star.comp.Math.XMLMetaImporter"),
188 m_bUseHTMLMLEntities);
190 if (nWarn != ERRCODE_IO_BROKENPACKAGE)
192 if (xStatusIndicator.is())
193 xStatusIndicator->setValue(nSteps++);
195 nWarn = ReadThroughComponent(rMedium.GetStorage(), m_xModel, "settings.xml", xContext,
196 xInfoSet,
197 (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsImporter"
198 : "com.sun.star.comp.Math.XMLSettingsImporter"),
199 m_bUseHTMLMLEntities);
201 if (nWarn != ERRCODE_IO_BROKENPACKAGE)
203 if (xStatusIndicator.is())
204 xStatusIndicator->setValue(nSteps++);
206 nError = ReadThroughComponent(
207 rMedium.GetStorage(), m_xModel, "content.xml", xContext, xInfoSet,
208 "com.sun.star.comp.Math.XMLImporter", m_bUseHTMLMLEntities);
210 else
211 nError = ERRCODE_IO_BROKENPACKAGE;
213 else
214 nError = ERRCODE_IO_BROKENPACKAGE;
216 else
218 Reference<io::XInputStream> xInputStream
219 = new utl::OInputStreamWrapper(rMedium.GetInStream());
221 if (xStatusIndicator.is())
222 xStatusIndicator->setValue(nSteps++);
224 nError = ReadThroughComponent(xInputStream, m_xModel, xContext, xInfoSet,
225 "com.sun.star.comp.Math.XMLImporter", false,
226 m_bUseHTMLMLEntities);
229 if (xStatusIndicator.is())
230 xStatusIndicator->end();
231 return nError;
234 /// read a component (file + filter version)
235 ErrCode SmXMLImportWrapper::ReadThroughComponent(const Reference<io::XInputStream>& xInputStream,
236 const Reference<XComponent>& xModelComponent,
237 Reference<uno::XComponentContext> const& rxContext,
238 Reference<beans::XPropertySet> const& rPropSet,
239 const char* pFilterName, bool bEncrypted,
240 bool bUseHTMLMLEntities)
242 ErrCode nError = ERRCODE_SFX_DOLOADFAILED;
243 OSL_ENSURE(xInputStream.is(), "input stream missing");
244 OSL_ENSURE(xModelComponent.is(), "document missing");
245 OSL_ENSURE(rxContext.is(), "factory missing");
246 OSL_ENSURE(nullptr != pFilterName, "I need a service name for the component!");
248 // prepare ParserInputSource
249 xml::sax::InputSource aParserInput;
250 aParserInput.aInputStream = xInputStream;
252 Sequence<Any> aArgs{ Any(rPropSet) };
254 // get filter
255 Reference<XInterface> xFilter
256 = rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
257 OUString::createFromAscii(pFilterName), aArgs, rxContext);
258 SAL_WARN_IF(!xFilter, "starmath", "Can't instantiate filter component " << pFilterName);
259 if (!xFilter.is())
260 return nError;
262 // connect model and filter
263 Reference<XImporter> xImporter(xFilter, UNO_QUERY);
264 xImporter->setTargetDocument(xModelComponent);
266 // finally, parser the stream
269 Reference<css::xml::sax::XFastParser> xFastParser(xFilter, UNO_QUERY);
270 Reference<css::xml::sax::XFastDocumentHandler> xFastDocHandler(xFilter, UNO_QUERY);
271 if (xFastParser)
273 if (bUseHTMLMLEntities)
274 xFastParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities);
275 xFastParser->parseStream(aParserInput);
277 else if (xFastDocHandler)
279 Reference<css::xml::sax::XFastParser> xParser
280 = css::xml::sax::FastParser::create(rxContext);
281 if (bUseHTMLMLEntities)
282 xParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities);
283 xParser->setFastDocumentHandler(xFastDocHandler);
284 xParser->parseStream(aParserInput);
286 else
288 Reference<css::xml::sax::XDocumentHandler> xDocHandler(xFilter, UNO_QUERY);
289 assert(xDocHandler);
290 Reference<css::xml::sax::XParser> xParser = css::xml::sax::Parser::create(rxContext);
291 xParser->setDocumentHandler(xDocHandler);
292 xParser->parseStream(aParserInput);
295 auto pFilter = dynamic_cast<SmXMLImport*>(xFilter.get());
296 if (pFilter && pFilter->GetSuccess())
297 nError = ERRCODE_NONE;
299 catch (const xml::sax::SAXParseException& r)
301 // sax parser sends wrapped exceptions,
302 // try to find the original one
303 xml::sax::SAXException aSaxEx = *static_cast<const xml::sax::SAXException*>(&r);
304 bool bTryChild = true;
306 while (bTryChild)
308 xml::sax::SAXException aTmp;
309 if (aSaxEx.WrappedException >>= aTmp)
310 aSaxEx = aTmp;
311 else
312 bTryChild = false;
315 packages::zip::ZipIOException aBrokenPackage;
316 if (aSaxEx.WrappedException >>= aBrokenPackage)
317 return ERRCODE_IO_BROKENPACKAGE;
319 if (bEncrypted)
320 nError = ERRCODE_SFX_WRONGPASSWORD;
322 catch (const xml::sax::SAXException& r)
324 packages::zip::ZipIOException aBrokenPackage;
325 if (r.WrappedException >>= aBrokenPackage)
326 return ERRCODE_IO_BROKENPACKAGE;
328 if (bEncrypted)
329 nError = ERRCODE_SFX_WRONGPASSWORD;
331 catch (const packages::zip::ZipIOException&)
333 nError = ERRCODE_IO_BROKENPACKAGE;
335 catch (const io::IOException&)
338 catch (const std::range_error&)
342 return nError;
345 ErrCode SmXMLImportWrapper::ReadThroughComponent(const uno::Reference<embed::XStorage>& xStorage,
346 const Reference<XComponent>& xModelComponent,
347 const char* pStreamName,
348 Reference<uno::XComponentContext> const& rxContext,
349 Reference<beans::XPropertySet> const& rPropSet,
350 const char* pFilterName, bool bUseHTMLMLEntities)
352 OSL_ENSURE(xStorage.is(), "Need storage!");
353 OSL_ENSURE(nullptr != pStreamName, "Please, please, give me a name!");
355 // open stream (and set parser input)
356 OUString sStreamName = OUString::createFromAscii(pStreamName);
358 // get input stream
361 uno::Reference<io::XStream> xEventsStream
362 = xStorage->openStreamElement(sStreamName, embed::ElementModes::READ);
364 // determine if stream is encrypted or not
365 uno::Reference<beans::XPropertySet> xProps(xEventsStream, uno::UNO_QUERY);
366 Any aAny = xProps->getPropertyValue("Encrypted");
367 bool bEncrypted = false;
368 if (aAny.getValueType() == cppu::UnoType<bool>::get())
369 aAny >>= bEncrypted;
371 // set Base URL
372 if (rPropSet.is())
374 rPropSet->setPropertyValue("StreamName", Any(sStreamName));
377 Reference<io::XInputStream> xStream = xEventsStream->getInputStream();
378 return ReadThroughComponent(xStream, xModelComponent, rxContext, rPropSet, pFilterName,
379 bEncrypted, bUseHTMLMLEntities);
381 catch (packages::WrongPasswordException&)
383 return ERRCODE_SFX_WRONGPASSWORD;
385 catch (packages::zip::ZipIOException&)
387 return ERRCODE_IO_BROKENPACKAGE;
389 catch (uno::Exception&)
393 return ERRCODE_SFX_DOLOADFAILED;
396 SmXMLImport::SmXMLImport(const css::uno::Reference<css::uno::XComponentContext>& rContext,
397 OUString const& implementationName, SvXMLImportFlags nImportFlags)
398 : SvXMLImport(rContext, implementationName, nImportFlags)
399 , bSuccess(false)
400 , nParseDepth(0)
401 , mnSmSyntaxVersion(SM_MOD()->GetConfig()->GetDefaultSmSyntaxVersion())
405 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
406 Math_XMLImporter_get_implementation(uno::XComponentContext* pCtx,
407 uno::Sequence<uno::Any> const& /*rSeq*/)
409 return cppu::acquire(
410 new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLImporter", SvXMLImportFlags::ALL));
413 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
414 Math_XMLOasisMetaImporter_get_implementation(uno::XComponentContext* pCtx,
415 uno::Sequence<uno::Any> const& /*rSeq*/)
417 return cppu::acquire(new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisMetaImporter",
418 SvXMLImportFlags::META));
421 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
422 Math_XMLOasisSettingsImporter_get_implementation(uno::XComponentContext* pCtx,
423 uno::Sequence<uno::Any> const& /*rSeq*/)
425 return cppu::acquire(new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisSettingsImporter",
426 SvXMLImportFlags::SETTINGS));
429 void SmXMLImport::endDocument()
431 //Set the resulted tree into the SmDocShell where it belongs
432 std::unique_ptr<SmNode> pTree = popOrZero(aNodeStack);
433 if (pTree && pTree->GetType() == SmNodeType::Table)
435 uno::Reference<frame::XModel> xModel = GetModel();
436 SmModel* pModel = dynamic_cast<SmModel*>(xModel.get());
438 if (pModel)
440 SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
441 auto pTreeTmp = pTree.get();
442 pDocShell->SetFormulaTree(static_cast<SmTableNode*>(pTree.release()));
443 if (aText.isEmpty()) //If we picked up no annotation text
445 // Get text from imported formula
446 SmNodeToTextVisitor tmpvisitor(pTreeTmp, aText);
449 // Convert symbol names
450 AbstractSmParser* rParser = pDocShell->GetParser();
451 bool bVal = rParser->IsImportSymbolNames();
452 rParser->SetImportSymbolNames(true);
453 auto pTmpTree = rParser->Parse(aText);
454 aText = rParser->GetText();
455 pTmpTree.reset();
456 rParser->SetImportSymbolNames(bVal);
458 pDocShell->SetText(aText);
459 pDocShell->SetSmSyntaxVersion(mnSmSyntaxVersion);
461 OSL_ENSURE(pModel, "So there *was* a UNO problem after all");
463 bSuccess = true;
466 SvXMLImport::endDocument();
469 namespace
471 class SmXMLImportContext : public SvXMLImportContext
473 public:
474 SmXMLImportContext(SmXMLImport& rImport)
475 : SvXMLImportContext(rImport)
477 GetSmImport().IncParseDepth();
480 virtual ~SmXMLImportContext() override { GetSmImport().DecParseDepth(); }
482 SmXMLImport& GetSmImport() { return static_cast<SmXMLImport&>(GetImport()); }
484 virtual void TCharacters(const OUString& /*rChars*/);
485 virtual void SAL_CALL characters(const OUString& rChars) override;
486 virtual void SAL_CALL startFastElement(
487 sal_Int32 /*nElement*/,
488 const css::uno::Reference<css::xml::sax::XFastAttributeList>& /*rAttrList*/) override
490 if (GetSmImport().TooDeep())
491 throw std::range_error("too deep");
496 void SmXMLImportContext::TCharacters(const OUString& /*rChars*/) {}
498 void SmXMLImportContext::characters(const OUString& rChars)
501 Whitespace occurring within the content of token elements is "trimmed"
502 from the ends (i.e. all whitespace at the beginning and end of the
503 content is removed), and "collapsed" internally (i.e. each sequence of
504 1 or more whitespace characters is replaced with one blank character).
506 //collapsing not done yet!
507 const OUString& rChars2 = rChars.trim();
508 if (!rChars2.isEmpty())
509 TCharacters(rChars2 /*.collapse()*/);
512 namespace
514 struct SmXMLContext_Helper
516 sal_Int8 nIsBold;
517 sal_Int8 nIsItalic;
518 double nFontSize;
519 OUString sFontFamily;
520 OUString sColor;
522 SmXMLImportContext& rContext;
524 explicit SmXMLContext_Helper(SmXMLImportContext& rImport)
525 : nIsBold(-1)
526 , nIsItalic(-1)
527 , nFontSize(0.0)
528 , rContext(rImport)
532 bool IsFontNodeNeeded() const;
533 void RetrieveAttrs(const uno::Reference<xml::sax::XFastAttributeList>& xAttrList);
534 void ApplyAttrs();
538 bool SmXMLContext_Helper::IsFontNodeNeeded() const
540 return nIsBold != -1 || nIsItalic != -1 || nFontSize != 0.0 || !sFontFamily.isEmpty()
541 || !sColor.isEmpty();
544 void SmXMLContext_Helper::RetrieveAttrs(
545 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
547 bool bMvFound = false;
548 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
550 // sometimes they have namespace, sometimes not?
551 switch (aIter.getToken() & TOKEN_MASK)
553 case XML_FONTWEIGHT:
554 nIsBold = sal_Int8(IsXMLToken(aIter, XML_BOLD));
555 break;
556 case XML_FONTSTYLE:
557 nIsItalic = sal_Int8(IsXMLToken(aIter, XML_ITALIC));
558 break;
559 case XML_FONTSIZE:
560 case XML_MATHSIZE:
562 OUString sValue = aIter.toString();
563 ::sax::Converter::convertDouble(nFontSize, sValue);
564 rContext.GetSmImport().GetMM100UnitConverter().SetXMLMeasureUnit(
565 util::MeasureUnit::POINT);
566 if (-1 == sValue.indexOf(GetXMLToken(XML_UNIT_PT)))
568 if (-1 == sValue.indexOf('%'))
569 nFontSize = 0.0;
570 else
572 rContext.GetSmImport().GetMM100UnitConverter().SetXMLMeasureUnit(
573 util::MeasureUnit::PERCENT);
576 break;
578 case XML_FONTFAMILY:
579 sFontFamily = aIter.toString();
580 break;
581 case XML_COLOR:
582 sColor = aIter.toString();
583 break;
584 case XML_MATHCOLOR:
585 sColor = aIter.toString();
586 break;
587 case XML_MATHVARIANT:
588 bMvFound = true;
589 break;
590 default:
591 XMLOFF_WARN_UNKNOWN("starmath", aIter);
592 break;
596 if (bMvFound)
598 // Ignore deprecated attributes fontfamily, fontweight, and fontstyle
599 // in favor of mathvariant, as specified in
600 // <https://www.w3.org/TR/MathML3/chapter3.html#presm.deprecatt>.
601 sFontFamily.clear();
602 nIsBold = -1;
603 nIsItalic = -1;
607 void SmXMLContext_Helper::ApplyAttrs()
609 SmNodeStack& rNodeStack = rContext.GetSmImport().GetNodeStack();
611 if (!IsFontNodeNeeded())
612 return;
614 SmToken aToken;
615 aToken.cMathChar = u"";
616 aToken.nLevel = 5;
618 if (nIsBold != -1)
620 if (nIsBold)
621 aToken.eType = TBOLD;
622 else
623 aToken.eType = TNBOLD;
624 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
625 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
626 rNodeStack.push_front(std::move(pFontNode));
628 if (nIsItalic != -1)
630 if (nIsItalic)
631 aToken.eType = TITALIC;
632 else
633 aToken.eType = TNITALIC;
634 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
635 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
636 rNodeStack.push_front(std::move(pFontNode));
638 if (nFontSize != 0.0)
640 aToken.eType = TSIZE;
641 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
643 if (util::MeasureUnit::PERCENT
644 == rContext.GetSmImport().GetMM100UnitConverter().GetXMLMeasureUnit())
646 if (nFontSize < 100.00)
647 pFontNode->SetSizeParameter(Fraction(100.00 / nFontSize), FontSizeType::DIVIDE);
648 else
649 pFontNode->SetSizeParameter(Fraction(nFontSize / 100.00), FontSizeType::MULTIPLY);
651 else
652 pFontNode->SetSizeParameter(Fraction(nFontSize), FontSizeType::ABSOLUT);
654 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
655 rNodeStack.push_front(std::move(pFontNode));
657 if (!sColor.isEmpty())
659 SmColorTokenTableEntry aSmColorTokenTableEntry;
660 aSmColorTokenTableEntry = starmathdatabase::Identify_ColorName_HTML(sColor);
661 if (aSmColorTokenTableEntry.eType == TRGB)
662 aSmColorTokenTableEntry = starmathdatabase::Identify_Color_Parser(
663 sal_uInt32(aSmColorTokenTableEntry.cColor));
664 if (aSmColorTokenTableEntry.eType != TERROR)
666 aToken = aSmColorTokenTableEntry;
667 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
668 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
669 rNodeStack.push_front(std::move(pFontNode));
671 // If not known, not implemented yet. Giving up.
673 if (sFontFamily.isEmpty())
674 return;
676 if (sFontFamily.equalsIgnoreAsciiCase(GetXMLToken(XML_FIXED)))
677 aToken.eType = TFIXED;
678 else if (sFontFamily.equalsIgnoreAsciiCase("sans"))
679 aToken.eType = TSANS;
680 else if (sFontFamily.equalsIgnoreAsciiCase("serif"))
681 aToken.eType = TSERIF;
682 else //Just give up, we need to extend our font mechanism to be
683 //more general
684 return;
686 aToken.aText = sFontFamily;
687 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
688 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
689 rNodeStack.push_front(std::move(pFontNode));
692 namespace
694 class SmXMLTokenAttrHelper
696 SmXMLImportContext& mrContext;
697 MathMLMathvariantValue meMv;
698 bool mbMvFound;
700 public:
701 SmXMLTokenAttrHelper(SmXMLImportContext& rContext)
702 : mrContext(rContext)
703 , meMv(MathMLMathvariantValue::Normal)
704 , mbMvFound(false)
708 void RetrieveAttrs(const uno::Reference<xml::sax::XFastAttributeList>& xAttrList);
709 void ApplyAttrs(MathMLMathvariantValue eDefaultMv);
713 void SmXMLTokenAttrHelper::RetrieveAttrs(
714 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
716 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
718 OUString sValue = aIter.toString();
719 switch (aIter.getToken())
721 case XML_MATHVARIANT:
722 if (!GetMathMLMathvariantValue(sValue, meMv))
723 SAL_WARN("starmath", "failed to recognize mathvariant: " << sValue);
724 mbMvFound = true;
725 break;
726 default:
727 XMLOFF_WARN_UNKNOWN("starmath", aIter);
728 break;
733 void SmXMLTokenAttrHelper::ApplyAttrs(MathMLMathvariantValue eDefaultMv)
735 assert(eDefaultMv == MathMLMathvariantValue::Normal
736 || eDefaultMv == MathMLMathvariantValue::Italic);
738 std::vector<SmTokenType> vVariant;
739 MathMLMathvariantValue eMv = mbMvFound ? meMv : eDefaultMv;
740 switch (eMv)
742 case MathMLMathvariantValue::Normal:
743 vVariant.push_back(TNITALIC);
744 break;
745 case MathMLMathvariantValue::Bold:
746 vVariant.push_back(TBOLD);
747 break;
748 case MathMLMathvariantValue::Italic:
749 // nothing to do
750 break;
751 case MathMLMathvariantValue::BoldItalic:
752 vVariant.push_back(TITALIC);
753 vVariant.push_back(TBOLD);
754 break;
755 case MathMLMathvariantValue::DoubleStruck:
756 // TODO
757 break;
758 case MathMLMathvariantValue::BoldFraktur:
759 // TODO: Fraktur
760 vVariant.push_back(TBOLD);
761 break;
762 case MathMLMathvariantValue::Script:
763 // TODO
764 break;
765 case MathMLMathvariantValue::BoldScript:
766 // TODO: Script
767 vVariant.push_back(TBOLD);
768 break;
769 case MathMLMathvariantValue::Fraktur:
770 // TODO
771 break;
772 case MathMLMathvariantValue::SansSerif:
773 vVariant.push_back(TSANS);
774 break;
775 case MathMLMathvariantValue::BoldSansSerif:
776 vVariant.push_back(TSANS);
777 vVariant.push_back(TBOLD);
778 break;
779 case MathMLMathvariantValue::SansSerifItalic:
780 vVariant.push_back(TITALIC);
781 vVariant.push_back(TSANS);
782 break;
783 case MathMLMathvariantValue::SansSerifBoldItalic:
784 vVariant.push_back(TITALIC);
785 vVariant.push_back(TBOLD);
786 vVariant.push_back(TSANS);
787 break;
788 case MathMLMathvariantValue::Monospace:
789 vVariant.push_back(TFIXED);
790 break;
791 case MathMLMathvariantValue::Initial:
792 case MathMLMathvariantValue::Tailed:
793 case MathMLMathvariantValue::Looped:
794 case MathMLMathvariantValue::Stretched:
795 // TODO
796 break;
798 if (vVariant.empty())
799 return;
800 SmNodeStack& rNodeStack = mrContext.GetSmImport().GetNodeStack();
801 for (auto eType : vVariant)
803 SmToken aToken;
804 aToken.eType = eType;
805 aToken.cMathChar = u"";
806 aToken.nLevel = 5;
807 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
808 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
809 rNodeStack.push_front(std::move(pFontNode));
813 namespace
815 class SmXMLDocContext_Impl : public SmXMLImportContext
817 public:
818 SmXMLDocContext_Impl(SmXMLImport& rImport)
819 : SmXMLImportContext(rImport)
823 virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
824 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
826 void SAL_CALL endFastElement(sal_Int32 nElement) override;
829 /*avert the gaze from the originator*/
830 class SmXMLRowContext_Impl : public SmXMLDocContext_Impl
832 protected:
833 size_t nElementCount;
835 public:
836 SmXMLRowContext_Impl(SmXMLImport& rImport)
837 : SmXMLDocContext_Impl(rImport)
838 , nElementCount(GetSmImport().GetNodeStack().size())
842 virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
843 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
845 uno::Reference<xml::sax::XFastContextHandler> StrictCreateChildContext(sal_Int32 nElement);
847 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
850 class SmXMLEncloseContext_Impl : public SmXMLRowContext_Impl
852 public:
853 // TODO/LATER: convert <menclose notation="horizontalstrike"> into
854 // "overstrike{}" and extend the Math syntax to support more notations
855 SmXMLEncloseContext_Impl(SmXMLImport& rImport)
856 : SmXMLRowContext_Impl(rImport)
860 void SAL_CALL endFastElement(sal_Int32 nElement) override;
864 void SmXMLEncloseContext_Impl::endFastElement(sal_Int32 nElement)
867 <menclose> accepts any number of arguments; if this number is not 1, its
868 contents are treated as a single "inferred <mrow>" containing its
869 arguments
871 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
872 SmXMLRowContext_Impl::endFastElement(nElement);
875 namespace
877 class SmXMLFracContext_Impl : public SmXMLRowContext_Impl
879 public:
880 // TODO/LATER: convert <mfrac bevelled="true"> into "wideslash{}{}"
881 SmXMLFracContext_Impl(SmXMLImport& rImport)
882 : SmXMLRowContext_Impl(rImport)
886 void SAL_CALL endFastElement(sal_Int32 nElement) override;
889 class SmXMLSqrtContext_Impl : public SmXMLRowContext_Impl
891 public:
892 SmXMLSqrtContext_Impl(SmXMLImport& rImport)
893 : SmXMLRowContext_Impl(rImport)
897 void SAL_CALL endFastElement(sal_Int32 nElement) override;
900 class SmXMLRootContext_Impl : public SmXMLRowContext_Impl
902 public:
903 SmXMLRootContext_Impl(SmXMLImport& rImport)
904 : SmXMLRowContext_Impl(rImport)
908 void SAL_CALL endFastElement(sal_Int32 nElement) override;
911 class SmXMLStyleContext_Impl : public SmXMLRowContext_Impl
913 protected:
914 SmXMLContext_Helper aStyleHelper;
916 public:
917 /*Right now the style tag is completely ignored*/
918 SmXMLStyleContext_Impl(SmXMLImport& rImport)
919 : SmXMLRowContext_Impl(rImport)
920 , aStyleHelper(*this)
924 void SAL_CALL endFastElement(sal_Int32 nElement) override;
925 void SAL_CALL startFastElement(
926 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
930 void SmXMLStyleContext_Impl::startFastElement(
931 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
933 aStyleHelper.RetrieveAttrs(xAttrList);
936 void SmXMLStyleContext_Impl::endFastElement(sal_Int32 nElement)
939 <mstyle> accepts any number of arguments; if this number is not 1, its
940 contents are treated as a single "inferred <mrow>" containing its
941 arguments
943 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
944 if (rNodeStack.size() - nElementCount != 1)
945 SmXMLRowContext_Impl::endFastElement(nElement);
946 aStyleHelper.ApplyAttrs();
949 namespace
951 class SmXMLPaddedContext_Impl : public SmXMLRowContext_Impl
953 public:
954 /*Right now the style tag is completely ignored*/
955 SmXMLPaddedContext_Impl(SmXMLImport& rImport)
956 : SmXMLRowContext_Impl(rImport)
960 void SAL_CALL endFastElement(sal_Int32 nElement) override;
964 void SmXMLPaddedContext_Impl::endFastElement(sal_Int32 nElement)
967 <mpadded> accepts any number of arguments; if this number is not 1, its
968 contents are treated as a single "inferred <mrow>" containing its
969 arguments
971 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
972 SmXMLRowContext_Impl::endFastElement(nElement);
975 namespace
977 class SmXMLPhantomContext_Impl : public SmXMLRowContext_Impl
979 public:
980 /*Right now the style tag is completely ignored*/
981 SmXMLPhantomContext_Impl(SmXMLImport& rImport)
982 : SmXMLRowContext_Impl(rImport)
986 void SAL_CALL endFastElement(sal_Int32 nElement) override;
990 void SmXMLPhantomContext_Impl::endFastElement(sal_Int32 nElement)
993 <mphantom> accepts any number of arguments; if this number is not 1, its
994 contents are treated as a single "inferred <mrow>" containing its
995 arguments
997 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
998 SmXMLRowContext_Impl::endFastElement(nElement);
1000 SmToken aToken;
1001 aToken.cMathChar = u"";
1002 aToken.nLevel = 5;
1003 aToken.eType = TPHANTOM;
1005 std::unique_ptr<SmFontNode> pPhantom(new SmFontNode(aToken));
1006 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1007 pPhantom->SetSubNodes(nullptr, popOrZero(rNodeStack));
1008 rNodeStack.push_front(std::move(pPhantom));
1011 namespace
1013 class SmXMLFencedContext_Impl : public SmXMLRowContext_Impl
1015 protected:
1016 sal_Unicode cBegin;
1017 sal_Unicode cEnd;
1018 bool bIsStretchy;
1020 public:
1021 SmXMLFencedContext_Impl(SmXMLImport& rImport)
1022 : SmXMLRowContext_Impl(rImport)
1023 , cBegin('(')
1024 , cEnd(')')
1025 , bIsStretchy(false)
1029 void SAL_CALL startFastElement(
1030 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1031 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1035 void SmXMLFencedContext_Impl::startFastElement(
1036 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1038 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
1040 switch (aIter.getToken())
1042 //temp, starmath cannot handle multichar brackets (I think)
1043 case XML_OPEN:
1044 cBegin = aIter.toString()[0];
1045 break;
1046 case XML_CLOSE:
1047 cEnd = aIter.toString()[0];
1048 break;
1049 case XML_STRETCHY:
1050 bIsStretchy = IsXMLToken(aIter, XML_TRUE);
1051 break;
1052 default:
1053 XMLOFF_WARN_UNKNOWN("starmath", aIter);
1054 /*Go to superclass*/
1055 break;
1060 void SmXMLFencedContext_Impl::endFastElement(sal_Int32 /*nElement*/)
1062 SmToken aToken;
1063 aToken.cMathChar = u"";
1064 aToken.aText = ",";
1065 aToken.nLevel = 5;
1067 std::unique_ptr<SmStructureNode> pSNode(new SmBraceNode(aToken));
1068 if (bIsStretchy)
1069 aToken = starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl(cBegin);
1070 else
1071 aToken = starmathdatabase::Identify_Prefix_SmXMLOperatorContext_Impl(cBegin);
1072 if (aToken.eType == TERROR)
1073 aToken = SmToken(TLPARENT, MS_LPARENT, "(", TG::LBrace, 5);
1074 std::unique_ptr<SmNode> pLeft(new SmMathSymbolNode(aToken));
1075 if (bIsStretchy)
1076 aToken = starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl(cEnd);
1077 else
1078 aToken = starmathdatabase::Identify_Postfix_SmXMLOperatorContext_Impl(cEnd);
1079 if (aToken.eType == TERROR)
1080 aToken = SmToken(TRPARENT, MS_RPARENT, ")", TG::LBrace, 5);
1081 std::unique_ptr<SmNode> pRight(new SmMathSymbolNode(aToken));
1083 SmNodeArray aRelationArray;
1084 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1085 aToken.cMathChar = u"";
1086 aToken.eType = TIDENT;
1088 auto i = rNodeStack.size() - nElementCount;
1089 if (rNodeStack.size() - nElementCount > 1)
1090 i += rNodeStack.size() - 1 - nElementCount;
1091 aRelationArray.resize(i);
1092 while (rNodeStack.size() > nElementCount)
1094 auto pNode = std::move(rNodeStack.front());
1095 rNodeStack.pop_front();
1096 aRelationArray[--i] = pNode.release();
1097 if (i > 1 && rNodeStack.size() > 1)
1098 aRelationArray[--i] = new SmGlyphSpecialNode(aToken);
1101 SmToken aDummy;
1102 std::unique_ptr<SmStructureNode> pBody(new SmExpressionNode(aDummy));
1103 pBody->SetSubNodes(std::move(aRelationArray));
1105 pSNode->SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight));
1106 // mfenced is always scalable. Stretchy keyword is not official, but in case of been in there
1107 // can be used as a hint.
1108 pSNode->SetScaleMode(SmScaleMode::Height);
1109 GetSmImport().GetNodeStack().push_front(std::move(pSNode));
1112 namespace
1114 class SmXMLErrorContext_Impl : public SmXMLRowContext_Impl
1116 public:
1117 SmXMLErrorContext_Impl(SmXMLImport& rImport)
1118 : SmXMLRowContext_Impl(rImport)
1122 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1126 void SmXMLErrorContext_Impl::endFastElement(sal_Int32 /*nElement*/)
1128 /*Right now the error tag is completely ignored, what
1129 can I do with it in starmath, ?, maybe we need a
1130 report window ourselves, do a test for validity of
1131 the xml input, use mirrors, and then generate
1132 the markup inside the merror with a big red colour
1133 of something. For now just throw them all away.
1135 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1136 while (rNodeStack.size() > nElementCount)
1138 rNodeStack.pop_front();
1142 namespace
1144 class SmXMLNumberContext_Impl : public SmXMLImportContext
1146 protected:
1147 SmToken aToken;
1149 public:
1150 SmXMLNumberContext_Impl(SmXMLImport& rImport)
1151 : SmXMLImportContext(rImport)
1153 aToken.cMathChar = u"";
1154 aToken.nLevel = 5;
1155 aToken.eType = TNUMBER;
1158 virtual void TCharacters(const OUString& rChars) override;
1160 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1164 void SmXMLNumberContext_Impl::TCharacters(const OUString& rChars) { aToken.aText = rChars; }
1166 void SmXMLNumberContext_Impl::endFastElement(sal_Int32)
1168 GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_NUMBER));
1171 namespace
1173 class SmXMLAnnotationContext_Impl : public SmXMLImportContext
1175 sal_uInt8 mnStarMathVersion;
1177 public:
1178 SmXMLAnnotationContext_Impl(SmXMLImport& rImport)
1179 : SmXMLImportContext(rImport)
1180 , mnStarMathVersion(0)
1184 void SAL_CALL characters(const OUString& rChars) override;
1186 void SAL_CALL startFastElement(
1187 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1191 void SmXMLAnnotationContext_Impl::startFastElement(
1192 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1194 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
1196 // sometimes they have namespace, sometimes not?
1197 switch (aIter.getToken() & TOKEN_MASK)
1199 case XML_ENCODING:
1200 mnStarMathVersion
1201 = aIter.toView() == "StarMath 5.0" ? 5 : aIter.toView() == "StarMath 6" ? 6 : 0;
1202 break;
1203 default:
1204 XMLOFF_WARN_UNKNOWN("starmath", aIter);
1205 break;
1210 void SmXMLAnnotationContext_Impl::characters(const OUString& rChars)
1212 if (mnStarMathVersion)
1214 GetSmImport().SetText(GetSmImport().GetText() + rChars);
1215 GetSmImport().SetSmSyntaxVersion(mnStarMathVersion);
1219 namespace
1221 class SmXMLTextContext_Impl : public SmXMLImportContext
1223 protected:
1224 SmToken aToken;
1226 public:
1227 SmXMLTextContext_Impl(SmXMLImport& rImport)
1228 : SmXMLImportContext(rImport)
1230 aToken.cMathChar = u"";
1231 aToken.nLevel = 5;
1232 aToken.eType = TTEXT;
1235 virtual void TCharacters(const OUString& rChars) override;
1237 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1241 void SmXMLTextContext_Impl::TCharacters(const OUString& rChars) { aToken.aText = rChars; }
1243 void SmXMLTextContext_Impl::endFastElement(sal_Int32)
1245 GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_TEXT));
1248 namespace
1250 class SmXMLStringContext_Impl : public SmXMLImportContext
1252 protected:
1253 SmToken aToken;
1255 public:
1256 SmXMLStringContext_Impl(SmXMLImport& rImport)
1257 : SmXMLImportContext(rImport)
1259 aToken.cMathChar = u"";
1260 aToken.nLevel = 5;
1261 aToken.eType = TTEXT;
1264 virtual void TCharacters(const OUString& rChars) override;
1266 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1270 void SmXMLStringContext_Impl::TCharacters(const OUString& rChars)
1273 The content of <ms> elements should be rendered with visible "escaping" of
1274 certain characters in the content, including at least "double quote"
1275 itself, and preferably whitespace other than individual blanks. The intent
1276 is for the viewer to see that the expression is a string literal, and to
1277 see exactly which characters form its content. For example, <ms>double
1278 quote is "</ms> might be rendered as "double quote is \"".
1280 Obviously this isn't fully done here.
1282 aToken.aText = "\"" + rChars + "\"";
1285 void SmXMLStringContext_Impl::endFastElement(sal_Int32)
1287 GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_FIXED));
1290 namespace
1292 class SmXMLIdentifierContext_Impl : public SmXMLImportContext
1294 SmXMLTokenAttrHelper maTokenAttrHelper;
1295 SmXMLContext_Helper aStyleHelper;
1296 SmToken aToken;
1298 public:
1299 SmXMLIdentifierContext_Impl(SmXMLImport& rImport)
1300 : SmXMLImportContext(rImport)
1301 , maTokenAttrHelper(*this)
1302 , aStyleHelper(*this)
1304 aToken.cMathChar = u"";
1305 aToken.nLevel = 5;
1306 aToken.eType = TIDENT;
1309 void TCharacters(const OUString& rChars) override;
1310 void SAL_CALL
1311 startFastElement(sal_Int32 /*nElement*/,
1312 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override
1314 maTokenAttrHelper.RetrieveAttrs(xAttrList);
1315 aStyleHelper.RetrieveAttrs(xAttrList);
1317 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1321 void SmXMLIdentifierContext_Impl::endFastElement(sal_Int32)
1323 std::unique_ptr<SmTextNode> pNode;
1324 //we will handle identifier italic/normal here instead of with a standalone
1325 //font node
1326 if (((aStyleHelper.nIsItalic == -1) && (aToken.aText.getLength() > 1))
1327 || ((aStyleHelper.nIsItalic == 0) && (aToken.aText.getLength() == 1)))
1329 pNode.reset(new SmTextNode(aToken, FNT_FUNCTION));
1330 pNode->GetFont().SetItalic(ITALIC_NONE);
1331 aStyleHelper.nIsItalic = -1;
1333 else
1334 pNode.reset(new SmTextNode(aToken, FNT_VARIABLE));
1335 if (aStyleHelper.nIsItalic != -1)
1337 if (aStyleHelper.nIsItalic)
1338 pNode->GetFont().SetItalic(ITALIC_NORMAL);
1339 else
1340 pNode->GetFont().SetItalic(ITALIC_NONE);
1341 aStyleHelper.nIsItalic = -1;
1343 GetSmImport().GetNodeStack().push_front(std::move(pNode));
1344 aStyleHelper.ApplyAttrs();
1346 maTokenAttrHelper.ApplyAttrs((aToken.aText.getLength() == 1) ? MathMLMathvariantValue::Italic
1347 : MathMLMathvariantValue::Normal);
1350 void SmXMLIdentifierContext_Impl::TCharacters(const OUString& rChars) { aToken.aText = rChars; }
1352 namespace
1354 class SmXMLOperatorContext_Impl : public SmXMLImportContext
1356 SmXMLTokenAttrHelper maTokenAttrHelper;
1357 bool bIsStretchy;
1358 bool bIsFenced;
1359 bool isPrefix;
1360 bool isInfix;
1361 bool isPostfix;
1362 SmToken aToken;
1364 public:
1365 SmXMLOperatorContext_Impl(SmXMLImport& rImport)
1366 : SmXMLImportContext(rImport)
1367 , maTokenAttrHelper(*this)
1368 , bIsStretchy(false)
1369 , bIsFenced(false)
1370 , isPrefix(false)
1371 , isInfix(false)
1372 , isPostfix(false)
1374 aToken.eType = TSPECIAL;
1375 aToken.nLevel = 5;
1378 void TCharacters(const OUString& rChars) override;
1379 void SAL_CALL startFastElement(
1380 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1381 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1385 void SmXMLOperatorContext_Impl::TCharacters(const OUString& rChars)
1387 aToken.setChar(rChars[0]);
1388 SmToken bToken;
1389 if (bIsFenced)
1391 if (isPrefix)
1392 bToken
1393 = starmathdatabase::Identify_Prefix_SmXMLOperatorContext_Impl(aToken.cMathChar[0]);
1394 else if (isInfix)
1395 bToken = SmToken(TMLINE, MS_VERTLINE, "mline", TG::NONE, 0);
1396 else if (isPostfix)
1397 bToken
1398 = starmathdatabase::Identify_Postfix_SmXMLOperatorContext_Impl(aToken.cMathChar[0]);
1399 else
1400 bToken = starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl(
1401 aToken.cMathChar[0]);
1403 else
1404 bToken = starmathdatabase::Identify_SmXMLOperatorContext_Impl(aToken.cMathChar[0],
1405 bIsStretchy);
1406 if (bToken.eType != TERROR)
1407 aToken = bToken;
1410 void SmXMLOperatorContext_Impl::endFastElement(sal_Int32)
1412 std::unique_ptr<SmMathSymbolNode> pNode(new SmMathSymbolNode(aToken));
1413 //For stretchy scaling the scaling must be retrieved from this node
1414 //and applied to the expression itself so as to get the expression
1415 //to scale the operator to the height of the expression itself
1416 if (bIsStretchy)
1417 pNode->SetScaleMode(SmScaleMode::Height);
1418 GetSmImport().GetNodeStack().push_front(std::move(pNode));
1420 // TODO: apply to non-alphabetic characters too
1421 if (rtl::isAsciiAlpha(aToken.cMathChar[0]))
1422 maTokenAttrHelper.ApplyAttrs(MathMLMathvariantValue::Normal);
1425 void SmXMLOperatorContext_Impl::startFastElement(
1426 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1428 maTokenAttrHelper.RetrieveAttrs(xAttrList);
1430 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
1432 switch (aIter.getToken())
1434 case XML_STRETCHY:
1435 bIsStretchy = IsXMLToken(aIter, XML_TRUE);
1436 break;
1437 case XML_FENCE:
1438 bIsFenced = IsXMLToken(aIter, XML_TRUE);
1439 break;
1440 case XML_FORM:
1441 isPrefix = IsXMLToken(aIter, XML_PREFIX); // <
1442 isInfix = IsXMLToken(aIter, XML_INFIX); // |
1443 isPostfix = IsXMLToken(aIter, XML_POSTFIX); // >
1444 break;
1445 default:
1446 XMLOFF_WARN_UNKNOWN("starmath", aIter);
1447 break;
1452 namespace
1454 class SmXMLSpaceContext_Impl : public SmXMLImportContext
1456 public:
1457 SmXMLSpaceContext_Impl(SmXMLImport& rImport)
1458 : SmXMLImportContext(rImport)
1462 void SAL_CALL startFastElement(
1463 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1466 bool lcl_CountBlanks(const MathMLAttributeLengthValue& rLV, sal_Int32* pWide, sal_Int32* pNarrow)
1468 assert(pWide);
1469 assert(pNarrow);
1470 if (rLV.aNumber.GetNumerator() == 0)
1472 *pWide = *pNarrow = 0;
1473 return true;
1475 // TODO: honor other units than em
1476 if (rLV.eUnit != MathMLLengthUnit::Em)
1477 return false;
1478 if (rLV.aNumber.GetNumerator() < 0)
1479 return false;
1480 const Fraction aTwo(2, 1);
1481 auto aWide = rLV.aNumber / aTwo;
1482 auto nWide = static_cast<sal_Int32>(static_cast<tools::Long>(aWide));
1483 if (nWide < 0)
1484 return false;
1485 const Fraction aPointFive(1, 2);
1486 auto aNarrow = (rLV.aNumber - Fraction(nWide, 1) * aTwo) / aPointFive;
1487 auto nNarrow = static_cast<sal_Int32>(static_cast<tools::Long>(aNarrow));
1488 if (nNarrow < 0)
1489 return false;
1490 *pWide = nWide;
1491 *pNarrow = nNarrow;
1492 return true;
1496 void SmXMLSpaceContext_Impl::startFastElement(
1497 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1499 // There is no syntax in Math to specify blank nodes of arbitrary size yet.
1500 MathMLAttributeLengthValue aLV;
1501 sal_Int32 nWide = 0, nNarrow = 0;
1503 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
1505 OUString sValue = aIter.toString();
1506 switch (aIter.getToken())
1508 case XML_WIDTH:
1509 if (!ParseMathMLAttributeLengthValue(o3tl::trim(sValue), aLV)
1510 || !lcl_CountBlanks(aLV, &nWide, &nNarrow))
1511 SAL_WARN("starmath", "ignore mspace's width: " << sValue);
1512 break;
1513 default:
1514 XMLOFF_WARN_UNKNOWN("starmath", aIter);
1515 break;
1518 SmToken aToken;
1519 aToken.eType = TBLANK;
1520 aToken.cMathChar = u"";
1521 aToken.nGroup = TG::Blank;
1522 aToken.nLevel = 5;
1523 std::unique_ptr<SmBlankNode> pBlank(new SmBlankNode(aToken));
1524 if (nWide > 0)
1525 pBlank->IncreaseBy(aToken, nWide);
1526 if (nNarrow > 0)
1528 aToken.eType = TSBLANK;
1529 pBlank->IncreaseBy(aToken, nNarrow);
1531 GetSmImport().GetNodeStack().push_front(std::move(pBlank));
1534 namespace
1536 class SmXMLSubContext_Impl : public SmXMLRowContext_Impl
1538 protected:
1539 void GenericEndElement(SmTokenType eType, SmSubSup aSubSup);
1541 public:
1542 SmXMLSubContext_Impl(SmXMLImport& rImport)
1543 : SmXMLRowContext_Impl(rImport)
1547 void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TRSUB, RSUB); }
1551 void SmXMLSubContext_Impl::GenericEndElement(SmTokenType eType, SmSubSup eSubSup)
1553 /*The <msub> element requires exactly 2 arguments.*/
1554 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
1555 OSL_ENSURE(bNodeCheck, "Sub has not two arguments");
1556 if (!bNodeCheck)
1557 return;
1559 SmToken aToken;
1560 aToken.cMathChar = u"";
1561 aToken.eType = eType;
1562 std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
1563 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1565 // initialize subnodes array
1566 SmNodeArray aSubNodes;
1567 aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
1568 for (size_t i = 1; i < aSubNodes.size(); i++)
1569 aSubNodes[i] = nullptr;
1571 aSubNodes[eSubSup + 1] = popOrZero(rNodeStack).release();
1572 aSubNodes[0] = popOrZero(rNodeStack).release();
1573 pNode->SetSubNodes(std::move(aSubNodes));
1574 rNodeStack.push_front(std::move(pNode));
1577 namespace
1579 class SmXMLSupContext_Impl : public SmXMLSubContext_Impl
1581 public:
1582 SmXMLSupContext_Impl(SmXMLImport& rImport)
1583 : SmXMLSubContext_Impl(rImport)
1587 void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TRSUP, RSUP); }
1590 class SmXMLSubSupContext_Impl : public SmXMLRowContext_Impl
1592 protected:
1593 void GenericEndElement(SmTokenType eType, SmSubSup aSub, SmSubSup aSup);
1595 public:
1596 SmXMLSubSupContext_Impl(SmXMLImport& rImport)
1597 : SmXMLRowContext_Impl(rImport)
1601 void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TRSUB, RSUB, RSUP); }
1605 void SmXMLSubSupContext_Impl::GenericEndElement(SmTokenType eType, SmSubSup aSub, SmSubSup aSup)
1607 /*The <msub> element requires exactly 3 arguments.*/
1608 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 3;
1609 OSL_ENSURE(bNodeCheck, "SubSup has not three arguments");
1610 if (!bNodeCheck)
1611 return;
1613 SmToken aToken;
1614 aToken.cMathChar = u"";
1615 aToken.eType = eType;
1616 std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
1617 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1619 // initialize subnodes array
1620 SmNodeArray aSubNodes;
1621 aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
1622 for (size_t i = 1; i < aSubNodes.size(); i++)
1623 aSubNodes[i] = nullptr;
1625 aSubNodes[aSup + 1] = popOrZero(rNodeStack).release();
1626 aSubNodes[aSub + 1] = popOrZero(rNodeStack).release();
1627 aSubNodes[0] = popOrZero(rNodeStack).release();
1628 pNode->SetSubNodes(std::move(aSubNodes));
1629 rNodeStack.push_front(std::move(pNode));
1632 namespace
1634 class SmXMLUnderContext_Impl : public SmXMLSubContext_Impl
1636 protected:
1637 sal_Int16 nAttrCount;
1639 public:
1640 SmXMLUnderContext_Impl(SmXMLImport& rImport)
1641 : SmXMLSubContext_Impl(rImport)
1642 , nAttrCount(0)
1646 void SAL_CALL startFastElement(
1647 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1648 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1649 void HandleAccent();
1653 void SmXMLUnderContext_Impl::startFastElement(
1654 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1656 sax_fastparser::FastAttributeList& rAttribList
1657 = sax_fastparser::castToFastAttributeList(xAttrList);
1658 nAttrCount = rAttribList.getFastAttributeTokens().size();
1661 void SmXMLUnderContext_Impl::HandleAccent()
1663 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
1664 OSL_ENSURE(bNodeCheck, "Sub has not two arguments");
1665 if (!bNodeCheck)
1666 return;
1668 /*Just one special case for the underline thing*/
1669 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1670 std::unique_ptr<SmNode> pTest = popOrZero(rNodeStack);
1671 SmToken aToken;
1672 aToken.cMathChar = u"";
1673 aToken.eType = TUNDERLINE;
1675 std::unique_ptr<SmNode> pFirst;
1676 std::unique_ptr<SmStructureNode> pNode(new SmAttributeNode(aToken));
1677 if ((pTest->GetToken().cMathChar[0] & 0x0FFF) == 0x0332)
1679 pFirst.reset(new SmRectangleNode(aToken));
1681 else
1682 pFirst = std::move(pTest);
1684 std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack);
1685 pNode->SetSubNodes(std::move(pFirst), std::move(pSecond));
1686 pNode->SetScaleMode(SmScaleMode::Width);
1687 rNodeStack.push_front(std::move(pNode));
1690 void SmXMLUnderContext_Impl::endFastElement(sal_Int32)
1692 if (!nAttrCount)
1693 GenericEndElement(TCSUB, CSUB);
1694 else
1695 HandleAccent();
1698 namespace
1700 class SmXMLOverContext_Impl : public SmXMLSubContext_Impl
1702 protected:
1703 sal_Int16 nAttrCount;
1705 public:
1706 SmXMLOverContext_Impl(SmXMLImport& rImport)
1707 : SmXMLSubContext_Impl(rImport)
1708 , nAttrCount(0)
1712 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1713 void SAL_CALL startFastElement(
1714 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1715 void HandleAccent();
1719 void SmXMLOverContext_Impl::startFastElement(
1720 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1722 sax_fastparser::FastAttributeList& rAttribList
1723 = sax_fastparser::castToFastAttributeList(xAttrList);
1724 nAttrCount = rAttribList.getFastAttributeTokens().size();
1727 void SmXMLOverContext_Impl::endFastElement(sal_Int32)
1729 if (!nAttrCount)
1730 GenericEndElement(TCSUP, CSUP);
1731 else
1732 HandleAccent();
1735 void SmXMLOverContext_Impl::HandleAccent()
1737 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
1738 OSL_ENSURE(bNodeCheck, "Sub has not two arguments");
1739 if (!bNodeCheck)
1740 return;
1742 SmToken aToken;
1743 aToken.cMathChar = u"";
1744 aToken.eType = TACUTE;
1746 std::unique_ptr<SmAttributeNode> pNode(new SmAttributeNode(aToken));
1747 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1749 std::unique_ptr<SmNode> pFirst = popOrZero(rNodeStack);
1750 std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack);
1751 pNode->SetSubNodes(std::move(pFirst), std::move(pSecond));
1752 pNode->SetScaleMode(SmScaleMode::Width);
1753 rNodeStack.push_front(std::move(pNode));
1756 namespace
1758 class SmXMLUnderOverContext_Impl : public SmXMLSubSupContext_Impl
1760 public:
1761 SmXMLUnderOverContext_Impl(SmXMLImport& rImport)
1762 : SmXMLSubSupContext_Impl(rImport)
1766 void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TCSUB, CSUB, CSUP); }
1769 class SmXMLMultiScriptsContext_Impl : public SmXMLSubSupContext_Impl
1771 bool bHasPrescripts;
1773 void ProcessSubSupPairs(bool bIsPrescript);
1775 public:
1776 SmXMLMultiScriptsContext_Impl(SmXMLImport& rImport)
1777 : SmXMLSubSupContext_Impl(rImport)
1778 , bHasPrescripts(false)
1782 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1783 virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
1784 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1787 class SmXMLNoneContext_Impl : public SmXMLImportContext
1789 public:
1790 SmXMLNoneContext_Impl(SmXMLImport& rImport)
1791 : SmXMLImportContext(rImport)
1795 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1799 void SmXMLNoneContext_Impl::endFastElement(sal_Int32)
1801 SmToken aToken;
1802 aToken.cMathChar = u"";
1803 aToken.aText.clear();
1804 aToken.nLevel = 5;
1805 aToken.eType = TIDENT;
1806 GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_VARIABLE));
1809 namespace
1811 class SmXMLPrescriptsContext_Impl : public SmXMLImportContext
1813 public:
1814 SmXMLPrescriptsContext_Impl(SmXMLImport& rImport)
1815 : SmXMLImportContext(rImport)
1820 class SmXMLTableRowContext_Impl : public SmXMLRowContext_Impl
1822 public:
1823 SmXMLTableRowContext_Impl(SmXMLImport& rImport)
1824 : SmXMLRowContext_Impl(rImport)
1828 virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
1829 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1832 class SmXMLTableContext_Impl : public SmXMLTableRowContext_Impl
1834 public:
1835 SmXMLTableContext_Impl(SmXMLImport& rImport)
1836 : SmXMLTableRowContext_Impl(rImport)
1840 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1841 virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
1842 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1845 class SmXMLTableCellContext_Impl : public SmXMLRowContext_Impl
1847 public:
1848 SmXMLTableCellContext_Impl(SmXMLImport& rImport)
1849 : SmXMLRowContext_Impl(rImport)
1854 class SmXMLAlignGroupContext_Impl : public SmXMLRowContext_Impl
1856 public:
1857 SmXMLAlignGroupContext_Impl(SmXMLImport& rImport)
1858 : SmXMLRowContext_Impl(rImport)
1862 /*Don't do anything with alignment for now*/
1865 class SmXMLActionContext_Impl : public SmXMLRowContext_Impl
1867 size_t mnSelection; // 1-based
1869 public:
1870 SmXMLActionContext_Impl(SmXMLImport& rImport)
1871 : SmXMLRowContext_Impl(rImport)
1872 , mnSelection(1)
1876 void SAL_CALL startFastElement(
1877 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1878 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1881 // NB: virtually inherit so we can multiply inherit properly
1882 // in SmXMLFlatDocContext_Impl
1883 class SmXMLOfficeContext_Impl : public virtual SvXMLImportContext
1885 public:
1886 SmXMLOfficeContext_Impl(SmXMLImport& rImport)
1887 : SvXMLImportContext(rImport)
1891 virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
1892 sal_Int32 nElement,
1893 const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList) override;
1897 uno::Reference<xml::sax::XFastContextHandler> SmXMLOfficeContext_Impl::createFastChildContext(
1898 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
1900 if (nElement == XML_ELEMENT(OFFICE, XML_META))
1902 SAL_WARN("starmath",
1903 "XML_TOK_DOC_META: should not have come here, maybe document is invalid?");
1905 else if (nElement == XML_ELEMENT(OFFICE, XML_SETTINGS))
1907 return new XMLDocumentSettingsContext(GetImport());
1909 return nullptr;
1912 namespace
1914 // context for flat file xml format
1915 class SmXMLFlatDocContext_Impl : public SmXMLOfficeContext_Impl, public SvXMLMetaDocumentContext
1917 public:
1918 SmXMLFlatDocContext_Impl(SmXMLImport& i_rImport,
1919 const uno::Reference<document::XDocumentProperties>& i_xDocProps);
1921 virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
1922 sal_Int32 nElement,
1923 const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList) override;
1927 SmXMLFlatDocContext_Impl::SmXMLFlatDocContext_Impl(
1928 SmXMLImport& i_rImport, const uno::Reference<document::XDocumentProperties>& i_xDocProps)
1929 : SvXMLImportContext(i_rImport)
1930 , SmXMLOfficeContext_Impl(i_rImport)
1931 , SvXMLMetaDocumentContext(i_rImport, i_xDocProps)
1935 uno::Reference<xml::sax::XFastContextHandler>
1936 SAL_CALL SmXMLFlatDocContext_Impl::createFastChildContext(
1937 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1939 // behave like meta base class iff we encounter office:meta
1940 if (nElement == XML_ELEMENT(OFFICE, XML_META))
1942 return SvXMLMetaDocumentContext::createFastChildContext(nElement, xAttrList);
1944 else
1946 return SmXMLOfficeContext_Impl::createFastChildContext(nElement, xAttrList);
1950 uno::Reference<xml::sax::XFastContextHandler> SmXMLDocContext_Impl::createFastChildContext(
1951 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
1953 uno::Reference<xml::sax::XFastContextHandler> xContext;
1955 switch (nElement)
1957 //Consider semantics a dummy except for any starmath annotations
1958 case XML_ELEMENT(MATH, XML_SEMANTICS):
1959 xContext = new SmXMLRowContext_Impl(GetSmImport());
1960 break;
1961 /*General Layout Schemata*/
1962 case XML_ELEMENT(MATH, XML_MROW):
1963 xContext = new SmXMLRowContext_Impl(GetSmImport());
1964 break;
1965 case XML_ELEMENT(MATH, XML_MENCLOSE):
1966 xContext = new SmXMLEncloseContext_Impl(GetSmImport());
1967 break;
1968 case XML_ELEMENT(MATH, XML_MFRAC):
1969 xContext = new SmXMLFracContext_Impl(GetSmImport());
1970 break;
1971 case XML_ELEMENT(MATH, XML_MSQRT):
1972 xContext = new SmXMLSqrtContext_Impl(GetSmImport());
1973 break;
1974 case XML_ELEMENT(MATH, XML_MROOT):
1975 xContext = new SmXMLRootContext_Impl(GetSmImport());
1976 break;
1977 case XML_ELEMENT(MATH, XML_MSTYLE):
1978 xContext = new SmXMLStyleContext_Impl(GetSmImport());
1979 break;
1980 case XML_ELEMENT(MATH, XML_MERROR):
1981 xContext = new SmXMLErrorContext_Impl(GetSmImport());
1982 break;
1983 case XML_ELEMENT(MATH, XML_MPADDED):
1984 xContext = new SmXMLPaddedContext_Impl(GetSmImport());
1985 break;
1986 case XML_ELEMENT(MATH, XML_MPHANTOM):
1987 xContext = new SmXMLPhantomContext_Impl(GetSmImport());
1988 break;
1989 case XML_ELEMENT(MATH, XML_MFENCED):
1990 xContext = new SmXMLFencedContext_Impl(GetSmImport());
1991 break;
1992 /*Script and Limit Schemata*/
1993 case XML_ELEMENT(MATH, XML_MSUB):
1994 xContext = new SmXMLSubContext_Impl(GetSmImport());
1995 break;
1996 case XML_ELEMENT(MATH, XML_MSUP):
1997 xContext = new SmXMLSupContext_Impl(GetSmImport());
1998 break;
1999 case XML_ELEMENT(MATH, XML_MSUBSUP):
2000 xContext = new SmXMLSubSupContext_Impl(GetSmImport());
2001 break;
2002 case XML_ELEMENT(MATH, XML_MUNDER):
2003 xContext = new SmXMLUnderContext_Impl(GetSmImport());
2004 break;
2005 case XML_ELEMENT(MATH, XML_MOVER):
2006 xContext = new SmXMLOverContext_Impl(GetSmImport());
2007 break;
2008 case XML_ELEMENT(MATH, XML_MUNDEROVER):
2009 xContext = new SmXMLUnderOverContext_Impl(GetSmImport());
2010 break;
2011 case XML_ELEMENT(MATH, XML_MMULTISCRIPTS):
2012 xContext = new SmXMLMultiScriptsContext_Impl(GetSmImport());
2013 break;
2014 case XML_ELEMENT(MATH, XML_MTABLE):
2015 xContext = new SmXMLTableContext_Impl(GetSmImport());
2016 break;
2017 case XML_ELEMENT(MATH, XML_MACTION):
2018 xContext = new SmXMLActionContext_Impl(GetSmImport());
2019 break;
2020 default:
2021 /*Basically there's an implicit mrow around certain bare
2022 *elements, use a RowContext to see if this is one of
2023 *those ones*/
2024 rtl::Reference<SmXMLRowContext_Impl> aTempContext(
2025 new SmXMLRowContext_Impl(GetSmImport()));
2027 xContext = aTempContext->StrictCreateChildContext(nElement);
2028 break;
2030 return xContext;
2033 void SmXMLDocContext_Impl::endFastElement(sal_Int32)
2035 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2037 std::unique_ptr<SmNode> pContextNode = popOrZero(rNodeStack);
2039 SmToken aDummy;
2040 std::unique_ptr<SmStructureNode> pSNode(new SmLineNode(aDummy));
2041 pSNode->SetSubNodes(std::move(pContextNode), nullptr);
2042 rNodeStack.push_front(std::move(pSNode));
2044 SmNodeArray LineArray;
2045 auto n = rNodeStack.size();
2046 LineArray.resize(n);
2047 for (size_t j = 0; j < n; j++)
2049 auto pNode = std::move(rNodeStack.front());
2050 rNodeStack.pop_front();
2051 LineArray[n - (j + 1)] = pNode.release();
2053 std::unique_ptr<SmStructureNode> pSNode2(new SmTableNode(aDummy));
2054 pSNode2->SetSubNodes(std::move(LineArray));
2055 rNodeStack.push_front(std::move(pSNode2));
2058 void SmXMLFracContext_Impl::endFastElement(sal_Int32)
2060 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2061 const bool bNodeCheck = rNodeStack.size() - nElementCount == 2;
2062 OSL_ENSURE(bNodeCheck, "Fraction (mfrac) tag is missing component");
2063 if (!bNodeCheck)
2064 return;
2066 SmToken aToken;
2067 aToken.cMathChar = u"";
2068 aToken.eType = TFRAC;
2069 std::unique_ptr<SmStructureNode> pSNode(new SmBinVerNode(aToken));
2070 std::unique_ptr<SmNode> pOper(new SmRectangleNode(aToken));
2071 std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack);
2072 std::unique_ptr<SmNode> pFirst = popOrZero(rNodeStack);
2073 pSNode->SetSubNodes(std::move(pFirst), std::move(pOper), std::move(pSecond));
2074 rNodeStack.push_front(std::move(pSNode));
2077 void SmXMLRootContext_Impl::endFastElement(sal_Int32)
2079 /*The <mroot> element requires exactly 2 arguments.*/
2080 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
2081 OSL_ENSURE(bNodeCheck, "Root tag is missing component");
2082 if (!bNodeCheck)
2083 return;
2085 SmToken aToken;
2086 aToken.setChar(MS_SQRT); //Temporary: alert, based on StarSymbol font
2087 aToken.eType = TNROOT;
2088 std::unique_ptr<SmStructureNode> pSNode(new SmRootNode(aToken));
2089 std::unique_ptr<SmNode> pOper(new SmRootSymbolNode(aToken));
2090 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2091 std::unique_ptr<SmNode> pIndex = popOrZero(rNodeStack);
2092 std::unique_ptr<SmNode> pBase = popOrZero(rNodeStack);
2093 pSNode->SetSubNodes(std::move(pIndex), std::move(pOper), std::move(pBase));
2094 rNodeStack.push_front(std::move(pSNode));
2097 void SmXMLSqrtContext_Impl::endFastElement(sal_Int32 nElement)
2100 <msqrt> accepts any number of arguments; if this number is not 1, its
2101 contents are treated as a single "inferred <mrow>" containing its
2102 arguments
2104 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
2105 SmXMLRowContext_Impl::endFastElement(nElement);
2107 SmToken aToken;
2108 aToken.setChar(MS_SQRT); //Temporary: alert, based on StarSymbol font
2109 aToken.eType = TSQRT;
2110 std::unique_ptr<SmStructureNode> pSNode(new SmRootNode(aToken));
2111 std::unique_ptr<SmNode> pOper(new SmRootSymbolNode(aToken));
2112 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2113 pSNode->SetSubNodes(nullptr, std::move(pOper), popOrZero(rNodeStack));
2114 rNodeStack.push_front(std::move(pSNode));
2117 void SmXMLRowContext_Impl::endFastElement(sal_Int32)
2119 SmNodeArray aRelationArray;
2120 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2122 if (rNodeStack.size() > nElementCount)
2124 auto nSize = rNodeStack.size() - nElementCount;
2126 aRelationArray.resize(nSize);
2127 for (auto j = nSize; j > 0; j--)
2129 auto pNode = std::move(rNodeStack.front());
2130 rNodeStack.pop_front();
2131 aRelationArray[j - 1] = pNode.release();
2134 //If the first or last element is an operator with stretchyness
2135 //set then we must create a brace node here from those elements,
2136 //removing the stretchness from the operators and applying it to
2137 //ourselves, and creating the appropriate dummy StarMath none bracket
2138 //to balance the arrangement
2139 if (((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height)
2140 && (aRelationArray[0]->GetType() == SmNodeType::Math))
2141 || ((aRelationArray[nSize - 1]->GetScaleMode() == SmScaleMode::Height)
2142 && (aRelationArray[nSize - 1]->GetType() == SmNodeType::Math)))
2144 SmToken aToken;
2145 aToken.cMathChar = u"";
2146 aToken.nLevel = 5;
2148 int nLeft = 0, nRight = 0;
2149 if ((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height)
2150 && (aRelationArray[0]->GetType() == SmNodeType::Math))
2152 aToken = aRelationArray[0]->GetToken();
2153 nLeft = 1;
2155 else
2156 aToken.cMathChar = u"";
2158 aToken.eType = TLPARENT;
2159 std::unique_ptr<SmNode> pLeft(new SmMathSymbolNode(aToken));
2161 if ((aRelationArray[nSize - 1]->GetScaleMode() == SmScaleMode::Height)
2162 && (aRelationArray[nSize - 1]->GetType() == SmNodeType::Math))
2164 aToken = aRelationArray[nSize - 1]->GetToken();
2165 nRight = 1;
2167 else
2168 aToken.cMathChar = u"";
2170 aToken.eType = TRPARENT;
2171 std::unique_ptr<SmNode> pRight(new SmMathSymbolNode(aToken));
2173 SmNodeArray aRelationArray2;
2175 //!! nSize-nLeft-nRight may be < 0 !!
2176 int nRelArrSize = nSize - nLeft - nRight;
2177 if (nRelArrSize > 0)
2179 aRelationArray2.resize(nRelArrSize);
2180 for (int i = 0; i < nRelArrSize; i++)
2182 aRelationArray2[i] = aRelationArray[i + nLeft];
2183 aRelationArray[i + nLeft] = nullptr;
2187 SmToken aDummy;
2188 std::unique_ptr<SmStructureNode> pSNode(new SmBraceNode(aToken));
2189 std::unique_ptr<SmStructureNode> pBody(new SmExpressionNode(aDummy));
2190 pBody->SetSubNodes(std::move(aRelationArray2));
2192 pSNode->SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight));
2193 pSNode->SetScaleMode(SmScaleMode::Height);
2194 rNodeStack.push_front(std::move(pSNode));
2196 for (auto a : aRelationArray)
2197 delete a;
2199 return;
2202 else
2204 // The elements msqrt, mstyle, merror, menclose, mpadded, mphantom, mtd, and math
2205 // treat their content as a single inferred mrow in case their content is empty.
2206 // Here an empty group {} is used to catch those cases and transform them without error
2207 // to StarMath.
2208 aRelationArray.resize(2);
2209 SmToken aToken;
2210 aToken.setChar(MS_LBRACE);
2211 aToken.nLevel = 5;
2212 aToken.eType = TLGROUP;
2213 aToken.nGroup = TG::NONE;
2214 aToken.aText = "{";
2215 aRelationArray[0] = new SmLineNode(aToken);
2217 aToken.setChar(MS_RBRACE);
2218 aToken.nLevel = 0;
2219 aToken.eType = TRGROUP;
2220 aToken.nGroup = TG::NONE;
2221 aToken.aText = "}";
2222 aRelationArray[1] = new SmLineNode(aToken);
2225 SmToken aDummy;
2226 std::unique_ptr<SmStructureNode> pSNode(new SmExpressionNode(aDummy));
2227 pSNode->SetSubNodes(std::move(aRelationArray));
2228 rNodeStack.push_front(std::move(pSNode));
2231 uno::Reference<xml::sax::XFastContextHandler>
2232 SmXMLRowContext_Impl::StrictCreateChildContext(sal_Int32 nElement)
2234 uno::Reference<xml::sax::XFastContextHandler> pContext;
2236 switch (nElement)
2238 /*Note that these should accept malignmark subelements, but do not*/
2239 case XML_ELEMENT(MATH, XML_MN):
2240 pContext = new SmXMLNumberContext_Impl(GetSmImport());
2241 break;
2242 case XML_ELEMENT(MATH, XML_MI):
2243 pContext = new SmXMLIdentifierContext_Impl(GetSmImport());
2244 break;
2245 case XML_ELEMENT(MATH, XML_MO):
2246 pContext = new SmXMLOperatorContext_Impl(GetSmImport());
2247 break;
2248 case XML_ELEMENT(MATH, XML_MTEXT):
2249 pContext = new SmXMLTextContext_Impl(GetSmImport());
2250 break;
2251 case XML_ELEMENT(MATH, XML_MSPACE):
2252 pContext = new SmXMLSpaceContext_Impl(GetSmImport());
2253 break;
2254 case XML_ELEMENT(MATH, XML_MS):
2255 pContext = new SmXMLStringContext_Impl(GetSmImport());
2256 break;
2258 /*Note: The maligngroup should only be seen when the row
2259 * (or descendants) are in a table*/
2260 case XML_ELEMENT(MATH, XML_MALIGNGROUP):
2261 pContext = new SmXMLAlignGroupContext_Impl(GetSmImport());
2262 break;
2264 case XML_ELEMENT(MATH, XML_ANNOTATION):
2265 pContext = new SmXMLAnnotationContext_Impl(GetSmImport());
2266 break;
2268 default:
2269 break;
2271 return pContext;
2274 uno::Reference<xml::sax::XFastContextHandler> SmXMLRowContext_Impl::createFastChildContext(
2275 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2277 uno::Reference<xml::sax::XFastContextHandler> xContext = StrictCreateChildContext(nElement);
2279 if (!xContext)
2281 //Hmm, unrecognized for this level, check to see if it's
2282 //an element that can have an implicit schema around it
2283 xContext = SmXMLDocContext_Impl::createFastChildContext(nElement, xAttrList);
2285 return xContext;
2288 uno::Reference<xml::sax::XFastContextHandler> SmXMLMultiScriptsContext_Impl::createFastChildContext(
2289 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2291 uno::Reference<xml::sax::XFastContextHandler> xContext;
2293 switch (nElement)
2295 case XML_ELEMENT(MATH, XML_MPRESCRIPTS):
2296 bHasPrescripts = true;
2297 ProcessSubSupPairs(false);
2298 xContext = new SmXMLPrescriptsContext_Impl(GetSmImport());
2299 break;
2300 case XML_ELEMENT(MATH, XML_NONE):
2301 xContext = new SmXMLNoneContext_Impl(GetSmImport());
2302 break;
2303 default:
2304 xContext = SmXMLRowContext_Impl::createFastChildContext(nElement, xAttrList);
2305 break;
2307 return xContext;
2310 void SmXMLMultiScriptsContext_Impl::ProcessSubSupPairs(bool bIsPrescript)
2312 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2314 if (rNodeStack.size() <= nElementCount)
2315 return;
2317 auto nCount = rNodeStack.size() - nElementCount - 1;
2318 if (nCount == 0)
2319 return;
2321 if (nCount % 2 == 0)
2323 SmToken aToken;
2324 aToken.cMathChar = u"";
2325 aToken.eType = bIsPrescript ? TLSUB : TRSUB;
2327 SmNodeStack aReverseStack;
2328 for (size_t i = 0; i < nCount + 1; i++)
2330 auto pNode = std::move(rNodeStack.front());
2331 rNodeStack.pop_front();
2332 aReverseStack.push_front(std::move(pNode));
2335 SmSubSup eSub = bIsPrescript ? LSUB : RSUB;
2336 SmSubSup eSup = bIsPrescript ? LSUP : RSUP;
2338 for (size_t i = 0; i < nCount; i += 2)
2340 std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
2342 // initialize subnodes array
2343 SmNodeArray aSubNodes(1 + SUBSUP_NUM_ENTRIES);
2345 /*On each loop the base and its sub sup pair becomes the
2346 base for the next loop to which the next sub sup pair is
2347 attached, i.e. wheels within wheels*/
2348 aSubNodes[0] = popOrZero(aReverseStack).release();
2350 std::unique_ptr<SmNode> pScriptNode = popOrZero(aReverseStack);
2352 if (pScriptNode
2353 && ((pScriptNode->GetToken().eType != TIDENT)
2354 || (!pScriptNode->GetToken().aText.isEmpty())))
2355 aSubNodes[eSub + 1] = pScriptNode.release();
2356 pScriptNode = popOrZero(aReverseStack);
2357 if (pScriptNode
2358 && ((pScriptNode->GetToken().eType != TIDENT)
2359 || (!pScriptNode->GetToken().aText.isEmpty())))
2360 aSubNodes[eSup + 1] = pScriptNode.release();
2362 pNode->SetSubNodes(std::move(aSubNodes));
2363 aReverseStack.push_front(std::move(pNode));
2365 assert(!aReverseStack.empty());
2366 auto pNode = std::move(aReverseStack.front());
2367 aReverseStack.pop_front();
2368 rNodeStack.push_front(std::move(pNode));
2370 else
2372 // Ignore odd number of elements.
2373 for (size_t i = 0; i < nCount; i++)
2375 rNodeStack.pop_front();
2380 void SmXMLTableContext_Impl::endFastElement(sal_Int32)
2382 SmNodeArray aExpressionArray;
2383 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2384 SmNodeStack aReverseStack;
2385 aExpressionArray.resize(rNodeStack.size() - nElementCount);
2387 size_t nRows = rNodeStack.size() - nElementCount;
2388 size_t nCols = 0;
2390 for (size_t i = nRows; i > 0; --i)
2392 SmNode* pArray = rNodeStack.front().release();
2393 rNodeStack.pop_front();
2394 if (pArray->GetNumSubNodes() == 0)
2396 //This is a little tricky, it is possible that there was
2397 //be elements that were not inside a <mtd> pair, in which
2398 //case they will not be in a row, i.e. they will not have
2399 //SubNodes, so we have to wait until here before we can
2400 //resolve the situation. Implicit surrounding tags are
2401 //surprisingly difficult to get right within this
2402 //architecture
2404 SmNodeArray aRelationArray;
2405 aRelationArray.resize(1);
2406 aRelationArray[0] = pArray;
2407 SmToken aDummy;
2408 SmExpressionNode* pExprNode = new SmExpressionNode(aDummy);
2409 pExprNode->SetSubNodes(std::move(aRelationArray));
2410 pArray = pExprNode;
2413 nCols = std::max(nCols, pArray->GetNumSubNodes());
2414 aReverseStack.push_front(std::unique_ptr<SmNode>(pArray));
2416 if (nCols > SAL_MAX_UINT16)
2417 throw std::range_error("column limit");
2418 if (nRows > SAL_MAX_UINT16)
2419 throw std::range_error("row limit");
2420 aExpressionArray.resize(nCols * nRows);
2421 size_t j = 0;
2422 for (auto& elem : aReverseStack)
2424 std::unique_ptr<SmStructureNode> xArray(static_cast<SmStructureNode*>(elem.release()));
2425 for (size_t i = 0; i < xArray->GetNumSubNodes(); ++i)
2426 aExpressionArray[j++] = xArray->GetSubNode(i);
2427 xArray->ClearSubNodes();
2429 aReverseStack.clear();
2431 SmToken aToken;
2432 aToken.cMathChar = u"";
2433 aToken.eType = TMATRIX;
2434 std::unique_ptr<SmMatrixNode> pSNode(new SmMatrixNode(aToken));
2435 pSNode->SetSubNodes(std::move(aExpressionArray));
2436 pSNode->SetRowCol(nRows, nCols);
2437 rNodeStack.push_front(std::move(pSNode));
2440 uno::Reference<xml::sax::XFastContextHandler> SmXMLTableRowContext_Impl::createFastChildContext(
2441 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2443 uno::Reference<xml::sax::XFastContextHandler> xContext;
2445 switch (nElement)
2447 case XML_ELEMENT(MATH, XML_MTD):
2448 xContext = new SmXMLTableCellContext_Impl(GetSmImport());
2449 break;
2450 default:
2451 xContext = SmXMLRowContext_Impl::createFastChildContext(nElement, xAttrList);
2452 break;
2454 return xContext;
2457 uno::Reference<xml::sax::XFastContextHandler> SmXMLTableContext_Impl::createFastChildContext(
2458 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2460 uno::Reference<xml::sax::XFastContextHandler> xContext;
2462 switch (nElement)
2464 case XML_ELEMENT(MATH, XML_MTR):
2465 xContext = new SmXMLTableRowContext_Impl(GetSmImport());
2466 break;
2467 default:
2468 xContext = SmXMLTableRowContext_Impl::createFastChildContext(nElement, xAttrList);
2469 break;
2471 return xContext;
2474 void SmXMLMultiScriptsContext_Impl::endFastElement(sal_Int32)
2476 ProcessSubSupPairs(bHasPrescripts);
2479 void SmXMLActionContext_Impl::startFastElement(
2480 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2482 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
2484 switch (aIter.getToken())
2486 case XML_SELECTION:
2488 sal_Int32 n = aIter.toInt32();
2489 if (n > 0)
2490 mnSelection = static_cast<size_t>(n);
2492 break;
2493 default:
2494 XMLOFF_WARN_UNKNOWN("starmath", aIter);
2495 break;
2500 void SmXMLActionContext_Impl::endFastElement(sal_Int32)
2502 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2503 auto nSize = rNodeStack.size();
2504 if (nSize <= nElementCount)
2506 // not compliant to maction's specification, e.g., no subexpressions
2507 return;
2509 assert(mnSelection > 0);
2510 if (nSize < nElementCount + mnSelection)
2512 // No selected subexpression exists, which is a MathML error;
2513 // fallback to selecting the first
2514 mnSelection = 1;
2516 assert(nSize >= nElementCount + mnSelection);
2517 for (auto i = nSize - (nElementCount + mnSelection); i > 0; i--)
2519 rNodeStack.pop_front();
2521 auto pSelected = std::move(rNodeStack.front());
2522 rNodeStack.pop_front();
2523 for (auto i = rNodeStack.size() - nElementCount; i > 0; i--)
2525 rNodeStack.pop_front();
2527 rNodeStack.push_front(std::move(pSelected));
2530 SvXMLImportContext*
2531 SmXMLImport::CreateFastContext(sal_Int32 nElement,
2532 const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
2534 SvXMLImportContext* pContext = nullptr;
2536 switch (nElement)
2538 case XML_ELEMENT(OFFICE, XML_DOCUMENT):
2539 case XML_ELEMENT(OFFICE, XML_DOCUMENT_META):
2541 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(),
2542 uno::UNO_QUERY_THROW);
2543 pContext = ((nElement & TOKEN_MASK) == XML_DOCUMENT_META)
2544 ? new SvXMLMetaDocumentContext(*this, xDPS->getDocumentProperties())
2545 // flat OpenDocument file format -- this has not been tested...
2546 : new SmXMLFlatDocContext_Impl(*this, xDPS->getDocumentProperties());
2548 break;
2549 default:
2550 if (IsTokenInNamespace(nElement, XML_NAMESPACE_OFFICE))
2551 pContext = new SmXMLOfficeContext_Impl(*this);
2552 else
2553 pContext = new SmXMLDocContext_Impl(*this);
2555 return pContext;
2558 SmXMLImport::~SmXMLImport() noexcept { cleanup(); }
2560 void SmXMLImport::SetViewSettings(const Sequence<PropertyValue>& aViewProps)
2562 uno::Reference<frame::XModel> xModel = GetModel();
2563 if (!xModel.is())
2564 return;
2566 SmModel* pModel = dynamic_cast<SmModel*>(xModel.get());
2568 if (!pModel)
2569 return;
2571 SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
2572 if (!pDocShell)
2573 return;
2575 tools::Rectangle aRect(pDocShell->GetVisArea());
2577 tools::Long nTmp = 0;
2579 for (const PropertyValue& rValue : aViewProps)
2581 if (rValue.Name == "ViewAreaTop")
2583 rValue.Value >>= nTmp;
2584 aRect.SaturatingSetPosY(nTmp);
2586 else if (rValue.Name == "ViewAreaLeft")
2588 rValue.Value >>= nTmp;
2589 aRect.SaturatingSetPosX(nTmp);
2591 else if (rValue.Name == "ViewAreaWidth")
2593 rValue.Value >>= nTmp;
2594 Size aSize(aRect.GetSize());
2595 aSize.setWidth(nTmp);
2596 aRect.SaturatingSetSize(aSize);
2598 else if (rValue.Name == "ViewAreaHeight")
2600 rValue.Value >>= nTmp;
2601 Size aSize(aRect.GetSize());
2602 aSize.setHeight(nTmp);
2603 aRect.SaturatingSetSize(aSize);
2607 pDocShell->SetVisArea(aRect);
2610 void SmXMLImport::SetConfigurationSettings(const Sequence<PropertyValue>& aConfProps)
2612 uno::Reference<XPropertySet> xProps(GetModel(), UNO_QUERY);
2613 if (!xProps.is())
2614 return;
2616 Reference<XPropertySetInfo> xInfo(xProps->getPropertySetInfo());
2617 if (!xInfo.is())
2618 return;
2620 static const OUStringLiteral sFormula(u"Formula");
2621 static const OUStringLiteral sBasicLibraries(u"BasicLibraries");
2622 static const OUStringLiteral sDialogLibraries(u"DialogLibraries");
2623 for (const PropertyValue& rValue : aConfProps)
2625 if (rValue.Name != sFormula && rValue.Name != sBasicLibraries
2626 && rValue.Name != sDialogLibraries)
2630 if (xInfo->hasPropertyByName(rValue.Name))
2631 xProps->setPropertyValue(rValue.Name, rValue.Value);
2633 catch (const beans::PropertyVetoException&)
2635 // dealing with read-only properties here. Nothing to do...
2637 catch (const Exception&)
2639 DBG_UNHANDLED_EXCEPTION("starmath");
2645 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportMML(SvStream& rStream)
2647 SmGlobals::ensure();
2649 SfxObjectShellLock xDocSh(new SmDocShell(SfxModelFlags::EMBEDDED_OBJECT));
2650 xDocSh->DoInitNew();
2651 uno::Reference<frame::XModel> xModel(xDocSh->GetModel());
2653 uno::Reference<beans::XPropertySet> xInfoSet;
2654 uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
2655 uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
2657 //SetLoading hack because the document properties will be re-initted
2658 //by the xml filter and during the init, while it's considered uninitialized,
2659 //setting a property will inform the document it's modified, which attempts
2660 //to update the properties, which throws cause the properties are uninitialized
2661 xDocSh->SetLoading(SfxLoadedFlags::NONE);
2663 ErrCode nRet = ERRCODE_SFX_DOLOADFAILED;
2667 nRet = SmXMLImportWrapper::ReadThroughComponent(xStream, xModel, xContext, xInfoSet,
2668 "com.sun.star.comp.Math.XMLImporter", false,
2669 false);
2671 catch (...)
2675 xDocSh->SetLoading(SfxLoadedFlags::ALL);
2677 xDocSh->DoClose();
2679 return nRet != ERRCODE_NONE;
2682 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */