nss: upgrade to release 3.73
[LibreOffice.git] / starmath / source / mathmlimport.cxx
blob2df8e642d925dc2bdba90d79a51f7f113756bc5c
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 .
21 /*todo: Change characters and tcharacters to accumulate the characters together
22 into one string, xml parser hands them to us line by line rather than all in
23 one go*/
25 #include <com/sun/star/xml/sax/InputSource.hpp>
26 #include <com/sun/star/xml/sax/FastParser.hpp>
27 #include <com/sun/star/xml/sax/Parser.hpp>
28 #include <com/sun/star/xml/sax/SAXParseException.hpp>
29 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
30 #include <com/sun/star/packages/WrongPasswordException.hpp>
31 #include <com/sun/star/packages/zip/ZipIOException.hpp>
32 #include <com/sun/star/beans/PropertyAttribute.hpp>
33 #include <com/sun/star/container/XNameAccess.hpp>
34 #include <com/sun/star/embed/ElementModes.hpp>
35 #include <com/sun/star/uno/Any.h>
36 #include <com/sun/star/task/XStatusIndicator.hpp>
38 #include <comphelper/fileformat.h>
39 #include <comphelper/genericpropertyset.hxx>
40 #include <comphelper/processfactory.hxx>
41 #include <comphelper/servicehelper.hxx>
42 #include <comphelper/propertysetinfo.hxx>
43 #include <rtl/character.hxx>
44 #include <sal/log.hxx>
45 #include <sfx2/frame.hxx>
46 #include <sfx2/docfile.hxx>
47 #include <sfx2/sfxsids.hrc>
48 #include <sfx2/sfxmodelfactory.hxx>
49 #include <osl/diagnose.h>
50 #include <sot/storage.hxx>
51 #include <svtools/sfxecode.hxx>
52 #include <svl/itemset.hxx>
53 #include <svl/stritem.hxx>
54 #include <unotools/streamwrap.hxx>
55 #include <sax/tools/converter.hxx>
56 #include <xmloff/DocumentSettingsContext.hxx>
57 #include <xmloff/xmlnamespace.hxx>
58 #include <xmloff/xmltoken.hxx>
59 #include <xmloff/namespacemap.hxx>
60 #include <xmloff/xmluconv.hxx>
61 #include <xmloff/xmlmetai.hxx>
62 #include <svx/dialmgr.hxx>
63 #include <svx/strings.hrc>
64 #include <tools/diagnose_ex.h>
66 #include <memory>
68 #include "mathmlattr.hxx"
69 #include "mathmlimport.hxx"
70 #include <document.hxx>
71 #include <smdll.hxx>
72 #include <unomodel.hxx>
73 #include <utility.hxx>
74 #include <visitors.hxx>
75 #include <starmathdatabase.hxx>
77 using namespace ::com::sun::star::beans;
78 using namespace ::com::sun::star::container;
79 using namespace ::com::sun::star::document;
80 using namespace ::com::sun::star::lang;
81 using namespace ::com::sun::star::uno;
82 using namespace ::com::sun::star;
83 using namespace ::xmloff::token;
85 namespace {
87 std::unique_ptr<SmNode> popOrZero(SmNodeStack& rStack)
89 if (rStack.empty())
90 return nullptr;
91 auto pTmp = std::move(rStack.front());
92 rStack.pop_front();
93 return pTmp;
98 ErrCode SmXMLImportWrapper::Import(SfxMedium &rMedium)
100 ErrCode nError = ERRCODE_SFX_DOLOADFAILED;
102 uno::Reference<uno::XComponentContext> xContext( comphelper::getProcessComponentContext() );
104 //Make a model component from our SmModel
105 uno::Reference< lang::XComponent > xModelComp = xModel;
106 OSL_ENSURE( xModelComp.is(), "XMLReader::Read: got no model" );
108 // try to get an XStatusIndicator from the Medium
109 uno::Reference<task::XStatusIndicator> xStatusIndicator;
111 bool bEmbedded = false;
112 SmModel *pModel = comphelper::getUnoTunnelImplementation<SmModel>(xModel);
114 SmDocShell *pDocShell = pModel ?
115 static_cast<SmDocShell*>(pModel->GetObjectShell()) : nullptr;
116 if (pDocShell)
118 OSL_ENSURE( pDocShell->GetMedium() == &rMedium,
119 "different SfxMedium found" );
121 SfxItemSet* pSet = rMedium.GetItemSet();
122 if (pSet)
124 const SfxUnoAnyItem* pItem = static_cast<const SfxUnoAnyItem*>(
125 pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL) );
126 if (pItem)
127 pItem->GetValue() >>= xStatusIndicator;
130 if ( SfxObjectCreateMode::EMBEDDED == pDocShell->GetCreateMode() )
131 bEmbedded = true;
134 comphelper::PropertyMapEntry aInfoMap[] =
136 { OUString("PrivateData"), 0,
137 cppu::UnoType<XInterface>::get(),
138 beans::PropertyAttribute::MAYBEVOID, 0 },
139 { OUString("BaseURI"), 0,
140 ::cppu::UnoType<OUString>::get(),
141 beans::PropertyAttribute::MAYBEVOID, 0 },
142 { OUString("StreamRelPath"), 0,
143 ::cppu::UnoType<OUString>::get(),
144 beans::PropertyAttribute::MAYBEVOID, 0 },
145 { OUString("StreamName"), 0,
146 ::cppu::UnoType<OUString>::get(),
147 beans::PropertyAttribute::MAYBEVOID, 0 },
148 { OUString(), 0, css::uno::Type(), 0, 0 }
150 uno::Reference< beans::XPropertySet > xInfoSet(
151 comphelper::GenericPropertySet_CreateInstance(
152 new comphelper::PropertySetInfo( aInfoMap ) ) );
154 // Set base URI
155 OUString const baseURI(rMedium.GetBaseURL());
156 // needed for relative URLs; but it's OK to import e.g. MathML from the
157 // clipboard without one
158 SAL_INFO_IF(baseURI.isEmpty(), "starmath", "SmXMLImportWrapper: no base URL");
159 xInfoSet->setPropertyValue("BaseURI", makeAny(baseURI));
161 sal_Int32 nSteps=3;
162 if ( !(rMedium.IsStorage()))
163 nSteps = 1;
165 sal_Int32 nProgressRange(nSteps);
166 if (xStatusIndicator.is())
168 xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange);
171 nSteps=0;
172 if (xStatusIndicator.is())
173 xStatusIndicator->setValue(nSteps++);
175 if ( rMedium.IsStorage())
177 // TODO/LATER: handle the case of embedded links gracefully
178 if ( bEmbedded ) // && !rMedium.GetStorage()->IsRoot() )
180 OUString aName( "dummyObjName" );
181 if ( rMedium.GetItemSet() )
183 const SfxStringItem* pDocHierarchItem = static_cast<const SfxStringItem*>(
184 rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME) );
185 if ( pDocHierarchItem )
186 aName = pDocHierarchItem->GetValue();
189 if ( !aName.isEmpty() )
191 xInfoSet->setPropertyValue("StreamRelPath", makeAny(aName));
195 bool bOASIS = ( SotStorage::GetVersion( rMedium.GetStorage() ) > SOFFICE_FILEFORMAT_60 );
196 if (xStatusIndicator.is())
197 xStatusIndicator->setValue(nSteps++);
199 auto nWarn = ReadThroughComponent(
200 rMedium.GetStorage(), xModelComp, "meta.xml",
201 xContext, xInfoSet,
202 (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaImporter"
203 : "com.sun.star.comp.Math.XMLMetaImporter") );
205 if ( nWarn != ERRCODE_IO_BROKENPACKAGE )
207 if (xStatusIndicator.is())
208 xStatusIndicator->setValue(nSteps++);
210 nWarn = ReadThroughComponent(
211 rMedium.GetStorage(), xModelComp, "settings.xml",
212 xContext, xInfoSet,
213 (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsImporter"
214 : "com.sun.star.comp.Math.XMLSettingsImporter" ) );
216 if ( nWarn != ERRCODE_IO_BROKENPACKAGE )
218 if (xStatusIndicator.is())
219 xStatusIndicator->setValue(nSteps++);
221 nError = ReadThroughComponent(
222 rMedium.GetStorage(), xModelComp, "content.xml",
223 xContext, xInfoSet, "com.sun.star.comp.Math.XMLImporter" );
225 else
226 nError = ERRCODE_IO_BROKENPACKAGE;
228 else
229 nError = ERRCODE_IO_BROKENPACKAGE;
231 else
233 Reference<io::XInputStream> xInputStream =
234 new utl::OInputStreamWrapper(rMedium.GetInStream());
236 if (xStatusIndicator.is())
237 xStatusIndicator->setValue(nSteps++);
239 nError = ReadThroughComponent( xInputStream, xModelComp,
240 xContext, xInfoSet, "com.sun.star.comp.Math.XMLImporter", false );
243 if (xStatusIndicator.is())
244 xStatusIndicator->end();
245 return nError;
249 /// read a component (file + filter version)
250 ErrCode SmXMLImportWrapper::ReadThroughComponent(
251 const Reference<io::XInputStream>& xInputStream,
252 const Reference<XComponent>& xModelComponent,
253 Reference<uno::XComponentContext> const & rxContext,
254 Reference<beans::XPropertySet> const & rPropSet,
255 const char* pFilterName,
256 bool bEncrypted )
258 ErrCode nError = ERRCODE_SFX_DOLOADFAILED;
259 OSL_ENSURE(xInputStream.is(), "input stream missing");
260 OSL_ENSURE(xModelComponent.is(), "document missing");
261 OSL_ENSURE(rxContext.is(), "factory missing");
262 OSL_ENSURE(nullptr != pFilterName,"I need a service name for the component!");
264 // prepare ParserInputSource
265 xml::sax::InputSource aParserInput;
266 aParserInput.aInputStream = xInputStream;
268 Sequence<Any> aArgs( 1 );
269 aArgs[0] <<= rPropSet;
271 // get filter
272 Reference< XInterface > xFilter =
273 rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
274 OUString::createFromAscii(pFilterName), aArgs, rxContext);
275 SAL_WARN_IF( !xFilter, "starmath", "Can't instantiate filter component " << pFilterName );
276 if ( !xFilter.is() )
277 return nError;
279 // connect model and filter
280 Reference < XImporter > xImporter( xFilter, UNO_QUERY );
281 xImporter->setTargetDocument( xModelComponent );
283 // finally, parser the stream
286 Reference<css::xml::sax::XFastParser> xFastParser(xFilter, UNO_QUERY);
287 Reference<css::xml::sax::XFastDocumentHandler> xFastDocHandler(xFilter, UNO_QUERY);
288 if (xFastParser)
289 xFastParser->parseStream( aParserInput );
290 else if (xFastDocHandler)
292 Reference<css::xml::sax::XFastParser> xParser = css::xml::sax::FastParser::create(rxContext);
293 xParser->setFastDocumentHandler(xFastDocHandler);
294 xParser->parseStream( aParserInput );
296 else
298 Reference<css::xml::sax::XDocumentHandler> xDocHandler(xFilter, UNO_QUERY);
299 assert(xDocHandler);
300 Reference<css::xml::sax::XParser> xParser = css::xml::sax::Parser::create(rxContext);
301 xParser->setDocumentHandler(xDocHandler);
302 xParser->parseStream( aParserInput );
305 auto pFilter = comphelper::getUnoTunnelImplementation<SmXMLImport>(xFilter);
306 if ( pFilter && pFilter->GetSuccess() )
307 nError = ERRCODE_NONE;
309 catch (const xml::sax::SAXParseException& r)
311 // sax parser sends wrapped exceptions,
312 // try to find the original one
313 xml::sax::SAXException aSaxEx = *static_cast<const xml::sax::SAXException*>(&r);
314 bool bTryChild = true;
316 while( bTryChild )
318 xml::sax::SAXException aTmp;
319 if ( aSaxEx.WrappedException >>= aTmp )
320 aSaxEx = aTmp;
321 else
322 bTryChild = false;
325 packages::zip::ZipIOException aBrokenPackage;
326 if ( aSaxEx.WrappedException >>= aBrokenPackage )
327 return ERRCODE_IO_BROKENPACKAGE;
329 if ( bEncrypted )
330 nError = ERRCODE_SFX_WRONGPASSWORD;
332 catch (const xml::sax::SAXException& r)
334 packages::zip::ZipIOException aBrokenPackage;
335 if ( r.WrappedException >>= aBrokenPackage )
336 return ERRCODE_IO_BROKENPACKAGE;
338 if ( bEncrypted )
339 nError = ERRCODE_SFX_WRONGPASSWORD;
341 catch (const packages::zip::ZipIOException&)
343 nError = ERRCODE_IO_BROKENPACKAGE;
345 catch (const io::IOException&)
348 catch (const std::range_error&)
352 return nError;
356 ErrCode SmXMLImportWrapper::ReadThroughComponent(
357 const uno::Reference< embed::XStorage >& xStorage,
358 const Reference<XComponent>& xModelComponent,
359 const char* pStreamName,
360 Reference<uno::XComponentContext> const & rxContext,
361 Reference<beans::XPropertySet> const & rPropSet,
362 const char* pFilterName )
364 OSL_ENSURE(xStorage.is(), "Need storage!");
365 OSL_ENSURE(nullptr != pStreamName, "Please, please, give me a name!");
367 // open stream (and set parser input)
368 OUString sStreamName = OUString::createFromAscii(pStreamName);
370 // get input stream
373 uno::Reference < io::XStream > xEventsStream = xStorage->openStreamElement( sStreamName, embed::ElementModes::READ );
375 // determine if stream is encrypted or not
376 uno::Reference < beans::XPropertySet > xProps( xEventsStream, uno::UNO_QUERY );
377 Any aAny = xProps->getPropertyValue( "Encrypted" );
378 bool bEncrypted = false;
379 if ( aAny.getValueType() == cppu::UnoType<bool>::get() )
380 aAny >>= bEncrypted;
382 // set Base URL
383 if ( rPropSet.is() )
385 rPropSet->setPropertyValue( "StreamName", makeAny( sStreamName ) );
389 Reference < io::XInputStream > xStream = xEventsStream->getInputStream();
390 return ReadThroughComponent( xStream, xModelComponent, rxContext, rPropSet, pFilterName, bEncrypted );
392 catch ( packages::WrongPasswordException& )
394 return ERRCODE_SFX_WRONGPASSWORD;
396 catch( packages::zip::ZipIOException& )
398 return ERRCODE_IO_BROKENPACKAGE;
400 catch ( uno::Exception& )
404 return ERRCODE_SFX_DOLOADFAILED;
408 SmXMLImport::SmXMLImport(
409 const css::uno::Reference< css::uno::XComponentContext >& rContext,
410 OUString const & implementationName, SvXMLImportFlags nImportFlags)
411 : SvXMLImport(rContext, implementationName, nImportFlags),
412 bSuccess(false),
413 nParseDepth(0)
417 namespace
419 class theSmXMLImportUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSmXMLImportUnoTunnelId> {};
422 const uno::Sequence< sal_Int8 > & SmXMLImport::getUnoTunnelId() throw()
424 return theSmXMLImportUnoTunnelId::get().getSeq();
427 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
428 Math_XMLImporter_get_implementation(uno::XComponentContext* pCtx,
429 uno::Sequence<uno::Any> const& /*rSeq*/)
431 return cppu::acquire(
432 new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLImporter", SvXMLImportFlags::ALL));
435 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
436 Math_XMLOasisMetaImporter_get_implementation(uno::XComponentContext* pCtx,
437 uno::Sequence<uno::Any> const& /*rSeq*/)
439 return cppu::acquire(new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisMetaImporter",
440 SvXMLImportFlags::META));
443 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
444 Math_XMLOasisSettingsImporter_get_implementation(uno::XComponentContext* pCtx,
445 uno::Sequence<uno::Any> const& /*rSeq*/)
447 return cppu::acquire(new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisSettingsImporter",
448 SvXMLImportFlags::SETTINGS));
451 sal_Int64 SAL_CALL SmXMLImport::getSomething(
452 const uno::Sequence< sal_Int8 >&rId )
454 if ( isUnoTunnelId<SmXMLImport>(rId) )
455 return sal::static_int_cast< sal_Int64 >(reinterpret_cast< sal_uIntPtr >(this));
457 return SvXMLImport::getSomething( rId );
460 void SmXMLImport::endDocument()
462 //Set the resulted tree into the SmDocShell where it belongs
463 std::unique_ptr<SmNode> pTree = popOrZero(aNodeStack);
464 if (pTree && pTree->GetType() == SmNodeType::Table)
466 uno::Reference <frame::XModel> xModel = GetModel();
467 SmModel *pModel = comphelper::getUnoTunnelImplementation<SmModel>(xModel);
469 if (pModel)
471 SmDocShell *pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
472 auto pTreeTmp = pTree.get();
473 pDocShell->SetFormulaTree(static_cast<SmTableNode *>(pTree.release()));
474 if (aText.isEmpty()) //If we picked up no annotation text
476 // Get text from imported formula
477 SmNodeToTextVisitor tmpvisitor( pTreeTmp, aText );
480 // Convert symbol names
481 SmParser &rParser = pDocShell->GetParser();
482 bool bVal = rParser.IsImportSymbolNames();
483 rParser.SetImportSymbolNames( true );
484 auto pTmpTree = rParser.Parse( aText );
485 aText = rParser.GetText();
486 pTmpTree.reset();
487 rParser.SetImportSymbolNames( bVal );
489 pDocShell->SetText( aText );
491 OSL_ENSURE(pModel,"So there *was* a UNO problem after all");
493 bSuccess = true;
496 SvXMLImport::endDocument();
499 namespace {
501 class SmXMLImportContext: public SvXMLImportContext
503 public:
504 SmXMLImportContext( SmXMLImport &rImport)
505 : SvXMLImportContext(rImport)
507 GetSmImport().IncParseDepth();
510 virtual ~SmXMLImportContext() override
512 GetSmImport().DecParseDepth();
515 SmXMLImport& GetSmImport()
517 return static_cast<SmXMLImport&>(GetImport());
520 virtual void TCharacters(const OUString & /*rChars*/);
521 virtual void SAL_CALL characters(const OUString &rChars) override;
522 virtual void SAL_CALL startFastElement(sal_Int32 /*nElement*/, const css::uno::Reference<css::xml::sax::XFastAttributeList>& /*rAttrList*/) override
524 if (GetSmImport().TooDeep())
525 throw std::range_error("too deep");
531 void SmXMLImportContext::TCharacters(const OUString & /*rChars*/)
535 void SmXMLImportContext::characters(const OUString &rChars)
538 Whitespace occurring within the content of token elements is "trimmed"
539 from the ends (i.e. all whitespace at the beginning and end of the
540 content is removed), and "collapsed" internally (i.e. each sequence of
541 1 or more whitespace characters is replaced with one blank character).
543 //collapsing not done yet!
544 const OUString &rChars2 = rChars.trim();
545 if (!rChars2.isEmpty())
546 TCharacters(rChars2/*.collapse()*/);
549 namespace {
551 struct SmXMLContext_Helper
553 sal_Int8 nIsBold;
554 sal_Int8 nIsItalic;
555 double nFontSize;
556 OUString sFontFamily;
557 OUString sColor;
559 SmXMLImportContext & rContext;
561 explicit SmXMLContext_Helper(SmXMLImportContext &rImport)
562 : nIsBold( -1 )
563 , nIsItalic( -1 )
564 , nFontSize( 0.0 )
565 , rContext( rImport )
568 bool IsFontNodeNeeded() const;
569 void RetrieveAttrs(const uno::Reference< xml::sax::XFastAttributeList > &xAttrList );
570 void ApplyAttrs();
575 bool SmXMLContext_Helper::IsFontNodeNeeded() const
577 return nIsBold != -1 ||
578 nIsItalic != -1 ||
579 nFontSize != 0.0 ||
580 !sFontFamily.isEmpty() ||
581 !sColor.isEmpty();
584 void SmXMLContext_Helper::RetrieveAttrs(const uno::Reference<
585 xml::sax::XFastAttributeList > & xAttrList )
587 bool bMvFound = false;
588 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
590 OUString sValue = aIter.toString();
591 // sometimes they have namespace, sometimes not?
592 switch(aIter.getToken() & TOKEN_MASK)
594 case XML_FONTWEIGHT:
595 nIsBold = sal_Int8(sValue == GetXMLToken(XML_BOLD));
596 break;
597 case XML_FONTSTYLE:
598 nIsItalic = sal_Int8(sValue == GetXMLToken(XML_ITALIC));
599 break;
600 case XML_FONTSIZE:
601 case XML_MATHSIZE:
602 ::sax::Converter::convertDouble(nFontSize, sValue);
603 rContext.GetSmImport().GetMM100UnitConverter().
604 SetXMLMeasureUnit(util::MeasureUnit::POINT);
605 if (-1 == sValue.indexOf(GetXMLToken(XML_UNIT_PT)))
607 if (-1 == sValue.indexOf('%'))
608 nFontSize=0.0;
609 else
611 rContext.GetSmImport().GetMM100UnitConverter().
612 SetXMLMeasureUnit(util::MeasureUnit::PERCENT);
615 break;
616 case XML_FONTFAMILY:
617 sFontFamily = sValue;
618 break;
619 case XML_COLOR:
620 sColor = sValue;
621 break;
622 case XML_MATHCOLOR:
623 sColor = sValue;
624 break;
625 case XML_MATHVARIANT:
626 bMvFound = true;
627 break;
628 default:
629 XMLOFF_WARN_UNKNOWN("starmath", aIter);
630 break;
634 if (bMvFound)
636 // Ignore deprecated attributes fontfamily, fontweight, and fontstyle
637 // in favor of mathvariant, as specified in
638 // <https://www.w3.org/TR/MathML3/chapter3.html#presm.deprecatt>.
639 sFontFamily.clear();
640 nIsBold = -1;
641 nIsItalic = -1;
645 void SmXMLContext_Helper::ApplyAttrs()
647 SmNodeStack &rNodeStack = rContext.GetSmImport().GetNodeStack();
649 if (!IsFontNodeNeeded())
650 return;
652 SmToken aToken;
653 aToken.cMathChar = '\0';
654 aToken.nLevel = 5;
656 if (nIsBold != -1)
658 if (nIsBold)
659 aToken.eType = TBOLD;
660 else
661 aToken.eType = TNBOLD;
662 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
663 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
664 rNodeStack.push_front(std::move(pFontNode));
666 if (nIsItalic != -1)
668 if (nIsItalic)
669 aToken.eType = TITALIC;
670 else
671 aToken.eType = TNITALIC;
672 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
673 pFontNode->SetSubNodes(nullptr,popOrZero(rNodeStack));
674 rNodeStack.push_front(std::move(pFontNode));
676 if (nFontSize != 0.0)
678 aToken.eType = TSIZE;
679 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
681 if (util::MeasureUnit::PERCENT == rContext.GetSmImport()
682 .GetMM100UnitConverter().GetXMLMeasureUnit())
684 if (nFontSize < 100.00)
685 pFontNode->SetSizeParameter(Fraction(100.00/nFontSize),
686 FontSizeType::DIVIDE);
687 else
688 pFontNode->SetSizeParameter(Fraction(nFontSize/100.00),
689 FontSizeType::MULTIPLY);
691 else
692 pFontNode->SetSizeParameter(Fraction(nFontSize),FontSizeType::ABSOLUT);
694 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
695 rNodeStack.push_front(std::move(pFontNode));
697 if (!sColor.isEmpty())
699 std::unique_ptr<SmColorTokenTableEntry> aSmColorTokenTableEntry;
700 aSmColorTokenTableEntry = starmathdatabase::Identify_ColorName_HTML( sColor );
701 if( aSmColorTokenTableEntry->eType == TRGB )
702 aSmColorTokenTableEntry = starmathdatabase::Identify_Color_Parser( sal_uInt32(aSmColorTokenTableEntry->cColor) );
703 if( aSmColorTokenTableEntry->eType != TERROR )
705 aToken = aSmColorTokenTableEntry;
706 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
707 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
708 rNodeStack.push_front(std::move(pFontNode));
710 // If not known, not implemented yet. Giving up.
712 if (!sFontFamily.isEmpty())
714 if (sFontFamily.equalsIgnoreAsciiCase(GetXMLToken(XML_FIXED)))
715 aToken.eType = TFIXED;
716 else if (sFontFamily.equalsIgnoreAsciiCase("sans"))
717 aToken.eType = TSANS;
718 else if (sFontFamily.equalsIgnoreAsciiCase("serif"))
719 aToken.eType = TSERIF;
720 else //Just give up, we need to extend our font mechanism to be
721 //more general
722 return;
724 aToken.aText = sFontFamily;
725 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
726 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
727 rNodeStack.push_front(std::move(pFontNode));
731 namespace {
733 class SmXMLTokenAttrHelper
735 SmXMLImportContext& mrContext;
736 MathMLMathvariantValue meMv;
737 bool mbMvFound;
739 public:
740 SmXMLTokenAttrHelper(SmXMLImportContext& rContext)
741 : mrContext(rContext)
742 , meMv(MathMLMathvariantValue::Normal)
743 , mbMvFound(false)
746 void RetrieveAttrs(const uno::Reference<xml::sax::XFastAttributeList>& xAttrList);
747 void ApplyAttrs(MathMLMathvariantValue eDefaultMv);
752 void SmXMLTokenAttrHelper::RetrieveAttrs(const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
754 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
756 OUString sValue = aIter.toString();
757 switch(aIter.getToken())
759 case XML_MATHVARIANT:
760 if (!GetMathMLMathvariantValue(sValue, meMv))
761 SAL_WARN("starmath", "failed to recognize mathvariant: " << sValue);
762 mbMvFound = true;
763 break;
764 default:
765 XMLOFF_WARN_UNKNOWN("starmath", aIter);
766 break;
771 void SmXMLTokenAttrHelper::ApplyAttrs(MathMLMathvariantValue eDefaultMv)
773 assert( eDefaultMv == MathMLMathvariantValue::Normal ||
774 eDefaultMv == MathMLMathvariantValue::Italic );
776 std::vector<SmTokenType> vVariant;
777 MathMLMathvariantValue eMv = mbMvFound ? meMv : eDefaultMv;
778 switch(eMv)
780 case MathMLMathvariantValue::Normal:
781 vVariant.push_back(TNITALIC);
782 break;
783 case MathMLMathvariantValue::Bold:
784 vVariant.push_back(TBOLD);
785 break;
786 case MathMLMathvariantValue::Italic:
787 // nothing to do
788 break;
789 case MathMLMathvariantValue::BoldItalic:
790 vVariant.push_back(TITALIC);
791 vVariant.push_back(TBOLD);
792 break;
793 case MathMLMathvariantValue::DoubleStruck:
794 // TODO
795 break;
796 case MathMLMathvariantValue::BoldFraktur:
797 // TODO: Fraktur
798 vVariant.push_back(TBOLD);
799 break;
800 case MathMLMathvariantValue::Script:
801 // TODO
802 break;
803 case MathMLMathvariantValue::BoldScript:
804 // TODO: Script
805 vVariant.push_back(TBOLD);
806 break;
807 case MathMLMathvariantValue::Fraktur:
808 // TODO
809 break;
810 case MathMLMathvariantValue::SansSerif:
811 vVariant.push_back(TSANS);
812 break;
813 case MathMLMathvariantValue::BoldSansSerif:
814 vVariant.push_back(TSANS);
815 vVariant.push_back(TBOLD);
816 break;
817 case MathMLMathvariantValue::SansSerifItalic:
818 vVariant.push_back(TITALIC);
819 vVariant.push_back(TSANS);
820 break;
821 case MathMLMathvariantValue::SansSerifBoldItalic:
822 vVariant.push_back(TITALIC);
823 vVariant.push_back(TBOLD);
824 vVariant.push_back(TSANS);
825 break;
826 case MathMLMathvariantValue::Monospace:
827 vVariant.push_back(TFIXED);
828 break;
829 case MathMLMathvariantValue::Initial:
830 case MathMLMathvariantValue::Tailed:
831 case MathMLMathvariantValue::Looped:
832 case MathMLMathvariantValue::Stretched:
833 // TODO
834 break;
836 if (vVariant.empty())
837 return;
838 SmNodeStack &rNodeStack = mrContext.GetSmImport().GetNodeStack();
839 for (auto eType : vVariant)
841 SmToken aToken;
842 aToken.eType = eType;
843 aToken.cMathChar = '\0';
844 aToken.nLevel = 5;
845 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
846 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
847 rNodeStack.push_front(std::move(pFontNode));
851 namespace {
853 class SmXMLDocContext_Impl : public SmXMLImportContext
855 public:
856 SmXMLDocContext_Impl( SmXMLImport &rImport)
857 : SmXMLImportContext(rImport) {}
859 virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
860 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList ) override;
862 void SAL_CALL endFastElement(sal_Int32 nElement) override;
866 /*avert the gaze from the originator*/
867 class SmXMLRowContext_Impl : public SmXMLDocContext_Impl
869 protected:
870 size_t nElementCount;
872 public:
873 SmXMLRowContext_Impl(SmXMLImport &rImport)
874 : SmXMLDocContext_Impl(rImport)
875 , nElementCount(GetSmImport().GetNodeStack().size())
879 virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
880 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList ) override;
882 uno::Reference< xml::sax::XFastContextHandler > StrictCreateChildContext(sal_Int32 nElement);
884 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
887 class SmXMLEncloseContext_Impl : public SmXMLRowContext_Impl
889 public:
890 // TODO/LATER: convert <menclose notation="horizontalstrike"> into
891 // "overstrike{}" and extend the Math syntax to support more notations
892 SmXMLEncloseContext_Impl(SmXMLImport &rImport)
893 : SmXMLRowContext_Impl(rImport) {}
895 void SAL_CALL endFastElement(sal_Int32 nElement) override;
900 void SmXMLEncloseContext_Impl::endFastElement(sal_Int32 nElement)
903 <menclose> accepts any number of arguments; if this number is not 1, its
904 contents are treated as a single "inferred <mrow>" containing its
905 arguments
907 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
908 SmXMLRowContext_Impl::endFastElement( nElement );
911 namespace {
913 class SmXMLFracContext_Impl : public SmXMLRowContext_Impl
915 public:
916 // TODO/LATER: convert <mfrac bevelled="true"> into "wideslash{}{}"
917 SmXMLFracContext_Impl(SmXMLImport &rImport)
918 : SmXMLRowContext_Impl(rImport) {}
920 void SAL_CALL endFastElement(sal_Int32 nElement) override;
924 class SmXMLSqrtContext_Impl : public SmXMLRowContext_Impl
926 public:
927 SmXMLSqrtContext_Impl(SmXMLImport &rImport)
928 : SmXMLRowContext_Impl(rImport) {}
930 void SAL_CALL endFastElement(sal_Int32 nElement) override;
934 class SmXMLRootContext_Impl : public SmXMLRowContext_Impl
936 public:
937 SmXMLRootContext_Impl(SmXMLImport &rImport)
938 : SmXMLRowContext_Impl(rImport) {}
940 void SAL_CALL endFastElement(sal_Int32 nElement) override;
944 class SmXMLStyleContext_Impl : public SmXMLRowContext_Impl
946 protected:
947 SmXMLContext_Helper aStyleHelper;
949 public:
950 /*Right now the style tag is completely ignored*/
951 SmXMLStyleContext_Impl(SmXMLImport &rImport) : SmXMLRowContext_Impl(rImport),
952 aStyleHelper(*this) {}
954 void SAL_CALL endFastElement(sal_Int32 nElement) override;
955 void SAL_CALL startFastElement(sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList > &xAttrList ) override;
960 void SmXMLStyleContext_Impl::startFastElement( sal_Int32 /*nElement*/, const uno::Reference<
961 xml::sax::XFastAttributeList > & xAttrList )
963 aStyleHelper.RetrieveAttrs(xAttrList);
967 void SmXMLStyleContext_Impl::endFastElement(sal_Int32 nElement)
970 <mstyle> accepts any number of arguments; if this number is not 1, its
971 contents are treated as a single "inferred <mrow>" containing its
972 arguments
974 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
975 if (rNodeStack.size() - nElementCount != 1)
976 SmXMLRowContext_Impl::endFastElement(nElement);
977 aStyleHelper.ApplyAttrs();
980 namespace {
982 class SmXMLPaddedContext_Impl : public SmXMLRowContext_Impl
984 public:
985 /*Right now the style tag is completely ignored*/
986 SmXMLPaddedContext_Impl(SmXMLImport &rImport)
987 : SmXMLRowContext_Impl(rImport) {}
989 void SAL_CALL endFastElement(sal_Int32 nElement) override;
994 void SmXMLPaddedContext_Impl::endFastElement(sal_Int32 nElement)
997 <mpadded> accepts any number of arguments; if this number is not 1, its
998 contents are treated as a single "inferred <mrow>" containing its
999 arguments
1001 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
1002 SmXMLRowContext_Impl::endFastElement(nElement);
1005 namespace {
1007 class SmXMLPhantomContext_Impl : public SmXMLRowContext_Impl
1009 public:
1010 /*Right now the style tag is completely ignored*/
1011 SmXMLPhantomContext_Impl(SmXMLImport &rImport)
1012 : SmXMLRowContext_Impl(rImport) {}
1014 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1019 void SmXMLPhantomContext_Impl::endFastElement(sal_Int32 nElement)
1022 <mphantom> accepts any number of arguments; if this number is not 1, its
1023 contents are treated as a single "inferred <mrow>" containing its
1024 arguments
1026 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
1027 SmXMLRowContext_Impl::endFastElement(nElement);
1029 SmToken aToken;
1030 aToken.cMathChar = '\0';
1031 aToken.nLevel = 5;
1032 aToken.eType = TPHANTOM;
1034 std::unique_ptr<SmFontNode> pPhantom(new SmFontNode(aToken));
1035 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1036 pPhantom->SetSubNodes(nullptr, popOrZero(rNodeStack));
1037 rNodeStack.push_front(std::move(pPhantom));
1040 namespace {
1042 class SmXMLFencedContext_Impl : public SmXMLRowContext_Impl
1044 protected:
1045 sal_Unicode cBegin;
1046 sal_Unicode cEnd;
1047 bool bIsStretchy;
1049 public:
1050 SmXMLFencedContext_Impl(SmXMLImport &rImport)
1051 : SmXMLRowContext_Impl(rImport)
1052 , cBegin('('), cEnd(')')
1053 , bIsStretchy(false) {}
1055 void SAL_CALL startFastElement(sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList > & xAttrList ) override;
1056 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1061 void SmXMLFencedContext_Impl::startFastElement(sal_Int32 /*nElement*/, const uno::Reference<
1062 xml::sax::XFastAttributeList > & xAttrList )
1064 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
1066 OUString sValue = aIter.toString();
1067 switch(aIter.getToken())
1069 //temp, starmath cannot handle multichar brackets (I think)
1070 case XML_OPEN:
1071 cBegin = sValue[0];
1072 break;
1073 case XML_CLOSE:
1074 cEnd = sValue[0];
1075 break;
1076 case XML_STRETCHY:
1077 bIsStretchy = sValue == GetXMLToken(XML_TRUE);
1078 break;
1079 default:
1080 XMLOFF_WARN_UNKNOWN("starmath", aIter);
1081 /*Go to superclass*/
1082 break;
1088 void SmXMLFencedContext_Impl::endFastElement(sal_Int32 /*nElement*/)
1090 SmToken aToken;
1091 aToken.cMathChar = '\0';
1092 aToken.aText = ",";
1093 aToken.nLevel = 5;
1095 std::unique_ptr<SmStructureNode> pSNode(new SmBraceNode(aToken));
1096 if( bIsStretchy ) aToken = starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl( cBegin );
1097 else aToken = starmathdatabase::Identify_Prefix_SmXMLOperatorContext_Impl( cBegin );
1098 if( aToken.eType == TERROR ) aToken = SmToken( TLPARENT, MS_LPARENT, "(", TG::LBrace, 5 );
1099 std::unique_ptr<SmNode> pLeft(new SmMathSymbolNode(aToken));
1100 if( bIsStretchy ) aToken = starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl( cEnd );
1101 else aToken = starmathdatabase::Identify_Postfix_SmXMLOperatorContext_Impl( cEnd );
1102 if( aToken.eType == TERROR ) aToken = SmToken( TRPARENT, MS_RPARENT, ")", TG::LBrace, 5 );
1103 std::unique_ptr<SmNode> pRight(new SmMathSymbolNode(aToken));
1105 SmNodeArray aRelationArray;
1106 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1107 aToken.cMathChar = '\0';
1108 aToken.eType = TIDENT;
1110 auto i = rNodeStack.size() - nElementCount;
1111 if (rNodeStack.size() - nElementCount > 1)
1112 i += rNodeStack.size() - 1 - nElementCount;
1113 aRelationArray.resize(i);
1114 while (rNodeStack.size() > nElementCount)
1116 auto pNode = std::move(rNodeStack.front());
1117 rNodeStack.pop_front();
1118 aRelationArray[--i] = pNode.release();
1119 if (i > 1 && rNodeStack.size() > 1)
1120 aRelationArray[--i] = new SmGlyphSpecialNode(aToken);
1123 SmToken aDummy;
1124 std::unique_ptr<SmStructureNode> pBody(new SmExpressionNode(aDummy));
1125 pBody->SetSubNodes(std::move(aRelationArray));
1128 pSNode->SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight));
1129 // mfenced is always scalable. Stretchy keyword is not official, but in case of been in there
1130 // can be used as a hint.
1131 pSNode->SetScaleMode(SmScaleMode::Height);
1132 GetSmImport().GetNodeStack().push_front(std::move(pSNode));
1135 namespace {
1137 class SmXMLErrorContext_Impl : public SmXMLRowContext_Impl
1139 public:
1140 SmXMLErrorContext_Impl(SmXMLImport &rImport)
1141 : SmXMLRowContext_Impl(rImport) {}
1143 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1148 void SmXMLErrorContext_Impl::endFastElement(sal_Int32 /*nElement*/)
1150 /*Right now the error tag is completely ignored, what
1151 can I do with it in starmath, ?, maybe we need a
1152 report window ourselves, do a test for validity of
1153 the xml input, use mirrors, and then generate
1154 the markup inside the merror with a big red colour
1155 of something. For now just throw them all away.
1157 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1158 while (rNodeStack.size() > nElementCount)
1160 rNodeStack.pop_front();
1164 namespace {
1166 class SmXMLNumberContext_Impl : public SmXMLImportContext
1168 protected:
1169 SmToken aToken;
1171 public:
1172 SmXMLNumberContext_Impl(SmXMLImport &rImport)
1173 : SmXMLImportContext(rImport)
1175 aToken.cMathChar = '\0';
1176 aToken.nLevel = 5;
1177 aToken.eType = TNUMBER;
1180 virtual void TCharacters(const OUString &rChars) override;
1182 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1187 void SmXMLNumberContext_Impl::TCharacters(const OUString &rChars)
1189 aToken.aText = rChars;
1192 void SmXMLNumberContext_Impl::endFastElement(sal_Int32 )
1194 GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken,FNT_NUMBER));
1197 namespace {
1199 class SmXMLAnnotationContext_Impl : public SmXMLImportContext
1201 bool bIsStarMath;
1203 public:
1204 SmXMLAnnotationContext_Impl(SmXMLImport &rImport)
1205 : SmXMLImportContext(rImport), bIsStarMath(false) {}
1207 void SAL_CALL characters(const OUString &rChars) override;
1209 void SAL_CALL startFastElement(sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList > & xAttrList ) override;
1214 void SmXMLAnnotationContext_Impl::startFastElement(sal_Int32 /*nElement*/, const uno::Reference<
1215 xml::sax::XFastAttributeList > & xAttrList )
1217 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
1219 OUString sValue = aIter.toString();
1220 // sometimes they have namespace, sometimes not?
1221 switch(aIter.getToken() & TOKEN_MASK)
1223 case XML_ENCODING:
1224 bIsStarMath= sValue == "StarMath 5.0";
1225 break;
1226 default:
1227 XMLOFF_WARN_UNKNOWN("starmath", aIter);
1228 break;
1233 void SmXMLAnnotationContext_Impl::characters(const OUString &rChars)
1235 if (bIsStarMath)
1236 GetSmImport().SetText( GetSmImport().GetText() + rChars );
1239 namespace {
1241 class SmXMLTextContext_Impl : public SmXMLImportContext
1243 protected:
1244 SmToken aToken;
1246 public:
1247 SmXMLTextContext_Impl(SmXMLImport &rImport)
1248 : SmXMLImportContext(rImport)
1250 aToken.cMathChar = '\0';
1251 aToken.nLevel = 5;
1252 aToken.eType = TTEXT;
1255 virtual void TCharacters(const OUString &rChars) override;
1257 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1262 void SmXMLTextContext_Impl::TCharacters(const OUString &rChars)
1264 aToken.aText = rChars;
1267 void SmXMLTextContext_Impl::endFastElement(sal_Int32 )
1269 GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken,FNT_TEXT));
1272 namespace {
1274 class SmXMLStringContext_Impl : public SmXMLImportContext
1276 protected:
1277 SmToken aToken;
1279 public:
1280 SmXMLStringContext_Impl(SmXMLImport &rImport)
1281 : SmXMLImportContext(rImport)
1283 aToken.cMathChar = '\0';
1284 aToken.nLevel = 5;
1285 aToken.eType = TTEXT;
1288 virtual void TCharacters(const OUString &rChars) override;
1290 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1295 void SmXMLStringContext_Impl::TCharacters(const OUString &rChars)
1298 The content of <ms> elements should be rendered with visible "escaping" of
1299 certain characters in the content, including at least "double quote"
1300 itself, and preferably whitespace other than individual blanks. The intent
1301 is for the viewer to see that the expression is a string literal, and to
1302 see exactly which characters form its content. For example, <ms>double
1303 quote is "</ms> might be rendered as "double quote is \"".
1305 Obviously this isn't fully done here.
1307 aToken.aText = "\"" + rChars + "\"";
1310 void SmXMLStringContext_Impl::endFastElement(sal_Int32 )
1312 GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken,FNT_FIXED));
1315 namespace {
1317 class SmXMLIdentifierContext_Impl : public SmXMLImportContext
1319 SmXMLTokenAttrHelper maTokenAttrHelper;
1320 SmXMLContext_Helper aStyleHelper;
1321 SmToken aToken;
1323 public:
1324 SmXMLIdentifierContext_Impl(SmXMLImport &rImport)
1325 : SmXMLImportContext(rImport)
1326 , maTokenAttrHelper(*this)
1327 , aStyleHelper(*this)
1329 aToken.cMathChar = '\0';
1330 aToken.nLevel = 5;
1331 aToken.eType = TIDENT;
1334 void TCharacters(const OUString &rChars) override;
1335 void SAL_CALL startFastElement(sal_Int32 /*nElement*/, const uno::Reference< xml::sax::XFastAttributeList > & xAttrList ) override
1337 maTokenAttrHelper.RetrieveAttrs(xAttrList);
1338 aStyleHelper.RetrieveAttrs(xAttrList);
1340 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1345 void SmXMLIdentifierContext_Impl::endFastElement(sal_Int32 )
1347 std::unique_ptr<SmTextNode> pNode;
1348 //we will handle identifier italic/normal here instead of with a standalone
1349 //font node
1350 if (((aStyleHelper.nIsItalic == -1) && (aToken.aText.getLength() > 1))
1351 || ((aStyleHelper.nIsItalic == 0) && (aToken.aText.getLength() == 1)))
1353 pNode.reset(new SmTextNode(aToken,FNT_FUNCTION));
1354 pNode->GetFont().SetItalic(ITALIC_NONE);
1355 aStyleHelper.nIsItalic = -1;
1357 else
1358 pNode.reset(new SmTextNode(aToken,FNT_VARIABLE));
1359 if (aStyleHelper.nIsItalic != -1)
1361 if (aStyleHelper.nIsItalic)
1362 pNode->GetFont().SetItalic(ITALIC_NORMAL);
1363 else
1364 pNode->GetFont().SetItalic(ITALIC_NONE);
1365 aStyleHelper.nIsItalic = -1;
1367 GetSmImport().GetNodeStack().push_front(std::move(pNode));
1368 aStyleHelper.ApplyAttrs();
1370 maTokenAttrHelper.ApplyAttrs( (aToken.aText.getLength() == 1)
1371 ? MathMLMathvariantValue::Italic
1372 : MathMLMathvariantValue::Normal );
1375 void SmXMLIdentifierContext_Impl::TCharacters(const OUString &rChars)
1377 aToken.aText = rChars;
1380 namespace {
1382 class SmXMLOperatorContext_Impl : public SmXMLImportContext
1384 SmXMLTokenAttrHelper maTokenAttrHelper;
1385 bool bIsStretchy;
1386 bool bIsFenced;
1387 bool isPrefix;
1388 bool isInfix;
1389 bool isPostfix;
1390 SmToken aToken;
1392 public:
1393 SmXMLOperatorContext_Impl(SmXMLImport &rImport)
1394 : SmXMLImportContext(rImport)
1395 , maTokenAttrHelper(*this)
1396 , bIsStretchy(false)
1397 , bIsFenced(false)
1398 , isPrefix(false)
1399 , isInfix(false)
1400 , isPostfix(false)
1402 aToken.eType = TSPECIAL;
1403 aToken.nLevel = 5;
1406 void TCharacters(const OUString &rChars) override;
1407 void SAL_CALL startFastElement(sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList > &xAttrList ) override;
1408 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1413 void SmXMLOperatorContext_Impl::TCharacters(const OUString &rChars)
1415 aToken.cMathChar = rChars[0];
1416 SmToken bToken;
1417 if( bIsFenced ){
1418 if( isPrefix ) bToken = starmathdatabase::Identify_Prefix_SmXMLOperatorContext_Impl( aToken.cMathChar );
1419 else if( isInfix ) bToken = SmToken( TMLINE, MS_VERTLINE, "mline", TG::NONE, 0 );
1420 else if( isPostfix ) bToken = starmathdatabase::Identify_Postfix_SmXMLOperatorContext_Impl( aToken.cMathChar );
1421 else bToken = starmathdatabase::Identify_PrefixPostfix_SmXMLOperatorContext_Impl( aToken.cMathChar );
1423 else bToken = starmathdatabase::Identify_SmXMLOperatorContext_Impl( aToken.cMathChar, bIsStretchy );
1424 if( bToken.eType != TERROR ) aToken = bToken;
1427 void SmXMLOperatorContext_Impl::endFastElement(sal_Int32 )
1429 std::unique_ptr<SmMathSymbolNode> pNode(new SmMathSymbolNode(aToken));
1430 //For stretchy scaling the scaling must be retrieved from this node
1431 //and applied to the expression itself so as to get the expression
1432 //to scale the operator to the height of the expression itself
1433 if (bIsStretchy)
1434 pNode->SetScaleMode(SmScaleMode::Height);
1435 GetSmImport().GetNodeStack().push_front(std::move(pNode));
1437 // TODO: apply to non-alphabetic characters too
1438 if (rtl::isAsciiAlpha(aToken.cMathChar))
1439 maTokenAttrHelper.ApplyAttrs(MathMLMathvariantValue::Normal);
1443 void SmXMLOperatorContext_Impl::startFastElement(sal_Int32 /*nElement*/, const uno::Reference<
1444 xml::sax::XFastAttributeList > & xAttrList )
1446 maTokenAttrHelper.RetrieveAttrs(xAttrList);
1448 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
1450 OUString sValue = aIter.toString();
1451 switch(aIter.getToken())
1453 case XML_STRETCHY:
1454 bIsStretchy = sValue == GetXMLToken(XML_TRUE);
1455 break;
1456 case XML_FENCE:
1457 bIsFenced = sValue == GetXMLToken(XML_TRUE);
1458 break;
1459 case XML_FORM:
1460 isPrefix = sValue == GetXMLToken(XML_PREFIX); // <
1461 isInfix = sValue == GetXMLToken(XML_INFIX); // |
1462 isPostfix = sValue == GetXMLToken(XML_POSTFIX); // >
1463 break;
1464 default:
1465 XMLOFF_WARN_UNKNOWN("starmath", aIter);
1466 break;
1471 namespace {
1473 class SmXMLSpaceContext_Impl : public SmXMLImportContext
1475 public:
1476 SmXMLSpaceContext_Impl(SmXMLImport &rImport)
1477 : SmXMLImportContext(rImport) {}
1479 void SAL_CALL startFastElement(sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList ) override;
1482 bool lcl_CountBlanks(const MathMLAttributeLengthValue &rLV,
1483 sal_Int32 *pWide, sal_Int32 *pNarrow)
1485 assert(pWide);
1486 assert(pNarrow);
1487 if (rLV.aNumber.GetNumerator() == 0)
1489 *pWide = *pNarrow = 0;
1490 return true;
1492 // TODO: honor other units than em
1493 if (rLV.eUnit != MathMLLengthUnit::Em)
1494 return false;
1495 if (rLV.aNumber.GetNumerator() < 0)
1496 return false;
1497 const Fraction aTwo(2, 1);
1498 auto aWide = rLV.aNumber / aTwo;
1499 auto nWide = static_cast<sal_Int32>(static_cast<tools::Long>(aWide));
1500 if (nWide < 0)
1501 return false;
1502 const Fraction aPointFive(1, 2);
1503 auto aNarrow = (rLV.aNumber - Fraction(nWide, 1) * aTwo) / aPointFive;
1504 auto nNarrow = static_cast<sal_Int32>(static_cast<tools::Long>(aNarrow));
1505 if (nNarrow < 0)
1506 return false;
1507 *pWide = nWide;
1508 *pNarrow = nNarrow;
1509 return true;
1514 void SmXMLSpaceContext_Impl::startFastElement(sal_Int32 /*nElement*/,
1515 const uno::Reference<xml::sax::XFastAttributeList > & xAttrList )
1517 // There is no syntax in Math to specify blank nodes of arbitrary size yet.
1518 MathMLAttributeLengthValue aLV;
1519 sal_Int32 nWide = 0, nNarrow = 0;
1521 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
1523 OUString sValue = aIter.toString();
1524 switch (aIter.getToken())
1526 case XML_WIDTH:
1527 if ( ParseMathMLAttributeLengthValue(sValue.trim(), aLV) <= 0 ||
1528 !lcl_CountBlanks(aLV, &nWide, &nNarrow) )
1529 SAL_WARN("starmath", "ignore mspace's width: " << sValue);
1530 break;
1531 default:
1532 XMLOFF_WARN_UNKNOWN("starmath", aIter);
1533 break;
1536 SmToken aToken;
1537 aToken.eType = TBLANK;
1538 aToken.cMathChar = '\0';
1539 aToken.nGroup = TG::Blank;
1540 aToken.nLevel = 5;
1541 std::unique_ptr<SmBlankNode> pBlank(new SmBlankNode(aToken));
1542 if (nWide > 0)
1543 pBlank->IncreaseBy(aToken, nWide);
1544 if (nNarrow > 0)
1546 aToken.eType = TSBLANK;
1547 pBlank->IncreaseBy(aToken, nNarrow);
1549 GetSmImport().GetNodeStack().push_front(std::move(pBlank));
1552 namespace {
1554 class SmXMLSubContext_Impl : public SmXMLRowContext_Impl
1556 protected:
1557 void GenericEndElement(SmTokenType eType,SmSubSup aSubSup);
1559 public:
1560 SmXMLSubContext_Impl(SmXMLImport &rImport)
1561 : SmXMLRowContext_Impl(rImport) {}
1563 void SAL_CALL endFastElement(sal_Int32 ) override
1565 GenericEndElement(TRSUB,RSUB);
1571 void SmXMLSubContext_Impl::GenericEndElement(SmTokenType eType, SmSubSup eSubSup)
1573 /*The <msub> element requires exactly 2 arguments.*/
1574 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
1575 OSL_ENSURE( bNodeCheck, "Sub has not two arguments" );
1576 if (!bNodeCheck)
1577 return;
1579 SmToken aToken;
1580 aToken.cMathChar = '\0';
1581 aToken.eType = eType;
1582 std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
1583 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1585 // initialize subnodes array
1586 SmNodeArray aSubNodes;
1587 aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
1588 for (size_t i = 1; i < aSubNodes.size(); i++)
1589 aSubNodes[i] = nullptr;
1591 aSubNodes[eSubSup+1] = popOrZero(rNodeStack).release();
1592 aSubNodes[0] = popOrZero(rNodeStack).release();
1593 pNode->SetSubNodes(std::move(aSubNodes));
1594 rNodeStack.push_front(std::move(pNode));
1597 namespace {
1599 class SmXMLSupContext_Impl : public SmXMLSubContext_Impl
1601 public:
1602 SmXMLSupContext_Impl(SmXMLImport &rImport)
1603 : SmXMLSubContext_Impl(rImport) {}
1605 void SAL_CALL endFastElement(sal_Int32 ) override
1607 GenericEndElement(TRSUP,RSUP);
1612 class SmXMLSubSupContext_Impl : public SmXMLRowContext_Impl
1614 protected:
1615 void GenericEndElement(SmTokenType eType, SmSubSup aSub,SmSubSup aSup);
1617 public:
1618 SmXMLSubSupContext_Impl(SmXMLImport &rImport)
1619 : SmXMLRowContext_Impl(rImport) {}
1621 void SAL_CALL endFastElement(sal_Int32 ) override
1623 GenericEndElement(TRSUB,RSUB,RSUP);
1629 void SmXMLSubSupContext_Impl::GenericEndElement(SmTokenType eType,
1630 SmSubSup aSub,SmSubSup aSup)
1632 /*The <msub> element requires exactly 3 arguments.*/
1633 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 3;
1634 OSL_ENSURE( bNodeCheck, "SubSup has not three arguments" );
1635 if (!bNodeCheck)
1636 return;
1638 SmToken aToken;
1639 aToken.cMathChar = '\0';
1640 aToken.eType = eType;
1641 std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
1642 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1644 // initialize subnodes array
1645 SmNodeArray aSubNodes;
1646 aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
1647 for (size_t i = 1; i < aSubNodes.size(); i++)
1648 aSubNodes[i] = nullptr;
1650 aSubNodes[aSup+1] = popOrZero(rNodeStack).release();
1651 aSubNodes[aSub+1] = popOrZero(rNodeStack).release();
1652 aSubNodes[0] = popOrZero(rNodeStack).release();
1653 pNode->SetSubNodes(std::move(aSubNodes));
1654 rNodeStack.push_front(std::move(pNode));
1657 namespace {
1659 class SmXMLUnderContext_Impl : public SmXMLSubContext_Impl
1661 protected:
1662 sal_Int16 nAttrCount;
1664 public:
1665 SmXMLUnderContext_Impl(SmXMLImport &rImport)
1666 : SmXMLSubContext_Impl(rImport)
1667 , nAttrCount( 0 )
1670 void SAL_CALL startFastElement(sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList > &xAttrList ) override;
1671 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1672 void HandleAccent();
1677 void SmXMLUnderContext_Impl::startFastElement(sal_Int32 /*nElement*/, const uno::Reference<
1678 xml::sax::XFastAttributeList > & xAttrList )
1680 sax_fastparser::FastAttributeList& rAttribList =
1681 sax_fastparser::castToFastAttributeList( xAttrList );
1682 nAttrCount = rAttribList.getFastAttributeTokens().size();
1685 void SmXMLUnderContext_Impl::HandleAccent()
1687 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
1688 OSL_ENSURE( bNodeCheck, "Sub has not two arguments" );
1689 if (!bNodeCheck)
1690 return;
1692 /*Just one special case for the underline thing*/
1693 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1694 std::unique_ptr<SmNode> pTest = popOrZero(rNodeStack);
1695 SmToken aToken;
1696 aToken.cMathChar = '\0';
1697 aToken.eType = TUNDERLINE;
1699 std::unique_ptr<SmNode> pFirst;
1700 std::unique_ptr<SmStructureNode> pNode(new SmAttributNode(aToken));
1701 if ((pTest->GetToken().cMathChar & 0x0FFF) == 0x0332)
1703 pFirst.reset(new SmRectangleNode(aToken));
1705 else
1706 pFirst = std::move(pTest);
1708 std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack);
1709 pNode->SetSubNodes(std::move(pFirst), std::move(pSecond));
1710 pNode->SetScaleMode(SmScaleMode::Width);
1711 rNodeStack.push_front(std::move(pNode));
1715 void SmXMLUnderContext_Impl::endFastElement(sal_Int32 )
1717 if (!nAttrCount)
1718 GenericEndElement(TCSUB,CSUB);
1719 else
1720 HandleAccent();
1723 namespace {
1725 class SmXMLOverContext_Impl : public SmXMLSubContext_Impl
1727 protected:
1728 sal_Int16 nAttrCount;
1730 public:
1731 SmXMLOverContext_Impl(SmXMLImport &rImport)
1732 : SmXMLSubContext_Impl(rImport), nAttrCount(0) {}
1734 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1735 void SAL_CALL startFastElement(sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList > &xAttrList ) override;
1736 void HandleAccent();
1741 void SmXMLOverContext_Impl::startFastElement(sal_Int32 /*nElement*/, const uno::Reference<
1742 xml::sax::XFastAttributeList > & xAttrList )
1744 sax_fastparser::FastAttributeList& rAttribList =
1745 sax_fastparser::castToFastAttributeList( xAttrList );
1746 nAttrCount = rAttribList.getFastAttributeTokens().size();
1750 void SmXMLOverContext_Impl::endFastElement(sal_Int32 )
1752 if (!nAttrCount)
1753 GenericEndElement(TCSUP,CSUP);
1754 else
1755 HandleAccent();
1759 void SmXMLOverContext_Impl::HandleAccent()
1761 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
1762 OSL_ENSURE (bNodeCheck, "Sub has not two arguments");
1763 if (!bNodeCheck)
1764 return;
1766 SmToken aToken;
1767 aToken.cMathChar = '\0';
1768 aToken.eType = TACUTE;
1770 std::unique_ptr<SmAttributNode> pNode(new SmAttributNode(aToken));
1771 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1773 std::unique_ptr<SmNode> pFirst = popOrZero(rNodeStack);
1774 std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack);
1775 pNode->SetSubNodes(std::move(pFirst), std::move(pSecond));
1776 pNode->SetScaleMode(SmScaleMode::Width);
1777 rNodeStack.push_front(std::move(pNode));
1781 namespace {
1783 class SmXMLUnderOverContext_Impl : public SmXMLSubSupContext_Impl
1785 public:
1786 SmXMLUnderOverContext_Impl(SmXMLImport &rImport)
1787 : SmXMLSubSupContext_Impl(rImport) {}
1789 void SAL_CALL endFastElement(sal_Int32 ) override
1791 GenericEndElement(TCSUB,CSUB,CSUP);
1796 class SmXMLMultiScriptsContext_Impl : public SmXMLSubSupContext_Impl
1798 bool bHasPrescripts;
1800 void ProcessSubSupPairs(bool bIsPrescript);
1802 public:
1803 SmXMLMultiScriptsContext_Impl(SmXMLImport &rImport) :
1804 SmXMLSubSupContext_Impl(rImport),
1805 bHasPrescripts(false) {}
1807 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1808 virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
1809 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList ) override;
1813 class SmXMLNoneContext_Impl : public SmXMLImportContext
1815 public:
1816 SmXMLNoneContext_Impl(SmXMLImport &rImport)
1817 : SmXMLImportContext(rImport) {}
1819 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1824 void SmXMLNoneContext_Impl::endFastElement(sal_Int32 )
1826 SmToken aToken;
1827 aToken.cMathChar = '\0';
1828 aToken.aText.clear();
1829 aToken.nLevel = 5;
1830 aToken.eType = TIDENT;
1831 GetSmImport().GetNodeStack().push_front(
1832 std::make_unique<SmTextNode>(aToken,FNT_VARIABLE));
1835 namespace {
1837 class SmXMLPrescriptsContext_Impl : public SmXMLImportContext
1839 public:
1840 SmXMLPrescriptsContext_Impl(SmXMLImport &rImport)
1841 : SmXMLImportContext(rImport) {}
1845 class SmXMLTableRowContext_Impl : public SmXMLRowContext_Impl
1847 public:
1848 SmXMLTableRowContext_Impl(SmXMLImport &rImport) :
1849 SmXMLRowContext_Impl(rImport)
1852 virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
1853 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList ) override;
1857 class SmXMLTableContext_Impl : public SmXMLTableRowContext_Impl
1859 public:
1860 SmXMLTableContext_Impl(SmXMLImport &rImport) :
1861 SmXMLTableRowContext_Impl(rImport)
1864 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1865 virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
1866 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList ) override;
1870 class SmXMLTableCellContext_Impl : public SmXMLRowContext_Impl
1872 public:
1873 SmXMLTableCellContext_Impl(SmXMLImport &rImport) :
1874 SmXMLRowContext_Impl(rImport)
1879 class SmXMLAlignGroupContext_Impl : public SmXMLRowContext_Impl
1881 public:
1882 SmXMLAlignGroupContext_Impl(SmXMLImport &rImport) :
1883 SmXMLRowContext_Impl(rImport)
1886 /*Don't do anything with alignment for now*/
1890 class SmXMLActionContext_Impl : public SmXMLRowContext_Impl
1892 size_t mnSelection; // 1-based
1894 public:
1895 SmXMLActionContext_Impl(SmXMLImport &rImport) :
1896 SmXMLRowContext_Impl(rImport)
1897 , mnSelection(1)
1900 void SAL_CALL startFastElement(sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList> &xAttrList) override;
1901 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1905 // NB: virtually inherit so we can multiply inherit properly
1906 // in SmXMLFlatDocContext_Impl
1907 class SmXMLOfficeContext_Impl : public virtual SvXMLImportContext
1909 public:
1910 SmXMLOfficeContext_Impl( SmXMLImport &rImport )
1911 : SvXMLImportContext(rImport) {}
1913 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
1914 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
1919 uno::Reference< xml::sax::XFastContextHandler > SmXMLOfficeContext_Impl::createFastChildContext(sal_Int32 nElement,
1920 const uno::Reference< xml::sax::XFastAttributeList > &/*xAttrList*/)
1922 if ( nElement == XML_ELEMENT(OFFICE, XML_META) )
1924 SAL_WARN("starmath", "XML_TOK_DOC_META: should not have come here, maybe document is invalid?");
1926 else if ( nElement == XML_ELEMENT(OFFICE, XML_SETTINGS) )
1928 return new XMLDocumentSettingsContext( GetImport() );
1930 return nullptr;
1933 namespace {
1935 // context for flat file xml format
1936 class SmXMLFlatDocContext_Impl
1937 : public SmXMLOfficeContext_Impl, public SvXMLMetaDocumentContext
1939 public:
1940 SmXMLFlatDocContext_Impl( SmXMLImport& i_rImport,
1941 const uno::Reference<document::XDocumentProperties>& i_xDocProps);
1943 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
1944 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
1949 SmXMLFlatDocContext_Impl::SmXMLFlatDocContext_Impl( SmXMLImport& i_rImport,
1950 const uno::Reference<document::XDocumentProperties>& i_xDocProps) :
1951 SvXMLImportContext(i_rImport),
1952 SmXMLOfficeContext_Impl(i_rImport),
1953 SvXMLMetaDocumentContext(i_rImport, i_xDocProps)
1957 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL SmXMLFlatDocContext_Impl::createFastChildContext(
1958 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
1960 // behave like meta base class iff we encounter office:meta
1961 if ( nElement == XML_ELEMENT(OFFICE, XML_META) )
1963 return SvXMLMetaDocumentContext::createFastChildContext(
1964 nElement, xAttrList );
1966 else
1968 return SmXMLOfficeContext_Impl::createFastChildContext(
1969 nElement, xAttrList );
1973 uno::Reference< xml::sax::XFastContextHandler > SmXMLDocContext_Impl::createFastChildContext(
1974 sal_Int32 nElement,
1975 const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
1977 uno::Reference< xml::sax::XFastContextHandler > xContext;
1979 switch(nElement)
1981 //Consider semantics a dummy except for any starmath annotations
1982 case XML_ELEMENT(MATH, XML_SEMANTICS):
1983 xContext = new SmXMLRowContext_Impl(GetSmImport());
1984 break;
1985 /*General Layout Schemata*/
1986 case XML_ELEMENT(MATH, XML_MROW):
1987 xContext = new SmXMLRowContext_Impl(GetSmImport());
1988 break;
1989 case XML_ELEMENT(MATH, XML_MENCLOSE):
1990 xContext = new SmXMLEncloseContext_Impl(GetSmImport());
1991 break;
1992 case XML_ELEMENT(MATH, XML_MFRAC):
1993 xContext = new SmXMLFracContext_Impl(GetSmImport());
1994 break;
1995 case XML_ELEMENT(MATH, XML_MSQRT):
1996 xContext = new SmXMLSqrtContext_Impl(GetSmImport());
1997 break;
1998 case XML_ELEMENT(MATH, XML_MROOT):
1999 xContext = new SmXMLRootContext_Impl(GetSmImport());
2000 break;
2001 case XML_ELEMENT(MATH, XML_MSTYLE):
2002 xContext = new SmXMLStyleContext_Impl(GetSmImport());
2003 break;
2004 case XML_ELEMENT(MATH, XML_MERROR):
2005 xContext = new SmXMLErrorContext_Impl(GetSmImport());
2006 break;
2007 case XML_ELEMENT(MATH, XML_MPADDED):
2008 xContext = new SmXMLPaddedContext_Impl(GetSmImport());
2009 break;
2010 case XML_ELEMENT(MATH, XML_MPHANTOM):
2011 xContext = new SmXMLPhantomContext_Impl(GetSmImport());
2012 break;
2013 case XML_ELEMENT(MATH, XML_MFENCED):
2014 xContext = new SmXMLFencedContext_Impl(GetSmImport());
2015 break;
2016 /*Script and Limit Schemata*/
2017 case XML_ELEMENT(MATH, XML_MSUB):
2018 xContext = new SmXMLSubContext_Impl(GetSmImport());
2019 break;
2020 case XML_ELEMENT(MATH, XML_MSUP):
2021 xContext = new SmXMLSupContext_Impl(GetSmImport());
2022 break;
2023 case XML_ELEMENT(MATH, XML_MSUBSUP):
2024 xContext = new SmXMLSubSupContext_Impl(GetSmImport());
2025 break;
2026 case XML_ELEMENT(MATH, XML_MUNDER):
2027 xContext = new SmXMLUnderContext_Impl(GetSmImport());
2028 break;
2029 case XML_ELEMENT(MATH, XML_MOVER):
2030 xContext = new SmXMLOverContext_Impl(GetSmImport());
2031 break;
2032 case XML_ELEMENT(MATH, XML_MUNDEROVER):
2033 xContext = new SmXMLUnderOverContext_Impl(GetSmImport());
2034 break;
2035 case XML_ELEMENT(MATH, XML_MMULTISCRIPTS):
2036 xContext = new SmXMLMultiScriptsContext_Impl(GetSmImport());
2037 break;
2038 case XML_ELEMENT(MATH, XML_MTABLE):
2039 xContext = new SmXMLTableContext_Impl(GetSmImport());
2040 break;
2041 case XML_ELEMENT(MATH, XML_MACTION):
2042 xContext = new SmXMLActionContext_Impl(GetSmImport());
2043 break;
2044 default:
2045 /*Basically there's an implicit mrow around certain bare
2046 *elements, use a RowContext to see if this is one of
2047 *those ones*/
2048 rtl::Reference<SmXMLRowContext_Impl> aTempContext(new SmXMLRowContext_Impl(GetSmImport()));
2050 xContext = aTempContext->StrictCreateChildContext(nElement);
2051 break;
2053 return xContext;
2056 void SmXMLDocContext_Impl::endFastElement(sal_Int32)
2058 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2060 std::unique_ptr<SmNode> pContextNode = popOrZero(rNodeStack);
2062 SmToken aDummy;
2063 std::unique_ptr<SmStructureNode> pSNode(new SmLineNode(aDummy));
2064 pSNode->SetSubNodes(std::move(pContextNode), nullptr);
2065 rNodeStack.push_front(std::move(pSNode));
2067 SmNodeArray LineArray;
2068 auto n = rNodeStack.size();
2069 LineArray.resize(n);
2070 for (size_t j = 0; j < n; j++)
2072 auto pNode = std::move(rNodeStack.front());
2073 rNodeStack.pop_front();
2074 LineArray[n - (j + 1)] = pNode.release();
2076 std::unique_ptr<SmStructureNode> pSNode2(new SmTableNode(aDummy));
2077 pSNode2->SetSubNodes(std::move(LineArray));
2078 rNodeStack.push_front(std::move(pSNode2));
2081 void SmXMLFracContext_Impl::endFastElement(sal_Int32 )
2083 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2084 const bool bNodeCheck = rNodeStack.size() - nElementCount == 2;
2085 OSL_ENSURE( bNodeCheck, "Fraction (mfrac) tag is missing component" );
2086 if (!bNodeCheck)
2087 return;
2089 SmToken aToken;
2090 aToken.cMathChar = '\0';
2091 aToken.eType = TFRAC;
2092 std::unique_ptr<SmStructureNode> pSNode(new SmBinVerNode(aToken));
2093 std::unique_ptr<SmNode> pOper(new SmRectangleNode(aToken));
2094 std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack);
2095 std::unique_ptr<SmNode> pFirst = popOrZero(rNodeStack);
2096 pSNode->SetSubNodes(std::move(pFirst), std::move(pOper), std::move(pSecond));
2097 rNodeStack.push_front(std::move(pSNode));
2100 void SmXMLRootContext_Impl::endFastElement(sal_Int32 )
2102 /*The <mroot> element requires exactly 2 arguments.*/
2103 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
2104 OSL_ENSURE( bNodeCheck, "Root tag is missing component");
2105 if (!bNodeCheck)
2106 return;
2108 SmToken aToken;
2109 aToken.cMathChar = MS_SQRT; //Temporary: alert, based on StarSymbol font
2110 aToken.eType = TNROOT;
2111 std::unique_ptr<SmStructureNode> pSNode(new SmRootNode(aToken));
2112 std::unique_ptr<SmNode> pOper(new SmRootSymbolNode(aToken));
2113 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2114 std::unique_ptr<SmNode> pIndex = popOrZero(rNodeStack);
2115 std::unique_ptr<SmNode> pBase = popOrZero(rNodeStack);
2116 pSNode->SetSubNodes(std::move(pIndex), std::move(pOper), std::move(pBase));
2117 rNodeStack.push_front(std::move(pSNode));
2120 void SmXMLSqrtContext_Impl::endFastElement(sal_Int32 nElement)
2123 <msqrt> accepts any number of arguments; if this number is not 1, its
2124 contents are treated as a single "inferred <mrow>" containing its
2125 arguments
2127 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
2128 SmXMLRowContext_Impl::endFastElement(nElement);
2130 SmToken aToken;
2131 aToken.cMathChar = MS_SQRT; //Temporary: alert, based on StarSymbol font
2132 aToken.eType = TSQRT;
2133 std::unique_ptr<SmStructureNode> pSNode(new SmRootNode(aToken));
2134 std::unique_ptr<SmNode> pOper(new SmRootSymbolNode(aToken));
2135 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2136 pSNode->SetSubNodes(nullptr, std::move(pOper), popOrZero(rNodeStack));
2137 rNodeStack.push_front(std::move(pSNode));
2140 void SmXMLRowContext_Impl::endFastElement(sal_Int32 )
2142 SmNodeArray aRelationArray;
2143 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2145 if (rNodeStack.size() > nElementCount)
2147 auto nSize = rNodeStack.size() - nElementCount;
2149 aRelationArray.resize(nSize);
2150 for (auto j=nSize;j > 0;j--)
2152 auto pNode = std::move(rNodeStack.front());
2153 rNodeStack.pop_front();
2154 aRelationArray[j-1] = pNode.release();
2157 //If the first or last element is an operator with stretchyness
2158 //set then we must create a brace node here from those elements,
2159 //removing the stretchness from the operators and applying it to
2160 //ourselves, and creating the appropriate dummy StarMath none bracket
2161 //to balance the arrangement
2162 if (((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height)
2163 && (aRelationArray[0]->GetType() == SmNodeType::Math))
2164 || ((aRelationArray[nSize-1]->GetScaleMode() == SmScaleMode::Height)
2165 && (aRelationArray[nSize-1]->GetType() == SmNodeType::Math)))
2167 SmToken aToken;
2168 aToken.cMathChar = '\0';
2169 aToken.nLevel = 5;
2171 int nLeft=0,nRight=0;
2172 if ((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height)
2173 && (aRelationArray[0]->GetType() == SmNodeType::Math))
2175 aToken = aRelationArray[0]->GetToken();
2176 nLeft=1;
2178 else
2179 aToken.cMathChar = '\0';
2181 aToken.eType = TLPARENT;
2182 std::unique_ptr<SmNode> pLeft(new SmMathSymbolNode(aToken));
2184 if ((aRelationArray[nSize-1]->GetScaleMode() == SmScaleMode::Height)
2185 && (aRelationArray[nSize-1]->GetType() == SmNodeType::Math))
2187 aToken = aRelationArray[nSize-1]->GetToken();
2188 nRight=1;
2190 else
2191 aToken.cMathChar = '\0';
2193 aToken.eType = TRPARENT;
2194 std::unique_ptr<SmNode> pRight(new SmMathSymbolNode(aToken));
2196 SmNodeArray aRelationArray2;
2198 //!! nSize-nLeft-nRight may be < 0 !!
2199 int nRelArrSize = nSize-nLeft-nRight;
2200 if (nRelArrSize > 0)
2202 aRelationArray2.resize(nRelArrSize);
2203 for (int i=0;i < nRelArrSize;i++)
2205 aRelationArray2[i] = aRelationArray[i+nLeft];
2206 aRelationArray[i+nLeft] = nullptr;
2210 SmToken aDummy;
2211 std::unique_ptr<SmStructureNode> pSNode(new SmBraceNode(aToken));
2212 std::unique_ptr<SmStructureNode> pBody(new SmExpressionNode(aDummy));
2213 pBody->SetSubNodes(std::move(aRelationArray2));
2215 pSNode->SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight));
2216 pSNode->SetScaleMode(SmScaleMode::Height);
2217 rNodeStack.push_front(std::move(pSNode));
2219 for (auto a : aRelationArray)
2220 delete a;
2222 return;
2225 else
2227 // The elements msqrt, mstyle, merror, menclose, mpadded, mphantom, mtd, and math
2228 // treat their content as a single inferred mrow in case their content is empty.
2229 // Here an empty group {} is used to catch those cases and transform them without error
2230 // to StarMath.
2231 aRelationArray.resize(2);
2232 SmToken aToken;
2233 aToken.cMathChar = MS_LBRACE;
2234 aToken.nLevel = 5;
2235 aToken.eType = TLGROUP;
2236 aToken.nGroup = TG::NONE;
2237 aToken.aText = "{";
2238 aRelationArray[0] = new SmLineNode(aToken);
2240 aToken.cMathChar = MS_RBRACE;
2241 aToken.nLevel = 0;
2242 aToken.eType = TRGROUP;
2243 aToken.nGroup = TG::NONE;
2244 aToken.aText = "}";
2245 aRelationArray[1] = new SmLineNode(aToken);
2248 SmToken aDummy;
2249 std::unique_ptr<SmStructureNode> pSNode(new SmExpressionNode(aDummy));
2250 pSNode->SetSubNodes(std::move(aRelationArray));
2251 rNodeStack.push_front(std::move(pSNode));
2254 uno::Reference< xml::sax::XFastContextHandler > SmXMLRowContext_Impl::StrictCreateChildContext(
2255 sal_Int32 nElement)
2257 uno::Reference< xml::sax::XFastContextHandler > pContext;
2259 switch(nElement)
2261 /*Note that these should accept malignmark subelements, but do not*/
2262 case XML_ELEMENT(MATH, XML_MN):
2263 pContext = new SmXMLNumberContext_Impl(GetSmImport());
2264 break;
2265 case XML_ELEMENT(MATH, XML_MI):
2266 pContext = new SmXMLIdentifierContext_Impl(GetSmImport());
2267 break;
2268 case XML_ELEMENT(MATH, XML_MO):
2269 pContext = new SmXMLOperatorContext_Impl(GetSmImport());
2270 break;
2271 case XML_ELEMENT(MATH, XML_MTEXT):
2272 pContext = new SmXMLTextContext_Impl(GetSmImport());
2273 break;
2274 case XML_ELEMENT(MATH, XML_MSPACE):
2275 pContext = new SmXMLSpaceContext_Impl(GetSmImport());
2276 break;
2277 case XML_ELEMENT(MATH, XML_MS):
2278 pContext = new SmXMLStringContext_Impl(GetSmImport());
2279 break;
2281 /*Note: The maligngroup should only be seen when the row
2282 * (or descendants) are in a table*/
2283 case XML_ELEMENT(MATH, XML_MALIGNGROUP):
2284 pContext = new SmXMLAlignGroupContext_Impl(GetSmImport());
2285 break;
2287 case XML_ELEMENT(MATH, XML_ANNOTATION):
2288 pContext = new SmXMLAnnotationContext_Impl(GetSmImport());
2289 break;
2291 default:
2292 break;
2294 return pContext;
2298 uno::Reference< xml::sax::XFastContextHandler > SmXMLRowContext_Impl::createFastChildContext(
2299 sal_Int32 nElement,
2300 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2302 uno::Reference< xml::sax::XFastContextHandler > xContext = StrictCreateChildContext(nElement);
2304 if (!xContext)
2306 //Hmm, unrecognized for this level, check to see if its
2307 //an element that can have an implicit schema around it
2308 xContext = SmXMLDocContext_Impl::createFastChildContext(nElement, xAttrList);
2310 return xContext;
2313 uno::Reference< xml::sax::XFastContextHandler > SmXMLMultiScriptsContext_Impl::createFastChildContext(
2314 sal_Int32 nElement,
2315 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2317 uno::Reference< xml::sax::XFastContextHandler > xContext;
2319 switch(nElement)
2321 case XML_ELEMENT(MATH, XML_MPRESCRIPTS):
2322 bHasPrescripts = true;
2323 ProcessSubSupPairs(false);
2324 xContext = new SmXMLPrescriptsContext_Impl(GetSmImport());
2325 break;
2326 case XML_ELEMENT(MATH, XML_NONE):
2327 xContext = new SmXMLNoneContext_Impl(GetSmImport());
2328 break;
2329 default:
2330 xContext = SmXMLRowContext_Impl::createFastChildContext(nElement,xAttrList);
2331 break;
2333 return xContext;
2336 void SmXMLMultiScriptsContext_Impl::ProcessSubSupPairs(bool bIsPrescript)
2338 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2340 if (rNodeStack.size() <= nElementCount)
2341 return;
2343 auto nCount = rNodeStack.size() - nElementCount - 1;
2344 if (nCount == 0)
2345 return;
2347 if (nCount % 2 == 0)
2349 SmToken aToken;
2350 aToken.cMathChar = '\0';
2351 aToken.eType = bIsPrescript ? TLSUB : TRSUB;
2353 SmNodeStack aReverseStack;
2354 for (size_t i = 0; i < nCount + 1; i++)
2356 auto pNode = std::move(rNodeStack.front());
2357 rNodeStack.pop_front();
2358 aReverseStack.push_front(std::move(pNode));
2361 SmSubSup eSub = bIsPrescript ? LSUB : RSUB;
2362 SmSubSup eSup = bIsPrescript ? LSUP : RSUP;
2364 for (size_t i = 0; i < nCount; i += 2)
2366 std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
2368 // initialize subnodes array
2369 SmNodeArray aSubNodes(1 + SUBSUP_NUM_ENTRIES);
2371 /*On each loop the base and its sub sup pair becomes the
2372 base for the next loop to which the next sub sup pair is
2373 attached, i.e. wheels within wheels*/
2374 aSubNodes[0] = popOrZero(aReverseStack).release();
2376 std::unique_ptr<SmNode> pScriptNode = popOrZero(aReverseStack);
2378 if (pScriptNode && ((pScriptNode->GetToken().eType != TIDENT) ||
2379 (!pScriptNode->GetToken().aText.isEmpty())))
2380 aSubNodes[eSub+1] = pScriptNode.release();
2381 pScriptNode = popOrZero(aReverseStack);
2382 if (pScriptNode && ((pScriptNode->GetToken().eType != TIDENT) ||
2383 (!pScriptNode->GetToken().aText.isEmpty())))
2384 aSubNodes[eSup+1] = pScriptNode.release();
2386 pNode->SetSubNodes(std::move(aSubNodes));
2387 aReverseStack.push_front(std::move(pNode));
2389 assert(!aReverseStack.empty());
2390 auto pNode = std::move(aReverseStack.front());
2391 aReverseStack.pop_front();
2392 rNodeStack.push_front(std::move(pNode));
2394 else
2396 // Ignore odd number of elements.
2397 for (size_t i = 0; i < nCount; i++)
2399 rNodeStack.pop_front();
2405 void SmXMLTableContext_Impl::endFastElement(sal_Int32 )
2407 SmNodeArray aExpressionArray;
2408 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2409 SmNodeStack aReverseStack;
2410 aExpressionArray.resize(rNodeStack.size()-nElementCount);
2412 size_t nRows = rNodeStack.size()-nElementCount;
2413 size_t nCols = 0;
2415 for (size_t i = nRows; i > 0; --i)
2417 SmNode* pArray = rNodeStack.front().release();
2418 rNodeStack.pop_front();
2419 if (pArray->GetNumSubNodes() == 0)
2421 //This is a little tricky, it is possible that there was
2422 //be elements that were not inside a <mtd> pair, in which
2423 //case they will not be in a row, i.e. they will not have
2424 //SubNodes, so we have to wait until here before we can
2425 //resolve the situation. Implicit surrounding tags are
2426 //surprisingly difficult to get right within this
2427 //architecture
2429 SmNodeArray aRelationArray;
2430 aRelationArray.resize(1);
2431 aRelationArray[0] = pArray;
2432 SmToken aDummy;
2433 SmExpressionNode* pExprNode = new SmExpressionNode(aDummy);
2434 pExprNode->SetSubNodes(std::move(aRelationArray));
2435 pArray = pExprNode;
2438 nCols = std::max(nCols, pArray->GetNumSubNodes());
2439 aReverseStack.push_front(std::unique_ptr<SmNode>(pArray));
2441 if (nCols > SAL_MAX_UINT16)
2442 throw std::range_error("column limit");
2443 if (nRows > SAL_MAX_UINT16)
2444 throw std::range_error("row limit");
2445 aExpressionArray.resize(nCols*nRows);
2446 size_t j=0;
2447 for (auto & elem : aReverseStack)
2449 std::unique_ptr<SmStructureNode> xArray(static_cast<SmStructureNode*>(elem.release()));
2450 for (size_t i = 0; i < xArray->GetNumSubNodes(); ++i)
2451 aExpressionArray[j++] = xArray->GetSubNode(i);
2452 xArray->ClearSubNodes();
2454 aReverseStack.clear();
2456 SmToken aToken;
2457 aToken.cMathChar = '\0';
2458 aToken.eType = TMATRIX;
2459 std::unique_ptr<SmMatrixNode> pSNode(new SmMatrixNode(aToken));
2460 pSNode->SetSubNodes(std::move(aExpressionArray));
2461 pSNode->SetRowCol(nRows, nCols);
2462 rNodeStack.push_front(std::move(pSNode));
2465 uno::Reference< xml::sax::XFastContextHandler > SmXMLTableRowContext_Impl::createFastChildContext(
2466 sal_Int32 nElement,
2467 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2469 uno::Reference< xml::sax::XFastContextHandler > xContext;
2471 switch(nElement)
2473 case XML_ELEMENT(MATH, XML_MTD):
2474 xContext = new SmXMLTableCellContext_Impl(GetSmImport());
2475 break;
2476 default:
2477 xContext = SmXMLRowContext_Impl::createFastChildContext(nElement,xAttrList);
2478 break;
2480 return xContext;
2483 uno::Reference< xml::sax::XFastContextHandler > SmXMLTableContext_Impl::createFastChildContext(
2484 sal_Int32 nElement,
2485 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2487 uno::Reference< xml::sax::XFastContextHandler > xContext;
2489 switch(nElement)
2491 case XML_ELEMENT(MATH, XML_MTR):
2492 xContext = new SmXMLTableRowContext_Impl(GetSmImport());
2493 break;
2494 default:
2495 xContext = SmXMLTableRowContext_Impl::createFastChildContext(nElement, xAttrList);
2496 break;
2498 return xContext;
2501 void SmXMLMultiScriptsContext_Impl::endFastElement(sal_Int32 )
2503 ProcessSubSupPairs(bHasPrescripts);
2506 void SmXMLActionContext_Impl::startFastElement(sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)
2508 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
2510 OUString sValue = aIter.toString();
2511 switch(aIter.getToken())
2513 case XML_SELECTION:
2515 sal_uInt32 n = sValue.toUInt32();
2516 if (n > 0) mnSelection = static_cast<size_t>(n);
2518 break;
2519 default:
2520 XMLOFF_WARN_UNKNOWN("starmath", aIter);
2521 break;
2526 void SmXMLActionContext_Impl::endFastElement(sal_Int32 )
2528 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2529 auto nSize = rNodeStack.size();
2530 if (nSize <= nElementCount) {
2531 // not compliant to maction's specification, e.g., no subexpressions
2532 return;
2534 assert(mnSelection > 0);
2535 if (nSize < nElementCount + mnSelection) {
2536 // No selected subexpression exists, which is a MathML error;
2537 // fallback to selecting the first
2538 mnSelection = 1;
2540 assert(nSize >= nElementCount + mnSelection);
2541 for (auto i=nSize-(nElementCount+mnSelection); i > 0; i--)
2543 rNodeStack.pop_front();
2545 auto pSelected = std::move(rNodeStack.front());
2546 rNodeStack.pop_front();
2547 for (auto i=rNodeStack.size()-nElementCount; i > 0; i--)
2549 rNodeStack.pop_front();
2551 rNodeStack.push_front(std::move(pSelected));
2554 SvXMLImportContext *SmXMLImport::CreateFastContext(sal_Int32 nElement,
2555 const uno::Reference <xml::sax::XFastAttributeList> & /*xAttrList*/)
2557 SvXMLImportContext *pContext = nullptr;
2559 switch (nElement)
2561 case XML_ELEMENT( OFFICE, XML_DOCUMENT ):
2562 case XML_ELEMENT( OFFICE, XML_DOCUMENT_META ):
2564 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
2565 GetModel(), uno::UNO_QUERY_THROW);
2566 pContext = ( (nElement & TOKEN_MASK) == XML_DOCUMENT_META )
2567 ? new SvXMLMetaDocumentContext( *this,
2568 xDPS->getDocumentProperties() )
2569 // flat OpenDocument file format -- this has not been tested...
2570 : new SmXMLFlatDocContext_Impl( *this,
2571 xDPS->getDocumentProperties() );
2573 break;
2574 default:
2575 if (IsTokenInNamespace(nElement, XML_NAMESPACE_OFFICE))
2576 pContext = new SmXMLOfficeContext_Impl(*this);
2577 else
2578 pContext = new SmXMLDocContext_Impl(*this);
2580 return pContext;
2583 SmXMLImport::~SmXMLImport() throw ()
2585 cleanup();
2588 void SmXMLImport::SetViewSettings(const Sequence<PropertyValue>& aViewProps)
2590 uno::Reference <frame::XModel> xModel = GetModel();
2591 if ( !xModel.is() )
2592 return;
2594 SmModel *pModel = comphelper::getUnoTunnelImplementation<SmModel>(xModel);
2596 if ( !pModel )
2597 return;
2599 SmDocShell *pDocShell =
2600 static_cast<SmDocShell*>(pModel->GetObjectShell());
2601 if ( !pDocShell )
2602 return;
2604 tools::Rectangle aRect( pDocShell->GetVisArea() );
2606 tools::Long nTmp = 0;
2608 for (const PropertyValue& rValue : aViewProps)
2610 if (rValue.Name == "ViewAreaTop" )
2612 rValue.Value >>= nTmp;
2613 aRect.SaturatingSetY(nTmp);
2615 else if (rValue.Name == "ViewAreaLeft" )
2617 rValue.Value >>= nTmp;
2618 aRect.SaturatingSetX(nTmp);
2620 else if (rValue.Name == "ViewAreaWidth" )
2622 rValue.Value >>= nTmp;
2623 Size aSize( aRect.GetSize() );
2624 aSize.setWidth( nTmp );
2625 aRect.SaturatingSetSize(aSize);
2627 else if (rValue.Name == "ViewAreaHeight" )
2629 rValue.Value >>= nTmp;
2630 Size aSize( aRect.GetSize() );
2631 aSize.setHeight( nTmp );
2632 aRect.SaturatingSetSize(aSize);
2636 pDocShell->SetVisArea ( aRect );
2639 void SmXMLImport::SetConfigurationSettings(const Sequence<PropertyValue>& aConfProps)
2641 uno::Reference < XPropertySet > xProps ( GetModel(), UNO_QUERY );
2642 if ( !xProps.is() )
2643 return;
2645 Reference < XPropertySetInfo > xInfo ( xProps->getPropertySetInfo() );
2646 if (!xInfo.is() )
2647 return;
2649 const OUString sFormula ( "Formula" );
2650 const OUString sBasicLibraries ( "BasicLibraries" );
2651 const OUString sDialogLibraries ( "DialogLibraries" );
2652 for ( const PropertyValue& rValue : aConfProps )
2654 if (rValue.Name != sFormula &&
2655 rValue.Name != sBasicLibraries &&
2656 rValue.Name != sDialogLibraries)
2660 if ( xInfo->hasPropertyByName( rValue.Name ) )
2661 xProps->setPropertyValue( rValue.Name, rValue.Value );
2663 catch (const beans::PropertyVetoException &)
2665 // dealing with read-only properties here. Nothing to do...
2667 catch (const Exception&)
2669 DBG_UNHANDLED_EXCEPTION("starmath");
2675 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportMML(SvStream &rStream)
2677 SmGlobals::ensure();
2679 SfxObjectShellLock xDocSh(new SmDocShell(SfxModelFlags::EMBEDDED_OBJECT));
2680 xDocSh->DoInitNew();
2681 uno::Reference<frame::XModel> xModel(xDocSh->GetModel());
2683 uno::Reference<beans::XPropertySet> xInfoSet;
2684 uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
2685 uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
2687 //SetLoading hack because the document properties will be re-initted
2688 //by the xml filter and during the init, while it's considered uninitialized,
2689 //setting a property will inform the document it's modified, which attempts
2690 //to update the properties, which throws cause the properties are uninitialized
2691 xDocSh->SetLoading(SfxLoadedFlags::NONE);
2693 ErrCode nRet = ERRCODE_SFX_DOLOADFAILED;
2697 nRet = SmXMLImportWrapper::ReadThroughComponent(xStream, xModel, xContext, xInfoSet, "com.sun.star.comp.Math.XMLImporter", false);
2699 catch (...)
2703 xDocSh->SetLoading(SfxLoadedFlags::ALL);
2705 xDocSh->DoClose();
2707 return nRet != ERRCODE_NONE;
2710 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */