docthemes: Save themes def. to a file when added to ColorSets
[LibreOffice.git] / starmath / source / mathml / import.cxx
blobb7d6699d1294cb88556ff063651b574865c25c14
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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/.
8 */
10 // Our mathml
11 #include <mathml/import.hxx>
13 // LO tools to use
14 #include <com/sun/star/beans/PropertyAttribute.hpp>
15 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
16 #include <com/sun/star/embed/ElementModes.hpp>
17 #include <com/sun/star/packages/WrongPasswordException.hpp>
18 #include <com/sun/star/packages/zip/ZipIOException.hpp>
19 #include <com/sun/star/task/XStatusIndicator.hpp>
20 #include <com/sun/star/xml/sax/FastParser.hpp>
21 #include <com/sun/star/xml/sax/InputSource.hpp>
22 #include <com/sun/star/xml/sax/Parser.hpp>
23 #include <com/sun/star/xml/sax/SAXParseException.hpp>
25 // Extra LO tools
26 #include <comphelper/fileformat.h>
27 #include <comphelper/genericpropertyset.hxx>
28 #include <comphelper/processfactory.hxx>
29 #include <comphelper/propertysetinfo.hxx>
30 #include <comphelper/servicehelper.hxx>
31 #include <rtl/character.hxx>
32 #include <sfx2/docfile.hxx>
33 #include <sfx2/frame.hxx>
34 #include <sfx2/sfxsids.hrc>
35 #include <sot/storage.hxx>
36 #include <svtools/sfxecode.hxx>
37 #include <svl/itemset.hxx>
38 #include <svl/stritem.hxx>
39 #include <svx/dialmgr.hxx>
40 #include <svx/strings.hrc>
41 #include <unotools/streamwrap.hxx>
42 #include <xmloff/DocumentSettingsContext.hxx>
43 #include <xmloff/xmlmetai.hxx>
44 #include <xmloff/xmlnamespace.hxx>
45 #include <xmloff/xmltoken.hxx>
46 #include <o3tl/string_view.hxx>
48 // Our starmath tools
49 #include <cfgitem.hxx>
50 #include <document.hxx>
51 #include <xparsmlbase.hxx>
52 #include <smmod.hxx>
53 #include <starmathdatabase.hxx>
54 #include <unomodel.hxx>
56 // Old parser
57 #include <mathmlimport.hxx>
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::beans;
61 using namespace ::com::sun::star::document;
62 using namespace ::com::sun::star::lang;
63 using namespace ::com::sun::star::uno;
64 using namespace com::sun::star::xml::sax;
65 using namespace ::xmloff::token;
67 // SmMLImportContext
68 /*************************************************************************************************/
70 SmMlElement* SmMLImportWrapper::getElementTree()
72 return m_pMlImport == nullptr ? nullptr : m_pMlImport->getElementTree();
75 ErrCode SmMLImportWrapper::Import(SfxMedium& rMedium)
77 // Fetch context
78 const uno::Reference<uno::XComponentContext>& xContext(
79 comphelper::getProcessComponentContext());
80 if (!xContext.is())
82 SAL_WARN("starmath", "Failed to fetch model while file input");
83 return ERRCODE_SFX_DOLOADFAILED;
86 // Check model
87 if (!m_xModel.is())
89 SAL_WARN("starmath", "Failed to fetch model while file input");
90 return ERRCODE_SFX_DOLOADFAILED;
93 // Try to get an XStatusIndicator from the Medium
94 uno::Reference<task::XStatusIndicator> xStatusIndicator;
96 // Get model via uno
97 SmModel* pModel = m_xModel.get();
98 if (pModel == nullptr)
100 SAL_WARN("starmath", "Failed to fetch sm model while file input");
101 return ERRCODE_SFX_DOLOADFAILED;
104 // Get doc shell
105 m_pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
106 if (m_pDocShell == nullptr)
108 SAL_WARN("starmath", "Failed to fetch smdoc shell while file input");
109 return ERRCODE_SFX_DOLOADFAILED;
112 // Check if it is an embed object
113 bool bEmbedded = m_pDocShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED;
115 if (!bEmbedded)
117 // Extra check to ensure everything is fine
118 if (m_pDocShell->GetMedium() != &rMedium)
120 SAL_WARN("starmath", "Given medium and doc shell medium differ while file input");
121 return ERRCODE_SFX_DOLOADFAILED;
124 // Fetch the item set
125 const SfxUnoAnyItem* pItem = rMedium.GetItemSet().GetItem(SID_PROGRESS_STATUSBAR_CONTROL);
126 if (pItem != nullptr)
127 pItem->GetValue() >>= xStatusIndicator;
130 // Create property list
131 static const comphelper::PropertyMapEntry aInfoMap[]
132 = { { u"PrivateData"_ustr, 0, cppu::UnoType<XInterface>::get(),
133 beans::PropertyAttribute::MAYBEVOID, 0 },
134 { u"BaseURI"_ustr, 0, ::cppu::UnoType<OUString>::get(),
135 beans::PropertyAttribute::MAYBEVOID, 0 },
136 { u"StreamRelPath"_ustr, 0, ::cppu::UnoType<OUString>::get(),
137 beans::PropertyAttribute::MAYBEVOID, 0 },
138 { u"StreamName"_ustr, 0, ::cppu::UnoType<OUString>::get(),
139 beans::PropertyAttribute::MAYBEVOID, 0 } };
140 uno::Reference<beans::XPropertySet> xInfoSet(
141 comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));
143 // Set base URI
144 // needed for relative URLs; but it's OK to import e.g. MathML from the clipboard without one
145 SAL_INFO_IF(rMedium.GetBaseURL().isEmpty(), "starmath", "SmMLImportWrapper: no base URL");
146 xInfoSet->setPropertyValue(u"BaseURI"_ustr, Any(rMedium.GetBaseURL()));
148 // Fetch progress range
149 sal_Int32 nProgressRange(rMedium.IsStorage() ? 3 : 1);
150 if (xStatusIndicator.is())
152 xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange);
153 xStatusIndicator->setValue(0);
156 // Get storage
157 if (rMedium.IsStorage())
159 // TODO/LATER: handle the case of embedded links gracefully
160 if (bEmbedded) // && !rMedium.GetStorage()->IsRoot() )
162 OUString aName(u"dummyObjName"_ustr);
163 const SfxStringItem* pDocHierarchItem
164 = rMedium.GetItemSet().GetItem(SID_DOC_HIERARCHICALNAME);
165 if (pDocHierarchItem != nullptr)
166 aName = pDocHierarchItem->GetValue();
168 if (!aName.isEmpty())
169 xInfoSet->setPropertyValue(u"StreamRelPath"_ustr, Any(aName));
172 // Check if use OASIS ( new document format )
173 bool bOASIS = SotStorage::GetVersion(rMedium.GetStorage()) > SOFFICE_FILEFORMAT_60;
174 if (xStatusIndicator.is())
175 xStatusIndicator->setValue(1);
177 // Error code in case of needed
178 ErrCode nWarn = ERRCODE_NONE;
180 // Read metadata
181 // read a component from storage
182 if (!bEmbedded)
184 if (bOASIS)
185 nWarn = ReadThroughComponentS(rMedium.GetStorage(), m_xModel, u"meta.xml", xContext,
186 xInfoSet,
187 u"com.sun.star.comp.Math.MLOasisMetaImporter", 6);
188 else
189 nWarn
190 = ReadThroughComponentS(rMedium.GetStorage(), m_xModel, u"meta.xml", xContext,
191 xInfoSet, u"com.sun.star.comp.Math.XMLMetaImporter", 5);
194 // Check if successful
195 if (nWarn != ERRCODE_NONE)
197 if (xStatusIndicator.is())
198 xStatusIndicator->end();
199 SAL_WARN("starmath", "Failed to read file");
200 return nWarn;
203 // Increase success indicator
204 if (xStatusIndicator.is())
205 xStatusIndicator->setValue(2);
207 // Read settings
208 // read a component from storage
209 if (bOASIS)
210 nWarn = ReadThroughComponentS(rMedium.GetStorage(), m_xModel, u"settings.xml", xContext,
211 xInfoSet,
212 u"com.sun.star.comp.Math.MLOasisSettingsImporter", 6);
213 else
214 nWarn
215 = ReadThroughComponentS(rMedium.GetStorage(), m_xModel, u"settings.xml", xContext,
216 xInfoSet, u"com.sun.star.comp.Math.XMLSettingsImporter", 5);
218 // Check if successful
219 if (nWarn != ERRCODE_NONE)
221 if (xStatusIndicator.is())
222 xStatusIndicator->end();
223 SAL_WARN("starmath", "Failed to read file");
224 return nWarn;
227 // Increase success indicator
228 if (xStatusIndicator.is())
229 xStatusIndicator->setValue(3);
231 // Read document
232 // read a component from storage
233 if (m_pDocShell->GetSmSyntaxVersion() == 5)
234 nWarn = ReadThroughComponentS(rMedium.GetStorage(), m_xModel, u"content.xml", xContext,
235 xInfoSet, u"com.sun.star.comp.Math.XMLImporter", 5);
236 else
237 nWarn = ReadThroughComponentS(rMedium.GetStorage(), m_xModel, u"content.xml", xContext,
238 xInfoSet, u"com.sun.star.comp.Math.MLImporter", 6);
239 // Check if successful
240 if (nWarn != ERRCODE_NONE)
242 if (xStatusIndicator.is())
243 xStatusIndicator->end();
244 SAL_WARN("starmath", "Failed to read file");
245 return nWarn;
248 // Finish
249 if (xStatusIndicator.is())
250 xStatusIndicator->end();
251 return ERRCODE_NONE;
253 else
255 // Create input stream
256 Reference<io::XInputStream> xInputStream
257 = new utl::OInputStreamWrapper(rMedium.GetInStream());
259 // Increase success indicator
260 if (xStatusIndicator.is())
261 xStatusIndicator->setValue(1);
263 // Read data
264 // read a component from input stream
265 ErrCode nError = ERRCODE_NONE;
266 if (m_pDocShell->GetSmSyntaxVersion() == 5)
267 nError = ReadThroughComponentIS(xInputStream, m_xModel, xContext, xInfoSet,
268 u"com.sun.star.comp.Math.XMLImporter", false, 5);
269 else
270 nError = ReadThroughComponentIS(xInputStream, m_xModel, xContext, xInfoSet,
271 u"com.sun.star.comp.Math.MLImporter", false, 6);
273 // Finish
274 if (xStatusIndicator.is())
275 xStatusIndicator->end();
277 // Declare any error
278 if (nError != ERRCODE_NONE)
279 SAL_WARN("starmath", "Failed to read file");
281 return nError;
285 ErrCode SmMLImportWrapper::Import(std::u16string_view aSource)
287 // Fetch context
288 const uno::Reference<uno::XComponentContext>& xContext(
289 comphelper::getProcessComponentContext());
290 if (!xContext.is())
292 SAL_WARN("starmath", "Failed to fetch model while file input");
293 return ERRCODE_SFX_DOLOADFAILED;
296 // Check model
297 if (!m_xModel.is())
299 SAL_WARN("starmath", "Failed to fetch model while file input");
300 return ERRCODE_SFX_DOLOADFAILED;
303 // Make a model component from our SmModel
304 uno::Reference<lang::XComponent> xModelComp = m_xModel;
305 if (!xModelComp.is())
307 SAL_WARN("starmath", "Failed to make model while file input");
308 return ERRCODE_SFX_DOLOADFAILED;
311 // Get model via uno
312 SmModel* pModel = m_xModel.get();
313 if (pModel == nullptr)
315 SAL_WARN("starmath", "Failed to fetch sm model while file input");
316 return ERRCODE_SFX_DOLOADFAILED;
319 // Get doc shell
320 m_pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
321 if (m_pDocShell == nullptr)
323 SAL_WARN("starmath", "Failed to fetch smdoc shell while file input");
324 return ERRCODE_SFX_DOLOADFAILED;
327 // Create property list
328 static const comphelper::PropertyMapEntry aInfoMap[]
329 = { { u"PrivateData"_ustr, 0, cppu::UnoType<XInterface>::get(),
330 beans::PropertyAttribute::MAYBEVOID, 0 },
331 { u"BaseURI"_ustr, 0, ::cppu::UnoType<OUString>::get(),
332 beans::PropertyAttribute::MAYBEVOID, 0 },
333 { u"StreamRelPath"_ustr, 0, ::cppu::UnoType<OUString>::get(),
334 beans::PropertyAttribute::MAYBEVOID, 0 },
335 { u"StreamName"_ustr, 0, ::cppu::UnoType<OUString>::get(),
336 beans::PropertyAttribute::MAYBEVOID, 0 } };
337 uno::Reference<beans::XPropertySet> xInfoSet(
338 comphelper::GenericPropertySet_CreateInstance(new comphelper::PropertySetInfo(aInfoMap)));
340 // Read data
341 // read a component from text
342 ErrCode nError = ReadThroughComponentMS(aSource, xModelComp, xContext, xInfoSet);
344 // Declare any error
345 if (nError != ERRCODE_NONE)
347 SAL_WARN("starmath", "Failed to read file");
348 return nError;
351 return ERRCODE_NONE;
354 // read a component from input stream
355 ErrCode SmMLImportWrapper::ReadThroughComponentIS(
356 const Reference<io::XInputStream>& xInputStream, const Reference<XComponent>& xModelComponent,
357 Reference<uno::XComponentContext> const& rxContext,
358 Reference<beans::XPropertySet> const& rPropSet, const char16_t* pFilterName, bool bEncrypted,
359 int_fast16_t nSyntaxVersion)
361 // Needs an input stream but checked by caller
362 // Needs a context but checked by caller
363 // Needs property set but checked by caller
364 // Needs a filter name but checked by caller
366 // Prepare ParserInputSource
367 xml::sax::InputSource aParserInput;
368 aParserInput.aInputStream = xInputStream;
370 // Prepare property list
371 Sequence<Any> aArgs{ Any(rPropSet) };
373 // Get filter
374 Reference<XInterface> xFilter
375 = rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
376 OUString(pFilterName), aArgs, rxContext);
377 if (!xFilter.is())
379 SAL_WARN("starmath", "Can't instantiate filter component " << OUString(pFilterName));
380 return ERRCODE_SFX_DOLOADFAILED;
383 // Connect model and filter
384 Reference<XImporter> xImporter(xFilter, UNO_QUERY);
385 xImporter->setTargetDocument(xModelComponent);
387 // Finally, parser the stream
390 Reference<css::xml::sax::XFastParser> xFastParser(xFilter, UNO_QUERY);
391 Reference<css::xml::sax::XFastDocumentHandler> xFastDocHandler(xFilter, UNO_QUERY);
392 if (xFastParser)
394 xFastParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities);
395 xFastParser->parseStream(aParserInput);
397 else if (xFastDocHandler)
399 Reference<css::xml::sax::XFastParser> xParser
400 = css::xml::sax::FastParser::create(rxContext);
401 xParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities);
402 xParser->setFastDocumentHandler(xFastDocHandler);
403 xParser->parseStream(aParserInput);
405 else
407 Reference<css::xml::sax::XDocumentHandler> xDocHandler(xFilter, UNO_QUERY);
408 assert(xDocHandler);
409 Reference<css::xml::sax::XParser> xParser = css::xml::sax::Parser::create(rxContext);
410 xParser->setDocumentHandler(xDocHandler);
411 xParser->parseStream(aParserInput);
414 if (nSyntaxVersion == 5)
416 SmXMLImport* pXMlImport = dynamic_cast<SmXMLImport*>(xFilter.get());
417 if (pXMlImport != nullptr && pXMlImport->GetSuccess())
418 return ERRCODE_NONE;
419 else
421 SAL_WARN("starmath", "Filter failed on file input");
422 // However this can not be included since it's not public
423 if (pXMlImport == nullptr)
424 return ERRCODE_NONE;
425 return ERRCODE_SFX_DOLOADFAILED;
429 m_pMlImport = dynamic_cast<SmMLImport*>(xFilter.get());
430 if (m_pMlImport != nullptr && m_pMlImport->getSuccess())
431 return ERRCODE_NONE;
432 else
434 SAL_WARN("starmath", "Filter failed on file input");
435 return ERRCODE_SFX_DOLOADFAILED;
438 catch (const xml::sax::SAXParseException& r)
440 // Sax parser sends wrapped exceptions, try to find the original one
441 xml::sax::SAXException aTmp;
442 xml::sax::SAXException aSaxEx = *static_cast<const xml::sax::SAXException*>(&r);
443 while (aSaxEx.WrappedException >>= aTmp)
444 aSaxEx = aTmp;
446 packages::zip::ZipIOException aBrokenPackage;
447 if (aSaxEx.WrappedException >>= aBrokenPackage)
449 SAL_WARN("starmath", "Failed to read file SAXParseException");
450 return ERRCODE_IO_BROKENPACKAGE;
453 if (bEncrypted)
455 SAL_WARN("starmath", "Wrong file password SAXParseException");
456 return ERRCODE_SFX_WRONGPASSWORD;
459 catch (const xml::sax::SAXException& r)
461 packages::zip::ZipIOException aBrokenPackage;
462 if (r.WrappedException >>= aBrokenPackage)
464 SAL_WARN("starmath", "Failed to read file SAXException");
465 return ERRCODE_IO_BROKENPACKAGE;
468 if (bEncrypted)
470 SAL_WARN("starmath", "Wrong file password SAXException");
471 return ERRCODE_SFX_WRONGPASSWORD;
474 catch (const packages::zip::ZipIOException&)
476 SAL_WARN("starmath", "Failed to unzip file ZipIOException");
477 return ERRCODE_IO_BROKENPACKAGE;
479 catch (const io::IOException&)
481 SAL_WARN("starmath", "Failed to read file ZipIOException");
482 return ERRCODE_IO_UNKNOWN;
484 catch (const std::range_error&)
486 SAL_WARN("starmath", "Failed to read file");
487 return ERRCODE_ABORT;
490 return ERRCODE_ABORT;
493 // read a component from storage
494 ErrCode SmMLImportWrapper::ReadThroughComponentS(const uno::Reference<embed::XStorage>& xStorage,
495 const Reference<XComponent>& xModelComponent,
496 const char16_t* pStreamName,
497 Reference<uno::XComponentContext> const& rxContext,
498 Reference<beans::XPropertySet> const& rPropSet,
499 const char16_t* pFilterName,
500 int_fast16_t nSyntaxVersion)
502 // Needs a storage but checked by caller
503 // Needs a model but checked by caller
504 // Needs a stream name but checked by caller
505 // Needs a context but checked by caller
506 // Needs a property set but checked by caller
507 // Needs a filter name but checked by caller
509 // Get the input stream
512 // Create the stream for the event read
513 uno::Reference<io::XStream> xEventsStream
514 = xStorage->openStreamElement(OUString(pStreamName), embed::ElementModes::READ);
516 // Determine if stream is encrypted or not
517 uno::Reference<beans::XPropertySet> xProps(xEventsStream, uno::UNO_QUERY);
518 Any aAny = xProps->getPropertyValue(u"Encrypted"_ustr);
519 bool bEncrypted = false;
520 aAny >>= bEncrypted;
522 // Set base URL and open stream
523 rPropSet->setPropertyValue(u"StreamName"_ustr, Any(OUString(pStreamName)));
524 Reference<io::XInputStream> xStream = xEventsStream->getInputStream();
526 // Execute read
527 return ReadThroughComponentIS(xStream, xModelComponent, rxContext, rPropSet, pFilterName,
528 bEncrypted, nSyntaxVersion);
530 catch (packages::WrongPasswordException&)
532 SAL_WARN("starmath", "Wrong file password");
533 return ERRCODE_SFX_WRONGPASSWORD;
535 catch (packages::zip::ZipIOException&)
537 SAL_WARN("starmath", "Failed to unzip file");
538 return ERRCODE_IO_BROKENPACKAGE;
540 catch (uno::Exception&)
544 return ERRCODE_SFX_DOLOADFAILED;
547 // read a component from text
548 ErrCode SmMLImportWrapper::ReadThroughComponentMS(
549 std::u16string_view aText, const css::uno::Reference<css::lang::XComponent>& xModelComponent,
550 css::uno::Reference<css::uno::XComponentContext> const& rxContext,
551 css::uno::Reference<css::beans::XPropertySet> const& rPropSet)
553 // Needs a storage but checked by caller
554 // Needs a model but checked by caller
555 // Needs a stream name but checked by caller
556 // Needs a context but checked by caller
557 // Needs a property set but checked by caller
558 // Needs a filter name but checked by caller
560 // Get the input stream
563 // Generate input memory stream
564 SvMemoryStream aMemoryStream;
565 aMemoryStream.WriteOString(OUStringToOString(aText, RTL_TEXTENCODING_UTF8));
566 uno::Reference<io::XInputStream> xStream(new utl::OInputStreamWrapper(aMemoryStream));
568 // Execute read
569 return ReadThroughComponentIS(xStream, xModelComponent, rxContext, rPropSet,
570 u"com.sun.star.comp.Math.MLImporter", false, 6);
572 catch (packages::WrongPasswordException&)
574 SAL_WARN("starmath", "Wrong file password");
575 return ERRCODE_SFX_WRONGPASSWORD;
577 catch (packages::zip::ZipIOException&)
579 SAL_WARN("starmath", "Failed to unzip file");
580 return ERRCODE_IO_BROKENPACKAGE;
582 catch (uno::Exception&)
586 return ERRCODE_SFX_DOLOADFAILED;
589 // SmMLImport technical
590 /*************************************************************************************************/
592 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
593 Math_MLImporter_get_implementation(uno::XComponentContext* pCtx,
594 uno::Sequence<uno::Any> const& /*rSeq*/)
596 return cppu::acquire(
597 new SmMLImport(pCtx, u"com.sun.star.comp.Math.XMLImporter"_ustr, SvXMLImportFlags::ALL));
600 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
601 Math_MLOasisMetaImporter_get_implementation(uno::XComponentContext* pCtx,
602 uno::Sequence<uno::Any> const& /*rSeq*/)
604 return cppu::acquire(new SmMLImport(pCtx, u"com.sun.star.comp.Math.XMLOasisMetaImporter"_ustr,
605 SvXMLImportFlags::META));
608 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
609 Math_MLOasisSettingsImporter_get_implementation(uno::XComponentContext* pCtx,
610 uno::Sequence<uno::Any> const& /*rSeq*/)
612 return cppu::acquire(new SmMLImport(
613 pCtx, u"com.sun.star.comp.Math.XMLOasisSettingsImporter"_ustr, SvXMLImportFlags::SETTINGS));
616 // SmMLImportContext
617 /*************************************************************************************************/
619 namespace
621 class SmMLImportContext : public SvXMLImportContext
623 private:
624 SmMlElement** m_pParent;
625 SmMlElement* m_pElement;
626 SmMlElement* m_pStyle;
628 public:
629 SmMLImportContext(SmMLImport& rImport, SmMlElement** pParent)
630 : SvXMLImportContext(rImport)
631 , m_pParent(pParent)
632 , m_pElement(nullptr)
633 , m_pStyle(nullptr)
637 private:
638 void declareMlError();
640 public:
641 /** Handles characters (text)
643 virtual void SAL_CALL characters(const OUString& aChars) override;
645 /** Starts the mathml element
647 virtual void SAL_CALL startFastElement(
648 sal_Int32 nElement, const Reference<XFastAttributeList>& aAttributeList) override;
650 /** Ends the mathml element
652 virtual void SAL_CALL endFastElement(sal_Int32 Element) override;
654 /** Creates child element
656 virtual uno::Reference<XFastContextHandler>
657 SAL_CALL createFastChildContext(sal_Int32 nElement,
658 const uno::Reference<XFastAttributeList>& Attribs) override;
660 /** Inherits the style from it's parents
662 void inheritStyle();
664 /** Inherits the style from it's parents on end
666 void inheritStyleEnd();
668 /** Handle mathml attributes
670 void handleAttributes(const Reference<XFastAttributeList>& aAttributeList);
672 /** Handle mathml length attributes
674 SmLengthValue handleLengthAttribute(const OUString& aAttribute);
677 uno::Reference<XFastContextHandler> SAL_CALL
678 SmMLImportContext::createFastChildContext(sal_Int32, const uno::Reference<XFastAttributeList>&)
680 uno::Reference<xml::sax::XFastContextHandler> xContext;
681 xContext = new SmMLImportContext(static_cast<SmMLImport&>(GetImport()), &m_pElement);
682 return xContext;
685 void SmMLImportContext::declareMlError()
687 SmMLImport& aSmMLImport = static_cast<SmMLImport&>(GetImport());
688 aSmMLImport.declareMlError();
691 void SmMLImportContext::inheritStyle()
693 while ((m_pStyle = m_pStyle->getParentElement()) != nullptr)
695 if (m_pStyle->getParentElement()->getMlElementType() == SmMlElementType::MlMstyle
696 || m_pStyle->getParentElement()->getMlElementType() == SmMlElementType::MlMath)
697 break;
700 // Parent inheritation
701 // Mathcolor, mathsize, dir and displaystyle are inherited from parent
702 SmMlElement* pParent = *m_pParent;
703 m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlMathcolor));
704 m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlMathsize));
705 m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlDir));
706 m_pElement->setAttribute(pParent->getAttribute(SmMlAttributeValueType::MlDisplaystyle));
708 // Inherit operator dictionary overwrites
709 if (m_pStyle != nullptr
710 && (m_pElement->getMlElementType() == SmMlElementType::MlMo
711 || m_pElement->getMlElementType() == SmMlElementType::MlMstyle
712 || m_pElement->getMlElementType() == SmMlElementType::MlMath))
714 // TODO fetch operator dictionary first and then overwrite
715 if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlAccent))
716 m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlAccent));
717 if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlFence))
718 m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlFence));
719 if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlLspace))
720 m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlLspace));
721 if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMaxsize))
722 m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlMaxsize));
723 if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMinsize))
724 m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlMinsize));
725 if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMovablelimits))
726 m_pElement->setAttribute(
727 m_pStyle->getAttribute(SmMlAttributeValueType::MlMovablelimits));
728 if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlRspace))
729 m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlRspace));
730 if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlSeparator))
731 m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlSeparator));
732 if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlStretchy))
733 m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlStretchy));
734 if (m_pStyle->isAttributeSet(SmMlAttributeValueType::MlSymmetric))
735 m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlSymmetric));
737 if (m_pElement->getMlElementType() == SmMlElementType::MlMo)
739 // Set form based in position
740 SmMlAttribute aAttribute(SmMlAttributeValueType::MlForm);
741 SmMlForm aForm;
742 if (m_pElement->getSubElementId() == 0)
743 aForm = { SmMlAttributeValueForm::MlPrefix };
744 else
745 aForm = { SmMlAttributeValueForm::MlInfix };
746 aAttribute.setMlForm(&aForm);
747 m_pElement->setAttribute(aAttribute);
751 // Inherit mathvariant
752 if (m_pStyle && m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMathvariant))
753 m_pElement->setAttribute(m_pStyle->getAttribute(SmMlAttributeValueType::MlMathvariant));
756 void SmMLImportContext::inheritStyleEnd()
758 // Mo: check it is the end: postfix
759 if (m_pElement->getMlElementType() == SmMlElementType::MlMo)
761 if ((*m_pParent)->getSubElementsCount() == m_pElement->getSubElementId())
763 // Set form based in position
764 SmMlAttribute aAttribute(SmMlAttributeValueType::MlForm);
765 SmMlForm aForm = { SmMlAttributeValueForm::MlPosfix };
766 aAttribute.setMlForm(&aForm);
767 m_pElement->setAttribute(aAttribute);
771 // Mi: 1 char -> italic
772 if (m_pElement->getMlElementType() != SmMlElementType::MlMi)
773 return;
775 // Inherit mathvariant
776 if (!m_pStyle->isAttributeSet(SmMlAttributeValueType::MlMathvariant))
778 sal_Int32 nIndexUtf16 = 0;
779 // Check if there is only one code point
780 m_pElement->getText().iterateCodePoints(&nIndexUtf16, 1);
781 // Mathml says that 1 code point -> italic
782 if (nIndexUtf16 == m_pElement->getText().getLength())
784 SmMlAttribute aAttribute(SmMlAttributeValueType::MlMathvariant);
785 SmMlMathvariant aMathvariant = { SmMlAttributeValueMathvariant::italic };
786 aAttribute.setMlMathvariant(&aMathvariant);
787 aAttribute.setSet(false);
788 m_pElement->setAttribute(aAttribute);
793 SmLengthValue SmMLImportContext::handleLengthAttribute(const OUString& aAttribute)
795 // Locate unit indication
796 int32_t nUnitPos;
797 for (nUnitPos = 0;
798 nUnitPos < aAttribute.getLength()
799 && (rtl::isAsciiHexDigit(aAttribute[nUnitPos]) || aAttribute[nUnitPos] == '.');
800 ++nUnitPos)
803 // Find unit
804 SmLengthUnit nUnit = SmLengthUnit::MlM;
805 if (nUnitPos != aAttribute.getLength())
807 OUString aUnit = aAttribute.copy(nUnitPos);
808 if (aUnit.compareToIgnoreAsciiCaseAscii("ex"))
809 nUnit = SmLengthUnit::MlEx;
810 if (aUnit.compareToIgnoreAsciiCaseAscii("px"))
811 nUnit = SmLengthUnit::MlPx;
812 if (aUnit.compareToIgnoreAsciiCaseAscii("in"))
813 nUnit = SmLengthUnit::MlIn;
814 if (aUnit.compareToIgnoreAsciiCaseAscii("cm"))
815 nUnit = SmLengthUnit::MlCm;
816 if (aUnit.compareToIgnoreAsciiCaseAscii("mm"))
817 nUnit = SmLengthUnit::MlMm;
818 if (aUnit.compareToIgnoreAsciiCaseAscii("pt"))
819 nUnit = SmLengthUnit::MlPt;
820 if (aUnit.compareToIgnoreAsciiCaseAscii("pc"))
821 nUnit = SmLengthUnit::MlPc;
822 if (aUnit.compareToIgnoreAsciiCaseAscii("%"))
823 nUnit = SmLengthUnit::MlP;
824 else
825 declareMlError();
828 // Get value
829 std::u16string_view aValue = aAttribute.subView(0, nUnitPos);
830 double nValue = o3tl::toDouble(aValue);
831 if (nValue == 0)
833 nUnit = SmLengthUnit::MlM;
834 nValue = 1.0;
835 declareMlError();
838 // Return
839 SmLengthValue aLengthValue = { nUnit, nValue, new OUString(aAttribute) };
840 return aLengthValue;
843 void SmMLImportContext::handleAttributes(const Reference<XFastAttributeList>& aAttributeList)
845 for (auto& aIter : sax_fastparser::castToFastAttributeList(aAttributeList))
847 SmMlAttribute aAttribute(SmMlAttributeValueType::NMlEmpty);
848 switch (aIter.getToken() & TOKEN_MASK)
850 case XML_ACCENT:
852 if (IsXMLToken(aIter, XML_TRUE))
854 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlAccent);
855 SmMlAccent aAccent = { SmMlAttributeValueAccent::MlTrue };
856 aAttribute.setMlAccent(&aAccent);
858 else if (IsXMLToken(aIter, XML_FALSE))
860 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlAccent);
861 SmMlAccent aAccent = { SmMlAttributeValueAccent::MlFalse };
862 aAttribute.setMlAccent(&aAccent);
864 else
866 declareMlError();
868 break;
870 case XML_DIR:
872 if (IsXMLToken(aIter, XML_RTL))
874 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDir);
875 SmMlDir aDir = { SmMlAttributeValueDir::MlRtl };
876 aAttribute.setMlDir(&aDir);
878 else if (IsXMLToken(aIter, XML_LTR))
880 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDir);
881 SmMlDir aDir = { SmMlAttributeValueDir::MlLtr };
882 aAttribute.setMlDir(&aDir);
884 else
886 declareMlError();
888 break;
890 case XML_DISPLAYSTYLE:
891 if (IsXMLToken(aIter, XML_TRUE))
893 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDisplaystyle);
894 SmMlDisplaystyle aDisplaystyle = { SmMlAttributeValueDisplaystyle::MlTrue };
895 aAttribute.setMlDisplaystyle(&aDisplaystyle);
897 else if (IsXMLToken(aIter, XML_FALSE))
899 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlDisplaystyle);
900 SmMlDisplaystyle aDisplaystyle = { SmMlAttributeValueDisplaystyle::MlFalse };
901 aAttribute.setMlDisplaystyle(&aDisplaystyle);
903 else
905 declareMlError();
907 break;
908 case XML_FENCE:
909 if (IsXMLToken(aIter, XML_TRUE))
911 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlFence);
912 SmMlFence aFence = { SmMlAttributeValueFence::MlTrue };
913 aAttribute.setMlFence(&aFence);
915 else if (IsXMLToken(aIter, XML_FALSE))
917 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlFence);
918 SmMlFence aFence = { SmMlAttributeValueFence::MlFalse };
919 aAttribute.setMlFence(&aFence);
921 else
923 declareMlError();
925 break;
926 case XML_HREF:
928 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlHref);
929 OUString* aRef = new OUString(aIter.toString());
930 SmMlHref aHref = { SmMlAttributeValueHref::NMlValid, aRef };
931 aAttribute.setMlHref(&aHref);
932 break;
934 case XML_LSPACE:
936 SmMlLspace aLspace;
937 aLspace.m_aLengthValue = handleLengthAttribute(aIter.toString());
938 aAttribute.setMlLspace(&aLspace);
939 break;
941 case XML_MATHBACKGROUND:
943 if (IsXMLToken(aIter, XML_TRANSPARENT))
945 SmMlMathbackground aMathbackground
946 = { SmMlAttributeValueMathbackground::MlTransparent, COL_TRANSPARENT };
947 aAttribute.setMlMathbackground(&aMathbackground);
949 else
951 Color aColor
952 = starmathdatabase::Identify_ColorName_HTML(aIter.toString()).cColor;
953 SmMlMathbackground aMathbackground
954 = { SmMlAttributeValueMathbackground::MlRgb, aColor };
955 aAttribute.setMlMathbackground(&aMathbackground);
957 break;
959 case XML_MATHCOLOR:
961 if (IsXMLToken(aIter, XML_DEFAULT))
963 SmMlMathcolor aMathcolor
964 = { SmMlAttributeValueMathcolor::MlDefault, COL_BLACK };
965 aAttribute.setMlMathcolor(&aMathcolor);
967 else
969 Color aColor
970 = starmathdatabase::Identify_ColorName_HTML(aIter.toString()).cColor;
971 SmMlMathcolor aMathcolor = { SmMlAttributeValueMathcolor::MlRgb, aColor };
972 aAttribute.setMlMathcolor(&aMathcolor);
974 break;
976 case XML_MATHSIZE:
978 SmMlMathsize aMathsize;
979 aMathsize.m_aLengthValue = handleLengthAttribute(aIter.toString());
980 aAttribute.setMlMathsize(&aMathsize);
981 break;
983 case XML_MATHVARIANT:
985 OUString aVariant = aIter.toString();
986 SmMlAttributeValueMathvariant nVariant = SmMlAttributeValueMathvariant::normal;
987 if (aVariant.compareTo(u"normal"))
988 nVariant = SmMlAttributeValueMathvariant::normal;
989 else if (aVariant.compareTo(u"bold"))
990 nVariant = SmMlAttributeValueMathvariant::bold;
991 else if (aVariant.compareTo(u"italic"))
992 nVariant = SmMlAttributeValueMathvariant::italic;
993 else if (aVariant.compareTo(u"double-struck"))
994 nVariant = SmMlAttributeValueMathvariant::double_struck;
995 else if (aVariant.compareTo(u"script"))
996 nVariant = SmMlAttributeValueMathvariant::script;
997 else if (aVariant.compareTo(u"fraktur"))
998 nVariant = SmMlAttributeValueMathvariant::fraktur;
999 else if (aVariant.compareTo(u"sans-serif"))
1000 nVariant = SmMlAttributeValueMathvariant::sans_serif;
1001 else if (aVariant.compareTo(u"monospace"))
1002 nVariant = SmMlAttributeValueMathvariant::monospace;
1003 else if (aVariant.compareTo(u"bold-italic"))
1004 nVariant = SmMlAttributeValueMathvariant::bold_italic;
1005 else if (aVariant.compareTo(u"bold-fracktur"))
1006 nVariant = SmMlAttributeValueMathvariant::bold_fraktur;
1007 else if (aVariant.compareTo(u"bold-script"))
1008 nVariant = SmMlAttributeValueMathvariant::bold_script;
1009 else if (aVariant.compareTo(u"bold-sans-serif"))
1010 nVariant = SmMlAttributeValueMathvariant::bold_sans_serif;
1011 else if (aVariant.compareTo(u"sans-serif-italic"))
1012 nVariant = SmMlAttributeValueMathvariant::sans_serif_italic;
1013 else if (aVariant.compareTo(u"sans-serif-bold-italic"))
1014 nVariant = SmMlAttributeValueMathvariant::sans_serif_bold_italic;
1015 else if (aVariant.compareTo(u"initial"))
1016 nVariant = SmMlAttributeValueMathvariant::initial;
1017 else if (aVariant.compareTo(u"tailed"))
1018 nVariant = SmMlAttributeValueMathvariant::tailed;
1019 else if (aVariant.compareTo(u"looped"))
1020 nVariant = SmMlAttributeValueMathvariant::looped;
1021 else if (aVariant.compareTo(u"stretched"))
1022 nVariant = SmMlAttributeValueMathvariant::stretched;
1023 else
1024 declareMlError();
1025 SmMlMathvariant aMathvariant = { nVariant };
1026 aAttribute.setMlMathvariant(&aMathvariant);
1027 break;
1029 case XML_MAXSIZE:
1031 SmMlMaxsize aMaxsize;
1032 if (IsXMLToken(aIter, XML_INFINITY))
1034 aMaxsize.m_aMaxsize = SmMlAttributeValueMaxsize::MlInfinity;
1035 aMaxsize.m_aLengthValue
1036 = { SmLengthUnit::MlP, 10000, new OUString(u"10000%"_ustr) };
1038 else
1040 aMaxsize.m_aMaxsize = SmMlAttributeValueMaxsize::MlFinite;
1041 aMaxsize.m_aLengthValue = handleLengthAttribute(aIter.toString());
1043 aAttribute.setMlMaxsize(&aMaxsize);
1044 break;
1046 case XML_MINSIZE:
1048 SmMlMinsize aMinsize;
1049 aMinsize.m_aLengthValue = handleLengthAttribute(aIter.toString());
1050 aAttribute.setMlMinsize(&aMinsize);
1051 break;
1053 case XML_MOVABLELIMITS:
1054 if (IsXMLToken(aIter, XML_TRUE))
1056 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlMovablelimits);
1057 SmMlMovablelimits aMovablelimits = { SmMlAttributeValueMovablelimits::MlTrue };
1058 aAttribute.setMlMovablelimits(&aMovablelimits);
1060 else if (IsXMLToken(aIter, XML_FALSE))
1062 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlMovablelimits);
1063 SmMlMovablelimits aMovablelimits = { SmMlAttributeValueMovablelimits::MlFalse };
1064 aAttribute.setMlMovablelimits(&aMovablelimits);
1066 else
1068 declareMlError();
1070 break;
1071 case XML_RSPACE:
1073 SmMlRspace aRspace;
1074 aRspace.m_aLengthValue = handleLengthAttribute(aIter.toString());
1075 aAttribute.setMlRspace(&aRspace);
1076 break;
1078 case XML_SEPARATOR:
1079 if (IsXMLToken(aIter, XML_TRUE))
1081 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSeparator);
1082 SmMlSeparator aSeparator = { SmMlAttributeValueSeparator::MlTrue };
1083 aAttribute.setMlSeparator(&aSeparator);
1085 else if (IsXMLToken(aIter, XML_FALSE))
1087 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSeparator);
1088 SmMlSeparator aSeparator = { SmMlAttributeValueSeparator::MlFalse };
1089 aAttribute.setMlSeparator(&aSeparator);
1091 else
1093 declareMlError();
1095 break;
1096 case XML_STRETCHY:
1097 if (IsXMLToken(aIter, XML_TRUE))
1099 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlStretchy);
1100 SmMlStretchy aStretchy = { SmMlAttributeValueStretchy::MlTrue };
1101 aAttribute.setMlStretchy(&aStretchy);
1103 else if (IsXMLToken(aIter, XML_FALSE))
1105 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlStretchy);
1106 SmMlStretchy aStretchy = { SmMlAttributeValueStretchy::MlFalse };
1107 aAttribute.setMlStretchy(&aStretchy);
1109 else
1111 declareMlError();
1113 break;
1114 case XML_SYMMETRIC:
1115 if (IsXMLToken(aIter, XML_TRUE))
1117 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSymmetric);
1118 SmMlSymmetric aSymmetric = { SmMlAttributeValueSymmetric::MlTrue };
1119 aAttribute.setMlSymmetric(&aSymmetric);
1121 else if (IsXMLToken(aIter, XML_FALSE))
1123 aAttribute.setMlAttributeValueType(SmMlAttributeValueType::MlSymmetric);
1124 SmMlSymmetric aSymmetric = { SmMlAttributeValueSymmetric::MlFalse };
1125 aAttribute.setMlSymmetric(&aSymmetric);
1127 else
1129 declareMlError();
1131 break;
1132 default:
1133 declareMlError();
1134 break;
1136 if (aAttribute.isNullAttribute())
1137 declareMlError();
1138 else
1139 m_pElement->setAttribute(aAttribute);
1143 void SmMLImportContext::characters(const OUString& aChars) { m_pElement->setText(aChars); }
1145 void SmMLImportContext::startFastElement(sal_Int32 nElement,
1146 const Reference<XFastAttributeList>& aAttributeList)
1148 switch (nElement)
1150 case XML_ELEMENT(MATH, XML_MATH):
1151 m_pElement = new SmMlElement(SmMlElementType::MlMath);
1152 break;
1153 case XML_ELEMENT(MATH, XML_MI):
1154 m_pElement = new SmMlElement(SmMlElementType::MlMi);
1155 break;
1156 case XML_ELEMENT(MATH, XML_MERROR):
1157 m_pElement = new SmMlElement(SmMlElementType::MlMerror);
1158 break;
1159 case XML_ELEMENT(MATH, XML_MN):
1160 m_pElement = new SmMlElement(SmMlElementType::MlMn);
1161 break;
1162 case XML_ELEMENT(MATH, XML_MO):
1163 m_pElement = new SmMlElement(SmMlElementType::MlMo);
1164 break;
1165 case XML_ELEMENT(MATH, XML_MROW):
1166 m_pElement = new SmMlElement(SmMlElementType::MlMrow);
1167 break;
1168 case XML_ELEMENT(MATH, XML_MTEXT):
1169 m_pElement = new SmMlElement(SmMlElementType::MlMtext);
1170 break;
1171 case XML_ELEMENT(MATH, XML_MSTYLE):
1172 m_pElement = new SmMlElement(SmMlElementType::MlMstyle);
1173 break;
1174 default:
1175 m_pElement = new SmMlElement(SmMlElementType::NMlEmpty);
1176 declareMlError();
1177 break;
1179 SmMlElement* pParent = *m_pParent;
1180 pParent->setSubElement(pParent->getSubElementsCount(), m_pElement);
1181 inheritStyle();
1182 handleAttributes(aAttributeList);
1185 void SmMLImportContext::endFastElement(sal_Int32) { inheritStyleEnd(); }
1188 // SmMLImport
1189 /*************************************************************************************************/
1191 SvXMLImportContext*
1192 SmMLImport::CreateFastContext(sal_Int32 nElement,
1193 const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
1195 SvXMLImportContext* pContext = nullptr;
1197 switch (nElement)
1199 case XML_ELEMENT(OFFICE, XML_DOCUMENT):
1201 if (m_pElementTree == nullptr)
1202 m_pElementTree = new SmMlElement(SmMlElementType::NMlEmpty);
1203 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(),
1204 uno::UNO_QUERY_THROW);
1205 pContext = new SmMLImportContext(*this, &m_pElementTree);
1206 break;
1208 case XML_ELEMENT(OFFICE, XML_DOCUMENT_META):
1210 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(),
1211 uno::UNO_QUERY_THROW);
1212 pContext = new SvXMLMetaDocumentContext(*this, xDPS->getDocumentProperties());
1213 break;
1215 case XML_ELEMENT(OFFICE, XML_DOCUMENT_SETTINGS):
1217 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(),
1218 uno::UNO_QUERY_THROW);
1219 pContext = new XMLDocumentSettingsContext(*this);
1220 break;
1222 default:
1223 declareMlError();
1224 break;
1226 return pContext;
1229 void SmMLImport::endDocument()
1231 uno::Reference<frame::XModel> xModel = GetModel();
1232 if (!xModel.is())
1234 SAL_WARN("starmath", "Failed to set view settings because missing model");
1235 SvXMLImport::endDocument();
1236 return;
1239 SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel);
1240 if (!pModel)
1242 SAL_WARN("starmath", "Failed to set view settings because missing sm model");
1243 SvXMLImport::endDocument();
1244 return;
1247 SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
1248 if (!pDocShell)
1250 SAL_WARN("starmath", "Failed to set view settings because missing sm doc shell");
1251 SvXMLImport::endDocument();
1252 return;
1255 // Check if there is element tree
1256 if (m_pElementTree == nullptr)
1258 m_bSuccess = true;
1259 SvXMLImport::endDocument();
1260 return;
1263 // Get element tree and setup
1265 if (m_pElementTree->getSubElementsCount() == 0)
1267 delete m_pElementTree;
1268 m_pElementTree = nullptr;
1270 else
1272 SmMlElement* pTmpElememt = m_pElementTree->getSubElement(0);
1273 delete m_pElementTree;
1274 m_pElementTree = pTmpElememt;
1276 pDocShell->SetMlElementTree(m_pElementTree);
1278 m_bSuccess = true;
1279 SvXMLImport::endDocument();
1282 void SmMLImport::SetViewSettings(const Sequence<PropertyValue>& aViewProps)
1284 uno::Reference<frame::XModel> xModel = GetModel();
1285 if (!xModel.is())
1287 SAL_WARN("starmath", "Failed to set view settings because missing model");
1288 return;
1291 SmModel* pModel = comphelper::getFromUnoTunnel<SmModel>(xModel);
1292 if (!pModel)
1294 SAL_WARN("starmath", "Failed to set view settings because missing sm model");
1295 return;
1298 SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
1299 if (!pDocShell)
1301 SAL_WARN("starmath", "Failed to set view settings because missing sm doc shell");
1302 return;
1305 tools::Rectangle aRect(pDocShell->GetVisArea());
1307 tools::Long nTmp = 0;
1309 for (const PropertyValue& rValue : aViewProps)
1311 if (rValue.Name == "ViewAreaTop")
1313 rValue.Value >>= nTmp;
1314 aRect.SaturatingSetPosY(nTmp);
1316 else if (rValue.Name == "ViewAreaLeft")
1318 rValue.Value >>= nTmp;
1319 aRect.SaturatingSetPosX(nTmp);
1321 else if (rValue.Name == "ViewAreaWidth")
1323 rValue.Value >>= nTmp;
1324 Size aSize(aRect.GetSize());
1325 aSize.setWidth(nTmp);
1326 aRect.SaturatingSetSize(aSize);
1328 else if (rValue.Name == "ViewAreaHeight")
1330 rValue.Value >>= nTmp;
1331 Size aSize(aRect.GetSize());
1332 aSize.setHeight(nTmp);
1333 aRect.SaturatingSetSize(aSize);
1337 pDocShell->SetVisArea(aRect);
1340 void SmMLImport::SetConfigurationSettings(const Sequence<PropertyValue>& aConfProps)
1342 uno::Reference<frame::XModel> xModel = GetModel();
1343 if (!xModel.is())
1345 SAL_WARN("starmath", "Failed to set view settings because missing model");
1346 return;
1349 uno::Reference<XPropertySet> xProps(xModel, UNO_QUERY);
1350 if (!xProps.is())
1352 SAL_WARN("starmath", "Failed to set view settings because missing model properties");
1353 return;
1356 Reference<XPropertySetInfo> xInfo(xProps->getPropertySetInfo());
1357 if (!xInfo.is())
1359 SAL_WARN("starmath",
1360 "Failed to set view settings because missing model properties information");
1361 return;
1364 static constexpr OUStringLiteral sFormula(u"Formula");
1365 static constexpr OUStringLiteral sBasicLibraries(u"BasicLibraries");
1366 static constexpr OUStringLiteral sDialogLibraries(u"DialogLibraries");
1367 for (const PropertyValue& rValue : aConfProps)
1369 if (rValue.Name != sFormula && rValue.Name != sBasicLibraries
1370 && rValue.Name != sDialogLibraries)
1374 if (xInfo->hasPropertyByName(rValue.Name))
1375 xProps->setPropertyValue(rValue.Name, rValue.Value);
1377 catch (const beans::PropertyVetoException&)
1379 // dealing with read-only properties here. Nothing to do...
1381 catch (const Exception&)
1383 SAL_WARN("starmath", "Unexpected issue while loading document properties");
1389 SmMLImport::SmMLImport(const css::uno::Reference<css::uno::XComponentContext>& rContext,
1390 OUString const& implementationName, SvXMLImportFlags nImportFlags)
1391 : SvXMLImport(rContext, implementationName, nImportFlags)
1392 , m_pElementTree(nullptr)
1393 , m_bSuccess(false)
1394 , m_nSmSyntaxVersion(SmModule::get()->GetConfig()->GetDefaultSmSyntaxVersion())
1398 /** Handles an error on the mathml structure
1400 void SmMLImport::declareMlError()
1402 m_bSuccess = false;
1403 SAL_WARN("starmath", "MathML error");
1406 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */