Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / starmath / source / mathmlimport.cxx
blob8c0fc3f3d97c2dcd6f7ed023bba22c181affa46d
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/Parser.hpp>
27 #include <com/sun/star/xml/sax/XFastParser.hpp>
28 #include <com/sun/star/document/XDocumentProperties.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>
37 #include <comphelper/fileformat.h>
38 #include <comphelper/genericpropertyset.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <comphelper/servicehelper.hxx>
41 #include <comphelper/string.hxx>
42 #include <o3tl/make_unique.hxx>
43 #include <rtl/character.hxx>
44 #include <sfx2/frame.hxx>
45 #include <sfx2/docfile.hxx>
46 #include <sfx2/sfxsids.hrc>
47 #include <osl/diagnose.h>
48 #include <svtools/sfxecode.hxx>
49 #include <svl/itemset.hxx>
50 #include <svl/stritem.hxx>
51 #include <unotools/streamwrap.hxx>
52 #include <sax/tools/converter.hxx>
53 #include <xmloff/DocumentSettingsContext.hxx>
54 #include <xmloff/xmlnmspe.hxx>
55 #include <xmloff/xmltoken.hxx>
56 #include <xmloff/nmspmap.hxx>
57 #include <xmloff/xmluconv.hxx>
58 #include <xmloff/xmlmetai.hxx>
59 #include <svx/dialmgr.hxx>
60 #include <svx/strings.hrc>
61 #include <tools/diagnose_ex.h>
63 #include <memory>
65 #include "mathmlattr.hxx"
66 #include "mathmlimport.hxx"
67 #include "register.hxx"
68 #include <document.hxx>
69 #include <smdll.hxx>
70 #include <unomodel.hxx>
71 #include <utility.hxx>
73 using namespace ::com::sun::star::beans;
74 using namespace ::com::sun::star::container;
75 using namespace ::com::sun::star::document;
76 using namespace ::com::sun::star::lang;
77 using namespace ::com::sun::star::uno;
78 using namespace ::com::sun::star;
79 using namespace ::xmloff::token;
82 #define IMPORT_SVC_NAME "com.sun.star.xml.XMLImportFilter"
84 namespace {
86 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.release();
97 ErrCode SmXMLImportWrapper::Import(SfxMedium &rMedium)
99 ErrCode nError = ERRCODE_SFX_DOLOADFAILED;
101 uno::Reference<uno::XComponentContext> xContext( comphelper::getProcessComponentContext() );
103 //Make a model component from our SmModel
104 uno::Reference< lang::XComponent > xModelComp( xModel, uno::UNO_QUERY );
105 OSL_ENSURE( xModelComp.is(), "XMLReader::Read: got no model" );
107 // try to get an XStatusIndicator from the Medium
108 uno::Reference<task::XStatusIndicator> xStatusIndicator;
110 bool bEmbedded = false;
111 uno::Reference <lang::XUnoTunnel> xTunnel(xModel,uno::UNO_QUERY);
112 SmModel *pModel = reinterpret_cast<SmModel *>
113 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
115 SmDocShell *pDocShell = pModel ?
116 static_cast<SmDocShell*>(pModel->GetObjectShell()) : nullptr;
117 if (pDocShell)
119 OSL_ENSURE( pDocShell->GetMedium() == &rMedium,
120 "different SfxMedium found" );
122 SfxItemSet* pSet = rMedium.GetItemSet();
123 if (pSet)
125 const SfxUnoAnyItem* pItem = static_cast<const SfxUnoAnyItem*>(
126 pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL) );
127 if (pItem)
128 pItem->GetValue() >>= xStatusIndicator;
131 if ( SfxObjectCreateMode::EMBEDDED == pDocShell->GetCreateMode() )
132 bEmbedded = true;
135 comphelper::PropertyMapEntry aInfoMap[] =
137 { OUString("PrivateData"), 0,
138 cppu::UnoType<XInterface>::get(),
139 beans::PropertyAttribute::MAYBEVOID, 0 },
140 { OUString("BaseURI"), 0,
141 ::cppu::UnoType<OUString>::get(),
142 beans::PropertyAttribute::MAYBEVOID, 0 },
143 { OUString("StreamRelPath"), 0,
144 ::cppu::UnoType<OUString>::get(),
145 beans::PropertyAttribute::MAYBEVOID, 0 },
146 { OUString("StreamName"), 0,
147 ::cppu::UnoType<OUString>::get(),
148 beans::PropertyAttribute::MAYBEVOID, 0 },
149 { OUString(), 0, css::uno::Type(), 0, 0 }
151 uno::Reference< beans::XPropertySet > xInfoSet(
152 comphelper::GenericPropertySet_CreateInstance(
153 new comphelper::PropertySetInfo( aInfoMap ) ) );
155 // Set base URI
156 OUString const baseURI(rMedium.GetBaseURL());
157 // needed for relative URLs; but it's OK to import e.g. MathML from the
158 // clipboard without one
159 SAL_INFO_IF(baseURI.isEmpty(), "starmath", "SmXMLImportWrapper: no base URL");
160 xInfoSet->setPropertyValue("BaseURI", makeAny(baseURI));
162 sal_Int32 nSteps=3;
163 if ( !(rMedium.IsStorage()))
164 nSteps = 1;
166 sal_Int32 nProgressRange(nSteps);
167 if (xStatusIndicator.is())
169 xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange);
172 nSteps=0;
173 if (xStatusIndicator.is())
174 xStatusIndicator->setValue(nSteps++);
176 if ( rMedium.IsStorage())
178 // TODO/LATER: handle the case of embedded links gracefully
179 if ( bEmbedded ) // && !rMedium.GetStorage()->IsRoot() )
181 OUString aName( "dummyObjName" );
182 if ( rMedium.GetItemSet() )
184 const SfxStringItem* pDocHierarchItem = static_cast<const SfxStringItem*>(
185 rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME) );
186 if ( pDocHierarchItem )
187 aName = pDocHierarchItem->GetValue();
190 if ( !aName.isEmpty() )
192 xInfoSet->setPropertyValue("StreamRelPath", makeAny(aName));
196 bool bOASIS = ( SotStorage::GetVersion( rMedium.GetStorage() ) > SOFFICE_FILEFORMAT_60 );
197 if (xStatusIndicator.is())
198 xStatusIndicator->setValue(nSteps++);
200 auto nWarn = ReadThroughComponent(
201 rMedium.GetStorage(), xModelComp, "meta.xml", "Meta.xml",
202 xContext, xInfoSet,
203 (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaImporter"
204 : "com.sun.star.comp.Math.XMLMetaImporter") );
206 if ( nWarn != ERRCODE_IO_BROKENPACKAGE )
208 if (xStatusIndicator.is())
209 xStatusIndicator->setValue(nSteps++);
211 nWarn = ReadThroughComponent(
212 rMedium.GetStorage(), xModelComp, "settings.xml", nullptr,
213 xContext, xInfoSet,
214 (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsImporter"
215 : "com.sun.star.comp.Math.XMLSettingsImporter" ) );
217 if ( nWarn != ERRCODE_IO_BROKENPACKAGE )
219 if (xStatusIndicator.is())
220 xStatusIndicator->setValue(nSteps++);
222 nError = ReadThroughComponent(
223 rMedium.GetStorage(), xModelComp, "content.xml", "Content.xml",
224 xContext, xInfoSet, "com.sun.star.comp.Math.XMLImporter" );
226 else
227 nError = ERRCODE_IO_BROKENPACKAGE;
229 else
230 nError = ERRCODE_IO_BROKENPACKAGE;
232 else
234 Reference<io::XInputStream> xInputStream =
235 new utl::OInputStreamWrapper(rMedium.GetInStream());
237 if (xStatusIndicator.is())
238 xStatusIndicator->setValue(nSteps++);
240 nError = ReadThroughComponent( xInputStream, xModelComp,
241 xContext, xInfoSet, "com.sun.star.comp.Math.XMLImporter", false );
244 if (xStatusIndicator.is())
245 xStatusIndicator->end();
246 return nError;
250 /// read a component (file + filter version)
251 ErrCode SmXMLImportWrapper::ReadThroughComponent(
252 const Reference<io::XInputStream>& xInputStream,
253 const Reference<XComponent>& xModelComponent,
254 Reference<uno::XComponentContext> const & rxContext,
255 Reference<beans::XPropertySet> const & rPropSet,
256 const sal_Char* pFilterName,
257 bool bEncrypted )
259 ErrCode nError = ERRCODE_SFX_DOLOADFAILED;
260 OSL_ENSURE(xInputStream.is(), "input stream missing");
261 OSL_ENSURE(xModelComponent.is(), "document missing");
262 OSL_ENSURE(rxContext.is(), "factory missing");
263 OSL_ENSURE(nullptr != pFilterName,"I need a service name for the component!");
265 // prepare ParserInputSrouce
266 xml::sax::InputSource aParserInput;
267 aParserInput.aInputStream = xInputStream;
269 // get parser
270 Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(rxContext);
272 Sequence<Any> aArgs( 1 );
273 aArgs[0] <<= rPropSet;
275 // get filter
276 Reference< xml::sax::XDocumentHandler > xFilter(
277 rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
278 OUString::createFromAscii(pFilterName), aArgs, rxContext),
279 UNO_QUERY );
280 OSL_ENSURE( xFilter.is(), "Can't instantiate filter component." );
281 if ( !xFilter.is() )
282 return nError;
284 // connect parser and filter
285 xParser->setDocumentHandler( xFilter );
287 // connect model and filter
288 Reference < XImporter > xImporter( xFilter, UNO_QUERY );
289 xImporter->setTargetDocument( xModelComponent );
291 uno::Reference< xml::sax::XFastParser > xFastParser = dynamic_cast<
292 xml::sax::XFastParser* >( xFilter.get() );
294 // finally, parser the stream
297 if( xFastParser.is() )
298 xFastParser->parseStream( aParserInput );
299 else
300 xParser->parseStream( aParserInput );
302 uno::Reference<lang::XUnoTunnel> xFilterTunnel( xFilter, uno::UNO_QUERY );
303 SmXMLImport *pFilter = reinterpret_cast< SmXMLImport * >(
304 sal::static_int_cast< sal_uIntPtr >(
305 xFilterTunnel->getSomething( SmXMLImport::getUnoTunnelId() )));
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 sal_Char* pStreamName,
360 const sal_Char* pCompatibilityStreamName,
361 Reference<uno::XComponentContext> const & rxContext,
362 Reference<beans::XPropertySet> const & rPropSet,
363 const sal_Char* pFilterName )
365 OSL_ENSURE(xStorage.is(), "Need storage!");
366 OSL_ENSURE(nullptr != pStreamName, "Please, please, give me a name!");
368 // open stream (and set parser input)
369 OUString sStreamName = OUString::createFromAscii(pStreamName);
370 uno::Reference < container::XNameAccess > xAccess( xStorage, uno::UNO_QUERY );
371 if ( !xAccess->hasByName(sStreamName) || !xStorage->isStreamElement(sStreamName) )
373 // stream name not found! Then try the compatibility name.
374 // do we even have an alternative name?
375 if ( pCompatibilityStreamName )
376 sStreamName = OUString::createFromAscii(pCompatibilityStreamName);
379 // get input stream
382 uno::Reference < io::XStream > xEventsStream = xStorage->openStreamElement( sStreamName, embed::ElementModes::READ );
384 // determine if stream is encrypted or not
385 uno::Reference < beans::XPropertySet > xProps( xEventsStream, uno::UNO_QUERY );
386 Any aAny = xProps->getPropertyValue( "Encrypted" );
387 bool bEncrypted = false;
388 if ( aAny.getValueType() == cppu::UnoType<bool>::get() )
389 aAny >>= bEncrypted;
391 // set Base URL
392 if ( rPropSet.is() )
394 rPropSet->setPropertyValue( "StreamName", makeAny( sStreamName ) );
398 Reference < io::XInputStream > xStream = xEventsStream->getInputStream();
399 return ReadThroughComponent( xStream, xModelComponent, rxContext, rPropSet, pFilterName, bEncrypted );
401 catch ( packages::WrongPasswordException& )
403 return ERRCODE_SFX_WRONGPASSWORD;
405 catch( packages::zip::ZipIOException& )
407 return ERRCODE_IO_BROKENPACKAGE;
409 catch ( uno::Exception& )
413 return ERRCODE_SFX_DOLOADFAILED;
417 SmXMLImport::SmXMLImport(
418 const css::uno::Reference< css::uno::XComponentContext >& rContext,
419 OUString const & implementationName, SvXMLImportFlags nImportFlags)
420 : SvXMLImport(rContext, implementationName, nImportFlags),
421 bSuccess(false),
422 nParseDepth(0)
426 namespace
428 class theSmXMLImportUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSmXMLImportUnoTunnelId> {};
431 const uno::Sequence< sal_Int8 > & SmXMLImport::getUnoTunnelId() throw()
433 return theSmXMLImportUnoTunnelId::get().getSeq();
436 OUString SmXMLImport_getImplementationName() throw()
438 return OUString( "com.sun.star.comp.Math.XMLImporter" );
441 uno::Sequence< OUString > SmXMLImport_getSupportedServiceNames()
442 throw()
444 return uno::Sequence<OUString>{ IMPORT_SVC_NAME };
447 uno::Reference< uno::XInterface > SmXMLImport_createInstance(
448 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
450 return static_cast<cppu::OWeakObject*>(new SmXMLImport(comphelper::getComponentContext(rSMgr), SmXMLImport_getImplementationName(), SvXMLImportFlags::ALL));
454 OUString SmXMLImportMeta_getImplementationName() throw()
456 return OUString( "com.sun.star.comp.Math.XMLOasisMetaImporter" );
459 uno::Sequence< OUString > SmXMLImportMeta_getSupportedServiceNames()
460 throw()
462 return uno::Sequence<OUString>{ IMPORT_SVC_NAME };
465 uno::Reference< uno::XInterface > SmXMLImportMeta_createInstance(
466 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
468 return static_cast<cppu::OWeakObject*>(new SmXMLImport( comphelper::getComponentContext(rSMgr), SmXMLImportMeta_getImplementationName(), SvXMLImportFlags::META ));
472 OUString SmXMLImportSettings_getImplementationName() throw()
474 return OUString( "com.sun.star.comp.Math.XMLOasisSettingsImporter" );
477 uno::Sequence< OUString > SmXMLImportSettings_getSupportedServiceNames()
478 throw()
480 return uno::Sequence<OUString>{ IMPORT_SVC_NAME };
483 uno::Reference< uno::XInterface > SmXMLImportSettings_createInstance(
484 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
486 return static_cast<cppu::OWeakObject*>(new SmXMLImport( comphelper::getComponentContext(rSMgr), SmXMLImportSettings_getImplementationName(), SvXMLImportFlags::SETTINGS ));
489 sal_Int64 SAL_CALL SmXMLImport::getSomething(
490 const uno::Sequence< sal_Int8 >&rId )
492 if ( rId.getLength() == 16 &&
493 0 == memcmp( getUnoTunnelId().getConstArray(),
494 rId.getConstArray(), 16 ) )
495 return sal::static_int_cast< sal_Int64 >(reinterpret_cast< sal_uIntPtr >(this));
497 return SvXMLImport::getSomething( rId );
500 void SmXMLImport::endDocument()
502 //Set the resulted tree into the SmDocShell where it belongs
503 SmNode *pTree = popOrZero(aNodeStack);
504 if (pTree && pTree->GetType() == SmNodeType::Table)
506 uno::Reference <frame::XModel> xModel = GetModel();
507 uno::Reference <lang::XUnoTunnel> xTunnel(xModel,uno::UNO_QUERY);
508 SmModel *pModel = reinterpret_cast<SmModel *>
509 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
511 if (pModel)
513 SmDocShell *pDocShell =
514 static_cast<SmDocShell*>(pModel->GetObjectShell());
515 pDocShell->SetFormulaTree(static_cast<SmTableNode *>(pTree));
516 if (aText.isEmpty()) //If we picked up no annotation text
518 OUStringBuffer aStrBuf;
519 // Get text from imported formula
520 pTree->CreateTextFromNode(aStrBuf);
521 aStrBuf.stripEnd(' ');
522 aText = aStrBuf.makeStringAndClear();
525 // Convert symbol names
526 SmParser &rParser = pDocShell->GetParser();
527 bool bVal = rParser.IsImportSymbolNames();
528 rParser.SetImportSymbolNames( true );
529 auto pTmpTree = rParser.Parse( aText );
530 aText = rParser.GetText();
531 pTmpTree.reset();
532 rParser.SetImportSymbolNames( bVal );
534 pDocShell->SetText( aText );
536 OSL_ENSURE(pModel,"So there *was* a uno problem after all");
538 bSuccess = true;
541 SvXMLImport::endDocument();
545 class SmXMLImportContext: public SvXMLImportContext
547 public:
548 SmXMLImportContext( SmXMLImport &rImport, sal_uInt16 nPrfx,
549 const OUString& rLName)
550 : SvXMLImportContext(rImport, nPrfx, rLName)
552 GetSmImport().IncParseDepth();
555 virtual ~SmXMLImportContext() override
557 GetSmImport().DecParseDepth();
560 SmXMLImport& GetSmImport()
562 return static_cast<SmXMLImport&>(GetImport());
565 virtual void TCharacters(const OUString & /*rChars*/);
566 virtual void Characters(const OUString &rChars) override;
567 virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 /*nPrefix*/, const OUString& /*rLocalName*/, const uno::Reference< xml::sax::XAttributeList > & /*xAttrList*/) override;
568 virtual void StartElement(const css::uno::Reference<css::xml::sax::XAttributeList>& rAttrList) override
570 if (GetSmImport().TooDeep())
571 throw std::range_error("too deep");
572 SvXMLImportContext::StartElement(rAttrList);
576 void SmXMLImportContext::TCharacters(const OUString & /*rChars*/)
580 void SmXMLImportContext::Characters(const OUString &rChars)
583 Whitespace occurring within the content of token elements is "trimmed"
584 from the ends (i.e. all whitespace at the beginning and end of the
585 content is removed), and "collapsed" internally (i.e. each sequence of
586 1 or more whitespace characters is replaced with one blank character).
588 //collapsing not done yet!
589 const OUString &rChars2 = rChars.trim();
590 if (!rChars2.isEmpty())
591 TCharacters(rChars2/*.collapse()*/);
594 SvXMLImportContextRef SmXMLImportContext::CreateChildContext(sal_uInt16 /*nPrefix*/,
595 const OUString& /*rLocalName*/,
596 const uno::Reference< xml::sax::XAttributeList > & /*xAttrList*/)
598 return nullptr;
602 struct SmXMLContext_Helper
604 sal_Int8 nIsBold;
605 sal_Int8 nIsItalic;
606 double nFontSize;
607 OUString sFontFamily;
608 OUString sColor;
610 SmXMLImportContext & rContext;
612 explicit SmXMLContext_Helper(SmXMLImportContext &rImport)
613 : nIsBold( -1 )
614 , nIsItalic( -1 )
615 , nFontSize( 0.0 )
616 , rContext( rImport )
619 bool IsFontNodeNeeded() const;
620 void RetrieveAttrs(const uno::Reference< xml::sax::XAttributeList > &xAttrList );
621 void ApplyAttrs();
624 bool SmXMLContext_Helper::IsFontNodeNeeded() const
626 return nIsBold != -1 ||
627 nIsItalic != -1 ||
628 nFontSize != 0.0 ||
629 !sFontFamily.isEmpty() ||
630 !sColor.isEmpty();
633 void SmXMLContext_Helper::RetrieveAttrs(const uno::Reference<
634 xml::sax::XAttributeList > & xAttrList )
636 bool bMvFound = false;
637 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
638 for (sal_Int16 i=0;i<nAttrCount;i++)
640 OUString sAttrName = xAttrList->getNameByIndex(i);
641 OUString aLocalName;
642 sal_uInt16 nPrefix = rContext.GetSmImport().GetNamespaceMap().
643 GetKeyByAttrName(sAttrName,&aLocalName);
644 OUString sValue = xAttrList->getValueByIndex(i);
645 const SvXMLTokenMap &rAttrTokenMap =
646 rContext.GetSmImport().GetPresLayoutAttrTokenMap();
647 switch(rAttrTokenMap.Get(nPrefix,aLocalName))
649 case XML_TOK_FONTWEIGHT:
650 nIsBold = sal_Int8(sValue == GetXMLToken(XML_BOLD));
651 break;
652 case XML_TOK_FONTSTYLE:
653 nIsItalic = sal_Int8(sValue == GetXMLToken(XML_ITALIC));
654 break;
655 case XML_TOK_FONTSIZE:
656 ::sax::Converter::convertDouble(nFontSize, sValue);
657 rContext.GetSmImport().GetMM100UnitConverter().
658 SetXMLMeasureUnit(util::MeasureUnit::POINT);
659 if (-1 == sValue.indexOf(GetXMLToken(XML_UNIT_PT)))
661 if (-1 == sValue.indexOf('%'))
662 nFontSize=0.0;
663 else
665 rContext.GetSmImport().GetMM100UnitConverter().
666 SetXMLMeasureUnit(util::MeasureUnit::PERCENT);
669 break;
670 case XML_TOK_FONTFAMILY:
671 sFontFamily = sValue;
672 break;
673 case XML_TOK_COLOR:
674 sColor = sValue;
675 break;
676 case XML_TOK_MATHCOLOR:
677 sColor = sValue;
678 break;
679 case XML_TOK_MATHVARIANT:
680 bMvFound = true;
681 break;
682 default:
683 break;
687 if (bMvFound)
689 // Ignore deprecated attributes fontfamily, fontweight, and fontstyle
690 // in favor of mathvariant, as specified in
691 // <https://www.w3.org/TR/MathML3/chapter3.html#presm.deprecatt>.
692 sFontFamily.clear();
693 nIsBold = -1;
694 nIsItalic = -1;
698 void SmXMLContext_Helper::ApplyAttrs()
700 SmNodeStack &rNodeStack = rContext.GetSmImport().GetNodeStack();
702 if (IsFontNodeNeeded())
704 SmToken aToken;
705 aToken.cMathChar = '\0';
706 aToken.nLevel = 5;
708 if (nIsBold != -1)
710 if (nIsBold)
711 aToken.eType = TBOLD;
712 else
713 aToken.eType = TNBOLD;
714 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
715 pFontNode->SetSubNodes(nullptr,popOrZero(rNodeStack));
716 rNodeStack.push_front(std::move(pFontNode));
718 if (nIsItalic != -1)
720 if (nIsItalic)
721 aToken.eType = TITALIC;
722 else
723 aToken.eType = TNITALIC;
724 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
725 pFontNode->SetSubNodes(nullptr,popOrZero(rNodeStack));
726 rNodeStack.push_front(std::move(pFontNode));
728 if (nFontSize != 0.0)
730 aToken.eType = TSIZE;
731 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
733 if (util::MeasureUnit::PERCENT == rContext.GetSmImport()
734 .GetMM100UnitConverter().GetXMLMeasureUnit())
736 if (nFontSize < 100.00)
737 pFontNode->SetSizeParameter(Fraction(100.00/nFontSize),
738 FontSizeType::DIVIDE);
739 else
740 pFontNode->SetSizeParameter(Fraction(nFontSize/100.00),
741 FontSizeType::MULTIPLY);
743 else
744 pFontNode->SetSizeParameter(Fraction(nFontSize),FontSizeType::ABSOLUT);
746 pFontNode->SetSubNodes(nullptr,popOrZero(rNodeStack));
747 rNodeStack.push_front(std::move(pFontNode));
749 if (!sFontFamily.isEmpty())
751 if (sFontFamily.equalsIgnoreAsciiCase(GetXMLToken(XML_FIXED)))
752 aToken.eType = TFIXED;
753 else if (sFontFamily.equalsIgnoreAsciiCase("sans"))
754 aToken.eType = TSANS;
755 else if (sFontFamily.equalsIgnoreAsciiCase("serif"))
756 aToken.eType = TSERIF;
757 else //Just give up, we need to extend our font mechanism to be
758 //more general
759 return;
761 aToken.aText = sFontFamily;
762 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
763 pFontNode->SetSubNodes(nullptr,popOrZero(rNodeStack));
764 rNodeStack.push_front(std::move(pFontNode));
766 if (!sColor.isEmpty())
768 //Again we can only handle a small set of colours in
769 //StarMath for now.
770 const SvXMLTokenMap& rTokenMap =
771 rContext.GetSmImport().GetColorTokenMap();
772 sal_uInt16 tok = rTokenMap.Get(XML_NAMESPACE_MATH, sColor);
773 if (tok != XML_TOK_UNKNOWN)
775 aToken.eType = static_cast<SmTokenType>(tok);
776 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
777 pFontNode->SetSubNodes(nullptr,popOrZero(rNodeStack));
778 rNodeStack.push_front(std::move(pFontNode));
786 class SmXMLTokenAttrHelper
788 SmXMLImportContext& mrContext;
789 MathMLMathvariantValue meMv;
790 bool mbMvFound;
792 public:
793 SmXMLTokenAttrHelper(SmXMLImportContext& rContext)
794 : mrContext(rContext)
795 , meMv(MathMLMathvariantValue::Normal)
796 , mbMvFound(false)
799 void RetrieveAttrs(const uno::Reference<xml::sax::XAttributeList>& xAttrList);
800 void ApplyAttrs(MathMLMathvariantValue eDefaultMv);
803 void SmXMLTokenAttrHelper::RetrieveAttrs(const uno::Reference<xml::sax::XAttributeList>& xAttrList)
805 if (!xAttrList.is())
806 return;
807 sal_Int16 nAttrCount = xAttrList->getLength();
808 for (sal_Int16 i=0;i<nAttrCount;i++)
810 OUString sAttrName = xAttrList->getNameByIndex(i);
811 OUString aLocalName;
812 sal_uInt16 nPrefix = mrContext.GetSmImport().GetNamespaceMap().
813 GetKeyByAttrName(sAttrName, &aLocalName);
814 OUString sValue = xAttrList->getValueByIndex(i);
815 const SvXMLTokenMap &rAttrTokenMap =
816 mrContext.GetSmImport().GetPresLayoutAttrTokenMap();
817 switch(rAttrTokenMap.Get(nPrefix, aLocalName))
819 case XML_TOK_MATHVARIANT:
820 if (!GetMathMLMathvariantValue(sValue, meMv))
821 SAL_WARN("starmath", "failed to recognize mathvariant: " << sValue);
822 mbMvFound = true;
823 break;
824 default:
825 break;
830 void SmXMLTokenAttrHelper::ApplyAttrs(MathMLMathvariantValue eDefaultMv)
832 assert( eDefaultMv == MathMLMathvariantValue::Normal ||
833 eDefaultMv == MathMLMathvariantValue::Italic );
835 std::vector<SmTokenType> vVariant;
836 MathMLMathvariantValue eMv = mbMvFound ? meMv : eDefaultMv;
837 switch(eMv)
839 case MathMLMathvariantValue::Normal:
840 vVariant.push_back(TNITALIC);
841 break;
842 case MathMLMathvariantValue::Bold:
843 vVariant.push_back(TBOLD);
844 break;
845 case MathMLMathvariantValue::Italic:
846 // nothing to do
847 break;
848 case MathMLMathvariantValue::BoldItalic:
849 vVariant.push_back(TITALIC);
850 vVariant.push_back(TBOLD);
851 break;
852 case MathMLMathvariantValue::DoubleStruck:
853 // TODO
854 break;
855 case MathMLMathvariantValue::BoldFraktur:
856 // TODO: Fraktur
857 vVariant.push_back(TBOLD);
858 break;
859 case MathMLMathvariantValue::Script:
860 // TODO
861 break;
862 case MathMLMathvariantValue::BoldScript:
863 // TODO: Script
864 vVariant.push_back(TBOLD);
865 break;
866 case MathMLMathvariantValue::Fraktur:
867 // TODO
868 break;
869 case MathMLMathvariantValue::SansSerif:
870 vVariant.push_back(TSANS);
871 break;
872 case MathMLMathvariantValue::BoldSansSerif:
873 vVariant.push_back(TSANS);
874 vVariant.push_back(TBOLD);
875 break;
876 case MathMLMathvariantValue::SansSerifItalic:
877 vVariant.push_back(TITALIC);
878 vVariant.push_back(TSANS);
879 break;
880 case MathMLMathvariantValue::SansSerifBoldItalic:
881 vVariant.push_back(TITALIC);
882 vVariant.push_back(TBOLD);
883 vVariant.push_back(TSANS);
884 break;
885 case MathMLMathvariantValue::Monospace:
886 vVariant.push_back(TFIXED);
887 break;
888 case MathMLMathvariantValue::Initial:
889 case MathMLMathvariantValue::Tailed:
890 case MathMLMathvariantValue::Looped:
891 case MathMLMathvariantValue::Stretched:
892 // TODO
893 break;
895 if (vVariant.empty())
896 return;
897 SmNodeStack &rNodeStack = mrContext.GetSmImport().GetNodeStack();
898 for (auto eType : vVariant)
900 SmToken aToken;
901 aToken.eType = eType;
902 aToken.cMathChar = '\0';
903 aToken.nLevel = 5;
904 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
905 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
906 rNodeStack.push_front(std::move(pFontNode));
911 class SmXMLDocContext_Impl : public SmXMLImportContext
913 public:
914 SmXMLDocContext_Impl( SmXMLImport &rImport, sal_uInt16 nPrfx,
915 const OUString& rLName)
916 : SmXMLImportContext(rImport,nPrfx,rLName) {}
918 virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &xAttrList) override;
920 void EndElement() override;
924 /*avert thy gaze from the proginator*/
925 class SmXMLRowContext_Impl : public SmXMLDocContext_Impl
927 protected:
928 size_t nElementCount;
930 public:
931 SmXMLRowContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
932 const OUString& rLName)
933 : SmXMLDocContext_Impl(rImport,nPrefix,rLName)
934 , nElementCount(GetSmImport().GetNodeStack().size())
938 virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &xAttrList) override;
940 SvXMLImportContext *StrictCreateChildContext(sal_uInt16 nPrefix,
941 const OUString& rLocalName);
943 void EndElement() override;
946 class SmXMLEncloseContext_Impl : public SmXMLRowContext_Impl
948 public:
949 // TODO/LATER: convert <menclose notation="horizontalstrike"> into
950 // "overstrike{}" and extend the Math syntax to support more notations
951 SmXMLEncloseContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
952 const OUString& rLName)
953 : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
955 void EndElement() override;
958 void SmXMLEncloseContext_Impl::EndElement()
961 <menclose> accepts any number of arguments; if this number is not 1, its
962 contents are treated as a single "inferred <mrow>" containing its
963 arguments
965 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
966 SmXMLRowContext_Impl::EndElement();
970 class SmXMLFracContext_Impl : public SmXMLRowContext_Impl
972 public:
973 // TODO/LATER: convert <mfrac bevelled="true"> into "wideslash{}{}"
974 SmXMLFracContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
975 const OUString& rLName)
976 : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
978 void EndElement() override;
982 class SmXMLSqrtContext_Impl : public SmXMLRowContext_Impl
984 public:
985 SmXMLSqrtContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
986 const OUString& rLName)
987 : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
989 void EndElement() override;
993 class SmXMLRootContext_Impl : public SmXMLRowContext_Impl
995 public:
996 SmXMLRootContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
997 const OUString& rLName)
998 : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1000 void EndElement() override;
1004 class SmXMLStyleContext_Impl : public SmXMLRowContext_Impl
1006 protected:
1007 SmXMLContext_Helper aStyleHelper;
1009 public:
1010 /*Right now the style tag is completely ignored*/
1011 SmXMLStyleContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1012 const OUString& rLName) : SmXMLRowContext_Impl(rImport,nPrefix,rLName),
1013 aStyleHelper(*this) {}
1015 void EndElement() override;
1016 void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList ) override;
1019 void SmXMLStyleContext_Impl::StartElement(const uno::Reference<
1020 xml::sax::XAttributeList > & xAttrList )
1022 aStyleHelper.RetrieveAttrs(xAttrList);
1026 void SmXMLStyleContext_Impl::EndElement()
1029 <mstyle> accepts any number of arguments; if this number is not 1, its
1030 contents are treated as a single "inferred <mrow>" containing its
1031 arguments
1033 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1034 if (rNodeStack.size() - nElementCount != 1)
1035 SmXMLRowContext_Impl::EndElement();
1036 aStyleHelper.ApplyAttrs();
1040 class SmXMLPaddedContext_Impl : public SmXMLRowContext_Impl
1042 public:
1043 /*Right now the style tag is completely ignored*/
1044 SmXMLPaddedContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1045 const OUString& rLName)
1046 : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1048 void EndElement() override;
1051 void SmXMLPaddedContext_Impl::EndElement()
1054 <mpadded> accepts any number of arguments; if this number is not 1, its
1055 contents are treated as a single "inferred <mrow>" containing its
1056 arguments
1058 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
1059 SmXMLRowContext_Impl::EndElement();
1063 class SmXMLPhantomContext_Impl : public SmXMLRowContext_Impl
1065 public:
1066 /*Right now the style tag is completely ignored*/
1067 SmXMLPhantomContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1068 const OUString& rLName)
1069 : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1071 void EndElement() override;
1074 void SmXMLPhantomContext_Impl::EndElement()
1077 <mphantom> accepts any number of arguments; if this number is not 1, its
1078 contents are treated as a single "inferred <mrow>" containing its
1079 arguments
1081 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
1082 SmXMLRowContext_Impl::EndElement();
1084 SmToken aToken;
1085 aToken.cMathChar = '\0';
1086 aToken.nLevel = 5;
1087 aToken.eType = TPHANTOM;
1089 std::unique_ptr<SmFontNode> pPhantom(new SmFontNode(aToken));
1090 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1091 pPhantom->SetSubNodes(nullptr,popOrZero(rNodeStack));
1092 rNodeStack.push_front(std::move(pPhantom));
1096 class SmXMLFencedContext_Impl : public SmXMLRowContext_Impl
1098 protected:
1099 sal_Unicode cBegin;
1100 sal_Unicode cEnd;
1102 public:
1103 SmXMLFencedContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1104 const OUString& rLName)
1105 : SmXMLRowContext_Impl(rImport,nPrefix,rLName),
1106 cBegin('('), cEnd(')') {}
1108 void StartElement(const uno::Reference< xml::sax::XAttributeList > & xAttrList ) override;
1109 void EndElement() override;
1113 void SmXMLFencedContext_Impl::StartElement(const uno::Reference<
1114 xml::sax::XAttributeList > & xAttrList )
1116 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1117 for (sal_Int16 i=0;i<nAttrCount;i++)
1119 OUString sAttrName = xAttrList->getNameByIndex(i);
1120 OUString aLocalName;
1121 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
1122 GetKeyByAttrName(sAttrName,&aLocalName);
1123 OUString sValue = xAttrList->getValueByIndex(i);
1124 const SvXMLTokenMap &rAttrTokenMap =
1125 GetSmImport().GetFencedAttrTokenMap();
1126 switch(rAttrTokenMap.Get(nPrefix,aLocalName))
1128 //temp, starmath cannot handle multichar brackets (I think)
1129 case XML_TOK_OPEN:
1130 cBegin = sValue[0];
1131 break;
1132 case XML_TOK_CLOSE:
1133 cEnd = sValue[0];
1134 break;
1135 default:
1136 /*Go to superclass*/
1137 break;
1143 void SmXMLFencedContext_Impl::EndElement()
1145 SmToken aToken;
1146 aToken.cMathChar = '\0';
1147 aToken.aText = ",";
1148 aToken.nLevel = 5;
1150 aToken.eType = TLPARENT;
1151 aToken.cMathChar = cBegin;
1152 std::unique_ptr<SmStructureNode> pSNode(new SmBraceNode(aToken));
1153 SmNode *pLeft = new SmMathSymbolNode(aToken);
1155 aToken.cMathChar = cEnd;
1156 aToken.eType = TRPARENT;
1157 SmNode *pRight = new SmMathSymbolNode(aToken);
1159 SmNodeArray aRelationArray;
1160 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1162 aToken.cMathChar = '\0';
1163 aToken.aText = ",";
1164 aToken.eType = TIDENT;
1166 auto i = rNodeStack.size() - nElementCount;
1167 if (rNodeStack.size() - nElementCount > 1)
1168 i += rNodeStack.size() - 1 - nElementCount;
1169 aRelationArray.resize(i);
1170 while (rNodeStack.size() > nElementCount)
1172 auto pNode = std::move(rNodeStack.front());
1173 rNodeStack.pop_front();
1174 aRelationArray[--i] = pNode.release();
1175 if (i > 1 && rNodeStack.size() > 1)
1176 aRelationArray[--i] = new SmGlyphSpecialNode(aToken);
1179 SmToken aDummy;
1180 SmStructureNode *pBody = new SmExpressionNode(aDummy);
1181 pBody->SetSubNodes(std::move(aRelationArray));
1184 pSNode->SetSubNodes(pLeft,pBody,pRight);
1185 pSNode->SetScaleMode(SmScaleMode::Height);
1186 GetSmImport().GetNodeStack().push_front(std::move(pSNode));
1190 class SmXMLErrorContext_Impl : public SmXMLRowContext_Impl
1192 public:
1193 SmXMLErrorContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1194 const OUString& rLName)
1195 : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1197 void EndElement() override;
1200 void SmXMLErrorContext_Impl::EndElement()
1202 /*Right now the error tag is completely ignored, what
1203 can I do with it in starmath, ?, maybe we need a
1204 report window ourselves, do a test for validity of
1205 the xml input, use mirrors, and then generate
1206 the markup inside the merror with a big red colour
1207 of something. For now just throw them all away.
1209 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1210 while (rNodeStack.size() > nElementCount)
1212 rNodeStack.pop_front();
1217 class SmXMLNumberContext_Impl : public SmXMLImportContext
1219 protected:
1220 SmToken aToken;
1222 public:
1223 SmXMLNumberContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1224 const OUString& rLName)
1225 : SmXMLImportContext(rImport,nPrefix,rLName)
1227 aToken.cMathChar = '\0';
1228 aToken.nLevel = 5;
1229 aToken.eType = TNUMBER;
1232 virtual void TCharacters(const OUString &rChars) override;
1234 void EndElement() override;
1237 void SmXMLNumberContext_Impl::TCharacters(const OUString &rChars)
1239 aToken.aText = rChars;
1242 void SmXMLNumberContext_Impl::EndElement()
1244 GetSmImport().GetNodeStack().push_front(o3tl::make_unique<SmTextNode>(aToken,FNT_NUMBER));
1248 class SmXMLAnnotationContext_Impl : public SmXMLImportContext
1250 bool bIsStarMath;
1252 public:
1253 SmXMLAnnotationContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1254 const OUString& rLName)
1255 : SmXMLImportContext(rImport,nPrefix,rLName), bIsStarMath(false) {}
1257 virtual void Characters(const OUString &rChars) override;
1259 void StartElement(const uno::Reference<xml::sax::XAttributeList > & xAttrList ) override;
1262 void SmXMLAnnotationContext_Impl::StartElement(const uno::Reference<
1263 xml::sax::XAttributeList > & xAttrList )
1265 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1266 for (sal_Int16 i=0;i<nAttrCount;i++)
1268 OUString sAttrName = xAttrList->getNameByIndex(i);
1269 OUString aLocalName;
1270 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
1271 GetKeyByAttrName(sAttrName,&aLocalName);
1273 OUString sValue = xAttrList->getValueByIndex(i);
1274 const SvXMLTokenMap &rAttrTokenMap =
1275 GetSmImport().GetAnnotationAttrTokenMap();
1276 switch(rAttrTokenMap.Get(nPrefix,aLocalName))
1278 case XML_TOK_ENCODING:
1279 bIsStarMath= sValue == "StarMath 5.0";
1280 break;
1281 default:
1282 break;
1287 void SmXMLAnnotationContext_Impl::Characters(const OUString &rChars)
1289 if (bIsStarMath)
1290 GetSmImport().SetText( GetSmImport().GetText() + rChars );
1294 class SmXMLTextContext_Impl : public SmXMLImportContext
1296 protected:
1297 SmToken aToken;
1299 public:
1300 SmXMLTextContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1301 const OUString& rLName)
1302 : SmXMLImportContext(rImport,nPrefix,rLName)
1304 aToken.cMathChar = '\0';
1305 aToken.nLevel = 5;
1306 aToken.eType = TTEXT;
1309 virtual void TCharacters(const OUString &rChars) override;
1311 void EndElement() override;
1314 void SmXMLTextContext_Impl::TCharacters(const OUString &rChars)
1316 aToken.aText = rChars;
1319 void SmXMLTextContext_Impl::EndElement()
1321 GetSmImport().GetNodeStack().push_front(o3tl::make_unique<SmTextNode>(aToken,FNT_TEXT));
1325 class SmXMLStringContext_Impl : public SmXMLImportContext
1327 protected:
1328 SmToken aToken;
1330 public:
1331 SmXMLStringContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1332 const OUString& rLName)
1333 : SmXMLImportContext(rImport,nPrefix,rLName)
1335 aToken.cMathChar = '\0';
1336 aToken.nLevel = 5;
1337 aToken.eType = TTEXT;
1340 virtual void TCharacters(const OUString &rChars) override;
1342 void EndElement() override;
1345 void SmXMLStringContext_Impl::TCharacters(const OUString &rChars)
1348 The content of <ms> elements should be rendered with visible "escaping" of
1349 certain characters in the content, including at least "double quote"
1350 itself, and preferably whitespace other than individual blanks. The intent
1351 is for the viewer to see that the expression is a string literal, and to
1352 see exactly which characters form its content. For example, <ms>double
1353 quote is "</ms> might be rendered as "double quote is \"".
1355 Obviously this isn't fully done here.
1357 aToken.aText = "\"" + rChars + "\"";
1360 void SmXMLStringContext_Impl::EndElement()
1362 GetSmImport().GetNodeStack().push_front(o3tl::make_unique<SmTextNode>(aToken,FNT_FIXED));
1366 class SmXMLIdentifierContext_Impl : public SmXMLImportContext
1368 SmXMLTokenAttrHelper maTokenAttrHelper;
1369 SmXMLContext_Helper aStyleHelper;
1370 SmToken aToken;
1372 public:
1373 SmXMLIdentifierContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1374 const OUString& rLName)
1375 : SmXMLImportContext(rImport,nPrefix,rLName)
1376 , maTokenAttrHelper(*this)
1377 , aStyleHelper(*this)
1379 aToken.cMathChar = '\0';
1380 aToken.nLevel = 5;
1381 aToken.eType = TIDENT;
1384 void TCharacters(const OUString &rChars) override;
1385 void StartElement(const uno::Reference< xml::sax::XAttributeList > & xAttrList ) override
1387 maTokenAttrHelper.RetrieveAttrs(xAttrList);
1388 aStyleHelper.RetrieveAttrs(xAttrList);
1390 void EndElement() override;
1393 void SmXMLIdentifierContext_Impl::EndElement()
1395 std::unique_ptr<SmTextNode> pNode;
1396 //we will handle identifier italic/normal here instead of with a standalone
1397 //font node
1398 if (((aStyleHelper.nIsItalic == -1) && (aToken.aText.getLength() > 1))
1399 || ((aStyleHelper.nIsItalic == 0) && (aToken.aText.getLength() == 1)))
1401 pNode.reset(new SmTextNode(aToken,FNT_FUNCTION));
1402 pNode->GetFont().SetItalic(ITALIC_NONE);
1403 aStyleHelper.nIsItalic = -1;
1405 else
1406 pNode.reset(new SmTextNode(aToken,FNT_VARIABLE));
1407 if (aStyleHelper.nIsItalic != -1)
1409 if (aStyleHelper.nIsItalic)
1410 pNode->GetFont().SetItalic(ITALIC_NORMAL);
1411 else
1412 pNode->GetFont().SetItalic(ITALIC_NONE);
1413 aStyleHelper.nIsItalic = -1;
1415 GetSmImport().GetNodeStack().push_front(std::move(pNode));
1416 aStyleHelper.ApplyAttrs();
1418 maTokenAttrHelper.ApplyAttrs( (aToken.aText.getLength() == 1)
1419 ? MathMLMathvariantValue::Italic
1420 : MathMLMathvariantValue::Normal );
1423 void SmXMLIdentifierContext_Impl::TCharacters(const OUString &rChars)
1425 aToken.aText = rChars;
1429 class SmXMLOperatorContext_Impl : public SmXMLImportContext
1431 SmXMLTokenAttrHelper maTokenAttrHelper;
1432 bool bIsStretchy;
1433 SmToken aToken;
1435 public:
1436 SmXMLOperatorContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1437 const OUString& rLName)
1438 : SmXMLImportContext(rImport,nPrefix,rLName)
1439 , maTokenAttrHelper(*this)
1440 , bIsStretchy(false)
1442 aToken.eType = TSPECIAL;
1443 aToken.nLevel = 5;
1446 void TCharacters(const OUString &rChars) override;
1447 void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList ) override;
1448 void EndElement() override;
1451 void SmXMLOperatorContext_Impl::TCharacters(const OUString &rChars)
1453 aToken.cMathChar = rChars[0];
1456 void SmXMLOperatorContext_Impl::EndElement()
1458 std::unique_ptr<SmMathSymbolNode> pNode(new SmMathSymbolNode(aToken));
1459 //For stretchy scaling the scaling must be retrieved from this node
1460 //and applied to the expression itself so as to get the expression
1461 //to scale the operator to the height of the expression itself
1462 if (bIsStretchy)
1463 pNode->SetScaleMode(SmScaleMode::Height);
1464 GetSmImport().GetNodeStack().push_front(std::move(pNode));
1466 // TODO: apply to non-alphabetic characters too
1467 if (rtl::isAsciiAlpha(aToken.cMathChar))
1468 maTokenAttrHelper.ApplyAttrs(MathMLMathvariantValue::Normal);
1472 void SmXMLOperatorContext_Impl::StartElement(const uno::Reference<
1473 xml::sax::XAttributeList > & xAttrList )
1475 maTokenAttrHelper.RetrieveAttrs(xAttrList);
1477 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1478 for (sal_Int16 i=0;i<nAttrCount;i++)
1480 OUString sAttrName = xAttrList->getNameByIndex(i);
1481 OUString aLocalName;
1482 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
1483 GetKeyByAttrName(sAttrName,&aLocalName);
1485 OUString sValue = xAttrList->getValueByIndex(i);
1486 const SvXMLTokenMap &rAttrTokenMap =
1487 GetSmImport().GetOperatorAttrTokenMap();
1488 switch(rAttrTokenMap.Get(nPrefix,aLocalName))
1490 case XML_TOK_STRETCHY:
1491 bIsStretchy = sValue == GetXMLToken(XML_TRUE);
1492 break;
1493 default:
1494 break;
1500 class SmXMLSpaceContext_Impl : public SmXMLImportContext
1502 public:
1503 SmXMLSpaceContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1504 const OUString& rLName)
1505 : SmXMLImportContext(rImport,nPrefix,rLName) {}
1507 void StartElement(const uno::Reference< xml::sax::XAttributeList >& xAttrList ) override;
1510 namespace {
1512 bool lcl_CountBlanks(const MathMLAttributeLengthValue &rLV,
1513 sal_Int32 *pWide, sal_Int32 *pNarrow)
1515 assert(pWide);
1516 assert(pNarrow);
1517 if (rLV.aNumber.GetNumerator() == 0)
1519 *pWide = *pNarrow = 0;
1520 return true;
1522 // TODO: honor other units than em
1523 if (rLV.eUnit != MathMLLengthUnit::Em)
1524 return false;
1525 if (rLV.aNumber.GetNumerator() < 0)
1526 return false;
1527 const Fraction aTwo(2, 1);
1528 auto aWide = rLV.aNumber / aTwo;
1529 auto nWide = static_cast<sal_Int32>(static_cast<long>(aWide));
1530 if (nWide < 0)
1531 return false;
1532 const Fraction aPointFive(1, 2);
1533 auto aNarrow = (rLV.aNumber - Fraction(nWide, 1) * aTwo) / aPointFive;
1534 auto nNarrow = static_cast<sal_Int32>(static_cast<long>(aNarrow));
1535 if (nNarrow < 0)
1536 return false;
1537 *pWide = nWide;
1538 *pNarrow = nNarrow;
1539 return true;
1544 void SmXMLSpaceContext_Impl::StartElement(
1545 const uno::Reference<xml::sax::XAttributeList > & xAttrList )
1547 // There is no syntax in Math to specify blank nodes of arbitrary size yet.
1548 MathMLAttributeLengthValue aLV;
1549 sal_Int32 nWide = 0, nNarrow = 0;
1551 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1552 for (sal_Int16 i=0;i<nAttrCount;i++)
1554 OUString sAttrName = xAttrList->getNameByIndex(i);
1555 OUString aLocalName;
1556 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
1557 OUString sValue = xAttrList->getValueByIndex(i);
1558 const SvXMLTokenMap &rAttrTokenMap = GetSmImport().GetMspaceAttrTokenMap();
1559 switch (rAttrTokenMap.Get(nPrefix, aLocalName))
1561 case XML_TOK_WIDTH:
1562 if ( ParseMathMLAttributeLengthValue(sValue.trim(), aLV) <= 0 ||
1563 !lcl_CountBlanks(aLV, &nWide, &nNarrow) )
1564 SAL_WARN("starmath", "ignore mspace's width: " << sValue);
1565 break;
1566 default:
1567 break;
1570 SmToken aToken;
1571 aToken.eType = TBLANK;
1572 aToken.cMathChar = '\0';
1573 aToken.nGroup = TG::Blank;
1574 aToken.nLevel = 5;
1575 std::unique_ptr<SmBlankNode> pBlank(new SmBlankNode(aToken));
1576 if (nWide > 0)
1577 pBlank->IncreaseBy(aToken, nWide);
1578 if (nNarrow > 0)
1580 aToken.eType = TSBLANK;
1581 pBlank->IncreaseBy(aToken, nNarrow);
1583 GetSmImport().GetNodeStack().push_front(std::move(pBlank));
1587 class SmXMLSubContext_Impl : public SmXMLRowContext_Impl
1589 protected:
1590 void GenericEndElement(SmTokenType eType,SmSubSup aSubSup);
1592 public:
1593 SmXMLSubContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1594 const OUString& rLName)
1595 : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1597 void EndElement() override
1599 GenericEndElement(TRSUB,RSUB);
1604 void SmXMLSubContext_Impl::GenericEndElement(SmTokenType eType, SmSubSup eSubSup)
1606 /*The <msub> element requires exactly 2 arguments.*/
1607 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
1608 OSL_ENSURE( bNodeCheck, "Sub has not two arguments" );
1609 if (!bNodeCheck)
1610 return;
1612 SmToken aToken;
1613 aToken.cMathChar = '\0';
1614 aToken.eType = eType;
1615 std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
1616 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1618 // initialize subnodes array
1619 SmNodeArray aSubNodes;
1620 aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
1621 for (size_t i = 1; i < aSubNodes.size(); i++)
1622 aSubNodes[i] = nullptr;
1624 aSubNodes[eSubSup+1] = popOrZero(rNodeStack);
1625 aSubNodes[0] = popOrZero(rNodeStack);
1626 pNode->SetSubNodes(std::move(aSubNodes));
1627 rNodeStack.push_front(std::move(pNode));
1631 class SmXMLSupContext_Impl : public SmXMLSubContext_Impl
1633 public:
1634 SmXMLSupContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1635 const OUString& rLName)
1636 : SmXMLSubContext_Impl(rImport,nPrefix,rLName) {}
1638 void EndElement() override
1640 GenericEndElement(TRSUP,RSUP);
1645 class SmXMLSubSupContext_Impl : public SmXMLRowContext_Impl
1647 protected:
1648 void GenericEndElement(SmTokenType eType, SmSubSup aSub,SmSubSup aSup);
1650 public:
1651 SmXMLSubSupContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1652 const OUString& rLName)
1653 : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1655 void EndElement() override
1657 GenericEndElement(TRSUB,RSUB,RSUP);
1661 void SmXMLSubSupContext_Impl::GenericEndElement(SmTokenType eType,
1662 SmSubSup aSub,SmSubSup aSup)
1664 /*The <msub> element requires exactly 3 arguments.*/
1665 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 3;
1666 OSL_ENSURE( bNodeCheck, "SubSup has not three arguments" );
1667 if (!bNodeCheck)
1668 return;
1670 SmToken aToken;
1671 aToken.cMathChar = '\0';
1672 aToken.eType = eType;
1673 std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
1674 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1676 // initialize subnodes array
1677 SmNodeArray aSubNodes;
1678 aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
1679 for (size_t i = 1; i < aSubNodes.size(); i++)
1680 aSubNodes[i] = nullptr;
1682 aSubNodes[aSup+1] = popOrZero(rNodeStack);
1683 aSubNodes[aSub+1] = popOrZero(rNodeStack);
1684 aSubNodes[0] = popOrZero(rNodeStack);
1685 pNode->SetSubNodes(std::move(aSubNodes));
1686 rNodeStack.push_front(std::move(pNode));
1690 class SmXMLUnderContext_Impl : public SmXMLSubContext_Impl
1692 protected:
1693 sal_Int16 nAttrCount;
1695 public:
1696 SmXMLUnderContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1697 const OUString& rLName)
1698 : SmXMLSubContext_Impl(rImport,nPrefix,rLName)
1699 , nAttrCount( 0 )
1702 void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList ) override;
1703 void EndElement() override;
1704 void HandleAccent();
1707 void SmXMLUnderContext_Impl::StartElement(const uno::Reference<
1708 xml::sax::XAttributeList > & xAttrList )
1710 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1713 void SmXMLUnderContext_Impl::HandleAccent()
1715 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
1716 OSL_ENSURE( bNodeCheck, "Sub has not two arguments" );
1717 if (!bNodeCheck)
1718 return;
1720 /*Just one special case for the underline thing*/
1721 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1722 SmNode *pTest = popOrZero(rNodeStack);
1723 SmToken aToken;
1724 aToken.cMathChar = '\0';
1725 aToken.eType = TUNDERLINE;
1727 SmNode *pFirst;
1728 std::unique_ptr<SmStructureNode> pNode(new SmAttributNode(aToken));
1729 if ((pTest->GetToken().cMathChar & 0x0FFF) == 0x0332)
1731 pFirst = new SmRectangleNode(aToken);
1732 delete pTest;
1734 else
1735 pFirst = pTest;
1737 SmNode *pSecond = popOrZero(rNodeStack);
1738 pNode->SetSubNodes(pFirst, pSecond);
1739 pNode->SetScaleMode(SmScaleMode::Width);
1740 rNodeStack.push_front(std::move(pNode));
1744 void SmXMLUnderContext_Impl::EndElement()
1746 if (!nAttrCount)
1747 GenericEndElement(TCSUB,CSUB);
1748 else
1749 HandleAccent();
1753 class SmXMLOverContext_Impl : public SmXMLSubContext_Impl
1755 protected:
1756 sal_Int16 nAttrCount;
1758 public:
1759 SmXMLOverContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1760 const OUString& rLName)
1761 : SmXMLSubContext_Impl(rImport,nPrefix,rLName), nAttrCount(0) {}
1763 void EndElement() override;
1764 void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList ) override;
1765 void HandleAccent();
1769 void SmXMLOverContext_Impl::StartElement(const uno::Reference<
1770 xml::sax::XAttributeList > & xAttrList )
1772 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1776 void SmXMLOverContext_Impl::EndElement()
1778 if (!nAttrCount)
1779 GenericEndElement(TCSUP,CSUP);
1780 else
1781 HandleAccent();
1785 void SmXMLOverContext_Impl::HandleAccent()
1787 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
1788 OSL_ENSURE (bNodeCheck, "Sub has not two arguments");
1789 if (!bNodeCheck)
1790 return;
1792 SmToken aToken;
1793 aToken.cMathChar = '\0';
1794 aToken.eType = TACUTE;
1796 std::unique_ptr<SmAttributNode> pNode(new SmAttributNode(aToken));
1797 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1799 SmNode *pFirst = popOrZero(rNodeStack);
1800 SmNode *pSecond = popOrZero(rNodeStack);
1801 pNode->SetSubNodes(pFirst, pSecond);
1802 pNode->SetScaleMode(SmScaleMode::Width);
1803 rNodeStack.push_front(std::move(pNode));
1808 class SmXMLUnderOverContext_Impl : public SmXMLSubSupContext_Impl
1810 public:
1811 SmXMLUnderOverContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1812 const OUString& rLName)
1813 : SmXMLSubSupContext_Impl(rImport,nPrefix,rLName) {}
1815 void EndElement() override
1817 GenericEndElement(TCSUB,CSUB,CSUP);
1822 class SmXMLMultiScriptsContext_Impl : public SmXMLSubSupContext_Impl
1824 bool bHasPrescripts;
1826 void ProcessSubSupPairs(bool bIsPrescript);
1828 public:
1829 SmXMLMultiScriptsContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1830 const OUString& rLName) :
1831 SmXMLSubSupContext_Impl(rImport,nPrefix,rLName),
1832 bHasPrescripts(false) {}
1834 void EndElement() override;
1835 SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix,
1836 const OUString& rLocalName,
1837 const uno::Reference< xml::sax::XAttributeList > &xAttrList) override;
1841 class SmXMLNoneContext_Impl : public SmXMLImportContext
1843 public:
1844 SmXMLNoneContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1845 const OUString& rLName)
1846 : SmXMLImportContext(rImport,nPrefix,rLName) {}
1848 void EndElement() override;
1852 void SmXMLNoneContext_Impl::EndElement()
1854 SmToken aToken;
1855 aToken.cMathChar = '\0';
1856 aToken.aText.clear();
1857 aToken.nLevel = 5;
1858 aToken.eType = TIDENT;
1859 GetSmImport().GetNodeStack().push_front(
1860 o3tl::make_unique<SmTextNode>(aToken,FNT_VARIABLE));
1864 class SmXMLPrescriptsContext_Impl : public SmXMLImportContext
1866 public:
1867 SmXMLPrescriptsContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1868 const OUString& rLName)
1869 : SmXMLImportContext(rImport,nPrefix,rLName) {}
1873 class SmXMLTableRowContext_Impl : public SmXMLRowContext_Impl
1875 public:
1876 SmXMLTableRowContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1877 const OUString& rLName) :
1878 SmXMLRowContext_Impl(rImport,nPrefix,rLName)
1881 SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix,
1882 const OUString& rLocalName,
1883 const uno::Reference< xml::sax::XAttributeList > &xAttrList) override;
1887 class SmXMLTableContext_Impl : public SmXMLTableRowContext_Impl
1889 public:
1890 SmXMLTableContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1891 const OUString& rLName) :
1892 SmXMLTableRowContext_Impl(rImport,nPrefix,rLName)
1895 void EndElement() override;
1896 SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix,
1897 const OUString& rLocalName,
1898 const uno::Reference< xml::sax::XAttributeList > &xAttrList) override;
1902 class SmXMLTableCellContext_Impl : public SmXMLRowContext_Impl
1904 public:
1905 SmXMLTableCellContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1906 const OUString& rLName) :
1907 SmXMLRowContext_Impl(rImport,nPrefix,rLName)
1912 class SmXMLAlignGroupContext_Impl : public SmXMLRowContext_Impl
1914 public:
1915 SmXMLAlignGroupContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1916 const OUString& rLName) :
1917 SmXMLRowContext_Impl(rImport,nPrefix,rLName)
1920 /*Don't do anything with alignment for now*/
1921 void EndElement() override
1927 class SmXMLActionContext_Impl : public SmXMLRowContext_Impl
1929 size_t mnSelection; // 1-based
1931 public:
1932 SmXMLActionContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1933 const OUString& rLName) :
1934 SmXMLRowContext_Impl(rImport,nPrefix,rLName)
1935 , mnSelection(1)
1938 void StartElement(const uno::Reference<xml::sax::XAttributeList> &xAttrList) override;
1939 void EndElement() override;
1943 // NB: virtually inherit so we can multiply inherit properly
1944 // in SmXMLFlatDocContext_Impl
1945 class SmXMLOfficeContext_Impl : public virtual SvXMLImportContext
1947 public:
1948 SmXMLOfficeContext_Impl( SmXMLImport &rImport )
1949 : SvXMLImportContext(rImport) {}
1951 virtual void SAL_CALL characters( const OUString& /*aChars*/ ) override {}
1953 virtual void SAL_CALL startFastElement( sal_Int32 /*nElement*/,
1954 const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ ) override {}
1956 virtual void SAL_CALL endFastElement( sal_Int32 /*nElement*/ ) override {}
1958 virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &xAttrList) override;
1960 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
1961 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
1964 SvXMLImportContextRef SmXMLOfficeContext_Impl::CreateChildContext(sal_uInt16 nPrefix,
1965 const OUString& rLocalName,
1966 const uno::Reference< xml::sax::XAttributeList > &xAttrList)
1968 SvXMLImportContext *pContext = nullptr;
1969 if ( XML_NAMESPACE_OFFICE == nPrefix &&
1970 rLocalName == GetXMLToken(XML_META) )
1972 SAL_WARN("starmath", "XML_TOK_DOC_META: should not have come here, maybe document is invalid?");
1974 else if ( XML_NAMESPACE_OFFICE == nPrefix &&
1975 rLocalName == GetXMLToken(XML_SETTINGS) )
1977 pContext = new XMLDocumentSettingsContext( GetImport(),
1978 XML_NAMESPACE_OFFICE, rLocalName,
1979 xAttrList );
1981 else
1982 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
1984 return pContext;
1987 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL SmXMLOfficeContext_Impl::createFastChildContext(
1988 sal_Int32 /*nElement*/, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
1990 return new SvXMLImportContext( GetImport() );
1994 // context for flat file xml format
1995 class SmXMLFlatDocContext_Impl
1996 : public SmXMLOfficeContext_Impl, public SvXMLMetaDocumentContext
1998 public:
1999 SmXMLFlatDocContext_Impl( SmXMLImport& i_rImport,
2000 const uno::Reference<document::XDocumentProperties>& i_xDocProps);
2002 virtual void SAL_CALL characters( const OUString& aChars ) override;
2004 virtual void SAL_CALL startFastElement( sal_Int32 nElement,
2005 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
2007 virtual void SAL_CALL endFastElement( sal_Int32 nElement ) override;
2009 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
2010 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
2013 SmXMLFlatDocContext_Impl::SmXMLFlatDocContext_Impl( SmXMLImport& i_rImport,
2014 const uno::Reference<document::XDocumentProperties>& i_xDocProps) :
2015 SvXMLImportContext(i_rImport),
2016 SmXMLOfficeContext_Impl(i_rImport),
2017 SvXMLMetaDocumentContext(i_rImport, i_xDocProps)
2021 void SAL_CALL SmXMLFlatDocContext_Impl::startFastElement( sal_Int32 nElement,
2022 const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
2024 SvXMLMetaDocumentContext::startFastElement(nElement, xAttrList);
2027 void SAL_CALL SmXMLFlatDocContext_Impl::endFastElement( sal_Int32 nElement )
2029 SvXMLMetaDocumentContext::endFastElement(nElement);
2032 void SAL_CALL SmXMLFlatDocContext_Impl::characters( const OUString& rChars )
2034 SvXMLMetaDocumentContext::characters(rChars);
2037 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL SmXMLFlatDocContext_Impl::createFastChildContext(
2038 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
2040 // behave like meta base class iff we encounter office:meta
2041 if ( nElement == XML_ELEMENT(OFFICE, XML_META) )
2043 return SvXMLMetaDocumentContext::createFastChildContext(
2044 nElement, xAttrList );
2046 else
2048 return SmXMLOfficeContext_Impl::createFastChildContext(
2049 nElement, xAttrList );
2053 static const SvXMLTokenMapEntry aPresLayoutElemTokenMap[] =
2055 { XML_NAMESPACE_MATH, XML_SEMANTICS, XML_TOK_SEMANTICS },
2056 { XML_NAMESPACE_MATH, XML_MATH, XML_TOK_MATH },
2057 { XML_NAMESPACE_MATH, XML_MSTYLE, XML_TOK_MSTYLE },
2058 { XML_NAMESPACE_MATH, XML_MERROR, XML_TOK_MERROR },
2059 { XML_NAMESPACE_MATH, XML_MPHANTOM, XML_TOK_MPHANTOM },
2060 { XML_NAMESPACE_MATH, XML_MROW, XML_TOK_MROW },
2061 { XML_NAMESPACE_MATH, XML_MENCLOSE, XML_TOK_MENCLOSE },
2062 { XML_NAMESPACE_MATH, XML_MFRAC, XML_TOK_MFRAC },
2063 { XML_NAMESPACE_MATH, XML_MSQRT, XML_TOK_MSQRT },
2064 { XML_NAMESPACE_MATH, XML_MROOT, XML_TOK_MROOT },
2065 { XML_NAMESPACE_MATH, XML_MSUB, XML_TOK_MSUB },
2066 { XML_NAMESPACE_MATH, XML_MSUP, XML_TOK_MSUP },
2067 { XML_NAMESPACE_MATH, XML_MSUBSUP, XML_TOK_MSUBSUP },
2068 { XML_NAMESPACE_MATH, XML_MUNDER, XML_TOK_MUNDER },
2069 { XML_NAMESPACE_MATH, XML_MOVER, XML_TOK_MOVER },
2070 { XML_NAMESPACE_MATH, XML_MUNDEROVER, XML_TOK_MUNDEROVER },
2071 { XML_NAMESPACE_MATH, XML_MMULTISCRIPTS, XML_TOK_MMULTISCRIPTS },
2072 { XML_NAMESPACE_MATH, XML_MTABLE, XML_TOK_MTABLE },
2073 { XML_NAMESPACE_MATH, XML_MACTION, XML_TOK_MACTION },
2074 { XML_NAMESPACE_MATH, XML_MFENCED, XML_TOK_MFENCED },
2075 { XML_NAMESPACE_MATH, XML_MPADDED, XML_TOK_MPADDED },
2076 XML_TOKEN_MAP_END
2079 static const SvXMLTokenMapEntry aPresLayoutAttrTokenMap[] =
2081 { XML_NAMESPACE_MATH, XML_FONTWEIGHT, XML_TOK_FONTWEIGHT },
2082 { XML_NAMESPACE_MATH, XML_FONTSTYLE, XML_TOK_FONTSTYLE },
2083 { XML_NAMESPACE_MATH, XML_FONTSIZE, XML_TOK_FONTSIZE },
2084 { XML_NAMESPACE_MATH, XML_FONTFAMILY, XML_TOK_FONTFAMILY },
2085 { XML_NAMESPACE_MATH, XML_COLOR, XML_TOK_COLOR },
2086 { XML_NAMESPACE_MATH, XML_MATHCOLOR, XML_TOK_MATHCOLOR },
2087 { XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_TOK_MATHVARIANT },
2088 XML_TOKEN_MAP_END
2091 static const SvXMLTokenMapEntry aFencedAttrTokenMap[] =
2093 { XML_NAMESPACE_MATH, XML_OPEN, XML_TOK_OPEN },
2094 { XML_NAMESPACE_MATH, XML_CLOSE, XML_TOK_CLOSE },
2095 XML_TOKEN_MAP_END
2098 static const SvXMLTokenMapEntry aOperatorAttrTokenMap[] =
2100 { XML_NAMESPACE_MATH, XML_STRETCHY, XML_TOK_STRETCHY },
2101 XML_TOKEN_MAP_END
2104 static const SvXMLTokenMapEntry aAnnotationAttrTokenMap[] =
2106 { XML_NAMESPACE_MATH, XML_ENCODING, XML_TOK_ENCODING },
2107 XML_TOKEN_MAP_END
2111 static const SvXMLTokenMapEntry aPresElemTokenMap[] =
2113 { XML_NAMESPACE_MATH, XML_ANNOTATION, XML_TOK_ANNOTATION },
2114 { XML_NAMESPACE_MATH, XML_MI, XML_TOK_MI },
2115 { XML_NAMESPACE_MATH, XML_MN, XML_TOK_MN },
2116 { XML_NAMESPACE_MATH, XML_MO, XML_TOK_MO },
2117 { XML_NAMESPACE_MATH, XML_MTEXT, XML_TOK_MTEXT },
2118 { XML_NAMESPACE_MATH, XML_MSPACE,XML_TOK_MSPACE },
2119 { XML_NAMESPACE_MATH, XML_MS, XML_TOK_MS },
2120 { XML_NAMESPACE_MATH, XML_MALIGNGROUP, XML_TOK_MALIGNGROUP },
2121 XML_TOKEN_MAP_END
2124 static const SvXMLTokenMapEntry aPresScriptEmptyElemTokenMap[] =
2126 { XML_NAMESPACE_MATH, XML_MPRESCRIPTS, XML_TOK_MPRESCRIPTS },
2127 { XML_NAMESPACE_MATH, XML_NONE, XML_TOK_NONE },
2128 XML_TOKEN_MAP_END
2131 static const SvXMLTokenMapEntry aPresTableElemTokenMap[] =
2133 { XML_NAMESPACE_MATH, XML_MTR, XML_TOK_MTR },
2134 { XML_NAMESPACE_MATH, XML_MTD, XML_TOK_MTD },
2135 XML_TOKEN_MAP_END
2138 static const SvXMLTokenMapEntry aColorTokenMap[] =
2140 { XML_NAMESPACE_MATH, XML_BLACK, TBLACK},
2141 { XML_NAMESPACE_MATH, XML_WHITE, TWHITE},
2142 { XML_NAMESPACE_MATH, XML_RED, TRED},
2143 { XML_NAMESPACE_MATH, XML_GREEN, TGREEN},
2144 { XML_NAMESPACE_MATH, XML_BLUE, TBLUE},
2145 { XML_NAMESPACE_MATH, XML_AQUA, TAQUA},
2146 { XML_NAMESPACE_MATH, XML_FUCHSIA, TFUCHSIA},
2147 { XML_NAMESPACE_MATH, XML_YELLOW, TYELLOW},
2148 { XML_NAMESPACE_MATH, XML_NAVY, TNAVY},
2149 { XML_NAMESPACE_MATH, XML_TEAL, TTEAL},
2150 { XML_NAMESPACE_MATH, XML_MAROON, TMAROON},
2151 { XML_NAMESPACE_MATH, XML_PURPLE, TPURPLE},
2152 { XML_NAMESPACE_MATH, XML_OLIVE, TOLIVE},
2153 { XML_NAMESPACE_MATH, XML_GRAY, TGRAY},
2154 { XML_NAMESPACE_MATH, XML_SILVER, TSILVER},
2155 { XML_NAMESPACE_MATH, XML_LIME, TLIME},
2156 XML_TOKEN_MAP_END
2159 static const SvXMLTokenMapEntry aActionAttrTokenMap[] =
2161 { XML_NAMESPACE_MATH, XML_SELECTION, XML_TOK_SELECTION },
2162 XML_TOKEN_MAP_END
2165 static const SvXMLTokenMapEntry aMspaceAttrTokenMap[] =
2167 { XML_NAMESPACE_MATH, XML_WIDTH, XML_TOK_WIDTH },
2168 XML_TOKEN_MAP_END
2172 const SvXMLTokenMap& SmXMLImport::GetPresLayoutElemTokenMap()
2174 if (!pPresLayoutElemTokenMap)
2175 pPresLayoutElemTokenMap.reset(new SvXMLTokenMap(aPresLayoutElemTokenMap));
2176 return *pPresLayoutElemTokenMap;
2179 const SvXMLTokenMap& SmXMLImport::GetPresLayoutAttrTokenMap()
2181 if (!pPresLayoutAttrTokenMap)
2182 pPresLayoutAttrTokenMap.reset(new SvXMLTokenMap(aPresLayoutAttrTokenMap));
2183 return *pPresLayoutAttrTokenMap;
2187 const SvXMLTokenMap& SmXMLImport::GetFencedAttrTokenMap()
2189 if (!pFencedAttrTokenMap)
2190 pFencedAttrTokenMap.reset(new SvXMLTokenMap(aFencedAttrTokenMap));
2191 return *pFencedAttrTokenMap;
2194 const SvXMLTokenMap& SmXMLImport::GetOperatorAttrTokenMap()
2196 if (!pOperatorAttrTokenMap)
2197 pOperatorAttrTokenMap.reset(new SvXMLTokenMap(aOperatorAttrTokenMap));
2198 return *pOperatorAttrTokenMap;
2201 const SvXMLTokenMap& SmXMLImport::GetAnnotationAttrTokenMap()
2203 if (!pAnnotationAttrTokenMap)
2204 pAnnotationAttrTokenMap.reset(new SvXMLTokenMap(aAnnotationAttrTokenMap));
2205 return *pAnnotationAttrTokenMap;
2208 const SvXMLTokenMap& SmXMLImport::GetPresElemTokenMap()
2210 if (!pPresElemTokenMap)
2211 pPresElemTokenMap.reset(new SvXMLTokenMap(aPresElemTokenMap));
2212 return *pPresElemTokenMap;
2215 const SvXMLTokenMap& SmXMLImport::GetPresScriptEmptyElemTokenMap()
2217 if (!pPresScriptEmptyElemTokenMap)
2218 pPresScriptEmptyElemTokenMap.reset(new
2219 SvXMLTokenMap(aPresScriptEmptyElemTokenMap));
2220 return *pPresScriptEmptyElemTokenMap;
2223 const SvXMLTokenMap& SmXMLImport::GetPresTableElemTokenMap()
2225 if (!pPresTableElemTokenMap)
2226 pPresTableElemTokenMap.reset(new SvXMLTokenMap(aPresTableElemTokenMap));
2227 return *pPresTableElemTokenMap;
2230 const SvXMLTokenMap& SmXMLImport::GetColorTokenMap()
2232 if (!pColorTokenMap)
2233 pColorTokenMap.reset(new SvXMLTokenMap(aColorTokenMap));
2234 return *pColorTokenMap;
2237 const SvXMLTokenMap& SmXMLImport::GetActionAttrTokenMap()
2239 if (!pActionAttrTokenMap)
2240 pActionAttrTokenMap.reset(new SvXMLTokenMap(aActionAttrTokenMap));
2241 return *pActionAttrTokenMap;
2244 const SvXMLTokenMap& SmXMLImport::GetMspaceAttrTokenMap()
2246 if (!pMspaceAttrTokenMap)
2247 pMspaceAttrTokenMap.reset(new SvXMLTokenMap(aMspaceAttrTokenMap));
2248 return *pMspaceAttrTokenMap;
2252 SvXMLImportContextRef SmXMLDocContext_Impl::CreateChildContext(
2253 sal_uInt16 nPrefix,
2254 const OUString& rLocalName,
2255 const uno::Reference<xml::sax::XAttributeList>& /*xAttrList*/)
2257 SvXMLImportContext* pContext = nullptr;
2259 const SvXMLTokenMap& rTokenMap = GetSmImport().GetPresLayoutElemTokenMap();
2261 switch(rTokenMap.Get(nPrefix, rLocalName))
2263 //Consider semantics a dummy except for any starmath annotations
2264 case XML_TOK_SEMANTICS:
2265 pContext = GetSmImport().CreateRowContext(nPrefix,rLocalName);
2266 break;
2267 /*General Layout Schemata*/
2268 case XML_TOK_MROW:
2269 pContext = GetSmImport().CreateRowContext(nPrefix,rLocalName);
2270 break;
2271 case XML_TOK_MENCLOSE:
2272 pContext = GetSmImport().CreateEncloseContext(nPrefix,rLocalName);
2273 break;
2274 case XML_TOK_MFRAC:
2275 pContext = GetSmImport().CreateFracContext(nPrefix,rLocalName);
2276 break;
2277 case XML_TOK_MSQRT:
2278 pContext = GetSmImport().CreateSqrtContext(nPrefix,rLocalName);
2279 break;
2280 case XML_TOK_MROOT:
2281 pContext = GetSmImport().CreateRootContext(nPrefix,rLocalName);
2282 break;
2283 case XML_TOK_MSTYLE:
2284 pContext = GetSmImport().CreateStyleContext(nPrefix,rLocalName);
2285 break;
2286 case XML_TOK_MERROR:
2287 pContext = GetSmImport().CreateErrorContext(nPrefix,rLocalName);
2288 break;
2289 case XML_TOK_MPADDED:
2290 pContext = GetSmImport().CreatePaddedContext(nPrefix,rLocalName);
2291 break;
2292 case XML_TOK_MPHANTOM:
2293 pContext = GetSmImport().CreatePhantomContext(nPrefix,rLocalName);
2294 break;
2295 case XML_TOK_MFENCED:
2296 pContext = GetSmImport().CreateFencedContext(nPrefix,rLocalName);
2297 break;
2298 /*Script and Limit Schemata*/
2299 case XML_TOK_MSUB:
2300 pContext = GetSmImport().CreateSubContext(nPrefix,rLocalName);
2301 break;
2302 case XML_TOK_MSUP:
2303 pContext = GetSmImport().CreateSupContext(nPrefix,rLocalName);
2304 break;
2305 case XML_TOK_MSUBSUP:
2306 pContext = GetSmImport().CreateSubSupContext(nPrefix,rLocalName);
2307 break;
2308 case XML_TOK_MUNDER:
2309 pContext = GetSmImport().CreateUnderContext(nPrefix,rLocalName);
2310 break;
2311 case XML_TOK_MOVER:
2312 pContext = GetSmImport().CreateOverContext(nPrefix,rLocalName);
2313 break;
2314 case XML_TOK_MUNDEROVER:
2315 pContext = GetSmImport().CreateUnderOverContext(nPrefix,rLocalName);
2316 break;
2317 case XML_TOK_MMULTISCRIPTS:
2318 pContext = GetSmImport().CreateMultiScriptsContext(nPrefix,
2319 rLocalName);
2320 break;
2321 case XML_TOK_MTABLE:
2322 pContext = GetSmImport().CreateTableContext(nPrefix,
2323 rLocalName);
2324 break;
2325 case XML_TOK_MACTION:
2326 pContext = GetSmImport().CreateActionContext(nPrefix,
2327 rLocalName);
2328 break;
2329 default:
2330 /*Basically there's an implicit mrow around certain bare
2331 *elements, use a RowContext to see if this is one of
2332 *those ones*/
2333 rtl::Reference<SmXMLRowContext_Impl> aTempContext(new SmXMLRowContext_Impl(GetSmImport(),nPrefix,
2334 GetXMLToken(XML_MROW)));
2336 pContext = aTempContext->StrictCreateChildContext(nPrefix,
2337 rLocalName);
2338 break;
2340 return pContext;
2343 void SmXMLDocContext_Impl::EndElement()
2345 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2347 SmNode *pContextNode = popOrZero(rNodeStack);
2349 SmToken aDummy;
2350 std::unique_ptr<SmStructureNode> pSNode(new SmLineNode(aDummy));
2351 pSNode->SetSubNodes(pContextNode, nullptr);
2352 rNodeStack.push_front(std::move(pSNode));
2354 SmNodeArray LineArray;
2355 auto n = rNodeStack.size();
2356 LineArray.resize(n);
2357 for (size_t j = 0; j < n; j++)
2359 auto pNode = std::move(rNodeStack.front());
2360 rNodeStack.pop_front();
2361 LineArray[n - (j + 1)] = pNode.release();
2363 std::unique_ptr<SmStructureNode> pSNode2(new SmTableNode(aDummy));
2364 pSNode2->SetSubNodes(std::move(LineArray));
2365 rNodeStack.push_front(std::move(pSNode2));
2368 void SmXMLFracContext_Impl::EndElement()
2370 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2371 const bool bNodeCheck = rNodeStack.size() - nElementCount == 2;
2372 OSL_ENSURE( bNodeCheck, "Fraction (mfrac) tag is missing component" );
2373 if (!bNodeCheck)
2374 return;
2376 SmToken aToken;
2377 aToken.cMathChar = '\0';
2378 aToken.eType = TOVER;
2379 std::unique_ptr<SmStructureNode> pSNode(new SmBinVerNode(aToken));
2380 SmNode *pOper = new SmRectangleNode(aToken);
2381 SmNode *pSecond = popOrZero(rNodeStack);
2382 SmNode *pFirst = popOrZero(rNodeStack);
2383 pSNode->SetSubNodes(pFirst,pOper,pSecond);
2384 rNodeStack.push_front(std::move(pSNode));
2387 void SmXMLRootContext_Impl::EndElement()
2389 /*The <mroot> element requires exactly 2 arguments.*/
2390 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
2391 OSL_ENSURE( bNodeCheck, "Root tag is missing component");
2392 if (!bNodeCheck)
2393 return;
2395 SmToken aToken;
2396 aToken.cMathChar = MS_SQRT; //Temporary: alert, based on StarSymbol font
2397 aToken.eType = TNROOT;
2398 std::unique_ptr<SmStructureNode> pSNode(new SmRootNode(aToken));
2399 SmNode *pOper = new SmRootSymbolNode(aToken);
2400 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2401 SmNode *pIndex = popOrZero(rNodeStack);
2402 SmNode *pBase = popOrZero(rNodeStack);
2403 pSNode->SetSubNodes(pIndex,pOper,pBase);
2404 rNodeStack.push_front(std::move(pSNode));
2407 void SmXMLSqrtContext_Impl::EndElement()
2410 <msqrt> accepts any number of arguments; if this number is not 1, its
2411 contents are treated as a single "inferred <mrow>" containing its
2412 arguments
2414 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
2415 SmXMLRowContext_Impl::EndElement();
2417 SmToken aToken;
2418 aToken.cMathChar = MS_SQRT; //Temporary: alert, based on StarSymbol font
2419 aToken.eType = TSQRT;
2420 std::unique_ptr<SmStructureNode> pSNode(new SmRootNode(aToken));
2421 SmNode *pOper = new SmRootSymbolNode(aToken);
2422 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2423 pSNode->SetSubNodes(nullptr,pOper,popOrZero(rNodeStack));
2424 rNodeStack.push_front(std::move(pSNode));
2427 void SmXMLRowContext_Impl::EndElement()
2429 SmNodeArray aRelationArray;
2430 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2432 if (rNodeStack.size() > nElementCount)
2434 auto nSize = rNodeStack.size() - nElementCount;
2436 aRelationArray.resize(nSize);
2437 for (auto j=nSize;j > 0;j--)
2439 auto pNode = std::move(rNodeStack.front());
2440 rNodeStack.pop_front();
2441 aRelationArray[j-1] = pNode.release();
2444 //If the first or last element is an operator with stretchyness
2445 //set then we must create a brace node here from those elements,
2446 //removing the stretchness from the operators and applying it to
2447 //ourselves, and creating the appropriate dummy StarMath none bracket
2448 //to balance the arrangement
2449 if (((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height)
2450 && (aRelationArray[0]->GetType() == SmNodeType::Math))
2451 || ((aRelationArray[nSize-1]->GetScaleMode() == SmScaleMode::Height)
2452 && (aRelationArray[nSize-1]->GetType() == SmNodeType::Math)))
2454 SmToken aToken;
2455 aToken.cMathChar = '\0';
2456 aToken.nLevel = 5;
2458 int nLeft=0,nRight=0;
2459 if ((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height)
2460 && (aRelationArray[0]->GetType() == SmNodeType::Math))
2462 aToken = aRelationArray[0]->GetToken();
2463 nLeft=1;
2465 else
2466 aToken.cMathChar = '\0';
2468 aToken.eType = TLPARENT;
2469 SmNode *pLeft = new SmMathSymbolNode(aToken);
2471 if ((aRelationArray[nSize-1]->GetScaleMode() == SmScaleMode::Height)
2472 && (aRelationArray[nSize-1]->GetType() == SmNodeType::Math))
2474 aToken = aRelationArray[nSize-1]->GetToken();
2475 nRight=1;
2477 else
2478 aToken.cMathChar = '\0';
2480 aToken.eType = TRPARENT;
2481 SmNode *pRight = new SmMathSymbolNode(aToken);
2483 SmNodeArray aRelationArray2;
2485 //!! nSize-nLeft-nRight may be < 0 !!
2486 int nRelArrSize = nSize-nLeft-nRight;
2487 if (nRelArrSize > 0)
2489 aRelationArray2.resize(nRelArrSize);
2490 for (int i=0;i < nRelArrSize;i++)
2492 aRelationArray2[i] = aRelationArray[i+nLeft];
2493 aRelationArray[i+nLeft] = nullptr;
2497 SmToken aDummy;
2498 std::unique_ptr<SmStructureNode> pSNode(new SmBraceNode(aToken));
2499 SmStructureNode *pBody = new SmExpressionNode(aDummy);
2500 pBody->SetSubNodes(std::move(aRelationArray2));
2502 pSNode->SetSubNodes(pLeft,pBody,pRight);
2503 pSNode->SetScaleMode(SmScaleMode::Height);
2504 rNodeStack.push_front(std::move(pSNode));
2506 for (auto a : aRelationArray)
2507 delete a;
2509 return;
2512 else
2514 // The elements msqrt, mstyle, merror, menclose, mpadded, mphantom, mtd, and math
2515 // treat their content as a single inferred mrow in case their content is empty.
2516 // Here an empty group {} is used to catch those cases and transform them without error
2517 // to StarMath.
2518 aRelationArray.resize(2);
2519 SmToken aToken;
2520 aToken.cMathChar = MS_LBRACE;
2521 aToken.nLevel = 5;
2522 aToken.eType = TLGROUP;
2523 aToken.aText = "{";
2524 aRelationArray[0] = new SmLineNode(aToken);
2526 aToken.cMathChar = MS_RBRACE;
2527 aToken.nLevel = 0;
2528 aToken.eType = TRGROUP;
2529 aToken.aText = "}";
2530 aRelationArray[1] = new SmLineNode(aToken);
2533 SmToken aDummy;
2534 std::unique_ptr<SmStructureNode> pSNode(new SmExpressionNode(aDummy));
2535 pSNode->SetSubNodes(std::move(aRelationArray));
2536 rNodeStack.push_front(std::move(pSNode));
2539 SvXMLImportContext* SmXMLRowContext_Impl::StrictCreateChildContext(
2540 sal_uInt16 nPrefix,
2541 const OUString& rLocalName)
2543 SvXMLImportContext* pContext = nullptr;
2545 const SvXMLTokenMap& rTokenMap = GetSmImport().GetPresElemTokenMap();
2546 switch(rTokenMap.Get(nPrefix, rLocalName))
2548 /*Note that these should accept malignmark subelements, but do not*/
2549 case XML_TOK_MN:
2550 pContext = GetSmImport().CreateNumberContext(nPrefix,rLocalName);
2551 break;
2552 case XML_TOK_MI:
2553 pContext = GetSmImport().CreateIdentifierContext(nPrefix,rLocalName);
2554 break;
2555 case XML_TOK_MO:
2556 pContext = GetSmImport().CreateOperatorContext(nPrefix,rLocalName);
2557 break;
2558 case XML_TOK_MTEXT:
2559 pContext = GetSmImport().CreateTextContext(nPrefix,rLocalName);
2560 break;
2561 case XML_TOK_MSPACE:
2562 pContext = GetSmImport().CreateSpaceContext(nPrefix,rLocalName);
2563 break;
2564 case XML_TOK_MS:
2565 pContext = GetSmImport().CreateStringContext(nPrefix,rLocalName);
2566 break;
2568 /*Note: The maligngroup should only be seen when the row
2569 * (or descendants) are in a table*/
2570 case XML_TOK_MALIGNGROUP:
2571 pContext = GetSmImport().CreateAlignGroupContext(nPrefix,rLocalName);
2572 break;
2574 case XML_TOK_ANNOTATION:
2575 pContext = GetSmImport().CreateAnnotationContext(nPrefix,rLocalName);
2576 break;
2578 default:
2579 break;
2581 return pContext;
2585 SvXMLImportContextRef SmXMLRowContext_Impl::CreateChildContext(
2586 sal_uInt16 nPrefix,
2587 const OUString& rLocalName,
2588 const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2590 SvXMLImportContextRef xContext = StrictCreateChildContext(nPrefix,
2591 rLocalName);
2593 if (!xContext)
2595 //Hmm, unrecognized for this level, check to see if its
2596 //an element that can have an implicit schema around it
2597 xContext = SmXMLDocContext_Impl::CreateChildContext(nPrefix,
2598 rLocalName,xAttrList);
2600 return xContext;
2603 SvXMLImportContextRef SmXMLMultiScriptsContext_Impl::CreateChildContext(
2604 sal_uInt16 nPrefix,
2605 const OUString& rLocalName,
2606 const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2608 SvXMLImportContextRef xContext;
2610 const SvXMLTokenMap& rTokenMap = GetSmImport().
2611 GetPresScriptEmptyElemTokenMap();
2612 switch(rTokenMap.Get(nPrefix, rLocalName))
2614 case XML_TOK_MPRESCRIPTS:
2615 bHasPrescripts = true;
2616 ProcessSubSupPairs(false);
2617 xContext = GetSmImport().CreatePrescriptsContext(nPrefix,
2618 rLocalName);
2619 break;
2620 case XML_TOK_NONE:
2621 xContext = GetSmImport().CreateNoneContext(nPrefix,rLocalName);
2622 break;
2623 default:
2624 xContext = SmXMLRowContext_Impl::CreateChildContext(nPrefix,
2625 rLocalName,xAttrList);
2626 break;
2628 return xContext;
2631 void SmXMLMultiScriptsContext_Impl::ProcessSubSupPairs(bool bIsPrescript)
2633 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2635 if (rNodeStack.size() <= nElementCount)
2636 return;
2638 auto nCount = rNodeStack.size() - nElementCount - 1;
2639 if (nCount == 0)
2640 return;
2642 if (nCount % 2 == 0)
2644 SmToken aToken;
2645 aToken.cMathChar = '\0';
2646 aToken.eType = bIsPrescript ? TLSUB : TRSUB;
2648 SmNodeStack aReverseStack;
2649 for (size_t i = 0; i < nCount + 1; i++)
2651 auto pNode = std::move(rNodeStack.front());
2652 rNodeStack.pop_front();
2653 aReverseStack.push_front(std::move(pNode));
2656 SmSubSup eSub = bIsPrescript ? LSUB : RSUB;
2657 SmSubSup eSup = bIsPrescript ? LSUP : RSUP;
2659 for (size_t i = 0; i < nCount; i += 2)
2661 std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
2663 // initialize subnodes array
2664 SmNodeArray aSubNodes(1 + SUBSUP_NUM_ENTRIES);
2666 /*On each loop the base and its sub sup pair becomes the
2667 base for the next loop to which the next sub sup pair is
2668 attached, i.e. wheels within wheels*/
2669 aSubNodes[0] = popOrZero(aReverseStack);
2671 SmNode *pScriptNode = popOrZero(aReverseStack);
2673 if (pScriptNode && ((pScriptNode->GetToken().eType != TIDENT) ||
2674 (!pScriptNode->GetToken().aText.isEmpty())))
2675 aSubNodes[eSub+1] = pScriptNode;
2676 pScriptNode = popOrZero(aReverseStack);
2677 if (pScriptNode && ((pScriptNode->GetToken().eType != TIDENT) ||
2678 (!pScriptNode->GetToken().aText.isEmpty())))
2679 aSubNodes[eSup+1] = pScriptNode;
2681 pNode->SetSubNodes(std::move(aSubNodes));
2682 aReverseStack.push_front(std::move(pNode));
2684 assert(!aReverseStack.empty());
2685 auto pNode = std::move(aReverseStack.front());
2686 aReverseStack.pop_front();
2687 rNodeStack.push_front(std::move(pNode));
2689 else
2691 // Ignore odd number of elements.
2692 for (size_t i = 0; i < nCount; i++)
2694 rNodeStack.pop_front();
2700 void SmXMLTableContext_Impl::EndElement()
2702 SmNodeArray aExpressionArray;
2703 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2704 SmNodeStack aReverseStack;
2705 aExpressionArray.resize(rNodeStack.size()-nElementCount);
2707 size_t nRows = rNodeStack.size()-nElementCount;
2708 size_t nCols = 0;
2710 for (size_t i = nRows; i > 0; --i)
2712 SmNode* pArray = rNodeStack.front().release();
2713 rNodeStack.pop_front();
2714 if (pArray->GetNumSubNodes() == 0)
2716 //This is a little tricky, it is possible that there was
2717 //be elements that were not inside a <mtd> pair, in which
2718 //case they will not be in a row, i.e. they will not have
2719 //SubNodes, so we have to wait until here before we can
2720 //resolve the situation. Implicit surrounding tags are
2721 //surprisingly difficult to get right within this
2722 //architecture
2724 SmNodeArray aRelationArray;
2725 aRelationArray.resize(1);
2726 aRelationArray[0] = pArray;
2727 SmToken aDummy;
2728 SmExpressionNode* pExprNode = new SmExpressionNode(aDummy);
2729 pExprNode->SetSubNodes(std::move(aRelationArray));
2730 pArray = pExprNode;
2733 nCols = std::max(nCols, pArray->GetNumSubNodes());
2734 aReverseStack.push_front(std::unique_ptr<SmNode>(pArray));
2736 if (nCols > SAL_MAX_UINT16)
2737 throw std::range_error("column limit");
2738 if (nRows > SAL_MAX_UINT16)
2739 throw std::range_error("row limit");
2740 aExpressionArray.resize(nCols*nRows);
2741 size_t j=0;
2742 for (auto & elem : aReverseStack)
2744 std::unique_ptr<SmStructureNode> xArray(static_cast<SmStructureNode*>(elem.release()));
2745 for (size_t i = 0; i < xArray->GetNumSubNodes(); ++i)
2746 aExpressionArray[j++] = xArray->GetSubNode(i);
2747 xArray->ClearSubNodes();
2749 aReverseStack.clear();
2751 SmToken aToken;
2752 aToken.cMathChar = '\0';
2753 aToken.eType = TMATRIX;
2754 std::unique_ptr<SmMatrixNode> pSNode(new SmMatrixNode(aToken));
2755 pSNode->SetSubNodes(std::move(aExpressionArray));
2756 pSNode->SetRowCol(nRows, nCols);
2757 rNodeStack.push_front(std::move(pSNode));
2760 SvXMLImportContextRef SmXMLTableRowContext_Impl::CreateChildContext(
2761 sal_uInt16 nPrefix,
2762 const OUString& rLocalName,
2763 const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2765 SvXMLImportContextRef xContext;
2767 const SvXMLTokenMap& rTokenMap = GetSmImport().
2768 GetPresTableElemTokenMap();
2769 switch(rTokenMap.Get(nPrefix, rLocalName))
2771 case XML_TOK_MTD:
2772 xContext = GetSmImport().CreateTableCellContext(nPrefix,
2773 rLocalName);
2774 break;
2775 default:
2776 xContext = SmXMLRowContext_Impl::CreateChildContext(nPrefix,
2777 rLocalName,xAttrList);
2778 break;
2780 return xContext;
2783 SvXMLImportContextRef SmXMLTableContext_Impl::CreateChildContext(
2784 sal_uInt16 nPrefix,
2785 const OUString& rLocalName,
2786 const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2788 SvXMLImportContextRef xContext;
2790 const SvXMLTokenMap& rTokenMap = GetSmImport().
2791 GetPresTableElemTokenMap();
2792 switch(rTokenMap.Get(nPrefix, rLocalName))
2794 case XML_TOK_MTR:
2795 xContext = GetSmImport().CreateTableRowContext(nPrefix,rLocalName);
2796 break;
2797 default:
2798 xContext = SmXMLTableRowContext_Impl::CreateChildContext(nPrefix,
2799 rLocalName,xAttrList);
2800 break;
2802 return xContext;
2805 void SmXMLMultiScriptsContext_Impl::EndElement()
2807 ProcessSubSupPairs(bHasPrescripts);
2810 void SmXMLActionContext_Impl::StartElement(const uno::Reference<xml::sax::XAttributeList> & xAttrList)
2812 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
2813 for (sal_Int16 i=0;i<nAttrCount;i++)
2815 OUString sAttrName = xAttrList->getNameByIndex(i);
2816 OUString aLocalName;
2817 sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
2818 GetKeyByAttrName(sAttrName,&aLocalName);
2820 OUString sValue = xAttrList->getValueByIndex(i);
2821 const SvXMLTokenMap &rAttrTokenMap =
2822 GetSmImport().GetActionAttrTokenMap();
2823 switch(rAttrTokenMap.Get(nPrefix,aLocalName))
2825 case XML_TOK_SELECTION:
2827 sal_uInt32 n = sValue.toUInt32();
2828 if (n > 0) mnSelection = static_cast<size_t>(n);
2830 break;
2831 default:
2832 break;
2837 void SmXMLActionContext_Impl::EndElement()
2839 SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2840 auto nSize = rNodeStack.size();
2841 if (nSize <= nElementCount) {
2842 // not compliant to maction's specification, e.g., no subexpressions
2843 return;
2845 assert(mnSelection > 0);
2846 if (nSize < nElementCount + mnSelection) {
2847 // No selected subexpression exists, which is a MathML error;
2848 // fallback to selecting the first
2849 mnSelection = 1;
2851 assert(nSize >= nElementCount + mnSelection);
2852 for (auto i=nSize-(nElementCount+mnSelection); i > 0; i--)
2854 rNodeStack.pop_front();
2856 auto pSelected = std::move(rNodeStack.front());
2857 rNodeStack.pop_front();
2858 for (auto i=rNodeStack.size()-nElementCount; i > 0; i--)
2860 rNodeStack.pop_front();
2862 rNodeStack.push_front(std::move(pSelected));
2865 SvXMLImportContext *SmXMLImport::CreateDocumentContext(sal_uInt16 nPrefix,
2866 const OUString &rLocalName,
2867 const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2869 SvXMLImportContext *pContext = nullptr;
2870 if ( XML_NAMESPACE_OFFICE != nPrefix )
2871 pContext = new SmXMLDocContext_Impl(*this,nPrefix,rLocalName);
2873 return pContext;
2876 SvXMLImportContext *SmXMLImport::CreateFastContext(sal_Int32 nElement,
2877 const uno::Reference <xml::sax::XFastAttributeList> & /*xAttrList*/)
2879 SvXMLImportContext *pContext = nullptr;
2881 switch (nElement)
2883 case XML_ELEMENT( OFFICE, XML_DOCUMENT ):
2884 case XML_ELEMENT( OFFICE, XML_DOCUMENT_META ):
2886 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
2887 GetModel(), uno::UNO_QUERY_THROW);
2888 pContext = ( (nElement & TOKEN_MASK) == XML_DOCUMENT_META )
2889 ? new SvXMLMetaDocumentContext( *this,
2890 xDPS->getDocumentProperties() )
2891 // flat OpenDocument file format -- this has not been tested...
2892 : new SmXMLFlatDocContext_Impl( *this,
2893 xDPS->getDocumentProperties() );
2895 break;
2896 default:
2897 if ((nElement & NMSP_MASK) == NAMESPACE_TOKEN(XML_NAMESPACE_OFFICE))
2898 pContext = new SmXMLOfficeContext_Impl(*this);
2899 else
2900 pContext = new SvXMLImportContext(*this);
2902 return pContext;
2905 SvXMLImportContext *SmXMLImport::CreateRowContext(sal_uInt16 nPrefix,
2906 const OUString &rLocalName)
2908 return new SmXMLRowContext_Impl(*this,nPrefix,rLocalName);
2911 SvXMLImportContext *SmXMLImport::CreateTextContext(sal_uInt16 nPrefix,
2912 const OUString &rLocalName)
2914 return new SmXMLTextContext_Impl(*this,nPrefix,rLocalName);
2917 SvXMLImportContext *SmXMLImport::CreateAnnotationContext(sal_uInt16 nPrefix,
2918 const OUString &rLocalName)
2920 return new SmXMLAnnotationContext_Impl(*this,nPrefix,rLocalName);
2923 SvXMLImportContext *SmXMLImport::CreateStringContext(sal_uInt16 nPrefix,
2924 const OUString &rLocalName)
2926 return new SmXMLStringContext_Impl(*this,nPrefix,rLocalName);
2929 SvXMLImportContext *SmXMLImport::CreateNumberContext(sal_uInt16 nPrefix,
2930 const OUString &rLocalName)
2932 return new SmXMLNumberContext_Impl(*this,nPrefix,rLocalName);
2935 SvXMLImportContext *SmXMLImport::CreateIdentifierContext(sal_uInt16 nPrefix,
2936 const OUString &rLocalName)
2938 return new SmXMLIdentifierContext_Impl(*this,nPrefix,rLocalName);
2941 SvXMLImportContext *SmXMLImport::CreateOperatorContext(sal_uInt16 nPrefix,
2942 const OUString &rLocalName)
2944 return new SmXMLOperatorContext_Impl(*this,nPrefix,rLocalName);
2947 SvXMLImportContext *SmXMLImport::CreateSpaceContext(sal_uInt16 nPrefix,
2948 const OUString &rLocalName)
2950 return new SmXMLSpaceContext_Impl(*this,nPrefix,rLocalName);
2954 SvXMLImportContext *SmXMLImport::CreateEncloseContext(sal_uInt16 nPrefix,
2955 const OUString &rLocalName)
2957 return new SmXMLEncloseContext_Impl(*this,nPrefix,rLocalName);
2960 SvXMLImportContext *SmXMLImport::CreateFracContext(sal_uInt16 nPrefix,
2961 const OUString &rLocalName)
2963 return new SmXMLFracContext_Impl(*this,nPrefix,rLocalName);
2966 SvXMLImportContext *SmXMLImport::CreateSqrtContext(sal_uInt16 nPrefix,
2967 const OUString &rLocalName)
2969 return new SmXMLSqrtContext_Impl(*this,nPrefix,rLocalName);
2972 SvXMLImportContext *SmXMLImport::CreateRootContext(sal_uInt16 nPrefix,
2973 const OUString &rLocalName)
2975 return new SmXMLRootContext_Impl(*this,nPrefix,rLocalName);
2978 SvXMLImportContext *SmXMLImport::CreateStyleContext(sal_uInt16 nPrefix,
2979 const OUString &rLocalName)
2981 return new SmXMLStyleContext_Impl(*this,nPrefix,rLocalName);
2984 SvXMLImportContext *SmXMLImport::CreatePaddedContext(sal_uInt16 nPrefix,
2985 const OUString &rLocalName)
2987 return new SmXMLPaddedContext_Impl(*this,nPrefix,rLocalName);
2990 SvXMLImportContext *SmXMLImport::CreatePhantomContext(sal_uInt16 nPrefix,
2991 const OUString &rLocalName)
2993 return new SmXMLPhantomContext_Impl(*this,nPrefix,rLocalName);
2996 SvXMLImportContext *SmXMLImport::CreateFencedContext(sal_uInt16 nPrefix,
2997 const OUString &rLocalName)
2999 return new SmXMLFencedContext_Impl(*this,nPrefix,rLocalName);
3002 SvXMLImportContext *SmXMLImport::CreateErrorContext(sal_uInt16 nPrefix,
3003 const OUString &rLocalName)
3005 return new SmXMLErrorContext_Impl(*this,nPrefix,rLocalName);
3008 SvXMLImportContext *SmXMLImport::CreateSubContext(sal_uInt16 nPrefix,
3009 const OUString &rLocalName)
3011 return new SmXMLSubContext_Impl(*this,nPrefix,rLocalName);
3014 SvXMLImportContext *SmXMLImport::CreateSubSupContext(sal_uInt16 nPrefix,
3015 const OUString &rLocalName)
3017 return new SmXMLSubSupContext_Impl(*this,nPrefix,rLocalName);
3020 SvXMLImportContext *SmXMLImport::CreateSupContext(sal_uInt16 nPrefix,
3021 const OUString &rLocalName)
3023 return new SmXMLSupContext_Impl(*this,nPrefix,rLocalName);
3026 SvXMLImportContext *SmXMLImport::CreateUnderContext(sal_uInt16 nPrefix,
3027 const OUString &rLocalName)
3029 return new SmXMLUnderContext_Impl(*this,nPrefix,rLocalName);
3032 SvXMLImportContext *SmXMLImport::CreateOverContext(sal_uInt16 nPrefix,
3033 const OUString &rLocalName)
3035 return new SmXMLOverContext_Impl(*this,nPrefix,rLocalName);
3038 SvXMLImportContext *SmXMLImport::CreateUnderOverContext(sal_uInt16 nPrefix,
3039 const OUString &rLocalName)
3041 return new SmXMLUnderOverContext_Impl(*this,nPrefix,rLocalName);
3044 SvXMLImportContext *SmXMLImport::CreateMultiScriptsContext(sal_uInt16 nPrefix,
3045 const OUString &rLocalName)
3047 return new SmXMLMultiScriptsContext_Impl(*this,nPrefix,rLocalName);
3050 SvXMLImportContext *SmXMLImport::CreateTableContext(sal_uInt16 nPrefix,
3051 const OUString &rLocalName)
3053 return new SmXMLTableContext_Impl(*this,nPrefix,rLocalName);
3055 SvXMLImportContext *SmXMLImport::CreateTableRowContext(sal_uInt16 nPrefix,
3056 const OUString &rLocalName)
3058 return new SmXMLTableRowContext_Impl(*this,nPrefix,rLocalName);
3060 SvXMLImportContext *SmXMLImport::CreateTableCellContext(sal_uInt16 nPrefix,
3061 const OUString &rLocalName)
3063 return new SmXMLTableCellContext_Impl(*this,nPrefix,rLocalName);
3066 SvXMLImportContext *SmXMLImport::CreateNoneContext(sal_uInt16 nPrefix,
3067 const OUString &rLocalName)
3069 return new SmXMLNoneContext_Impl(*this,nPrefix,rLocalName);
3072 SvXMLImportContext *SmXMLImport::CreatePrescriptsContext(sal_uInt16 nPrefix,
3073 const OUString &rLocalName)
3075 return new SmXMLPrescriptsContext_Impl(*this,nPrefix,rLocalName);
3078 SvXMLImportContext *SmXMLImport::CreateAlignGroupContext(sal_uInt16 nPrefix,
3079 const OUString &rLocalName)
3081 return new SmXMLAlignGroupContext_Impl(*this,nPrefix,rLocalName);
3084 SvXMLImportContext *SmXMLImport::CreateActionContext(sal_uInt16 nPrefix,
3085 const OUString &rLocalName)
3087 return new SmXMLActionContext_Impl(*this,nPrefix,rLocalName);
3090 SmXMLImport::~SmXMLImport() throw ()
3092 cleanup();
3095 void SmXMLImport::SetViewSettings(const Sequence<PropertyValue>& aViewProps)
3097 uno::Reference <frame::XModel> xModel = GetModel();
3098 if ( !xModel.is() )
3099 return;
3101 uno::Reference <lang::XUnoTunnel> xTunnel(xModel,uno::UNO_QUERY);
3102 SmModel *pModel = reinterpret_cast<SmModel *>
3103 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
3105 if ( !pModel )
3106 return;
3108 SmDocShell *pDocShell =
3109 static_cast<SmDocShell*>(pModel->GetObjectShell());
3110 if ( !pDocShell )
3111 return;
3113 tools::Rectangle aRect( pDocShell->GetVisArea() );
3115 sal_Int32 nCount = aViewProps.getLength();
3116 const PropertyValue *pValue = aViewProps.getConstArray();
3118 long nTmp = 0;
3120 for (sal_Int32 i = 0; i < nCount ; i++)
3122 if (pValue->Name == "ViewAreaTop" )
3124 pValue->Value >>= nTmp;
3125 aRect.SaturatingSetY(nTmp);
3127 else if (pValue->Name == "ViewAreaLeft" )
3129 pValue->Value >>= nTmp;
3130 aRect.SaturatingSetX(nTmp);
3132 else if (pValue->Name == "ViewAreaWidth" )
3134 pValue->Value >>= nTmp;
3135 Size aSize( aRect.GetSize() );
3136 aSize.setWidth( nTmp );
3137 aRect.SaturatingSetSize(aSize);
3139 else if (pValue->Name == "ViewAreaHeight" )
3141 pValue->Value >>= nTmp;
3142 Size aSize( aRect.GetSize() );
3143 aSize.setHeight( nTmp );
3144 aRect.SaturatingSetSize(aSize);
3146 pValue++;
3149 pDocShell->SetVisArea ( aRect );
3152 void SmXMLImport::SetConfigurationSettings(const Sequence<PropertyValue>& aConfProps)
3154 uno::Reference < XPropertySet > xProps ( GetModel(), UNO_QUERY );
3155 if ( xProps.is() )
3157 Reference < XPropertySetInfo > xInfo ( xProps->getPropertySetInfo() );
3158 if (xInfo.is() )
3160 sal_Int32 nCount = aConfProps.getLength();
3161 const PropertyValue* pValues = aConfProps.getConstArray();
3163 const OUString sFormula ( "Formula" );
3164 const OUString sBasicLibraries ( "BasicLibraries" );
3165 const OUString sDialogLibraries ( "DialogLibraries" );
3166 while ( nCount-- )
3168 if (pValues->Name != sFormula &&
3169 pValues->Name != sBasicLibraries &&
3170 pValues->Name != sDialogLibraries)
3174 if ( xInfo->hasPropertyByName( pValues->Name ) )
3175 xProps->setPropertyValue( pValues->Name, pValues->Value );
3177 catch (const beans::PropertyVetoException &)
3179 // dealing with read-only properties here. Nothing to do...
3181 catch (const Exception&)
3183 DBG_UNHANDLED_EXCEPTION("starmath");
3187 pValues++;
3193 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportMML(SvStream &rStream)
3195 SmGlobals::ensure();
3197 SfxObjectShellLock xDocSh(new SmDocShell(SfxModelFlags::EMBEDDED_OBJECT));
3198 xDocSh->DoInitNew();
3199 uno::Reference<frame::XModel> xModel(xDocSh->GetModel());
3201 uno::Reference<beans::XPropertySet> xInfoSet;
3202 uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
3203 uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory());
3204 uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
3206 //SetLoading hack because the document properties will be re-initted
3207 //by the xml filter and during the init, while its considered uninitialized,
3208 //setting a property will inform the document its modified, which attempts
3209 //to update the properties, which throws cause the properties are uninitialized
3210 xDocSh->SetLoading(SfxLoadedFlags::NONE);
3212 ErrCode nRet = ERRCODE_SFX_DOLOADFAILED;
3216 nRet = SmXMLImportWrapper::ReadThroughComponent(xStream, xModel, xContext, xInfoSet, "com.sun.star.comp.Math.XMLImporter", false);
3218 catch (...)
3222 xDocSh->SetLoading(SfxLoadedFlags::ALL);
3224 xDocSh->DoClose();
3226 return nRet != ERRCODE_NONE;
3229 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */