LibreOffice Module starmath (master) 1
mathmlimport.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20/*todo: Change characters and tcharacters to accumulate the characters together
21into one string, xml parser hands them to us line by line rather than all in
22one go*/
23
24#include <com/sun/star/xml/sax/InputSource.hpp>
25#include <com/sun/star/xml/sax/FastParser.hpp>
26#include <com/sun/star/xml/sax/Parser.hpp>
27#include <com/sun/star/xml/sax/SAXParseException.hpp>
28#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
29#include <com/sun/star/packages/WrongPasswordException.hpp>
30#include <com/sun/star/packages/zip/ZipIOException.hpp>
31#include <com/sun/star/beans/PropertyAttribute.hpp>
32#include <com/sun/star/embed/ElementModes.hpp>
33#include <com/sun/star/uno/Any.h>
34#include <com/sun/star/task/XStatusIndicator.hpp>
35
41#include <rtl/character.hxx>
42#include <sal/log.hxx>
43#include <sfx2/frame.hxx>
44#include <sfx2/docfile.hxx>
45#include <sfx2/sfxsids.hrc>
47#include <osl/diagnose.h>
48#include <sot/storage.hxx>
49#include <svtools/sfxecode.hxx>
50#include <svl/itemset.hxx>
51#include <svl/stritem.hxx>
56#include <xmloff/xmltoken.hxx>
57#include <xmloff/xmluconv.hxx>
58#include <xmloff/xmlmetai.hxx>
59#include <svx/dialmgr.hxx>
60#include <svx/strings.hrc>
62#include <o3tl/string_view.hxx>
63
64#include <mathmlattr.hxx>
65#include <xparsmlbase.hxx>
66#include <mathmlimport.hxx>
67#include <document.hxx>
68#include <smdll.hxx>
69#include <unomodel.hxx>
70#include <utility.hxx>
71#include <visitors.hxx>
72#include <starmathdatabase.hxx>
73#include <smmod.hxx>
74#include <cfgitem.hxx>
75
76using namespace ::com::sun::star::beans;
77using namespace ::com::sun::star::container;
78using namespace ::com::sun::star::document;
79using namespace ::com::sun::star::lang;
80using namespace ::com::sun::star::uno;
81using namespace ::com::sun::star;
82using namespace ::xmloff::token;
83
84namespace
85{
86std::unique_ptr<SmNode> popOrZero(SmNodeStack& rStack)
87{
88 if (rStack.empty())
89 return nullptr;
90 auto pTmp = std::move(rStack.front());
91 rStack.pop_front();
92 return pTmp;
93}
94}
95
97{
99
100 uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
101
102 OSL_ENSURE(m_xModel.is(), "XMLReader::Read: got no model");
103
104 // try to get an XStatusIndicator from the Medium
105 uno::Reference<task::XStatusIndicator> xStatusIndicator;
106
107 bool bEmbedded = false;
108 SmModel* pModel = m_xModel.get();
109
110 SmDocShell* pDocShell = pModel ? static_cast<SmDocShell*>(pModel->GetObjectShell()) : nullptr;
111 if (pDocShell)
112 {
113 OSL_ENSURE(pDocShell->GetMedium() == &rMedium, "different SfxMedium found");
114
115 const SfxUnoAnyItem* pItem = rMedium.GetItemSet().GetItem(SID_PROGRESS_STATUSBAR_CONTROL);
116 if (pItem)
117 pItem->GetValue() >>= xStatusIndicator;
118
119 if (SfxObjectCreateMode::EMBEDDED == pDocShell->GetCreateMode())
120 bEmbedded = true;
121 }
122
123 static const comphelper::PropertyMapEntry aInfoMap[]
124 = { { OUString("PrivateData"), 0, cppu::UnoType<XInterface>::get(),
125 beans::PropertyAttribute::MAYBEVOID, 0 },
126 { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(),
127 beans::PropertyAttribute::MAYBEVOID, 0 },
128 { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(),
129 beans::PropertyAttribute::MAYBEVOID, 0 },
130 { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(),
131 beans::PropertyAttribute::MAYBEVOID, 0 } };
132 uno::Reference<beans::XPropertySet> xInfoSet(
134
135 // Set base URI
136 OUString const baseURI(rMedium.GetBaseURL());
137 // needed for relative URLs; but it's OK to import e.g. MathML from the
138 // clipboard without one
139 SAL_INFO_IF(baseURI.isEmpty(), "starmath", "SmXMLImportWrapper: no base URL");
140 xInfoSet->setPropertyValue("BaseURI", Any(baseURI));
141
142 sal_Int32 nSteps = 3;
143 if (!(rMedium.IsStorage()))
144 nSteps = 1;
145
146 sal_Int32 nProgressRange(nSteps);
147 if (xStatusIndicator.is())
148 {
149 xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange);
150 }
151
152 nSteps = 0;
153 if (xStatusIndicator.is())
154 xStatusIndicator->setValue(nSteps++);
155
156 if (rMedium.IsStorage())
157 {
158 // TODO/LATER: handle the case of embedded links gracefully
159 if (bEmbedded) // && !rMedium.GetStorage()->IsRoot() )
160 {
161 OUString aName("dummyObjName");
162 const SfxStringItem* pDocHierarchItem
163 = rMedium.GetItemSet().GetItem(SID_DOC_HIERARCHICALNAME);
164 if (pDocHierarchItem)
165 aName = pDocHierarchItem->GetValue();
166
167 if (!aName.isEmpty())
168 {
169 xInfoSet->setPropertyValue("StreamRelPath", Any(aName));
170 }
171 }
172
173 bool bOASIS = (SotStorage::GetVersion(rMedium.GetStorage()) > SOFFICE_FILEFORMAT_60);
174 if (xStatusIndicator.is())
175 xStatusIndicator->setValue(nSteps++);
176
177 auto nWarn
178 = ReadThroughComponent(rMedium.GetStorage(), m_xModel, "meta.xml", xContext, xInfoSet,
179 (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaImporter"
180 : "com.sun.star.comp.Math.XMLMetaImporter"),
182
183 if (nWarn != ERRCODE_IO_BROKENPACKAGE)
184 {
185 if (xStatusIndicator.is())
186 xStatusIndicator->setValue(nSteps++);
187
188 nWarn = ReadThroughComponent(rMedium.GetStorage(), m_xModel, "settings.xml", xContext,
189 xInfoSet,
190 (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsImporter"
191 : "com.sun.star.comp.Math.XMLSettingsImporter"),
193
194 if (nWarn != ERRCODE_IO_BROKENPACKAGE)
195 {
196 if (xStatusIndicator.is())
197 xStatusIndicator->setValue(nSteps++);
198
199 nError = ReadThroughComponent(
200 rMedium.GetStorage(), m_xModel, "content.xml", xContext, xInfoSet,
201 "com.sun.star.comp.Math.XMLImporter", m_bUseHTMLMLEntities);
202 }
203 else
205 }
206 else
208 }
209 else
210 {
211 Reference<io::XInputStream> xInputStream
212 = new utl::OInputStreamWrapper(rMedium.GetInStream());
213
214 if (xStatusIndicator.is())
215 xStatusIndicator->setValue(nSteps++);
216
217 nError = ReadThroughComponent(xInputStream, m_xModel, xContext, xInfoSet,
218 "com.sun.star.comp.Math.XMLImporter", false,
220 }
221
222 if (xStatusIndicator.is())
223 xStatusIndicator->end();
224 return nError;
225}
226
228ErrCode SmXMLImportWrapper::ReadThroughComponent(const Reference<io::XInputStream>& xInputStream,
229 const Reference<XComponent>& xModelComponent,
230 Reference<uno::XComponentContext> const& rxContext,
231 Reference<beans::XPropertySet> const& rPropSet,
232 const char* pFilterName, bool bEncrypted,
233 bool bUseHTMLMLEntities)
234{
236 OSL_ENSURE(xInputStream.is(), "input stream missing");
237 OSL_ENSURE(xModelComponent.is(), "document missing");
238 OSL_ENSURE(rxContext.is(), "factory missing");
239 OSL_ENSURE(nullptr != pFilterName, "I need a service name for the component!");
240
241 // prepare ParserInputSource
242 xml::sax::InputSource aParserInput;
243 aParserInput.aInputStream = xInputStream;
244
245 Sequence<Any> aArgs{ Any(rPropSet) };
246
247 // get filter
248 Reference<XInterface> xFilter
249 = rxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
250 OUString::createFromAscii(pFilterName), aArgs, rxContext);
251 SAL_WARN_IF(!xFilter, "starmath", "Can't instantiate filter component " << pFilterName);
252 if (!xFilter.is())
253 return nError;
254
255 // connect model and filter
256 Reference<XImporter> xImporter(xFilter, UNO_QUERY);
257 xImporter->setTargetDocument(xModelComponent);
258
259 // finally, parser the stream
260 try
261 {
262 Reference<css::xml::sax::XFastParser> xFastParser(xFilter, UNO_QUERY);
263 Reference<css::xml::sax::XFastDocumentHandler> xFastDocHandler(xFilter, UNO_QUERY);
264 if (xFastParser)
265 {
266 if (bUseHTMLMLEntities)
267 xFastParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities);
268 xFastParser->parseStream(aParserInput);
269 }
270 else if (xFastDocHandler)
271 {
272 Reference<css::xml::sax::XFastParser> xParser
273 = css::xml::sax::FastParser::create(rxContext);
274 if (bUseHTMLMLEntities)
275 xParser->setCustomEntityNames(starmathdatabase::icustomMathmlHtmlEntities);
276 xParser->setFastDocumentHandler(xFastDocHandler);
277 xParser->parseStream(aParserInput);
278 }
279 else
280 {
281 Reference<css::xml::sax::XDocumentHandler> xDocHandler(xFilter, UNO_QUERY);
282 assert(xDocHandler);
283 Reference<css::xml::sax::XParser> xParser = css::xml::sax::Parser::create(rxContext);
284 xParser->setDocumentHandler(xDocHandler);
285 xParser->parseStream(aParserInput);
286 }
287
288 auto pFilter = dynamic_cast<SmXMLImport*>(xFilter.get());
289 if (pFilter && pFilter->GetSuccess())
290 nError = ERRCODE_NONE;
291 }
292 catch (const xml::sax::SAXParseException& r)
293 {
294 // sax parser sends wrapped exceptions,
295 // try to find the original one
296 xml::sax::SAXException aSaxEx = *static_cast<const xml::sax::SAXException*>(&r);
297 bool bTryChild = true;
298
299 while (bTryChild)
300 {
301 xml::sax::SAXException aTmp;
302 if (aSaxEx.WrappedException >>= aTmp)
303 aSaxEx = aTmp;
304 else
305 bTryChild = false;
306 }
307
308 packages::zip::ZipIOException aBrokenPackage;
309 if (aSaxEx.WrappedException >>= aBrokenPackage)
311
312 if (bEncrypted)
314 }
315 catch (const xml::sax::SAXException& r)
316 {
317 packages::zip::ZipIOException aBrokenPackage;
318 if (r.WrappedException >>= aBrokenPackage)
320
321 if (bEncrypted)
323 }
324 catch (const packages::zip::ZipIOException&)
325 {
327 }
328 catch (const io::IOException&)
329 {
330 }
331 catch (const std::range_error&)
332 {
333 }
334
335 return nError;
336}
337
338ErrCode SmXMLImportWrapper::ReadThroughComponent(const uno::Reference<embed::XStorage>& xStorage,
339 const Reference<XComponent>& xModelComponent,
340 const char* pStreamName,
341 Reference<uno::XComponentContext> const& rxContext,
342 Reference<beans::XPropertySet> const& rPropSet,
343 const char* pFilterName, bool bUseHTMLMLEntities)
344{
345 OSL_ENSURE(xStorage.is(), "Need storage!");
346 OSL_ENSURE(nullptr != pStreamName, "Please, please, give me a name!");
347
348 // open stream (and set parser input)
349 OUString sStreamName = OUString::createFromAscii(pStreamName);
350
351 // get input stream
352 try
353 {
354 uno::Reference<io::XStream> xEventsStream
355 = xStorage->openStreamElement(sStreamName, embed::ElementModes::READ);
356
357 // determine if stream is encrypted or not
358 uno::Reference<beans::XPropertySet> xProps(xEventsStream, uno::UNO_QUERY);
359 Any aAny = xProps->getPropertyValue("Encrypted");
360 bool bEncrypted = false;
361 if (aAny.getValueType() == cppu::UnoType<bool>::get())
362 aAny >>= bEncrypted;
363
364 // set Base URL
365 if (rPropSet.is())
366 {
367 rPropSet->setPropertyValue("StreamName", Any(sStreamName));
368 }
369
370 Reference<io::XInputStream> xStream = xEventsStream->getInputStream();
371 return ReadThroughComponent(xStream, xModelComponent, rxContext, rPropSet, pFilterName,
372 bEncrypted, bUseHTMLMLEntities);
373 }
374 catch (packages::WrongPasswordException&)
375 {
377 }
378 catch (packages::zip::ZipIOException&)
379 {
381 }
382 catch (uno::Exception&)
383 {
384 }
385
387}
388
389SmXMLImport::SmXMLImport(const css::uno::Reference<css::uno::XComponentContext>& rContext,
390 OUString const& implementationName, SvXMLImportFlags nImportFlags)
391 : SvXMLImport(rContext, implementationName, nImportFlags)
392 , bSuccess(false)
393 , nParseDepth(0)
394 , mnSmSyntaxVersion(SM_MOD()->GetConfig()->GetDefaultSmSyntaxVersion())
395{
396}
397
398extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
399Math_XMLImporter_get_implementation(uno::XComponentContext* pCtx,
400 uno::Sequence<uno::Any> const& /*rSeq*/)
401{
402 return cppu::acquire(
403 new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLImporter", SvXMLImportFlags::ALL));
404}
405
406extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
408 uno::Sequence<uno::Any> const& /*rSeq*/)
409{
410 return cppu::acquire(new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisMetaImporter",
411 SvXMLImportFlags::META));
412}
413
414extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
416 uno::Sequence<uno::Any> const& /*rSeq*/)
417{
418 return cppu::acquire(new SmXMLImport(pCtx, "com.sun.star.comp.Math.XMLOasisSettingsImporter",
419 SvXMLImportFlags::SETTINGS));
420}
421
423{
424 //Set the resulted tree into the SmDocShell where it belongs
425 std::unique_ptr<SmNode> pTree = popOrZero(aNodeStack);
426 if (pTree && pTree->GetType() == SmNodeType::Table)
427 {
428 uno::Reference<frame::XModel> xModel = GetModel();
429 SmModel* pModel = dynamic_cast<SmModel*>(xModel.get());
430
431 if (pModel)
432 {
433 SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
434 auto pTreeTmp = pTree.get();
435 pDocShell->SetFormulaTree(static_cast<SmTableNode*>(pTree.release()));
436 if (aText.isEmpty()) //If we picked up no annotation text
437 {
438 // Get text from imported formula
439 SmNodeToTextVisitor tmpvisitor(pTreeTmp, aText);
440 }
441
442 // Convert symbol names
443 AbstractSmParser* rParser = pDocShell->GetParser();
444 bool bVal = rParser->IsImportSymbolNames();
445 rParser->SetImportSymbolNames(true);
446 auto pTmpTree = rParser->Parse(aText);
447 aText = rParser->GetText();
448 pTmpTree.reset();
449 rParser->SetImportSymbolNames(bVal);
450
451 pDocShell->SetText(aText);
453 }
454 OSL_ENSURE(pModel, "So there *was* a UNO problem after all");
455
456 bSuccess = true;
457 }
458
459 SvXMLImport::endDocument();
460}
461
462namespace
463{
464class SmXMLImportContext : public SvXMLImportContext
465{
466public:
467 SmXMLImportContext(SmXMLImport& rImport)
468 : SvXMLImportContext(rImport)
469 {
470 GetSmImport().IncParseDepth();
471 }
472
473 virtual ~SmXMLImportContext() override { GetSmImport().DecParseDepth(); }
474
475 SmXMLImport& GetSmImport() { return static_cast<SmXMLImport&>(GetImport()); }
476
477 virtual void TCharacters(const OUString& /*rChars*/);
478 virtual void SAL_CALL characters(const OUString& rChars) override;
479 virtual void SAL_CALL startFastElement(
480 sal_Int32 /*nElement*/,
481 const css::uno::Reference<css::xml::sax::XFastAttributeList>& /*rAttrList*/) override
482 {
483 if (GetSmImport().TooDeep())
484 throw std::range_error("too deep");
485 }
486};
487}
488
489void SmXMLImportContext::TCharacters(const OUString& /*rChars*/) {}
490
491void SmXMLImportContext::characters(const OUString& rChars)
492{
493 /*
494 Whitespace occurring within the content of token elements is "trimmed"
495 from the ends (i.e. all whitespace at the beginning and end of the
496 content is removed), and "collapsed" internally (i.e. each sequence of
497 1 or more whitespace characters is replaced with one blank character).
498 */
499 //collapsing not done yet!
500 const OUString& rChars2 = rChars.trim();
501 if (!rChars2.isEmpty())
502 TCharacters(rChars2 /*.collapse()*/);
503}
504
505namespace
506{
507struct SmXMLContext_Helper
508{
509 sal_Int8 nIsBold;
510 sal_Int8 nIsItalic;
511 double nFontSize;
512 OUString sFontFamily;
513 OUString sColor;
514
515 SmXMLImportContext& rContext;
516
517 explicit SmXMLContext_Helper(SmXMLImportContext& rImport)
518 : nIsBold(-1)
519 , nIsItalic(-1)
520 , nFontSize(0.0)
521 , rContext(rImport)
522 {
523 }
524
525 bool IsFontNodeNeeded() const;
526 void RetrieveAttrs(const uno::Reference<xml::sax::XFastAttributeList>& xAttrList);
527 void ApplyAttrs();
528};
529}
530
531bool SmXMLContext_Helper::IsFontNodeNeeded() const
532{
533 return nIsBold != -1 || nIsItalic != -1 || nFontSize != 0.0 || !sFontFamily.isEmpty()
534 || !sColor.isEmpty();
535}
536
537void SmXMLContext_Helper::RetrieveAttrs(
538 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
539{
540 bool bMvFound = false;
541 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
542 {
543 // sometimes they have namespace, sometimes not?
544 switch (aIter.getToken() & TOKEN_MASK)
545 {
546 case XML_FONTWEIGHT:
547 nIsBold = sal_Int8(IsXMLToken(aIter, XML_BOLD));
548 break;
549 case XML_FONTSTYLE:
550 nIsItalic = sal_Int8(IsXMLToken(aIter, XML_ITALIC));
551 break;
552 case XML_FONTSIZE:
553 case XML_MATHSIZE:
554 {
555 OUString sValue = aIter.toString();
556 ::sax::Converter::convertDouble(nFontSize, sValue);
557 rContext.GetSmImport().GetMM100UnitConverter().SetXMLMeasureUnit(
558 util::MeasureUnit::POINT);
559 if (-1 == sValue.indexOf(GetXMLToken(XML_UNIT_PT)))
560 {
561 if (-1 == sValue.indexOf('%'))
562 nFontSize = 0.0;
563 else
564 {
565 rContext.GetSmImport().GetMM100UnitConverter().SetXMLMeasureUnit(
566 util::MeasureUnit::PERCENT);
567 }
568 }
569 break;
570 }
571 case XML_FONTFAMILY:
572 sFontFamily = aIter.toString();
573 break;
574 case XML_COLOR:
575 sColor = aIter.toString();
576 break;
577 case XML_MATHCOLOR:
578 sColor = aIter.toString();
579 break;
580 case XML_MATHVARIANT:
581 bMvFound = true;
582 break;
583 default:
584 XMLOFF_WARN_UNKNOWN("starmath", aIter);
585 break;
586 }
587 }
588
589 if (bMvFound)
590 {
591 // Ignore deprecated attributes fontfamily, fontweight, and fontstyle
592 // in favor of mathvariant, as specified in
593 // <https://www.w3.org/TR/MathML3/chapter3.html#presm.deprecatt>.
594 sFontFamily.clear();
595 nIsBold = -1;
596 nIsItalic = -1;
597 }
598}
599
600void SmXMLContext_Helper::ApplyAttrs()
601{
602 SmNodeStack& rNodeStack = rContext.GetSmImport().GetNodeStack();
603
604 if (!IsFontNodeNeeded())
605 return;
606
607 SmToken aToken;
608 aToken.cMathChar = u"";
609 aToken.nLevel = 5;
610
611 if (nIsBold != -1)
612 {
613 if (nIsBold)
614 aToken.eType = TBOLD;
615 else
616 aToken.eType = TNBOLD;
617 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
618 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
619 rNodeStack.push_front(std::move(pFontNode));
620 }
621 if (nIsItalic != -1)
622 {
623 if (nIsItalic)
624 aToken.eType = TITALIC;
625 else
626 aToken.eType = TNITALIC;
627 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
628 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
629 rNodeStack.push_front(std::move(pFontNode));
630 }
631 if (nFontSize != 0.0)
632 {
633 aToken.eType = TSIZE;
634 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
635
636 if (util::MeasureUnit::PERCENT
637 == rContext.GetSmImport().GetMM100UnitConverter().GetXMLMeasureUnit())
638 {
639 if (nFontSize < 100.00)
640 pFontNode->SetSizeParameter(Fraction(100.00 / nFontSize), FontSizeType::DIVIDE);
641 else
642 pFontNode->SetSizeParameter(Fraction(nFontSize / 100.00), FontSizeType::MULTIPLY);
643 }
644 else
645 pFontNode->SetSizeParameter(Fraction(nFontSize), FontSizeType::ABSOLUT);
646
647 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
648 rNodeStack.push_front(std::move(pFontNode));
649 }
650 if (!sColor.isEmpty())
651 {
652 SmColorTokenTableEntry aSmColorTokenTableEntry;
653 aSmColorTokenTableEntry = starmathdatabase::Identify_ColorName_HTML(sColor);
654 if (aSmColorTokenTableEntry.eType == TRGB)
655 aSmColorTokenTableEntry = starmathdatabase::Identify_Color_Parser(
656 sal_uInt32(aSmColorTokenTableEntry.cColor));
657 if (aSmColorTokenTableEntry.eType != TERROR)
658 {
659 aToken = aSmColorTokenTableEntry;
660 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
661 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
662 rNodeStack.push_front(std::move(pFontNode));
663 }
664 // If not known, not implemented yet. Giving up.
665 }
666 if (sFontFamily.isEmpty())
667 return;
668
669 if (sFontFamily.equalsIgnoreAsciiCase(GetXMLToken(XML_FIXED)))
670 aToken.eType = TFIXED;
671 else if (sFontFamily.equalsIgnoreAsciiCase("sans"))
672 aToken.eType = TSANS;
673 else if (sFontFamily.equalsIgnoreAsciiCase("serif"))
674 aToken.eType = TSERIF;
675 else //Just give up, we need to extend our font mechanism to be
676 //more general
677 return;
678
679 aToken.aText = sFontFamily;
680 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
681 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
682 rNodeStack.push_front(std::move(pFontNode));
683}
684
685namespace
686{
687class SmXMLTokenAttrHelper
688{
689 SmXMLImportContext& mrContext;
691 bool mbMvFound;
692
693public:
694 SmXMLTokenAttrHelper(SmXMLImportContext& rContext)
695 : mrContext(rContext)
697 , mbMvFound(false)
698 {
699 }
700
701 void RetrieveAttrs(const uno::Reference<xml::sax::XFastAttributeList>& xAttrList);
702 void ApplyAttrs(MathMLMathvariantValue eDefaultMv);
703};
704}
705
706void SmXMLTokenAttrHelper::RetrieveAttrs(
707 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
708{
709 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
710 {
711 OUString sValue = aIter.toString();
712 switch (aIter.getToken())
713 {
714 case XML_MATHVARIANT:
715 if (!GetMathMLMathvariantValue(sValue, meMv))
716 SAL_WARN("starmath", "failed to recognize mathvariant: " << sValue);
717 mbMvFound = true;
718 break;
719 default:
720 XMLOFF_WARN_UNKNOWN("starmath", aIter);
721 break;
722 }
723 }
724}
725
726void SmXMLTokenAttrHelper::ApplyAttrs(MathMLMathvariantValue eDefaultMv)
727{
728 assert(eDefaultMv == MathMLMathvariantValue::Normal
729 || eDefaultMv == MathMLMathvariantValue::Italic);
730
731 std::vector<SmTokenType> vVariant;
732 MathMLMathvariantValue eMv = mbMvFound ? meMv : eDefaultMv;
733 switch (eMv)
734 {
736 vVariant.push_back(TNITALIC);
737 break;
739 vVariant.push_back(TBOLD);
740 break;
742 // nothing to do
743 break;
745 vVariant.push_back(TITALIC);
746 vVariant.push_back(TBOLD);
747 break;
749 // TODO
750 break;
752 // TODO: Fraktur
753 vVariant.push_back(TBOLD);
754 break;
756 // TODO
757 break;
759 // TODO: Script
760 vVariant.push_back(TBOLD);
761 break;
763 // TODO
764 break;
766 vVariant.push_back(TSANS);
767 break;
769 vVariant.push_back(TSANS);
770 vVariant.push_back(TBOLD);
771 break;
773 vVariant.push_back(TITALIC);
774 vVariant.push_back(TSANS);
775 break;
777 vVariant.push_back(TITALIC);
778 vVariant.push_back(TBOLD);
779 vVariant.push_back(TSANS);
780 break;
782 vVariant.push_back(TFIXED);
783 break;
788 // TODO
789 break;
790 }
791 if (vVariant.empty())
792 return;
793 SmNodeStack& rNodeStack = mrContext.GetSmImport().GetNodeStack();
794 for (auto eType : vVariant)
795 {
796 SmToken aToken;
797 aToken.eType = eType;
798 aToken.cMathChar = u"";
799 aToken.nLevel = 5;
800 std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(aToken));
801 pFontNode->SetSubNodes(nullptr, popOrZero(rNodeStack));
802 rNodeStack.push_front(std::move(pFontNode));
803 }
804}
805
806namespace
807{
808class SmXMLDocContext_Impl : public SmXMLImportContext
809{
810public:
811 SmXMLDocContext_Impl(SmXMLImport& rImport)
812 : SmXMLImportContext(rImport)
813 {
814 }
815
816 virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
817 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
818
819 void SAL_CALL endFastElement(sal_Int32 nElement) override;
820};
821
822/*avert the gaze from the originator*/
823class SmXMLRowContext_Impl : public SmXMLDocContext_Impl
824{
825protected:
826 size_t nElementCount;
827
828public:
829 SmXMLRowContext_Impl(SmXMLImport& rImport)
830 : SmXMLDocContext_Impl(rImport)
831 , nElementCount(GetSmImport().GetNodeStack().size())
832 {
833 }
834
835 virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
836 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
837
838 uno::Reference<xml::sax::XFastContextHandler> StrictCreateChildContext(sal_Int32 nElement);
839
840 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
841};
842
843class SmXMLEncloseContext_Impl : public SmXMLRowContext_Impl
844{
845public:
846 // TODO/LATER: convert <menclose notation="horizontalstrike"> into
847 // "overstrike{}" and extend the Math syntax to support more notations
848 SmXMLEncloseContext_Impl(SmXMLImport& rImport)
849 : SmXMLRowContext_Impl(rImport)
850 {
851 }
852
853 void SAL_CALL endFastElement(sal_Int32 nElement) override;
854};
855}
856
857void SmXMLEncloseContext_Impl::endFastElement(sal_Int32 nElement)
858{
859 /*
860 <menclose> accepts any number of arguments; if this number is not 1, its
861 contents are treated as a single "inferred <mrow>" containing its
862 arguments
863 */
864 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
865 SmXMLRowContext_Impl::endFastElement(nElement);
866}
867
868namespace
869{
870class SmXMLFracContext_Impl : public SmXMLRowContext_Impl
871{
872public:
873 // TODO/LATER: convert <mfrac bevelled="true"> into "wideslash{}{}"
874 SmXMLFracContext_Impl(SmXMLImport& rImport)
875 : SmXMLRowContext_Impl(rImport)
876 {
877 }
878
879 void SAL_CALL endFastElement(sal_Int32 nElement) override;
880};
881
882class SmXMLSqrtContext_Impl : public SmXMLRowContext_Impl
883{
884public:
885 SmXMLSqrtContext_Impl(SmXMLImport& rImport)
886 : SmXMLRowContext_Impl(rImport)
887 {
888 }
889
890 void SAL_CALL endFastElement(sal_Int32 nElement) override;
891};
892
893class SmXMLRootContext_Impl : public SmXMLRowContext_Impl
894{
895public:
896 SmXMLRootContext_Impl(SmXMLImport& rImport)
897 : SmXMLRowContext_Impl(rImport)
898 {
899 }
900
901 void SAL_CALL endFastElement(sal_Int32 nElement) override;
902};
903
904class SmXMLStyleContext_Impl : public SmXMLRowContext_Impl
905{
906protected:
907 SmXMLContext_Helper aStyleHelper;
908
909public:
910 /*Right now the style tag is completely ignored*/
911 SmXMLStyleContext_Impl(SmXMLImport& rImport)
912 : SmXMLRowContext_Impl(rImport)
913 , aStyleHelper(*this)
914 {
915 }
916
917 void SAL_CALL endFastElement(sal_Int32 nElement) override;
918 void SAL_CALL startFastElement(
919 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
920};
921}
922
923void SmXMLStyleContext_Impl::startFastElement(
924 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
925{
926 aStyleHelper.RetrieveAttrs(xAttrList);
927}
928
929void SmXMLStyleContext_Impl::endFastElement(sal_Int32 nElement)
930{
931 /*
932 <mstyle> accepts any number of arguments; if this number is not 1, its
933 contents are treated as a single "inferred <mrow>" containing its
934 arguments
935 */
936 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
937 if (rNodeStack.size() - nElementCount != 1)
938 SmXMLRowContext_Impl::endFastElement(nElement);
939 aStyleHelper.ApplyAttrs();
940}
941
942namespace
943{
944class SmXMLPaddedContext_Impl : public SmXMLRowContext_Impl
945{
946public:
947 /*Right now the style tag is completely ignored*/
948 SmXMLPaddedContext_Impl(SmXMLImport& rImport)
949 : SmXMLRowContext_Impl(rImport)
950 {
951 }
952
953 void SAL_CALL endFastElement(sal_Int32 nElement) override;
954};
955}
956
957void SmXMLPaddedContext_Impl::endFastElement(sal_Int32 nElement)
958{
959 /*
960 <mpadded> accepts any number of arguments; if this number is not 1, its
961 contents are treated as a single "inferred <mrow>" containing its
962 arguments
963 */
964 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
965 SmXMLRowContext_Impl::endFastElement(nElement);
966}
967
968namespace
969{
970class SmXMLPhantomContext_Impl : public SmXMLRowContext_Impl
971{
972public:
973 /*Right now the style tag is completely ignored*/
974 SmXMLPhantomContext_Impl(SmXMLImport& rImport)
975 : SmXMLRowContext_Impl(rImport)
976 {
977 }
978
979 void SAL_CALL endFastElement(sal_Int32 nElement) override;
980};
981}
982
983void SmXMLPhantomContext_Impl::endFastElement(sal_Int32 nElement)
984{
985 /*
986 <mphantom> accepts any number of arguments; if this number is not 1, its
987 contents are treated as a single "inferred <mrow>" containing its
988 arguments
989 */
990 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
991 SmXMLRowContext_Impl::endFastElement(nElement);
992
993 SmToken aToken;
994 aToken.cMathChar = u"";
995 aToken.nLevel = 5;
996 aToken.eType = TPHANTOM;
997
998 std::unique_ptr<SmFontNode> pPhantom(new SmFontNode(aToken));
999 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1000 pPhantom->SetSubNodes(nullptr, popOrZero(rNodeStack));
1001 rNodeStack.push_front(std::move(pPhantom));
1002}
1003
1004namespace
1005{
1006class SmXMLFencedContext_Impl : public SmXMLRowContext_Impl
1007{
1008protected:
1009 sal_Unicode cBegin;
1010 sal_Unicode cEnd;
1011 bool bIsStretchy;
1012
1013public:
1014 SmXMLFencedContext_Impl(SmXMLImport& rImport)
1015 : SmXMLRowContext_Impl(rImport)
1016 , cBegin('(')
1017 , cEnd(')')
1018 , bIsStretchy(false)
1019 {
1020 }
1021
1022 void SAL_CALL startFastElement(
1023 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1024 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1025};
1026}
1027
1028void SmXMLFencedContext_Impl::startFastElement(
1029 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1030{
1031 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
1032 {
1033 switch (aIter.getToken())
1034 {
1035 //temp, starmath cannot handle multichar brackets (I think)
1036 case XML_OPEN:
1037 cBegin = aIter.toString()[0];
1038 break;
1039 case XML_CLOSE:
1040 cEnd = aIter.toString()[0];
1041 break;
1042 case XML_STRETCHY:
1043 bIsStretchy = IsXMLToken(aIter, XML_TRUE);
1044 break;
1045 default:
1046 XMLOFF_WARN_UNKNOWN("starmath", aIter);
1047 /*Go to superclass*/
1048 break;
1049 }
1050 }
1051}
1052
1053void SmXMLFencedContext_Impl::endFastElement(sal_Int32 /*nElement*/)
1054{
1055 SmToken aToken;
1056 aToken.cMathChar = u"";
1057 aToken.aText = ",";
1058 aToken.nLevel = 5;
1059
1060 std::unique_ptr<SmStructureNode> pSNode(new SmBraceNode(aToken));
1061 if (bIsStretchy)
1063 else
1065 if (aToken.eType == TERROR)
1066 aToken = SmToken(TLPARENT, MS_LPARENT, "(", TG::LBrace, 5);
1067 std::unique_ptr<SmNode> pLeft(new SmMathSymbolNode(aToken));
1068 if (bIsStretchy)
1070 else
1072 if (aToken.eType == TERROR)
1073 aToken = SmToken(TRPARENT, MS_RPARENT, ")", TG::LBrace, 5);
1074 std::unique_ptr<SmNode> pRight(new SmMathSymbolNode(aToken));
1075
1076 SmNodeArray aRelationArray;
1077 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1078 aToken.cMathChar = u"";
1079 aToken.eType = TIDENT;
1080
1081 auto i = rNodeStack.size() - nElementCount;
1082 if (rNodeStack.size() - nElementCount > 1)
1083 i += rNodeStack.size() - 1 - nElementCount;
1084 aRelationArray.resize(i);
1085 while (rNodeStack.size() > nElementCount)
1086 {
1087 auto pNode = std::move(rNodeStack.front());
1088 rNodeStack.pop_front();
1089 aRelationArray[--i] = pNode.release();
1090 if (i > 1 && rNodeStack.size() > 1)
1091 aRelationArray[--i] = new SmGlyphSpecialNode(aToken);
1092 }
1093
1094 SmToken aDummy;
1095 std::unique_ptr<SmStructureNode> pBody(new SmExpressionNode(aDummy));
1096 pBody->SetSubNodes(std::move(aRelationArray));
1097
1098 pSNode->SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight));
1099 // mfenced is always scalable. Stretchy keyword is not official, but in case of been in there
1100 // can be used as a hint.
1101 pSNode->SetScaleMode(SmScaleMode::Height);
1102 GetSmImport().GetNodeStack().push_front(std::move(pSNode));
1103}
1104
1105namespace
1106{
1107class SmXMLErrorContext_Impl : public SmXMLRowContext_Impl
1108{
1109public:
1110 SmXMLErrorContext_Impl(SmXMLImport& rImport)
1111 : SmXMLRowContext_Impl(rImport)
1112 {
1113 }
1114
1115 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1116};
1117}
1118
1119void SmXMLErrorContext_Impl::endFastElement(sal_Int32 /*nElement*/)
1120{
1121 /*Right now the error tag is completely ignored, what
1122 can I do with it in starmath, ?, maybe we need a
1123 report window ourselves, do a test for validity of
1124 the xml input, use mirrors, and then generate
1125 the markup inside the merror with a big red colour
1126 of something. For now just throw them all away.
1127 */
1128 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1129 while (rNodeStack.size() > nElementCount)
1130 {
1131 rNodeStack.pop_front();
1132 }
1133}
1134
1135namespace
1136{
1137class SmXMLNumberContext_Impl : public SmXMLImportContext
1138{
1139protected:
1140 SmToken aToken;
1141
1142public:
1143 SmXMLNumberContext_Impl(SmXMLImport& rImport)
1144 : SmXMLImportContext(rImport)
1145 {
1146 aToken.cMathChar = u"";
1147 aToken.nLevel = 5;
1148 aToken.eType = TNUMBER;
1149 }
1150
1151 virtual void TCharacters(const OUString& rChars) override;
1152
1153 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1154};
1155}
1156
1157void SmXMLNumberContext_Impl::TCharacters(const OUString& rChars) { aToken.aText = rChars; }
1158
1159void SmXMLNumberContext_Impl::endFastElement(sal_Int32)
1160{
1161 GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_NUMBER));
1162}
1163
1164namespace
1165{
1166class SmXMLAnnotationContext_Impl : public SmXMLImportContext
1167{
1168 sal_uInt8 mnStarMathVersion;
1169
1170public:
1171 SmXMLAnnotationContext_Impl(SmXMLImport& rImport)
1172 : SmXMLImportContext(rImport)
1173 , mnStarMathVersion(0)
1174 {
1175 }
1176
1177 void SAL_CALL characters(const OUString& rChars) override;
1178
1179 void SAL_CALL startFastElement(
1180 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1181};
1182}
1183
1184void SmXMLAnnotationContext_Impl::startFastElement(
1185 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1186{
1187 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
1188 {
1189 // sometimes they have namespace, sometimes not?
1190 switch (aIter.getToken() & TOKEN_MASK)
1191 {
1192 case XML_ENCODING:
1193 mnStarMathVersion
1194 = aIter.toView() == "StarMath 5.0" ? 5 : aIter.toView() == "StarMath 6" ? 6 : 0;
1195 break;
1196 default:
1197 XMLOFF_WARN_UNKNOWN("starmath", aIter);
1198 break;
1199 }
1200 }
1201}
1202
1203void SmXMLAnnotationContext_Impl::characters(const OUString& rChars)
1204{
1205 if (mnStarMathVersion)
1206 {
1207 GetSmImport().SetText(GetSmImport().GetText() + rChars);
1208 GetSmImport().SetSmSyntaxVersion(mnStarMathVersion);
1209 }
1210}
1211
1212namespace
1213{
1214class SmXMLTextContext_Impl : public SmXMLImportContext
1215{
1216protected:
1217 SmToken aToken;
1218
1219public:
1220 SmXMLTextContext_Impl(SmXMLImport& rImport)
1221 : SmXMLImportContext(rImport)
1222 {
1223 aToken.cMathChar = u"";
1224 aToken.nLevel = 5;
1225 aToken.eType = TTEXT;
1226 }
1227
1228 virtual void TCharacters(const OUString& rChars) override;
1229
1230 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1231};
1232}
1233
1234void SmXMLTextContext_Impl::TCharacters(const OUString& rChars) { aToken.aText = rChars; }
1235
1236void SmXMLTextContext_Impl::endFastElement(sal_Int32)
1237{
1238 GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_TEXT));
1239}
1240
1241namespace
1242{
1243class SmXMLStringContext_Impl : public SmXMLImportContext
1244{
1245protected:
1246 SmToken aToken;
1247
1248public:
1249 SmXMLStringContext_Impl(SmXMLImport& rImport)
1250 : SmXMLImportContext(rImport)
1251 {
1252 aToken.cMathChar = u"";
1253 aToken.nLevel = 5;
1254 aToken.eType = TTEXT;
1255 }
1256
1257 virtual void TCharacters(const OUString& rChars) override;
1258
1259 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1260};
1261}
1262
1263void SmXMLStringContext_Impl::TCharacters(const OUString& rChars)
1264{
1265 /*
1266 The content of <ms> elements should be rendered with visible "escaping" of
1267 certain characters in the content, including at least "double quote"
1268 itself, and preferably whitespace other than individual blanks. The intent
1269 is for the viewer to see that the expression is a string literal, and to
1270 see exactly which characters form its content. For example, <ms>double
1271 quote is "</ms> might be rendered as "double quote is \"".
1272
1273 Obviously this isn't fully done here.
1274 */
1275 aToken.aText = "\"" + rChars + "\"";
1276}
1277
1278void SmXMLStringContext_Impl::endFastElement(sal_Int32)
1279{
1280 GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_FIXED));
1281}
1282
1283namespace
1284{
1285class SmXMLIdentifierContext_Impl : public SmXMLImportContext
1286{
1287 SmXMLTokenAttrHelper maTokenAttrHelper;
1288 SmXMLContext_Helper aStyleHelper;
1289 SmToken aToken;
1290
1291public:
1292 SmXMLIdentifierContext_Impl(SmXMLImport& rImport)
1293 : SmXMLImportContext(rImport)
1294 , maTokenAttrHelper(*this)
1295 , aStyleHelper(*this)
1296 {
1297 aToken.cMathChar = u"";
1298 aToken.nLevel = 5;
1299 aToken.eType = TIDENT;
1300 }
1301
1302 void TCharacters(const OUString& rChars) override;
1303 void SAL_CALL
1304 startFastElement(sal_Int32 /*nElement*/,
1305 const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override
1306 {
1307 maTokenAttrHelper.RetrieveAttrs(xAttrList);
1308 aStyleHelper.RetrieveAttrs(xAttrList);
1309 };
1310 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1311};
1312}
1313
1314void SmXMLIdentifierContext_Impl::endFastElement(sal_Int32)
1315{
1316 std::unique_ptr<SmTextNode> pNode;
1317 //we will handle identifier italic/normal here instead of with a standalone
1318 //font node
1319 if (((aStyleHelper.nIsItalic == -1) && (aToken.aText.getLength() > 1))
1320 || ((aStyleHelper.nIsItalic == 0) && (aToken.aText.getLength() == 1)))
1321 {
1322 pNode.reset(new SmTextNode(aToken, FNT_FUNCTION));
1323 pNode->GetFont().SetItalic(ITALIC_NONE);
1324 aStyleHelper.nIsItalic = -1;
1325 }
1326 else
1327 pNode.reset(new SmTextNode(aToken, FNT_VARIABLE));
1328 if (aStyleHelper.nIsItalic != -1)
1329 {
1330 if (aStyleHelper.nIsItalic)
1331 pNode->GetFont().SetItalic(ITALIC_NORMAL);
1332 else
1333 pNode->GetFont().SetItalic(ITALIC_NONE);
1334 aStyleHelper.nIsItalic = -1;
1335 }
1336 GetSmImport().GetNodeStack().push_front(std::move(pNode));
1337 aStyleHelper.ApplyAttrs();
1338
1339 maTokenAttrHelper.ApplyAttrs((aToken.aText.getLength() == 1) ? MathMLMathvariantValue::Italic
1341}
1342
1343void SmXMLIdentifierContext_Impl::TCharacters(const OUString& rChars) { aToken.aText = rChars; }
1344
1345namespace
1346{
1347class SmXMLOperatorContext_Impl : public SmXMLImportContext
1348{
1349 SmXMLTokenAttrHelper maTokenAttrHelper;
1350 bool bIsStretchy;
1351 bool bIsFenced;
1352 bool isPrefix;
1353 bool isInfix;
1354 bool isPostfix;
1355 SmToken aToken;
1356
1357public:
1358 SmXMLOperatorContext_Impl(SmXMLImport& rImport)
1359 : SmXMLImportContext(rImport)
1360 , maTokenAttrHelper(*this)
1361 , bIsStretchy(false)
1362 , bIsFenced(false)
1363 , isPrefix(false)
1364 , isInfix(false)
1365 , isPostfix(false)
1366 {
1367 aToken.eType = TSPECIAL;
1368 aToken.nLevel = 5;
1369 }
1370
1371 void TCharacters(const OUString& rChars) override;
1372 void SAL_CALL startFastElement(
1373 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1374 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1375};
1376}
1377
1378void SmXMLOperatorContext_Impl::TCharacters(const OUString& rChars)
1379{
1380 aToken.setChar(rChars[0]);
1381 SmToken bToken;
1382 if (bIsFenced)
1383 {
1384 if (isPrefix)
1385 bToken
1387 else if (isInfix)
1388 bToken = SmToken(TMLINE, MS_VERTLINE, "mline", TG::NONE, 0);
1389 else if (isPostfix)
1390 bToken
1392 else
1394 aToken.cMathChar[0]);
1395 }
1396 else
1398 bIsStretchy);
1399 if (bToken.eType != TERROR)
1400 aToken = bToken;
1401}
1402
1403void SmXMLOperatorContext_Impl::endFastElement(sal_Int32)
1404{
1405 std::unique_ptr<SmMathSymbolNode> pNode(new SmMathSymbolNode(aToken));
1406 //For stretchy scaling the scaling must be retrieved from this node
1407 //and applied to the expression itself so as to get the expression
1408 //to scale the operator to the height of the expression itself
1409 if (bIsStretchy)
1410 pNode->SetScaleMode(SmScaleMode::Height);
1411 GetSmImport().GetNodeStack().push_front(std::move(pNode));
1412
1413 // TODO: apply to non-alphabetic characters too
1414 if (rtl::isAsciiAlpha(aToken.cMathChar[0]))
1415 maTokenAttrHelper.ApplyAttrs(MathMLMathvariantValue::Normal);
1416}
1417
1418void SmXMLOperatorContext_Impl::startFastElement(
1419 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1420{
1421 maTokenAttrHelper.RetrieveAttrs(xAttrList);
1422
1423 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
1424 {
1425 switch (aIter.getToken())
1426 {
1427 case XML_STRETCHY:
1428 bIsStretchy = IsXMLToken(aIter, XML_TRUE);
1429 break;
1430 case XML_FENCE:
1431 bIsFenced = IsXMLToken(aIter, XML_TRUE);
1432 break;
1433 case XML_FORM:
1434 isPrefix = IsXMLToken(aIter, XML_PREFIX); // <
1435 isInfix = IsXMLToken(aIter, XML_INFIX); // |
1436 isPostfix = IsXMLToken(aIter, XML_POSTFIX); // >
1437 break;
1438 default:
1439 XMLOFF_WARN_UNKNOWN("starmath", aIter);
1440 break;
1441 }
1442 }
1443}
1444
1445namespace
1446{
1447class SmXMLSpaceContext_Impl : public SmXMLImportContext
1448{
1449public:
1450 SmXMLSpaceContext_Impl(SmXMLImport& rImport)
1451 : SmXMLImportContext(rImport)
1452 {
1453 }
1454
1455 void SAL_CALL startFastElement(
1456 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1457};
1458
1459bool lcl_CountBlanks(const MathMLAttributeLengthValue& rLV, sal_Int32* pWide, sal_Int32* pNarrow)
1460{
1461 assert(pWide);
1462 assert(pNarrow);
1463 if (rLV.aNumber.GetNumerator() == 0)
1464 {
1465 *pWide = *pNarrow = 0;
1466 return true;
1467 }
1468 // TODO: honor other units than em
1469 if (rLV.eUnit != MathMLLengthUnit::Em)
1470 return false;
1471 if (rLV.aNumber.GetNumerator() < 0)
1472 return false;
1473 const Fraction aTwo(2, 1);
1474 auto aWide = rLV.aNumber / aTwo;
1475 auto nWide = static_cast<sal_Int32>(static_cast<tools::Long>(aWide));
1476 if (nWide < 0)
1477 return false;
1478 const Fraction aPointFive(1, 2);
1479 auto aNarrow = (rLV.aNumber - Fraction(nWide, 1) * aTwo) / aPointFive;
1480 auto nNarrow = static_cast<sal_Int32>(static_cast<tools::Long>(aNarrow));
1481 if (nNarrow < 0)
1482 return false;
1483 *pWide = nWide;
1484 *pNarrow = nNarrow;
1485 return true;
1486}
1487}
1488
1489void SmXMLSpaceContext_Impl::startFastElement(
1490 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1491{
1492 // There is no syntax in Math to specify blank nodes of arbitrary size yet.
1494 sal_Int32 nWide = 0, nNarrow = 0;
1495
1496 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
1497 {
1498 OUString sValue = aIter.toString();
1499 switch (aIter.getToken())
1500 {
1501 case XML_WIDTH:
1503 || !lcl_CountBlanks(aLV, &nWide, &nNarrow))
1504 SAL_WARN("starmath", "ignore mspace's width: " << sValue);
1505 break;
1506 default:
1507 XMLOFF_WARN_UNKNOWN("starmath", aIter);
1508 break;
1509 }
1510 }
1511 SmToken aToken;
1512 aToken.eType = TBLANK;
1513 aToken.cMathChar = u"";
1514 aToken.nGroup = TG::Blank;
1515 aToken.nLevel = 5;
1516 std::unique_ptr<SmBlankNode> pBlank(new SmBlankNode(aToken));
1517 if (nWide > 0)
1518 pBlank->IncreaseBy(aToken, nWide);
1519 if (nNarrow > 0)
1520 {
1521 aToken.eType = TSBLANK;
1522 pBlank->IncreaseBy(aToken, nNarrow);
1523 }
1524 GetSmImport().GetNodeStack().push_front(std::move(pBlank));
1525}
1526
1527namespace
1528{
1529class SmXMLSubContext_Impl : public SmXMLRowContext_Impl
1530{
1531protected:
1532 void GenericEndElement(SmTokenType eType, SmSubSup aSubSup);
1533
1534public:
1535 SmXMLSubContext_Impl(SmXMLImport& rImport)
1536 : SmXMLRowContext_Impl(rImport)
1537 {
1538 }
1539
1540 void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TRSUB, RSUB); }
1541};
1542}
1543
1544void SmXMLSubContext_Impl::GenericEndElement(SmTokenType eType, SmSubSup eSubSup)
1545{
1546 /*The <msub> element requires exactly 2 arguments.*/
1547 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
1548 OSL_ENSURE(bNodeCheck, "Sub has not two arguments");
1549 if (!bNodeCheck)
1550 return;
1551
1552 SmToken aToken;
1553 aToken.cMathChar = u"";
1554 aToken.eType = eType;
1555 std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
1556 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1557
1558 // initialize subnodes array
1559 SmNodeArray aSubNodes;
1560 aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
1561 for (size_t i = 1; i < aSubNodes.size(); i++)
1562 aSubNodes[i] = nullptr;
1563
1564 aSubNodes[eSubSup + 1] = popOrZero(rNodeStack).release();
1565 aSubNodes[0] = popOrZero(rNodeStack).release();
1566 pNode->SetSubNodes(std::move(aSubNodes));
1567 rNodeStack.push_front(std::move(pNode));
1568}
1569
1570namespace
1571{
1572class SmXMLSupContext_Impl : public SmXMLSubContext_Impl
1573{
1574public:
1575 SmXMLSupContext_Impl(SmXMLImport& rImport)
1576 : SmXMLSubContext_Impl(rImport)
1577 {
1578 }
1579
1580 void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TRSUP, RSUP); }
1581};
1582
1583class SmXMLSubSupContext_Impl : public SmXMLRowContext_Impl
1584{
1585protected:
1586 void GenericEndElement(SmTokenType eType, SmSubSup aSub, SmSubSup aSup);
1587
1588public:
1589 SmXMLSubSupContext_Impl(SmXMLImport& rImport)
1590 : SmXMLRowContext_Impl(rImport)
1591 {
1592 }
1593
1594 void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TRSUB, RSUB, RSUP); }
1595};
1596}
1597
1598void SmXMLSubSupContext_Impl::GenericEndElement(SmTokenType eType, SmSubSup aSub, SmSubSup aSup)
1599{
1600 /*The <msub> element requires exactly 3 arguments.*/
1601 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 3;
1602 OSL_ENSURE(bNodeCheck, "SubSup has not three arguments");
1603 if (!bNodeCheck)
1604 return;
1605
1606 SmToken aToken;
1607 aToken.cMathChar = u"";
1608 aToken.eType = eType;
1609 std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
1610 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1611
1612 // initialize subnodes array
1613 SmNodeArray aSubNodes;
1614 aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
1615 for (size_t i = 1; i < aSubNodes.size(); i++)
1616 aSubNodes[i] = nullptr;
1617
1618 aSubNodes[aSup + 1] = popOrZero(rNodeStack).release();
1619 aSubNodes[aSub + 1] = popOrZero(rNodeStack).release();
1620 aSubNodes[0] = popOrZero(rNodeStack).release();
1621 pNode->SetSubNodes(std::move(aSubNodes));
1622 rNodeStack.push_front(std::move(pNode));
1623}
1624
1625namespace
1626{
1627class SmXMLUnderContext_Impl : public SmXMLSubContext_Impl
1628{
1629protected:
1630 sal_Int16 nAttrCount;
1631
1632public:
1633 SmXMLUnderContext_Impl(SmXMLImport& rImport)
1634 : SmXMLSubContext_Impl(rImport)
1635 , nAttrCount(0)
1636 {
1637 }
1638
1639 void SAL_CALL startFastElement(
1640 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1641 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1642 void HandleAccent();
1643};
1644}
1645
1646void SmXMLUnderContext_Impl::startFastElement(
1647 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1648{
1651 nAttrCount = rAttribList.getFastAttributeTokens().size();
1652}
1653
1654void SmXMLUnderContext_Impl::HandleAccent()
1655{
1656 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
1657 OSL_ENSURE(bNodeCheck, "Sub has not two arguments");
1658 if (!bNodeCheck)
1659 return;
1660
1661 /*Just one special case for the underline thing*/
1662 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1663 std::unique_ptr<SmNode> pTest = popOrZero(rNodeStack);
1664 SmToken aToken;
1665 aToken.cMathChar = u"";
1666 aToken.eType = TUNDERLINE;
1667
1668 std::unique_ptr<SmNode> pFirst;
1669 std::unique_ptr<SmStructureNode> pNode(new SmAttributeNode(aToken));
1670 if ((pTest->GetToken().cMathChar[0] & 0x0FFF) == 0x0332)
1671 {
1672 pFirst.reset(new SmRectangleNode(aToken));
1673 }
1674 else
1675 pFirst = std::move(pTest);
1676
1677 std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack);
1678 pNode->SetSubNodes(std::move(pFirst), std::move(pSecond));
1679 pNode->SetScaleMode(SmScaleMode::Width);
1680 rNodeStack.push_front(std::move(pNode));
1681}
1682
1683void SmXMLUnderContext_Impl::endFastElement(sal_Int32)
1684{
1685 if (!nAttrCount)
1686 GenericEndElement(TCSUB, CSUB);
1687 else
1688 HandleAccent();
1689}
1690
1691namespace
1692{
1693class SmXMLOverContext_Impl : public SmXMLSubContext_Impl
1694{
1695protected:
1696 sal_Int16 nAttrCount;
1697
1698public:
1699 SmXMLOverContext_Impl(SmXMLImport& rImport)
1700 : SmXMLSubContext_Impl(rImport)
1701 , nAttrCount(0)
1702 {
1703 }
1704
1705 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1706 void SAL_CALL startFastElement(
1707 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1708 void HandleAccent();
1709};
1710}
1711
1712void SmXMLOverContext_Impl::startFastElement(
1713 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1714{
1717 nAttrCount = rAttribList.getFastAttributeTokens().size();
1718}
1719
1720void SmXMLOverContext_Impl::endFastElement(sal_Int32)
1721{
1722 if (!nAttrCount)
1723 GenericEndElement(TCSUP, CSUP);
1724 else
1725 HandleAccent();
1726}
1727
1728void SmXMLOverContext_Impl::HandleAccent()
1729{
1730 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
1731 OSL_ENSURE(bNodeCheck, "Sub has not two arguments");
1732 if (!bNodeCheck)
1733 return;
1734
1735 SmToken aToken;
1736 aToken.cMathChar = u"";
1737 aToken.eType = TACUTE;
1738
1739 std::unique_ptr<SmAttributeNode> pNode(new SmAttributeNode(aToken));
1740 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
1741
1742 std::unique_ptr<SmNode> pFirst = popOrZero(rNodeStack);
1743 std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack);
1744 pNode->SetSubNodes(std::move(pFirst), std::move(pSecond));
1745 pNode->SetScaleMode(SmScaleMode::Width);
1746 rNodeStack.push_front(std::move(pNode));
1747}
1748
1749namespace
1750{
1751class SmXMLUnderOverContext_Impl : public SmXMLSubSupContext_Impl
1752{
1753public:
1754 SmXMLUnderOverContext_Impl(SmXMLImport& rImport)
1755 : SmXMLSubSupContext_Impl(rImport)
1756 {
1757 }
1758
1759 void SAL_CALL endFastElement(sal_Int32) override { GenericEndElement(TCSUB, CSUB, CSUP); }
1760};
1761
1762class SmXMLMultiScriptsContext_Impl : public SmXMLSubSupContext_Impl
1763{
1764 bool bHasPrescripts;
1765
1766 void ProcessSubSupPairs(bool bIsPrescript);
1767
1768public:
1769 SmXMLMultiScriptsContext_Impl(SmXMLImport& rImport)
1770 : SmXMLSubSupContext_Impl(rImport)
1771 , bHasPrescripts(false)
1772 {
1773 }
1774
1775 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1776 virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
1777 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1778};
1779
1780class SmXMLNoneContext_Impl : public SmXMLImportContext
1781{
1782public:
1783 SmXMLNoneContext_Impl(SmXMLImport& rImport)
1784 : SmXMLImportContext(rImport)
1785 {
1786 }
1787
1788 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1789};
1790}
1791
1792void SmXMLNoneContext_Impl::endFastElement(sal_Int32)
1793{
1794 SmToken aToken;
1795 aToken.cMathChar = u"";
1796 aToken.aText.clear();
1797 aToken.nLevel = 5;
1798 aToken.eType = TIDENT;
1799 GetSmImport().GetNodeStack().push_front(std::make_unique<SmTextNode>(aToken, FNT_VARIABLE));
1800}
1801
1802namespace
1803{
1804class SmXMLPrescriptsContext_Impl : public SmXMLImportContext
1805{
1806public:
1807 SmXMLPrescriptsContext_Impl(SmXMLImport& rImport)
1808 : SmXMLImportContext(rImport)
1809 {
1810 }
1811};
1812
1813class SmXMLTableRowContext_Impl : public SmXMLRowContext_Impl
1814{
1815public:
1816 SmXMLTableRowContext_Impl(SmXMLImport& rImport)
1817 : SmXMLRowContext_Impl(rImport)
1818 {
1819 }
1820
1821 virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
1822 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1823};
1824
1825class SmXMLTableContext_Impl : public SmXMLTableRowContext_Impl
1826{
1827public:
1828 SmXMLTableContext_Impl(SmXMLImport& rImport)
1829 : SmXMLTableRowContext_Impl(rImport)
1830 {
1831 }
1832
1833 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1834 virtual uno::Reference<xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
1835 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1836};
1837
1838class SmXMLTableCellContext_Impl : public SmXMLRowContext_Impl
1839{
1840public:
1841 SmXMLTableCellContext_Impl(SmXMLImport& rImport)
1842 : SmXMLRowContext_Impl(rImport)
1843 {
1844 }
1845};
1846
1847class SmXMLAlignGroupContext_Impl : public SmXMLRowContext_Impl
1848{
1849public:
1850 SmXMLAlignGroupContext_Impl(SmXMLImport& rImport)
1851 : SmXMLRowContext_Impl(rImport)
1852 {
1853 }
1854
1855 /*Don't do anything with alignment for now*/
1856};
1857
1858class SmXMLActionContext_Impl : public SmXMLRowContext_Impl
1859{
1860 size_t mnSelection; // 1-based
1861
1862public:
1863 SmXMLActionContext_Impl(SmXMLImport& rImport)
1864 : SmXMLRowContext_Impl(rImport)
1865 , mnSelection(1)
1866 {
1867 }
1868
1869 void SAL_CALL startFastElement(
1870 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList) override;
1871 void SAL_CALL endFastElement(sal_Int32 nElement) override;
1872};
1873
1874// NB: virtually inherit so we can multiply inherit properly
1875// in SmXMLFlatDocContext_Impl
1876class SmXMLOfficeContext_Impl : public virtual SvXMLImportContext
1877{
1878public:
1879 SmXMLOfficeContext_Impl(SmXMLImport& rImport)
1880 : SvXMLImportContext(rImport)
1881 {
1882 }
1883
1884 virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
1885 sal_Int32 nElement,
1886 const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList) override;
1887};
1888}
1889
1890uno::Reference<xml::sax::XFastContextHandler> SmXMLOfficeContext_Impl::createFastChildContext(
1891 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
1892{
1893 if (nElement == XML_ELEMENT(OFFICE, XML_META))
1894 {
1895 SAL_WARN("starmath",
1896 "XML_TOK_DOC_META: should not have come here, maybe document is invalid?");
1897 }
1898 else if (nElement == XML_ELEMENT(OFFICE, XML_SETTINGS))
1899 {
1900 return new XMLDocumentSettingsContext(GetImport());
1901 }
1902 return nullptr;
1903}
1904
1905namespace
1906{
1907// context for flat file xml format
1908class SmXMLFlatDocContext_Impl : public SmXMLOfficeContext_Impl, public SvXMLMetaDocumentContext
1909{
1910public:
1911 SmXMLFlatDocContext_Impl(SmXMLImport& i_rImport,
1912 const uno::Reference<document::XDocumentProperties>& i_xDocProps);
1913
1914 virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
1915 sal_Int32 nElement,
1916 const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList) override;
1917};
1918}
1919
1920SmXMLFlatDocContext_Impl::SmXMLFlatDocContext_Impl(
1921 SmXMLImport& i_rImport, const uno::Reference<document::XDocumentProperties>& i_xDocProps)
1922 : SvXMLImportContext(i_rImport)
1923 , SmXMLOfficeContext_Impl(i_rImport)
1924 , SvXMLMetaDocumentContext(i_rImport, i_xDocProps)
1925{
1926}
1927
1928uno::Reference<xml::sax::XFastContextHandler>
1929 SAL_CALL SmXMLFlatDocContext_Impl::createFastChildContext(
1930 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
1931{
1932 // behave like meta base class iff we encounter office:meta
1933 if (nElement == XML_ELEMENT(OFFICE, XML_META))
1934 {
1935 return SvXMLMetaDocumentContext::createFastChildContext(nElement, xAttrList);
1936 }
1937 else
1938 {
1939 return SmXMLOfficeContext_Impl::createFastChildContext(nElement, xAttrList);
1940 }
1941}
1942
1943uno::Reference<xml::sax::XFastContextHandler> SmXMLDocContext_Impl::createFastChildContext(
1944 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
1945{
1946 uno::Reference<xml::sax::XFastContextHandler> xContext;
1947
1948 switch (nElement)
1949 {
1950 //Consider semantics a dummy except for any starmath annotations
1951 case XML_ELEMENT(MATH, XML_SEMANTICS):
1952 xContext = new SmXMLRowContext_Impl(GetSmImport());
1953 break;
1954 /*General Layout Schemata*/
1955 case XML_ELEMENT(MATH, XML_MROW):
1956 xContext = new SmXMLRowContext_Impl(GetSmImport());
1957 break;
1958 case XML_ELEMENT(MATH, XML_MENCLOSE):
1959 xContext = new SmXMLEncloseContext_Impl(GetSmImport());
1960 break;
1961 case XML_ELEMENT(MATH, XML_MFRAC):
1962 xContext = new SmXMLFracContext_Impl(GetSmImport());
1963 break;
1964 case XML_ELEMENT(MATH, XML_MSQRT):
1965 xContext = new SmXMLSqrtContext_Impl(GetSmImport());
1966 break;
1967 case XML_ELEMENT(MATH, XML_MROOT):
1968 xContext = new SmXMLRootContext_Impl(GetSmImport());
1969 break;
1970 case XML_ELEMENT(MATH, XML_MSTYLE):
1971 xContext = new SmXMLStyleContext_Impl(GetSmImport());
1972 break;
1973 case XML_ELEMENT(MATH, XML_MERROR):
1974 xContext = new SmXMLErrorContext_Impl(GetSmImport());
1975 break;
1976 case XML_ELEMENT(MATH, XML_MPADDED):
1977 xContext = new SmXMLPaddedContext_Impl(GetSmImport());
1978 break;
1979 case XML_ELEMENT(MATH, XML_MPHANTOM):
1980 xContext = new SmXMLPhantomContext_Impl(GetSmImport());
1981 break;
1982 case XML_ELEMENT(MATH, XML_MFENCED):
1983 xContext = new SmXMLFencedContext_Impl(GetSmImport());
1984 break;
1985 /*Script and Limit Schemata*/
1986 case XML_ELEMENT(MATH, XML_MSUB):
1987 xContext = new SmXMLSubContext_Impl(GetSmImport());
1988 break;
1989 case XML_ELEMENT(MATH, XML_MSUP):
1990 xContext = new SmXMLSupContext_Impl(GetSmImport());
1991 break;
1992 case XML_ELEMENT(MATH, XML_MSUBSUP):
1993 xContext = new SmXMLSubSupContext_Impl(GetSmImport());
1994 break;
1995 case XML_ELEMENT(MATH, XML_MUNDER):
1996 xContext = new SmXMLUnderContext_Impl(GetSmImport());
1997 break;
1998 case XML_ELEMENT(MATH, XML_MOVER):
1999 xContext = new SmXMLOverContext_Impl(GetSmImport());
2000 break;
2001 case XML_ELEMENT(MATH, XML_MUNDEROVER):
2002 xContext = new SmXMLUnderOverContext_Impl(GetSmImport());
2003 break;
2004 case XML_ELEMENT(MATH, XML_MMULTISCRIPTS):
2005 xContext = new SmXMLMultiScriptsContext_Impl(GetSmImport());
2006 break;
2007 case XML_ELEMENT(MATH, XML_MTABLE):
2008 xContext = new SmXMLTableContext_Impl(GetSmImport());
2009 break;
2010 case XML_ELEMENT(MATH, XML_MACTION):
2011 xContext = new SmXMLActionContext_Impl(GetSmImport());
2012 break;
2013 default:
2014 /*Basically there's an implicit mrow around certain bare
2015 *elements, use a RowContext to see if this is one of
2016 *those ones*/
2018 new SmXMLRowContext_Impl(GetSmImport()));
2019
2020 xContext = aTempContext->StrictCreateChildContext(nElement);
2021 break;
2022 }
2023 return xContext;
2024}
2025
2026void SmXMLDocContext_Impl::endFastElement(sal_Int32)
2027{
2028 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2029
2030 std::unique_ptr<SmNode> pContextNode = popOrZero(rNodeStack);
2031
2032 SmToken aDummy;
2033 std::unique_ptr<SmStructureNode> pSNode(new SmLineNode(aDummy));
2034 pSNode->SetSubNodes(std::move(pContextNode), nullptr);
2035 rNodeStack.push_front(std::move(pSNode));
2036
2037 SmNodeArray LineArray;
2038 auto n = rNodeStack.size();
2039 LineArray.resize(n);
2040 for (size_t j = 0; j < n; j++)
2041 {
2042 auto pNode = std::move(rNodeStack.front());
2043 rNodeStack.pop_front();
2044 LineArray[n - (j + 1)] = pNode.release();
2045 }
2046 std::unique_ptr<SmStructureNode> pSNode2(new SmTableNode(aDummy));
2047 pSNode2->SetSubNodes(std::move(LineArray));
2048 rNodeStack.push_front(std::move(pSNode2));
2049}
2050
2051void SmXMLFracContext_Impl::endFastElement(sal_Int32)
2052{
2053 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2054 const bool bNodeCheck = rNodeStack.size() - nElementCount == 2;
2055 OSL_ENSURE(bNodeCheck, "Fraction (mfrac) tag is missing component");
2056 if (!bNodeCheck)
2057 return;
2058
2059 SmToken aToken;
2060 aToken.cMathChar = u"";
2061 aToken.eType = TFRAC;
2062 std::unique_ptr<SmStructureNode> pSNode(new SmBinVerNode(aToken));
2063 std::unique_ptr<SmNode> pOper(new SmRectangleNode(aToken));
2064 std::unique_ptr<SmNode> pSecond = popOrZero(rNodeStack);
2065 std::unique_ptr<SmNode> pFirst = popOrZero(rNodeStack);
2066 pSNode->SetSubNodes(std::move(pFirst), std::move(pOper), std::move(pSecond));
2067 rNodeStack.push_front(std::move(pSNode));
2068}
2069
2070void SmXMLRootContext_Impl::endFastElement(sal_Int32)
2071{
2072 /*The <mroot> element requires exactly 2 arguments.*/
2073 const bool bNodeCheck = GetSmImport().GetNodeStack().size() - nElementCount == 2;
2074 OSL_ENSURE(bNodeCheck, "Root tag is missing component");
2075 if (!bNodeCheck)
2076 return;
2077
2078 SmToken aToken;
2079 aToken.setChar(MS_SQRT); //Temporary: alert, based on StarSymbol font
2080 aToken.eType = TNROOT;
2081 std::unique_ptr<SmStructureNode> pSNode(new SmRootNode(aToken));
2082 std::unique_ptr<SmNode> pOper(new SmRootSymbolNode(aToken));
2083 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2084 std::unique_ptr<SmNode> pIndex = popOrZero(rNodeStack);
2085 std::unique_ptr<SmNode> pBase = popOrZero(rNodeStack);
2086 pSNode->SetSubNodes(std::move(pIndex), std::move(pOper), std::move(pBase));
2087 rNodeStack.push_front(std::move(pSNode));
2088}
2089
2090void SmXMLSqrtContext_Impl::endFastElement(sal_Int32 nElement)
2091{
2092 /*
2093 <msqrt> accepts any number of arguments; if this number is not 1, its
2094 contents are treated as a single "inferred <mrow>" containing its
2095 arguments
2096 */
2097 if (GetSmImport().GetNodeStack().size() - nElementCount != 1)
2098 SmXMLRowContext_Impl::endFastElement(nElement);
2099
2100 SmToken aToken;
2101 aToken.setChar(MS_SQRT); //Temporary: alert, based on StarSymbol font
2102 aToken.eType = TSQRT;
2103 std::unique_ptr<SmStructureNode> pSNode(new SmRootNode(aToken));
2104 std::unique_ptr<SmNode> pOper(new SmRootSymbolNode(aToken));
2105 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2106 pSNode->SetSubNodes(nullptr, std::move(pOper), popOrZero(rNodeStack));
2107 rNodeStack.push_front(std::move(pSNode));
2108}
2109
2110void SmXMLRowContext_Impl::endFastElement(sal_Int32)
2111{
2112 SmNodeArray aRelationArray;
2113 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2114
2115 if (rNodeStack.size() > nElementCount)
2116 {
2117 auto nSize = rNodeStack.size() - nElementCount;
2118
2119 aRelationArray.resize(nSize);
2120 for (auto j = nSize; j > 0; j--)
2121 {
2122 auto pNode = std::move(rNodeStack.front());
2123 rNodeStack.pop_front();
2124 aRelationArray[j - 1] = pNode.release();
2125 }
2126
2127 //If the first or last element is an operator with stretchyness
2128 //set then we must create a brace node here from those elements,
2129 //removing the stretchness from the operators and applying it to
2130 //ourselves, and creating the appropriate dummy StarMath none bracket
2131 //to balance the arrangement
2132 if (((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height)
2133 && (aRelationArray[0]->GetType() == SmNodeType::Math))
2134 || ((aRelationArray[nSize - 1]->GetScaleMode() == SmScaleMode::Height)
2135 && (aRelationArray[nSize - 1]->GetType() == SmNodeType::Math)))
2136 {
2137 SmToken aToken;
2138 aToken.cMathChar = u"";
2139 aToken.nLevel = 5;
2140
2141 int nLeft = 0, nRight = 0;
2142 if ((aRelationArray[0]->GetScaleMode() == SmScaleMode::Height)
2143 && (aRelationArray[0]->GetType() == SmNodeType::Math))
2144 {
2145 aToken = aRelationArray[0]->GetToken();
2146 nLeft = 1;
2147 }
2148 else
2149 aToken.cMathChar = u"";
2150
2151 aToken.eType = TLPARENT;
2152 std::unique_ptr<SmNode> pLeft(new SmMathSymbolNode(aToken));
2153
2154 if ((aRelationArray[nSize - 1]->GetScaleMode() == SmScaleMode::Height)
2155 && (aRelationArray[nSize - 1]->GetType() == SmNodeType::Math))
2156 {
2157 aToken = aRelationArray[nSize - 1]->GetToken();
2158 nRight = 1;
2159 }
2160 else
2161 aToken.cMathChar = u"";
2162
2163 aToken.eType = TRPARENT;
2164 std::unique_ptr<SmNode> pRight(new SmMathSymbolNode(aToken));
2165
2166 SmNodeArray aRelationArray2;
2167
2169 int nRelArrSize = nSize - nLeft - nRight;
2170 if (nRelArrSize > 0)
2171 {
2172 aRelationArray2.resize(nRelArrSize);
2173 for (int i = 0; i < nRelArrSize; i++)
2174 {
2175 aRelationArray2[i] = aRelationArray[i + nLeft];
2176 aRelationArray[i + nLeft] = nullptr;
2177 }
2178 }
2179
2180 SmToken aDummy;
2181 std::unique_ptr<SmStructureNode> pSNode(new SmBraceNode(aToken));
2182 std::unique_ptr<SmStructureNode> pBody(new SmExpressionNode(aDummy));
2183 pBody->SetSubNodes(std::move(aRelationArray2));
2184
2185 pSNode->SetSubNodes(std::move(pLeft), std::move(pBody), std::move(pRight));
2186 pSNode->SetScaleMode(SmScaleMode::Height);
2187 rNodeStack.push_front(std::move(pSNode));
2188
2189 for (auto a : aRelationArray)
2190 delete a;
2191
2192 return;
2193 }
2194 }
2195 else
2196 {
2197 // The elements msqrt, mstyle, merror, menclose, mpadded, mphantom, mtd, and math
2198 // treat their content as a single inferred mrow in case their content is empty.
2199 // Here an empty group {} is used to catch those cases and transform them without error
2200 // to StarMath.
2201 aRelationArray.resize(2);
2202 SmToken aToken;
2203 aToken.setChar(MS_LBRACE);
2204 aToken.nLevel = 5;
2205 aToken.eType = TLGROUP;
2206 aToken.nGroup = TG::NONE;
2207 aToken.aText = "{";
2208 aRelationArray[0] = new SmLineNode(aToken);
2209
2210 aToken.setChar(MS_RBRACE);
2211 aToken.nLevel = 0;
2212 aToken.eType = TRGROUP;
2213 aToken.nGroup = TG::NONE;
2214 aToken.aText = "}";
2215 aRelationArray[1] = new SmLineNode(aToken);
2216 }
2217
2218 SmToken aDummy;
2219 std::unique_ptr<SmStructureNode> pSNode(new SmExpressionNode(aDummy));
2220 pSNode->SetSubNodes(std::move(aRelationArray));
2221 rNodeStack.push_front(std::move(pSNode));
2222}
2223
2224uno::Reference<xml::sax::XFastContextHandler>
2225SmXMLRowContext_Impl::StrictCreateChildContext(sal_Int32 nElement)
2226{
2227 uno::Reference<xml::sax::XFastContextHandler> pContext;
2228
2229 switch (nElement)
2230 {
2231 /*Note that these should accept malignmark subelements, but do not*/
2232 case XML_ELEMENT(MATH, XML_MN):
2233 pContext = new SmXMLNumberContext_Impl(GetSmImport());
2234 break;
2235 case XML_ELEMENT(MATH, XML_MI):
2236 pContext = new SmXMLIdentifierContext_Impl(GetSmImport());
2237 break;
2238 case XML_ELEMENT(MATH, XML_MO):
2239 pContext = new SmXMLOperatorContext_Impl(GetSmImport());
2240 break;
2241 case XML_ELEMENT(MATH, XML_MTEXT):
2242 pContext = new SmXMLTextContext_Impl(GetSmImport());
2243 break;
2244 case XML_ELEMENT(MATH, XML_MSPACE):
2245 pContext = new SmXMLSpaceContext_Impl(GetSmImport());
2246 break;
2247 case XML_ELEMENT(MATH, XML_MS):
2248 pContext = new SmXMLStringContext_Impl(GetSmImport());
2249 break;
2250
2251 /*Note: The maligngroup should only be seen when the row
2252 * (or descendants) are in a table*/
2253 case XML_ELEMENT(MATH, XML_MALIGNGROUP):
2254 pContext = new SmXMLAlignGroupContext_Impl(GetSmImport());
2255 break;
2256
2257 case XML_ELEMENT(MATH, XML_ANNOTATION):
2258 pContext = new SmXMLAnnotationContext_Impl(GetSmImport());
2259 break;
2260
2261 default:
2262 break;
2263 }
2264 return pContext;
2265}
2266
2267uno::Reference<xml::sax::XFastContextHandler> SmXMLRowContext_Impl::createFastChildContext(
2268 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2269{
2270 uno::Reference<xml::sax::XFastContextHandler> xContext = StrictCreateChildContext(nElement);
2271
2272 if (!xContext)
2273 {
2274 //Hmm, unrecognized for this level, check to see if it's
2275 //an element that can have an implicit schema around it
2276 xContext = SmXMLDocContext_Impl::createFastChildContext(nElement, xAttrList);
2277 }
2278 return xContext;
2279}
2280
2281uno::Reference<xml::sax::XFastContextHandler> SmXMLMultiScriptsContext_Impl::createFastChildContext(
2282 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2283{
2284 uno::Reference<xml::sax::XFastContextHandler> xContext;
2285
2286 switch (nElement)
2287 {
2288 case XML_ELEMENT(MATH, XML_MPRESCRIPTS):
2289 bHasPrescripts = true;
2290 ProcessSubSupPairs(false);
2291 xContext = new SmXMLPrescriptsContext_Impl(GetSmImport());
2292 break;
2293 case XML_ELEMENT(MATH, XML_NONE):
2294 xContext = new SmXMLNoneContext_Impl(GetSmImport());
2295 break;
2296 default:
2297 xContext = SmXMLRowContext_Impl::createFastChildContext(nElement, xAttrList);
2298 break;
2299 }
2300 return xContext;
2301}
2302
2303void SmXMLMultiScriptsContext_Impl::ProcessSubSupPairs(bool bIsPrescript)
2304{
2305 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2306
2307 if (rNodeStack.size() <= nElementCount)
2308 return;
2309
2310 auto nCount = rNodeStack.size() - nElementCount - 1;
2311 if (nCount == 0)
2312 return;
2313
2314 if (nCount % 2 == 0)
2315 {
2316 SmToken aToken;
2317 aToken.cMathChar = u"";
2318 aToken.eType = bIsPrescript ? TLSUB : TRSUB;
2319
2320 SmNodeStack aReverseStack;
2321 for (size_t i = 0; i < nCount + 1; i++)
2322 {
2323 auto pNode = std::move(rNodeStack.front());
2324 rNodeStack.pop_front();
2325 aReverseStack.push_front(std::move(pNode));
2326 }
2327
2328 SmSubSup eSub = bIsPrescript ? LSUB : RSUB;
2329 SmSubSup eSup = bIsPrescript ? LSUP : RSUP;
2330
2331 for (size_t i = 0; i < nCount; i += 2)
2332 {
2333 std::unique_ptr<SmSubSupNode> pNode(new SmSubSupNode(aToken));
2334
2335 // initialize subnodes array
2336 SmNodeArray aSubNodes(1 + SUBSUP_NUM_ENTRIES);
2337
2338 /*On each loop the base and its sub sup pair becomes the
2339 base for the next loop to which the next sub sup pair is
2340 attached, i.e. wheels within wheels*/
2341 aSubNodes[0] = popOrZero(aReverseStack).release();
2342
2343 std::unique_ptr<SmNode> pScriptNode = popOrZero(aReverseStack);
2344
2345 if (pScriptNode
2346 && ((pScriptNode->GetToken().eType != TIDENT)
2347 || (!pScriptNode->GetToken().aText.isEmpty())))
2348 aSubNodes[eSub + 1] = pScriptNode.release();
2349 pScriptNode = popOrZero(aReverseStack);
2350 if (pScriptNode
2351 && ((pScriptNode->GetToken().eType != TIDENT)
2352 || (!pScriptNode->GetToken().aText.isEmpty())))
2353 aSubNodes[eSup + 1] = pScriptNode.release();
2354
2355 pNode->SetSubNodes(std::move(aSubNodes));
2356 aReverseStack.push_front(std::move(pNode));
2357 }
2358 assert(!aReverseStack.empty());
2359 auto pNode = std::move(aReverseStack.front());
2360 aReverseStack.pop_front();
2361 rNodeStack.push_front(std::move(pNode));
2362 }
2363 else
2364 {
2365 // Ignore odd number of elements.
2366 for (size_t i = 0; i < nCount; i++)
2367 {
2368 rNodeStack.pop_front();
2369 }
2370 }
2371}
2372
2373void SmXMLTableContext_Impl::endFastElement(sal_Int32)
2374{
2375 SmNodeArray aExpressionArray;
2376 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2377 SmNodeStack aReverseStack;
2378 aExpressionArray.resize(rNodeStack.size() - nElementCount);
2379
2380 size_t nRows = rNodeStack.size() - nElementCount;
2381 size_t nCols = 0;
2382
2383 for (size_t i = nRows; i > 0; --i)
2384 {
2385 SmNode* pArray = rNodeStack.front().release();
2386 rNodeStack.pop_front();
2387 if (pArray->GetNumSubNodes() == 0)
2388 {
2389 //This is a little tricky, it is possible that there was
2390 //be elements that were not inside a <mtd> pair, in which
2391 //case they will not be in a row, i.e. they will not have
2392 //SubNodes, so we have to wait until here before we can
2393 //resolve the situation. Implicit surrounding tags are
2394 //surprisingly difficult to get right within this
2395 //architecture
2396
2397 SmNodeArray aRelationArray;
2398 aRelationArray.resize(1);
2399 aRelationArray[0] = pArray;
2400 SmToken aDummy;
2401 SmExpressionNode* pExprNode = new SmExpressionNode(aDummy);
2402 pExprNode->SetSubNodes(std::move(aRelationArray));
2403 pArray = pExprNode;
2404 }
2405
2406 nCols = std::max(nCols, pArray->GetNumSubNodes());
2407 aReverseStack.push_front(std::unique_ptr<SmNode>(pArray));
2408 }
2409 if (nCols > SAL_MAX_UINT16)
2410 throw std::range_error("column limit");
2411 if (nRows > SAL_MAX_UINT16)
2412 throw std::range_error("row limit");
2413 aExpressionArray.resize(nCols * nRows);
2414 size_t j = 0;
2415 for (auto& elem : aReverseStack)
2416 {
2417 std::unique_ptr<SmStructureNode> xArray(static_cast<SmStructureNode*>(elem.release()));
2418 for (size_t i = 0; i < xArray->GetNumSubNodes(); ++i)
2419 aExpressionArray[j++] = xArray->GetSubNode(i);
2420 xArray->ClearSubNodes();
2421 }
2422 aReverseStack.clear();
2423
2424 SmToken aToken;
2425 aToken.cMathChar = u"";
2426 aToken.eType = TMATRIX;
2427 std::unique_ptr<SmMatrixNode> pSNode(new SmMatrixNode(aToken));
2428 pSNode->SetSubNodes(std::move(aExpressionArray));
2429 pSNode->SetRowCol(nRows, nCols);
2430 rNodeStack.push_front(std::move(pSNode));
2431}
2432
2433uno::Reference<xml::sax::XFastContextHandler> SmXMLTableRowContext_Impl::createFastChildContext(
2434 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2435{
2436 uno::Reference<xml::sax::XFastContextHandler> xContext;
2437
2438 switch (nElement)
2439 {
2440 case XML_ELEMENT(MATH, XML_MTD):
2441 xContext = new SmXMLTableCellContext_Impl(GetSmImport());
2442 break;
2443 default:
2444 xContext = SmXMLRowContext_Impl::createFastChildContext(nElement, xAttrList);
2445 break;
2446 }
2447 return xContext;
2448}
2449
2450uno::Reference<xml::sax::XFastContextHandler> SmXMLTableContext_Impl::createFastChildContext(
2451 sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2452{
2453 uno::Reference<xml::sax::XFastContextHandler> xContext;
2454
2455 switch (nElement)
2456 {
2457 case XML_ELEMENT(MATH, XML_MTR):
2458 xContext = new SmXMLTableRowContext_Impl(GetSmImport());
2459 break;
2460 default:
2461 xContext = SmXMLTableRowContext_Impl::createFastChildContext(nElement, xAttrList);
2462 break;
2463 }
2464 return xContext;
2465}
2466
2467void SmXMLMultiScriptsContext_Impl::endFastElement(sal_Int32)
2468{
2469 ProcessSubSupPairs(bHasPrescripts);
2470}
2471
2472void SmXMLActionContext_Impl::startFastElement(
2473 sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
2474{
2475 for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
2476 {
2477 switch (aIter.getToken())
2478 {
2479 case XML_SELECTION:
2480 {
2481 sal_Int32 n = aIter.toInt32();
2482 if (n > 0)
2483 mnSelection = static_cast<size_t>(n);
2484 }
2485 break;
2486 default:
2487 XMLOFF_WARN_UNKNOWN("starmath", aIter);
2488 break;
2489 }
2490 }
2491}
2492
2493void SmXMLActionContext_Impl::endFastElement(sal_Int32)
2494{
2495 SmNodeStack& rNodeStack = GetSmImport().GetNodeStack();
2496 auto nSize = rNodeStack.size();
2497 if (nSize <= nElementCount)
2498 {
2499 // not compliant to maction's specification, e.g., no subexpressions
2500 return;
2501 }
2502 assert(mnSelection > 0);
2503 if (nSize < nElementCount + mnSelection)
2504 {
2505 // No selected subexpression exists, which is a MathML error;
2506 // fallback to selecting the first
2507 mnSelection = 1;
2508 }
2509 assert(nSize >= nElementCount + mnSelection);
2510 for (auto i = nSize - (nElementCount + mnSelection); i > 0; i--)
2511 {
2512 rNodeStack.pop_front();
2513 }
2514 auto pSelected = std::move(rNodeStack.front());
2515 rNodeStack.pop_front();
2516 for (auto i = rNodeStack.size() - nElementCount; i > 0; i--)
2517 {
2518 rNodeStack.pop_front();
2519 }
2520 rNodeStack.push_front(std::move(pSelected));
2521}
2522
2525 const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
2526{
2527 SvXMLImportContext* pContext = nullptr;
2528
2529 switch (nElement)
2530 {
2533 {
2534 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(),
2535 uno::UNO_QUERY_THROW);
2536 pContext = ((nElement & TOKEN_MASK) == XML_DOCUMENT_META)
2537 ? new SvXMLMetaDocumentContext(*this, xDPS->getDocumentProperties())
2538 // flat OpenDocument file format -- this has not been tested...
2539 : new SmXMLFlatDocContext_Impl(*this, xDPS->getDocumentProperties());
2540 }
2541 break;
2542 default:
2544 pContext = new SmXMLOfficeContext_Impl(*this);
2545 else
2546 pContext = new SmXMLDocContext_Impl(*this);
2547 }
2548 return pContext;
2549}
2550
2552
2553void SmXMLImport::SetViewSettings(const Sequence<PropertyValue>& aViewProps)
2554{
2555 uno::Reference<frame::XModel> xModel = GetModel();
2556 if (!xModel.is())
2557 return;
2558
2559 SmModel* pModel = dynamic_cast<SmModel*>(xModel.get());
2560
2561 if (!pModel)
2562 return;
2563
2564 SmDocShell* pDocShell = static_cast<SmDocShell*>(pModel->GetObjectShell());
2565 if (!pDocShell)
2566 return;
2567
2568 tools::Rectangle aRect(pDocShell->GetVisArea());
2569
2570 tools::Long nTmp = 0;
2571
2572 for (const PropertyValue& rValue : aViewProps)
2573 {
2574 if (rValue.Name == "ViewAreaTop")
2575 {
2576 rValue.Value >>= nTmp;
2577 aRect.SaturatingSetPosY(nTmp);
2578 }
2579 else if (rValue.Name == "ViewAreaLeft")
2580 {
2581 rValue.Value >>= nTmp;
2582 aRect.SaturatingSetPosX(nTmp);
2583 }
2584 else if (rValue.Name == "ViewAreaWidth")
2585 {
2586 rValue.Value >>= nTmp;
2587 Size aSize(aRect.GetSize());
2588 aSize.setWidth(nTmp);
2589 aRect.SaturatingSetSize(aSize);
2590 }
2591 else if (rValue.Name == "ViewAreaHeight")
2592 {
2593 rValue.Value >>= nTmp;
2594 Size aSize(aRect.GetSize());
2595 aSize.setHeight(nTmp);
2596 aRect.SaturatingSetSize(aSize);
2597 }
2598 }
2599
2600 pDocShell->SetVisArea(aRect);
2601}
2602
2603void SmXMLImport::SetConfigurationSettings(const Sequence<PropertyValue>& aConfProps)
2604{
2605 uno::Reference<XPropertySet> xProps(GetModel(), UNO_QUERY);
2606 if (!xProps.is())
2607 return;
2608
2609 Reference<XPropertySetInfo> xInfo(xProps->getPropertySetInfo());
2610 if (!xInfo.is())
2611 return;
2612
2613 static constexpr OUStringLiteral sFormula(u"Formula");
2614 static constexpr OUStringLiteral sBasicLibraries(u"BasicLibraries");
2615 static constexpr OUStringLiteral sDialogLibraries(u"DialogLibraries");
2616 for (const PropertyValue& rValue : aConfProps)
2617 {
2618 if (rValue.Name != sFormula && rValue.Name != sBasicLibraries
2619 && rValue.Name != sDialogLibraries)
2620 {
2621 try
2622 {
2623 if (xInfo->hasPropertyByName(rValue.Name))
2624 xProps->setPropertyValue(rValue.Name, rValue.Value);
2625 }
2626 catch (const beans::PropertyVetoException&)
2627 {
2628 // dealing with read-only properties here. Nothing to do...
2629 }
2630 catch (const Exception&)
2631 {
2632 DBG_UNHANDLED_EXCEPTION("starmath");
2633 }
2634 }
2635 }
2636}
2637
2638extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportMML(SvStream& rStream)
2639{
2641
2642 SfxObjectShellLock xDocSh(new SmDocShell(SfxModelFlags::EMBEDDED_OBJECT));
2643 xDocSh->DoInitNew();
2644 uno::Reference<frame::XModel> xModel(xDocSh->GetModel());
2645
2646 uno::Reference<beans::XPropertySet> xInfoSet;
2647 uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
2648 uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
2649
2650 //SetLoading hack because the document properties will be re-initted
2651 //by the xml filter and during the init, while it's considered uninitialized,
2652 //setting a property will inform the document it's modified, which attempts
2653 //to update the properties, which throws cause the properties are uninitialized
2654 xDocSh->SetLoading(SfxLoadedFlags::NONE);
2655
2657
2658 try
2659 {
2660 nRet = SmXMLImportWrapper::ReadThroughComponent(xStream, xModel, xContext, xInfoSet,
2661 "com.sun.star.comp.Math.XMLImporter", false,
2662 false);
2663 }
2664 catch (...)
2665 {
2666 }
2667
2668 xDocSh->SetLoading(SfxLoadedFlags::ALL);
2669
2670 xDocSh->DoClose();
2671
2672 return nRet != ERRCODE_NONE;
2673}
2674
2675/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XInputStream > xStream
const NodeContext & mrContext
virtual bool IsImportSymbolNames() const =0
virtual void SetImportSymbolNames(bool bVal)=0
virtual std::unique_ptr< SmTableNode > Parse(const OUString &rBuffer)=0
Parse rBuffer to formula tree.
virtual const OUString & GetText() const =0
const OUString & GetValue() const
sal_Int32 GetNumerator() const
SfxObjectShell * GetObjectShell() const
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
OUString GetBaseURL(bool bForSaving=false)
SfxItemSet & GetItemSet() const
css::uno::Reference< css::embed::XStorage > GetStorage(bool bCreateTempFile=true)
bool IsStorage()
SvStream * GetInStream()
SfxMedium * GetMedium() const
css::uno::Reference< css::frame::XModel3 > GetModel() const
void SetLoading(SfxLoadedFlags nFlags)
virtual tools::Rectangle GetVisArea(sal_uInt16 nAspect) const
SfxObjectCreateMode GetCreateMode() const
const css::uno::Any & GetValue() const
void setWidth(tools::Long nWidth)
void setHeight(tools::Long nHeight)
Attribute node.
Definition: node.hxx:1890
Binary horizontal node.
Definition: node.hxx:1425
Node for whitespace.
Definition: node.hxx:2056
Node for brace construction.
Definition: node.hxx:1646
void SetText(const OUString &rBuffer)
Definition: document.cxx:138
virtual void SetVisArea(const tools::Rectangle &rVisArea) override
Definition: document.cxx:1153
void SetSmSyntaxVersion(sal_uInt16 nSmSyntaxVersion)
Definition: document.cxx:101
AbstractSmParser * GetParser()
Definition: document.hxx:175
void SetFormulaTree(SmTableNode *pTree)
Definition: document.hxx:177
Expression node.
Definition: node.hxx:1244
Font node.
Definition: node.hxx:1932
Glyph node for custom operators.
Definition: node.hxx:926
A line.
Definition: node.hxx:1178
Math symbol node.
Definition: node.hxx:955
Matrix node.
Definition: node.hxx:2000
Extract command text from pNodes.
Definition: visitors.hxx:465
Definition: node.hxx:125
virtual size_t GetNumSubNodes() const =0
Gets the number of subnodes.
Draws a rectangle.
Definition: node.hxx:665
Root node.
Definition: node.hxx:1307
Root symbol node.
Definition: node.hxx:1020
Abstract baseclass for all composite node.
Definition: node.hxx:471
void SetSubNodes(std::unique_ptr< SmNode > pFirst, std::unique_ptr< SmNode > pSecond, std::unique_ptr< SmNode > pThird=nullptr)
Sets subnodes, used for operators.
Definition: node.cxx:364
Super- and subscript node.
Definition: node.hxx:1559
Table node.
Definition: node.hxx:1139
Text node.
Definition: node.hxx:747
ErrCode Import(SfxMedium &rMedium)
rtl::Reference< SmModel > m_xModel
static ErrCode ReadThroughComponent(const css::uno::Reference< css::io::XInputStream > &xInputStream, const css::uno::Reference< css::lang::XComponent > &xModelComponent, css::uno::Reference< css::uno::XComponentContext > const &rxContext, css::uno::Reference< css::beans::XPropertySet > const &rPropSet, const char *pFilterName, bool bEncrypted, bool bUseHTMLMLEntities)
SmXMLImport(const css::uno::Reference< css::uno::XComponentContext > &rContext, OUString const &implementationName, SvXMLImportFlags nImportFlags)
virtual ~SmXMLImport() noexcept override
SvXMLImportContext * CreateFastContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
void SAL_CALL endDocument() override
SmNodeStack aNodeStack
OUString aText
virtual void SetViewSettings(const css::uno::Sequence< css::beans::PropertyValue > &aViewProps) override
virtual void SetConfigurationSettings(const css::uno::Sequence< css::beans::PropertyValue > &aViewProps) override
sal_uInt16 mnSmSyntaxVersion
sal_Int32 GetVersion() const
virtual void SAL_CALL startFastElement(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
SvXMLImport & GetImport()
virtual css::uno::Reference< XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual void SAL_CALL characters(const OUString &aChars) override
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
css::uno::Type const & get()
static void convertDouble(OUStringBuffer &rBuffer, double fNumber, bool bWriteUnits, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
const std::vector< sal_Int32 > & getFastAttributeTokens() const
void SaturatingSetPosX(tools::Long x)
void SaturatingSetPosY(tools::Long y)
constexpr Size GetSize() const
void SaturatingSetSize(const Size &rSize)
constexpr OUStringLiteral sColor
int nCount
#define DBG_UNHANDLED_EXCEPTION(...)
SVXCORE_DLLPUBLIC OUString SvxResId(TranslateId aId)
OString sFormula
float u
#define ERRCODE_IO_BROKENPACKAGE
#define ERRCODE_NONE
#define SOFFICE_FILEFORMAT_60
DocumentType eType
#define FNT_FIXED
Definition: format.hxx:52
#define FNT_FUNCTION
Definition: format.hxx:47
#define FNT_NUMBER
Definition: format.hxx:48
#define FNT_TEXT
Definition: format.hxx:49
#define FNT_VARIABLE
Definition: format.hxx:46
OUString aName
sal_Int64 n
uno_Any a
#define SAL_INFO_IF(condition, area, stream)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
bool ParseMathMLAttributeLengthValue(std::u16string_view rStr, MathMLAttributeLengthValue &rV)
Definition: mathmlattr.cxx:84
bool GetMathMLMathvariantValue(const OUString &rStr, MathMLMathvariantValue &rV)
Definition: mathmlattr.cxx:133
MathMLMathvariantValue
Definition: mathmlattr.hxx:56
SAL_DLLPUBLIC_EXPORT uno::XInterface * Math_XMLImporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
SAL_DLLPUBLIC_EXPORT bool TestImportMML(SvStream &rStream)
SAL_DLLPUBLIC_EXPORT uno::XInterface * Math_XMLOasisMetaImporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
SAL_DLLPUBLIC_EXPORT uno::XInterface * Math_XMLOasisSettingsImporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
std::deque< std::unique_ptr< SmNode > > SmNodeStack
void ensure()
Definition: smdll.cxx:79
size
tDoubleVectorPair cleanup(const css::uno::Sequence< double > &rXValues, const css::uno::Sequence< double > &rYValues, Pred aPred)
@ Exception
COMPHELPER_DLLPUBLIC css::uno::Reference< css::beans::XPropertySet > GenericPropertySet_CreateInstance(PropertySetInfo *pInfo)
Reference< XComponentContext > getProcessComponentContext()
int i
constexpr OUStringLiteral implementationName
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
const ::css::uno::Sequence<::css::beans::Pair<::rtl::OUString, ::rtl::OUString > > icustomMathmlHtmlEntities
Entity names for mathml.
SmToken Identify_SmXMLOperatorContext_Impl(sal_Unicode cChar, bool bIsStretchy=true)
Identifies operator chars tokens for importing mathml.
SmColorTokenTableEntry Identify_Color_Parser(sal_uInt32 cColor)
Identifies color from color code cColor.
SmToken Identify_PrefixPostfix_SmXMLOperatorContext_Impl(sal_Unicode cChar)
Identifies opening / closing brace tokens for importing mathml.
SmColorTokenTableEntry Identify_ColorName_HTML(std::u16string_view colorname)
Identifies color from color name.
SmToken Identify_Postfix_SmXMLOperatorContext_Impl(sal_Unicode cChar)
Identifies closing brace tokens for importing mathml.
SmToken Identify_Prefix_SmXMLOperatorContext_Impl(sal_Unicode cChar)
Identifies opening brace tokens for importing mathml.
long Long
XML_MATHSIZE
XML_FONTFAMILY
XML_STRETCHY
XML_DOCUMENT
XML_FONTWEIGHT
XML_FORM
XML_WIDTH
XML_FENCE
XML_SELECTION
XML_ENCODING
XML_DOCUMENT_META
XML_MATHCOLOR
XML_MATHVARIANT
XML_OPEN
XML_COLOR
XML_FONTSIZE
XML_FONTSTYLE
XML_CLOSE
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
std::vector< SmNode * > SmNodeArray
Definition: node.hxx:113
SmSubSup
Enum used to index sub-/supscripts in the 'maSubNodes' array in 'SmSubSupNode'.
Definition: node.hxx:1536
@ LSUB
Definition: node.hxx:1536
@ CSUB
Definition: node.hxx:1536
@ RSUP
Definition: node.hxx:1536
@ RSUB
Definition: node.hxx:1536
@ LSUP
Definition: node.hxx:1536
@ CSUP
Definition: node.hxx:1536
#define SUBSUP_NUM_ENTRIES
numbers of entries in the above enum (that is: the number of possible sub-/supscripts)
Definition: node.hxx:1542
#define ERRCODE_SFX_WRONGPASSWORD
#define ERRCODE_SFX_DOLOADFAILED
#define SM_MOD()
Definition: smmod.hxx:98
MathMLLengthUnit eUnit
Definition: mathmlattr.hxx:43
SmTokenType eType
Definition: token.hxx:163
SmTokenType eType
Definition: token.hxx:213
sal_uInt16 nLevel
Definition: token.hxx:218
OUString cMathChar
Definition: token.hxx:214
OUString aText
Definition: token.hxx:212
TG nGroup
Definition: token.hxx:217
void setChar(sal_Unicode cChar)
Definition: token.hxx:283
Reference< XModel > xModel
@ LBrace
@ NONE
@ Blank
SmTokenType
Definition: token.hxx:71
@ TFRAC
Definition: token.hxx:89
@ TSIZE
Definition: token.hxx:115
@ TNITALIC
Definition: token.hxx:116
@ TUNDERLINE
Definition: token.hxx:118
@ TSQRT
Definition: token.hxx:144
@ TMATRIX
Definition: token.hxx:91
@ TACUTE
Definition: token.hxx:120
@ TNROOT
Definition: token.hxx:144
@ TRGROUP
Definition: token.hxx:127
@ TSERIF
Definition: token.hxx:119
@ TSPECIAL
Definition: token.hxx:74
@ TRSUP
Definition: token.hxx:104
@ TNBOLD
Definition: token.hxx:116
@ TNUMBER
Definition: token.hxx:124
@ TMLINE
Definition: token.hxx:132
@ TSANS
Definition: token.hxx:119
@ TRGB
Definition: token.hxx:146
@ TBOLD
Definition: token.hxx:116
@ TLGROUP
Definition: token.hxx:127
@ TCSUP
Definition: token.hxx:104
@ TLPARENT
Definition: token.hxx:127
@ TCSUB
Definition: token.hxx:104
@ TSBLANK
Definition: token.hxx:75
@ TERROR
Definition: token.hxx:77
@ TLSUB
Definition: token.hxx:104
@ TBLANK
Definition: token.hxx:75
@ TFIXED
Definition: token.hxx:119
@ TITALIC
Definition: token.hxx:116
@ TTEXT
Definition: token.hxx:124
@ TIDENT
Definition: token.hxx:124
@ TPHANTOM
Definition: token.hxx:115
@ TRPARENT
Definition: token.hxx:127
@ TRSUB
Definition: token.hxx:104
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
signed char sal_Int8
sal_Unicode const MS_RPARENT
Definition: types.hxx:166
sal_Unicode const MS_RBRACE
Definition: types.hxx:170
sal_Unicode const MS_SQRT
Definition: types.hxx:128
sal_Unicode const MS_LBRACE
Definition: types.hxx:169
sal_Unicode const MS_LPARENT
Definition: types.hxx:165
sal_Unicode const MS_VERTLINE
Definition: types.hxx:109
#define XMLOFF_WARN_UNKNOWN(area, rIter)
#define XML_ELEMENT(prefix, name)
constexpr bool IsTokenInNamespace(sal_Int32 nToken, sal_uInt16 nNamespacePrefix)
SvXMLImportFlags
constexpr sal_Int32 TOKEN_MASK
constexpr sal_uInt16 XML_NAMESPACE_OFFICE