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 #include <com/sun/star/beans/XPropertySet.hpp>
21 #include <com/sun/star/text/RelOrientation.hpp>
22 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
23 #include <com/sun/star/xml/sax/FastShapeContextHandler.hpp>
24 #include <com/sun/star/xml/sax/SAXException.hpp>
25 #include <ooxml/resourceids.hxx>
26 #include <oox/mathml/import.hxx>
27 #include <oox/token/namespaces.hxx>
28 #include <sal/log.hxx>
29 #include <comphelper/embeddedobjectcontainer.hxx>
30 #include <cppuhelper/exc_hlp.hxx>
31 #include <tools/globname.hxx>
32 #include <comphelper/classids.hxx>
33 #include <sfx2/sfxbasemodel.hxx>
34 #include "OOXMLFastContextHandler.hxx"
35 #include "OOXMLFactory.hxx"
36 #include "Handler.hxx"
37 #include <dmapper/CommentProperties.hxx>
38 #include <dmapper/PropertyIds.hxx>
39 #include <comphelper/propertysequence.hxx>
40 #include <comphelper/sequenceashashmap.hxx>
41 
42 const sal_Unicode uCR = 0xd;
43 const sal_Unicode uFtnEdnRef = 0x2;
44 const sal_Unicode uFtnEdnSep = 0x3;
45 const sal_Unicode uFtnSep = 0x5;
46 const sal_Unicode uTab = 0x9;
47 const sal_Unicode uPgNum = 0x0;
48 const sal_Unicode uNoBreakHyphen = 0x2011;
49 const sal_Unicode uSoftHyphen = 0xAD;
50 
51 const sal_uInt8 cFtnEdnCont = 0x4;
52 
53 namespace writerfilter::ooxml
54 {
55 using namespace ::com::sun::star;
56 using namespace oox;
57 using namespace ::std;
58 using namespace ::com::sun::star::xml::sax;
59 
60 /*
61   class OOXMLFastContextHandler
62  */
63 
OOXMLFastContextHandler(uno::Reference<uno::XComponentContext> const & context)64 OOXMLFastContextHandler::OOXMLFastContextHandler
65 (uno::Reference< uno::XComponentContext > const & context)
66 : mpParent(nullptr),
67   mId(0),
68   mnDefine(0),
69   mnToken(oox::XML_TOKEN_COUNT),
70   mnMathJcVal(0),
71   mbIsMathPara(false),
72   mpStream(nullptr),
73   mnTableDepth(0),
74   inPositionV(false),
75   mbAllowInCell(true),
76   mbIsVMLfound(false),
77   m_xContext(context),
78   m_bDiscardChildren(false),
79   m_bTookChoice(false)
80 {
81     if (!mpParserState)
82         mpParserState = new OOXMLParserState();
83 
84     mpParserState->incContextCount();
85 }
86 
OOXMLFastContextHandler(OOXMLFastContextHandler * pContext)87 OOXMLFastContextHandler::OOXMLFastContextHandler(OOXMLFastContextHandler * pContext)
88 : cppu::WeakImplHelper<xml::sax::XFastContextHandler>(),
89   mpParent(pContext),
90   mId(0),
91   mnDefine(0),
92   mnToken(oox::XML_TOKEN_COUNT),
93   mnMathJcVal(pContext->mnMathJcVal),
94   mbIsMathPara(pContext->mbIsMathPara),
95   mpStream(pContext->mpStream),
96   mpParserState(pContext->mpParserState),
97   mnTableDepth(pContext->mnTableDepth),
98   inPositionV(pContext->inPositionV),
99   mbAllowInCell(pContext->mbAllowInCell),
100   mbIsVMLfound(pContext->mbIsVMLfound),
101   m_xContext(pContext->m_xContext),
102   m_bDiscardChildren(pContext->m_bDiscardChildren),
103   m_bTookChoice(pContext->m_bTookChoice)
104 {
105     if (!mpParserState)
106         mpParserState = new OOXMLParserState();
107 
108     mpParserState->incContextCount();
109 }
110 
~OOXMLFastContextHandler()111 OOXMLFastContextHandler::~OOXMLFastContextHandler()
112 {
113 }
114 
prepareMceContext(Token_t nElement,const uno::Reference<xml::sax::XFastAttributeList> & rAttribs)115 bool OOXMLFastContextHandler::prepareMceContext(Token_t nElement, const uno::Reference<xml::sax::XFastAttributeList>& rAttribs)
116 {
117     switch (oox::getBaseToken(nElement))
118     {
119         case XML_AlternateContent:
120             {
121                 SavedAlternateState aState;
122                 aState.m_bDiscardChildren = m_bDiscardChildren;
123                 m_bDiscardChildren = false;
124                 aState.m_bTookChoice = m_bTookChoice;
125                 m_bTookChoice = false;
126                 mpParserState->getSavedAlternateStates().push_back(aState);
127             }
128             break;
129         case XML_Choice:
130         {
131             OUString aRequires = rAttribs->getOptionalValue(XML_Requires);
132             static const char* aFeatures[] = {
133                 "wps",
134                 "wpg",
135                 "w14",
136             };
137             for (const char *p : aFeatures)
138             {
139                 if (aRequires.equalsAscii(p))
140                 {
141                     m_bTookChoice = true;
142                     return false;
143                 }
144             }
145             return true;
146         }
147             break;
148         case XML_Fallback:
149             // If Choice is already taken, then let's ignore the Fallback.
150             return m_bTookChoice;
151         default:
152             SAL_WARN("writerfilter", "OOXMLFastContextHandler::prepareMceContext: unhandled element:" << oox::getBaseToken(nElement));
153             break;
154     }
155     return false;
156 }
157 
158 // xml::sax::XFastContextHandler:
startFastElement(sal_Int32 Element,const uno::Reference<xml::sax::XFastAttributeList> & Attribs)159 void SAL_CALL OOXMLFastContextHandler::startFastElement
160 (sal_Int32 Element,
161  const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
162 {
163     // Set xml:space value early, to allow child contexts use it when dealing with strings.
164     if (Attribs && Attribs->hasAttribute(oox::NMSP_xml | oox::XML_space))
165     {
166         mbPreserveSpace = Attribs->getValue(oox::NMSP_xml | oox::XML_space) == "preserve";
167         mbPreserveSpaceSet = true;
168     }
169     if (Element == W_TOKEN(footnote) || Element == W_TOKEN(endnote))
170     {
171         // send uFtnSep to sign new footnote content, but skip footnote separators
172         if (!Attribs->hasAttribute(W_TOKEN(type)) ||
173                 ( Attribs->getValue(W_TOKEN(type)) != "separator" &&
174                   Attribs->getValue(W_TOKEN(type)) != "continuationSeparator" &&
175                   Attribs->getValue(W_TOKEN(type)) != "continuationNotice" ))
176         {
177             mpParserState->setStartFootnote(true);
178         }
179     }
180     else if (Element == (NMSP_officeMath | XML_oMathPara))
181     {
182         mnMathJcVal = eMathParaJc::CENTER;
183         mbIsMathPara = true;
184     }
185     else if (Element == (NMSP_officeMath | XML_jc) && mpParent && mpParent->mpParent )
186     {
187         mbIsMathPara = true;
188         auto aAttrLst = Attribs->getFastAttributes();
189         if (aAttrLst[0].Value == "center") mpParent->mpParent->mnMathJcVal = eMathParaJc::CENTER;
190         if (aAttrLst[0].Value == "left") mpParent->mpParent->mnMathJcVal = eMathParaJc::LEFT;
191         if (aAttrLst[0].Value == "right") mpParent->mpParent->mnMathJcVal = eMathParaJc::RIGHT;
192     }
193 
194     if (oox::getNamespace(Element) == NMSP_mce)
195         m_bDiscardChildren = prepareMceContext(Element, Attribs);
196 
197     else if (!m_bDiscardChildren)
198     {
199         attributes(Attribs);
200         lcl_startFastElement(Element, Attribs);
201     }
202 }
203 
startUnknownElement(const OUString &,const OUString &,const uno::Reference<xml::sax::XFastAttributeList> &)204 void SAL_CALL OOXMLFastContextHandler::startUnknownElement
205 (const OUString & /*Namespace*/, const OUString & /*Name*/,
206  const uno::Reference< xml::sax::XFastAttributeList > & /*Attribs*/)
207 {
208 }
209 
endFastElement(sal_Int32 Element)210 void SAL_CALL OOXMLFastContextHandler::endFastElement(sal_Int32 Element)
211 {
212     if (Element == (NMSP_mce | XML_Choice) || Element == (NMSP_mce | XML_Fallback))
213         m_bDiscardChildren = false;
214     else if (Element == (NMSP_mce | XML_AlternateContent))
215     {
216         SavedAlternateState aState(mpParserState->getSavedAlternateStates().back());
217         mpParserState->getSavedAlternateStates().pop_back();
218         m_bDiscardChildren = aState.m_bDiscardChildren;
219         m_bTookChoice = aState.m_bTookChoice;
220     }
221     else if (!m_bDiscardChildren)
222         lcl_endFastElement(Element);
223 }
224 
lcl_startFastElement(Token_t Element,const uno::Reference<xml::sax::XFastAttributeList> &)225 void OOXMLFastContextHandler::lcl_startFastElement
226 (Token_t Element,
227  const uno::Reference< xml::sax::XFastAttributeList > & /*Attribs*/)
228 {
229     OOXMLFactory::startAction(this);
230     if( Element == (NMSP_dmlWordDr|XML_positionV) )
231         inPositionV = true;
232     else if( Element == (NMSP_dmlWordDr|XML_positionH) )
233         inPositionV = false;
234 
235 }
236 
lcl_endFastElement(Token_t)237 void OOXMLFastContextHandler::lcl_endFastElement
238 (Token_t /*Element*/)
239 {
240     OOXMLFactory::endAction(this);
241 }
242 
endUnknownElement(const OUString &,const OUString &)243 void SAL_CALL OOXMLFastContextHandler::endUnknownElement
244 (const OUString & , const OUString & )
245 {
246 }
247 
248 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
createFastChildContext(sal_Int32 Element,const uno::Reference<xml::sax::XFastAttributeList> & Attribs)249  OOXMLFastContextHandler::createFastChildContext
250 (sal_Int32 Element,
251  const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
252 {
253     uno::Reference< xml::sax::XFastContextHandler > xResult;
254     if (oox::getNamespace(Element) != NMSP_mce && !m_bDiscardChildren)
255         xResult.set(lcl_createFastChildContext(Element, Attribs));
256     else if (oox::getNamespace(Element) == NMSP_mce)
257         xResult = this;
258 
259     return xResult;
260 }
261 
262 uno::Reference< xml::sax::XFastContextHandler >
lcl_createFastChildContext(Token_t Element,const uno::Reference<xml::sax::XFastAttributeList> &)263  OOXMLFastContextHandler::lcl_createFastChildContext
264 (Token_t Element,
265  const uno::Reference< xml::sax::XFastAttributeList > & /*Attribs*/)
266 {
267     return OOXMLFactory::createFastChildContext(this, Element);
268 }
269 
270 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
createUnknownChildContext(const OUString &,const OUString &,const uno::Reference<xml::sax::XFastAttributeList> &)271 OOXMLFastContextHandler::createUnknownChildContext
272 (const OUString &,
273  const OUString &,
274  const uno::Reference< xml::sax::XFastAttributeList > & /*Attribs*/)
275 {
276     return uno::Reference< xml::sax::XFastContextHandler >
277         (new OOXMLFastContextHandler(*const_cast<const OOXMLFastContextHandler *>(this)));
278 }
279 
characters(const OUString & aChars)280 void SAL_CALL OOXMLFastContextHandler::characters
281 (const OUString & aChars)
282 {
283     lcl_characters(aChars);
284 }
285 
lcl_characters(const OUString & rString)286 void OOXMLFastContextHandler::lcl_characters
287 (const OUString & rString)
288 {
289     if (!m_bDiscardChildren)
290         OOXMLFactory::characters(this, rString);
291 }
292 
setStream(Stream * pStream)293 void OOXMLFastContextHandler::setStream(Stream * pStream)
294 {
295     mpStream = pStream;
296 }
297 
getValue() const298 OOXMLValue::Pointer_t OOXMLFastContextHandler::getValue() const
299 {
300     return OOXMLValue::Pointer_t();
301 }
302 
attributes(const uno::Reference<xml::sax::XFastAttributeList> & Attribs)303 void OOXMLFastContextHandler::attributes
304 (const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
305 {
306     OOXMLFactory::attributes(this, Attribs);
307 }
308 
startAction()309 void OOXMLFastContextHandler::startAction()
310 {
311     OOXMLFactory::startAction(this);
312 }
313 
endAction()314 void OOXMLFastContextHandler::endAction()
315 {
316     OOXMLFactory::endAction(this);
317 }
318 
setId(Id rId)319 void OOXMLFastContextHandler::setId(Id rId)
320 {
321     mId = rId;
322 }
323 
getId() const324 Id OOXMLFastContextHandler::getId() const
325 {
326     return mId;
327 }
328 
setDefine(Id nDefine)329 void OOXMLFastContextHandler::setDefine(Id nDefine)
330 {
331     mnDefine = nDefine;
332 }
333 
334 
setToken(Token_t nToken)335 void OOXMLFastContextHandler::setToken(Token_t nToken)
336 {
337     mnToken = nToken;
338 }
339 
getToken() const340 Token_t OOXMLFastContextHandler::getToken() const
341 {
342     return mnToken;
343 }
344 
sendTableDepth() const345 void OOXMLFastContextHandler::sendTableDepth() const
346 {
347     if (mnTableDepth <= 0)
348         return;
349 
350     OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
351     {
352         OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(mnTableDepth);
353         pProps->add(NS_ooxml::LN_tblDepth, pVal, OOXMLProperty::SPRM);
354     }
355     {
356         OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
357         pProps->add(NS_ooxml::LN_inTbl, pVal, OOXMLProperty::SPRM);
358     }
359 
360     mpStream->props(pProps.get());
361 }
362 
setHandle()363 void OOXMLFastContextHandler::setHandle()
364 {
365     mpParserState->setHandle();
366     mpStream->info(mpParserState->getHandle());
367 }
368 
startCharacterGroup()369 void OOXMLFastContextHandler::startCharacterGroup()
370 {
371     if (!isForwardEvents())
372         return;
373 
374     if (mpParserState->isInCharacterGroup())
375         endCharacterGroup();
376 
377     if (! mpParserState->isInParagraphGroup())
378         startParagraphGroup();
379 
380     if (! mpParserState->isInCharacterGroup())
381     {
382         mpStream->startCharacterGroup();
383         mpParserState->setInCharacterGroup(true);
384         mpParserState->resolveCharacterProperties(*mpStream);
385         if (mpParserState->isStartFootnote())
386         {
387             mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uFtnSep), 1);
388             mpParserState->setStartFootnote(false);
389         }
390     }
391 
392     // tdf#108714 : if we have a postponed break information,
393     // then apply it now, before any other paragraph content.
394     mpParserState->resolvePostponedBreak(*mpStream);
395 }
396 
endCharacterGroup()397 void OOXMLFastContextHandler::endCharacterGroup()
398 {
399     if (isForwardEvents() && mpParserState->isInCharacterGroup())
400     {
401         mpStream->endCharacterGroup();
402         mpParserState->setInCharacterGroup(false);
403     }
404 }
405 
pushBiDiEmbedLevel()406 void OOXMLFastContextHandler::pushBiDiEmbedLevel() {}
407 
popBiDiEmbedLevel()408 void OOXMLFastContextHandler::popBiDiEmbedLevel() {}
409 
startParagraphGroup()410 void OOXMLFastContextHandler::startParagraphGroup()
411 {
412     if (!isForwardEvents())
413         return;
414 
415     if (mpParserState->isInParagraphGroup())
416         endParagraphGroup();
417 
418     if (! mpParserState->isInSectionGroup())
419         startSectionGroup();
420 
421     if (! mpParserState->isInParagraphGroup())
422     {
423         mpStream->startParagraphGroup();
424         mpParserState->setInParagraphGroup(true);
425 
426         if (const auto& pPropSet = getPropertySet())
427         {
428             OOXMLPropertySetEntryToString aHandler(NS_ooxml::LN_AG_Parids_paraId);
429             pPropSet->resolve(aHandler);
430             if (const OUString& sText = aHandler.getString(); !sText.isEmpty())
431             {
432                 OOXMLStringValue::Pointer_t pVal = new OOXMLStringValue(sText);
433                 OOXMLPropertySet::Pointer_t pPropertySet(new OOXMLPropertySet);
434                 pPropertySet->add(NS_ooxml::LN_AG_Parids_paraId, pVal, OOXMLProperty::ATTRIBUTE);
435                 mpStream->props(pPropertySet.get());
436             }
437         }
438 
439     }
440 }
441 
endParagraphGroup()442 void OOXMLFastContextHandler::endParagraphGroup()
443 {
444     if (isForwardEvents())
445     {
446         if (mpParserState->isInCharacterGroup())
447             endCharacterGroup();
448 
449         if (mpParserState->isInParagraphGroup())
450         {
451             mpStream->endParagraphGroup();
452             mpParserState->setInParagraphGroup(false);
453         }
454     }
455 }
456 
startSdt()457 void OOXMLFastContextHandler::startSdt()
458 {
459     OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
460     OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
461     pProps->add(NS_ooxml::LN_CT_SdtBlock_sdtContent, pVal, OOXMLProperty::ATTRIBUTE);
462     mpStream->props(pProps.get());
463 }
464 
endSdt()465 void OOXMLFastContextHandler::endSdt()
466 {
467     OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
468     OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
469     pProps->add(NS_ooxml::LN_CT_SdtBlock_sdtEndContent, pVal, OOXMLProperty::ATTRIBUTE);
470     mpStream->props(pProps.get());
471 }
472 
startSectionGroup()473 void OOXMLFastContextHandler::startSectionGroup()
474 {
475     if (isForwardEvents())
476     {
477         if (mpParserState->isInSectionGroup())
478             endSectionGroup();
479 
480         if (! mpParserState->isInSectionGroup())
481         {
482             mpStream->info(mpParserState->getHandle());
483             mpStream->startSectionGroup();
484             mpParserState->setInSectionGroup(true);
485         }
486     }
487 }
488 
endSectionGroup()489 void OOXMLFastContextHandler::endSectionGroup()
490 {
491     if (isForwardEvents())
492     {
493         if (mpParserState->isInParagraphGroup())
494             endParagraphGroup();
495 
496         if (mpParserState->isInSectionGroup())
497         {
498             mpStream->endSectionGroup();
499             mpParserState->setInSectionGroup(false);
500         }
501     }
502 }
503 
setLastParagraphInSection()504 void OOXMLFastContextHandler::setLastParagraphInSection()
505 {
506     mpParserState->setLastParagraphInSection(true);
507     mpStream->markLastParagraphInSection( );
508 }
509 
setLastSectionGroup()510 void OOXMLFastContextHandler::setLastSectionGroup()
511 {
512     mpStream->markLastSectionGroup( );
513 }
514 
newProperty(Id,const OOXMLValue::Pointer_t &)515 void OOXMLFastContextHandler::newProperty
516 (Id /*nId*/, const OOXMLValue::Pointer_t& /*pVal*/)
517 {
518 }
519 
setPropertySet(const OOXMLPropertySet::Pointer_t &)520 void OOXMLFastContextHandler::setPropertySet
521 (const OOXMLPropertySet::Pointer_t& /* pPropertySet */)
522 {
523 }
524 
getPropertySet() const525 OOXMLPropertySet::Pointer_t OOXMLFastContextHandler::getPropertySet() const
526 {
527     return OOXMLPropertySet::Pointer_t();
528 }
529 
startField()530 void OOXMLFastContextHandler::startField()
531 {
532     startCharacterGroup();
533     if (isForwardEvents())
534         mpStream->text(&cFieldStart, 1);
535     endCharacterGroup();
536 }
537 
fieldSeparator()538 void OOXMLFastContextHandler::fieldSeparator()
539 {
540     startCharacterGroup();
541     if (isForwardEvents())
542         mpStream->text(&cFieldSep, 1);
543     endCharacterGroup();
544 }
545 
endField()546 void OOXMLFastContextHandler::endField()
547 {
548     startCharacterGroup();
549     if (isForwardEvents())
550         mpStream->text(&cFieldEnd, 1);
551     endCharacterGroup();
552 }
553 
lockField()554 void OOXMLFastContextHandler::lockField()
555 {
556     startCharacterGroup();
557     if (isForwardEvents())
558         mpStream->text(&cFieldLock, 1);
559     endCharacterGroup();
560 }
561 
ftnednref()562 void OOXMLFastContextHandler::ftnednref()
563 {
564     if (isForwardEvents())
565         mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uFtnEdnRef), 1);
566 }
567 
ftnednsep()568 void OOXMLFastContextHandler::ftnednsep()
569 {
570     if (isForwardEvents())
571         mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uFtnEdnSep), 1);
572 }
573 
ftnedncont()574 void OOXMLFastContextHandler::ftnedncont()
575 {
576     if (isForwardEvents())
577         mpStream->text(&cFtnEdnCont, 1);
578 }
579 
pgNum()580 void OOXMLFastContextHandler::pgNum()
581 {
582     if (isForwardEvents())
583         mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uPgNum), 1);
584 }
585 
tab()586 void OOXMLFastContextHandler::tab()
587 {
588     if (isForwardEvents())
589         mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uTab), 1);
590 }
591 
symbol()592 void OOXMLFastContextHandler::symbol()
593 {
594     if (isForwardEvents())
595         sendPropertiesWithId(NS_ooxml::LN_EG_RunInnerContent_sym);
596 }
597 
cr()598 void OOXMLFastContextHandler::cr()
599 {
600     if (isForwardEvents())
601         mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uCR), 1);
602 }
603 
noBreakHyphen()604 void OOXMLFastContextHandler::noBreakHyphen()
605 {
606     if (isForwardEvents())
607         mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uNoBreakHyphen), 1);
608 }
609 
softHyphen()610 void OOXMLFastContextHandler::softHyphen()
611 {
612     if (isForwardEvents())
613         mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uSoftHyphen), 1);
614 }
615 
handleLastParagraphInSection()616 void OOXMLFastContextHandler::handleLastParagraphInSection()
617 {
618     if (mpParserState->isLastParagraphInSection())
619     {
620         mpParserState->setLastParagraphInSection(false);
621         startSectionGroup();
622     }
623 }
624 
endOfParagraph()625 void OOXMLFastContextHandler::endOfParagraph()
626 {
627     if (! mpParserState->isInCharacterGroup())
628         startCharacterGroup();
629     if (isForwardEvents())
630         mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uCR), 1);
631 
632     mpParserState->getDocument()->incrementProgress();
633 }
634 
startTxbxContent()635 void OOXMLFastContextHandler::startTxbxContent()
636 {
637 /*
638     This usually means there are recursive <w:p> elements, and the ones
639     inside and outside of w:txbxContent should not interfere (e.g.
640     the lastParagraphInSection setting). So save the whole state
641     and possibly start new groups for the nested content (not section
642     group though, as that'd cause the txbxContent to be moved onto
643     another page, I'm not sure how that should work exactly).
644 */
645     mpParserState->startTxbxContent();
646     startParagraphGroup();
647 }
648 
endTxbxContent()649 void OOXMLFastContextHandler::endTxbxContent()
650 {
651     endParagraphGroup();
652     mpParserState->endTxbxContent();
653 }
654 
655 namespace {
656 // XML schema defines white space as one of four characters:
657 // #x9 (tab), #xA (line feed), #xD (carriage return), and #x20 (space)
IsXMLWhitespace(sal_Unicode cChar)658 bool IsXMLWhitespace(sal_Unicode cChar)
659 {
660     return cChar == 0x9 || cChar == 0xA || cChar == 0xD || cChar == 0x20;
661 }
662 
TrimXMLWhitespace(const OUString & sText)663 OUString TrimXMLWhitespace(const OUString & sText)
664 {
665     sal_Int32 nTrimmedStart = 0;
666     const sal_Int32 nLen = sText.getLength();
667     sal_Int32 nTrimmedEnd = nLen - 1;
668     while (nTrimmedStart < nLen && IsXMLWhitespace(sText[nTrimmedStart]))
669         ++nTrimmedStart;
670     while (nTrimmedStart <= nTrimmedEnd && IsXMLWhitespace(sText[nTrimmedEnd]))
671         --nTrimmedEnd;
672     if ((nTrimmedStart == 0) && (nTrimmedEnd == nLen - 1))
673         return sText;
674     else if (nTrimmedStart > nTrimmedEnd)
675         return OUString();
676     else
677         return sText.copy(nTrimmedStart, nTrimmedEnd-nTrimmedStart+1);
678 }
679 }
680 
text(const OUString & sText)681 void OOXMLFastContextHandler::text(const OUString & sText)
682 {
683     if (!isForwardEvents())
684         return;
685 
686     // tdf#108806: CRLFs in XML were converted to \n before this point.
687     // These must be converted to spaces before further processing.
688     OUString sNormalizedText = sText.replaceAll("\n", " ");
689     // tdf#108995: by default, leading and trailing white space is ignored;
690     // tabs are converted to spaces
691     if (!IsPreserveSpace())
692     {
693         sNormalizedText = TrimXMLWhitespace(sNormalizedText).replaceAll("\t", " ");
694     }
695     mpStream->utext(reinterpret_cast < const sal_uInt8 * >
696                     (sNormalizedText.getStr()),
697                     sNormalizedText.getLength());
698 }
699 
positionOffset(const OUString & rText)700 void OOXMLFastContextHandler::positionOffset(const OUString& rText)
701 {
702     if (isForwardEvents())
703         mpStream->positionOffset(rText, inPositionV);
704 }
705 
ignore()706 void OOXMLFastContextHandler::ignore()
707 {
708 }
709 
alignH(const OUString & rText)710 void OOXMLFastContextHandler::alignH(const OUString& rText)
711 {
712     if (isForwardEvents())
713         mpStream->align(rText, /*bVertical=*/false);
714 }
715 
alignV(const OUString & rText)716 void OOXMLFastContextHandler::alignV(const OUString& rText)
717 {
718     if (isForwardEvents())
719         mpStream->align(rText, /*bVertical=*/true);
720 }
721 
positivePercentage(const OUString & rText)722 void OOXMLFastContextHandler::positivePercentage(const OUString& rText)
723 {
724     if (isForwardEvents())
725         mpStream->positivePercentage(rText);
726 }
727 
startGlossaryEntry()728 void OOXMLFastContextHandler::startGlossaryEntry()
729 {
730     if (isForwardEvents())
731         mpStream->startGlossaryEntry();
732 }
733 
endGlossaryEntry()734 void OOXMLFastContextHandler::endGlossaryEntry()
735 {
736     if (isForwardEvents())
737         mpStream->endGlossaryEntry();
738 }
739 
propagateCharacterProperties()740 void OOXMLFastContextHandler::propagateCharacterProperties()
741 {
742     mpParserState->setCharacterProperties(getPropertySet());
743 }
744 
propagateCellProperties()745 void OOXMLFastContextHandler::propagateCellProperties()
746 {
747     mpParserState->setCellProperties(getPropertySet());
748 }
749 
propagateRowProperties()750 void OOXMLFastContextHandler::propagateRowProperties()
751 {
752     mpParserState->setRowProperties(getPropertySet());
753 }
754 
propagateTableProperties()755 void OOXMLFastContextHandler::propagateTableProperties()
756 {
757     OOXMLPropertySet::Pointer_t pProps = getPropertySet();
758 
759     mpParserState->setTableProperties(pProps);
760 }
761 
sendCellProperties()762 void OOXMLFastContextHandler::sendCellProperties()
763 {
764     mpParserState->resolveCellProperties(*mpStream);
765 }
766 
sendRowProperties()767 void OOXMLFastContextHandler::sendRowProperties()
768 {
769     mpParserState->resolveRowProperties(*mpStream);
770 }
771 
sendTableProperties()772 void OOXMLFastContextHandler::sendTableProperties()
773 {
774     mpParserState->resolveTableProperties(*mpStream);
775 }
776 
clearTableProps()777 void OOXMLFastContextHandler::clearTableProps()
778 {
779     mpParserState->setTableProperties(new OOXMLPropertySet());
780 }
781 
sendPropertiesWithId(Id nId)782 void OOXMLFastContextHandler::sendPropertiesWithId(Id nId)
783 {
784     OOXMLValue::Pointer_t pValue(new OOXMLPropertySetValue(getPropertySet()));
785     OOXMLPropertySet::Pointer_t pPropertySet(new OOXMLPropertySet);
786 
787     pPropertySet->add(nId, pValue, OOXMLProperty::SPRM);
788     mpStream->props(pPropertySet.get());
789 }
790 
clearProps()791 void OOXMLFastContextHandler::clearProps()
792 {
793     setPropertySet(new OOXMLPropertySet());
794 }
795 
setDefaultBooleanValue()796 void OOXMLFastContextHandler::setDefaultBooleanValue()
797 {
798 }
799 
setDefaultIntegerValue()800 void OOXMLFastContextHandler::setDefaultIntegerValue()
801 {
802 }
803 
setDefaultHexValue()804 void OOXMLFastContextHandler::setDefaultHexValue()
805 {
806 }
807 
setDefaultStringValue()808 void OOXMLFastContextHandler::setDefaultStringValue()
809 {
810 }
811 
setDocument(OOXMLDocumentImpl * pDocument)812 void OOXMLFastContextHandler::setDocument(OOXMLDocumentImpl* pDocument)
813 {
814     mpParserState->setDocument(pDocument);
815 }
816 
getDocument()817 OOXMLDocumentImpl* OOXMLFastContextHandler::getDocument()
818 {
819     return mpParserState->getDocument();
820 }
821 
setForwardEvents(bool bForwardEvents)822 void OOXMLFastContextHandler::setForwardEvents(bool bForwardEvents)
823 {
824     mpParserState->setForwardEvents(bForwardEvents);
825 }
826 
isForwardEvents() const827 bool OOXMLFastContextHandler::isForwardEvents() const
828 {
829     return mpParserState->isForwardEvents();
830 }
831 
setXNoteId(const sal_Int32 nId)832 void OOXMLFastContextHandler::setXNoteId(const sal_Int32 nId)
833 {
834     mpParserState->setXNoteId(nId);
835 }
836 
setXNoteId(const OOXMLValue::Pointer_t & pValue)837 void OOXMLFastContextHandler::setXNoteId(const OOXMLValue::Pointer_t& pValue)
838 {
839     mpParserState->setXNoteId(sal_Int32(pValue->getInt()));
840 }
841 
getXNoteId() const842 sal_Int32 OOXMLFastContextHandler::getXNoteId() const
843 {
844     return mpParserState->getXNoteId();
845 }
846 
resolveFootnote(const sal_Int32 nId)847 void OOXMLFastContextHandler::resolveFootnote
848 (const sal_Int32 nId)
849 {
850     mpParserState->getDocument()->resolveFootnote
851         (*mpStream, 0, nId);
852 }
853 
resolveEndnote(const sal_Int32 nId)854 void OOXMLFastContextHandler::resolveEndnote(const sal_Int32 nId)
855 {
856     mpParserState->getDocument()->resolveEndnote
857         (*mpStream, 0, nId);
858 }
859 
resolveComment(const sal_Int32 nId)860 void OOXMLFastContextHandler::resolveComment(const sal_Int32 nId)
861 {
862     mpParserState->getDocument()->resolveComment(*mpStream, nId);
863 }
864 
resolvePicture(const OUString & rId)865 void OOXMLFastContextHandler::resolvePicture(const OUString & rId)
866 {
867     mpParserState->getDocument()->resolvePicture(*mpStream, rId);
868 }
869 
resolveHeader(const sal_Int32 type,const OUString & rId)870 void OOXMLFastContextHandler::resolveHeader
871 (const sal_Int32 type, const OUString & rId)
872 {
873     mpParserState->getDocument()->resolveHeader(*mpStream, type, rId);
874 }
875 
resolveFooter(const sal_Int32 type,const OUString & rId)876 void OOXMLFastContextHandler::resolveFooter
877 (const sal_Int32 type, const OUString & rId)
878 {
879     mpParserState->getDocument()->resolveFooter(*mpStream, type, rId);
880 }
881 
882 // Add the data pointed to by the reference as another property.
resolveData(const OUString & rId)883 void OOXMLFastContextHandler::resolveData(const OUString & rId)
884 {
885     OOXMLDocument * objDocument = getDocument();
886     SAL_WARN_IF(!objDocument, "writerfilter", "no document to resolveData");
887     if (!objDocument)
888         return;
889 
890     uno::Reference<io::XInputStream> xInputStream
891         (objDocument->getInputStreamForId(rId));
892 
893     OOXMLValue::Pointer_t aValue(new OOXMLInputStreamValue(xInputStream));
894 
895     newProperty(NS_ooxml::LN_inputstream, aValue);
896 }
897 
getTargetForId(const OUString & rId)898 OUString OOXMLFastContextHandler::getTargetForId
899 (const OUString & rId)
900 {
901     return mpParserState->getDocument()->getTargetForId(rId);
902 }
903 
sendPropertyToParent()904 void OOXMLFastContextHandler::sendPropertyToParent()
905 {
906     if (mpParent != nullptr)
907     {
908         OOXMLPropertySet::Pointer_t pProps(mpParent->getPropertySet());
909 
910         if (pProps)
911         {
912             pProps->add(mId, getValue(), OOXMLProperty::SPRM);
913         }
914     }
915 }
916 
sendPropertiesToParent()917 void OOXMLFastContextHandler::sendPropertiesToParent()
918 {
919     if (mpParent == nullptr)
920         return;
921 
922     OOXMLPropertySet::Pointer_t pParentProps(mpParent->getPropertySet());
923 
924     if (!pParentProps)
925         return;
926 
927     OOXMLPropertySet::Pointer_t pProps(getPropertySet());
928 
929     if (pProps)
930     {
931         OOXMLValue::Pointer_t pValue
932             (new OOXMLPropertySetValue(getPropertySet()));
933 
934         pParentProps->add(getId(), pValue, OOXMLProperty::SPRM);
935 
936     }
937 }
938 
IsPreserveSpace() const939 bool OOXMLFastContextHandler::IsPreserveSpace() const
940 {
941     // xml:space attribute applies to all elements within the content of the element where it is specified,
942     // unless overridden with another instance of the xml:space attribute
943     if (mbPreserveSpaceSet)
944         return mbPreserveSpace;
945     if (mpParent)
946         return mpParent->IsPreserveSpace();
947     return false; // default value
948 }
949 
950 /*
951   class OOXMLFastContextHandlerStream
952  */
953 
OOXMLFastContextHandlerStream(OOXMLFastContextHandler * pContext)954 OOXMLFastContextHandlerStream::OOXMLFastContextHandlerStream
955 (OOXMLFastContextHandler * pContext)
956 : OOXMLFastContextHandler(pContext),
957   mpPropertySetAttrs(new OOXMLPropertySet)
958 {
959 }
960 
~OOXMLFastContextHandlerStream()961 OOXMLFastContextHandlerStream::~OOXMLFastContextHandlerStream()
962 {
963 }
964 
newProperty(Id nId,const OOXMLValue::Pointer_t & pVal)965 void OOXMLFastContextHandlerStream::newProperty(Id nId,
966                                                 const OOXMLValue::Pointer_t& pVal)
967 {
968     if (nId != 0x0)
969     {
970         mpPropertySetAttrs->add(nId, pVal, OOXMLProperty::ATTRIBUTE);
971     }
972 }
973 
sendProperty(Id nId)974 void OOXMLFastContextHandlerStream::sendProperty(Id nId)
975 {
976     OOXMLPropertySetEntryToString aHandler(nId);
977     getPropertySetAttrs()->resolve(aHandler);
978     const OUString & sText = aHandler.getString();
979     mpStream->utext(reinterpret_cast < const sal_uInt8 * >
980                     (sText.getStr()),
981                     sText.getLength());
982 }
983 
984 
getPropertySet() const985 OOXMLPropertySet::Pointer_t OOXMLFastContextHandlerStream::getPropertySet()
986     const
987 {
988     return getPropertySetAttrs();
989 }
990 
handleHyperlink()991 void OOXMLFastContextHandlerStream::handleHyperlink()
992 {
993     OOXMLHyperlinkHandler aHyperlinkHandler(this);
994     getPropertySetAttrs()->resolve(aHyperlinkHandler);
995     aHyperlinkHandler.writetext();
996 }
997 
998 /*
999   class OOXMLFastContextHandlerProperties
1000  */
OOXMLFastContextHandlerProperties(OOXMLFastContextHandler * pContext)1001 OOXMLFastContextHandlerProperties::OOXMLFastContextHandlerProperties
1002 (OOXMLFastContextHandler * pContext)
1003 : OOXMLFastContextHandler(pContext), mpPropertySet(new OOXMLPropertySet),
1004   mbResolve(false)
1005 {
1006     if (pContext->getResource() == STREAM)
1007         mbResolve = true;
1008 }
1009 
~OOXMLFastContextHandlerProperties()1010 OOXMLFastContextHandlerProperties::~OOXMLFastContextHandlerProperties()
1011 {
1012 }
1013 
lcl_endFastElement(Token_t)1014 void OOXMLFastContextHandlerProperties::lcl_endFastElement
1015 (Token_t /*Element*/)
1016 {
1017     try
1018     {
1019         endAction();
1020 
1021         if (mbResolve)
1022         {
1023             if (isForwardEvents())
1024             {
1025                 mpStream->props(mpPropertySet.get());
1026             }
1027         }
1028         else
1029         {
1030             sendPropertiesToParent();
1031         }
1032     }
1033     catch (const uno::RuntimeException&)
1034     {
1035         throw;
1036     }
1037     catch (const xml::sax::SAXException&)
1038     {
1039         throw;
1040     }
1041     catch (const uno::Exception& e)
1042     {
1043         auto a = cppu::getCaughtException();
1044         throw lang::WrappedTargetRuntimeException(e.Message, e.Context, a);
1045     }
1046 }
1047 
getValue() const1048 OOXMLValue::Pointer_t OOXMLFastContextHandlerProperties::getValue() const
1049 {
1050     return OOXMLValue::Pointer_t(new OOXMLPropertySetValue(mpPropertySet));
1051 }
1052 
newProperty(Id nId,const OOXMLValue::Pointer_t & pVal)1053 void OOXMLFastContextHandlerProperties::newProperty
1054 (Id nId, const OOXMLValue::Pointer_t& pVal)
1055 {
1056     if (nId != 0x0)
1057     {
1058         mpPropertySet->add(nId, pVal, OOXMLProperty::ATTRIBUTE);
1059     }
1060 }
1061 
handleXNotes()1062 void OOXMLFastContextHandlerProperties::handleXNotes()
1063 {
1064     switch (mnToken)
1065     {
1066     case W_TOKEN(footnoteReference):
1067         {
1068             OOXMLFootnoteHandler aFootnoteHandler(this);
1069             mpPropertySet->resolve(aFootnoteHandler);
1070         }
1071         break;
1072     case W_TOKEN(endnoteReference):
1073         {
1074             OOXMLEndnoteHandler aEndnoteHandler(this);
1075             mpPropertySet->resolve(aEndnoteHandler);
1076         }
1077         break;
1078     default:
1079         break;
1080     }
1081 }
1082 
handleHdrFtr()1083 void OOXMLFastContextHandlerProperties::handleHdrFtr()
1084 {
1085     switch (mnToken)
1086     {
1087     case W_TOKEN(footerReference):
1088         {
1089             OOXMLFooterHandler aFooterHandler(this);
1090             mpPropertySet->resolve(aFooterHandler);
1091             aFooterHandler.finalize();
1092         }
1093         break;
1094     case W_TOKEN(headerReference):
1095         {
1096             OOXMLHeaderHandler aHeaderHandler(this);
1097             mpPropertySet->resolve(aHeaderHandler);
1098             aHeaderHandler.finalize();
1099         }
1100         break;
1101     default:
1102         break;
1103     }
1104 }
1105 
handleComment()1106 void OOXMLFastContextHandlerProperties::handleComment()
1107 {
1108     OOXMLCommentHandler aCommentHandler(this);
1109     getPropertySet()->resolve(aCommentHandler);
1110 }
1111 
handlePicture()1112 void OOXMLFastContextHandlerProperties::handlePicture()
1113 {
1114     OOXMLPictureHandler aPictureHandler(this);
1115     getPropertySet()->resolve(aPictureHandler);
1116 }
1117 
handleBreak()1118 void OOXMLFastContextHandlerProperties::handleBreak()
1119 {
1120     if(isForwardEvents())
1121     {
1122         OOXMLBreakHandler aBreakHandler(*mpStream);
1123         getPropertySet()->resolve(aBreakHandler);
1124     }
1125 }
1126 
1127 // tdf#108714 : allow <w:br> at block level (despite this is illegal according to ECMA-376-1:2016)
handleOutOfOrderBreak()1128 void OOXMLFastContextHandlerProperties::handleOutOfOrderBreak()
1129 {
1130     if(isForwardEvents())
1131     {
1132         mpParserState->setPostponedBreak(getPropertySet());
1133     }
1134 }
1135 
handleOLE()1136 void OOXMLFastContextHandlerProperties::handleOLE()
1137 {
1138     OOXMLOLEHandler aOLEHandler(this);
1139     getPropertySet()->resolve(aOLEHandler);
1140 }
1141 
handleFontRel()1142 void OOXMLFastContextHandlerProperties::handleFontRel()
1143 {
1144     OOXMLEmbeddedFontHandler handler(this);
1145     getPropertySet()->resolve(handler);
1146 }
1147 
handleHyperlinkURL()1148 void OOXMLFastContextHandlerProperties::handleHyperlinkURL() {
1149     OOXMLHyperlinkURLHandler aHyperlinkURLHandler(this);
1150     getPropertySet()->resolve(aHyperlinkURLHandler);
1151 }
1152 
handleAltChunk()1153 void OOXMLFastContextHandlerProperties::handleAltChunk()
1154 {
1155     OOXMLAltChunkHandler aHandler(this);
1156     getPropertySet()->resolve(aHandler);
1157 }
1158 
setPropertySet(const OOXMLPropertySet::Pointer_t & pPropertySet)1159 void OOXMLFastContextHandlerProperties::setPropertySet
1160 (const OOXMLPropertySet::Pointer_t& pPropertySet)
1161 {
1162     if (pPropertySet)
1163         mpPropertySet = pPropertySet;
1164 }
1165 
1166 OOXMLPropertySet::Pointer_t
getPropertySet() const1167 OOXMLFastContextHandlerProperties::getPropertySet() const
1168 {
1169     return mpPropertySet;
1170 }
1171 
1172 /*
1173  * class OOXMLFasContextHandlerPropertyTable
1174  */
1175 
OOXMLFastContextHandlerPropertyTable(OOXMLFastContextHandler * pContext)1176 OOXMLFastContextHandlerPropertyTable::OOXMLFastContextHandlerPropertyTable
1177 (OOXMLFastContextHandler * pContext)
1178 : OOXMLFastContextHandlerProperties(pContext)
1179 {
1180 }
1181 
~OOXMLFastContextHandlerPropertyTable()1182 OOXMLFastContextHandlerPropertyTable::~OOXMLFastContextHandlerPropertyTable()
1183 {
1184 }
1185 
lcl_endFastElement(Token_t)1186 void OOXMLFastContextHandlerPropertyTable::lcl_endFastElement
1187 (Token_t /*Element*/)
1188 {
1189     OOXMLPropertySet::Pointer_t pPropSet(mpPropertySet->clone());
1190     OOXMLTable::ValuePointer_t pTmpVal
1191         (new OOXMLPropertySetValue(pPropSet));
1192 
1193     mTable.add(pTmpVal);
1194 
1195     writerfilter::Reference<Table>::Pointer_t pTable(mTable.clone());
1196 
1197     mpStream->table(mId, pTable);
1198 
1199     endAction();
1200 }
1201 
1202 /*
1203  class OOXMLFastContextHandlerValue
1204 */
1205 
OOXMLFastContextHandlerValue(OOXMLFastContextHandler * pContext)1206 OOXMLFastContextHandlerValue::OOXMLFastContextHandlerValue
1207 (OOXMLFastContextHandler * pContext)
1208 : OOXMLFastContextHandler(pContext)
1209 {
1210 }
1211 
~OOXMLFastContextHandlerValue()1212 OOXMLFastContextHandlerValue::~OOXMLFastContextHandlerValue()
1213 {
1214 }
1215 
setValue(const OOXMLValue::Pointer_t & pValue)1216 void OOXMLFastContextHandlerValue::setValue(const OOXMLValue::Pointer_t& pValue)
1217 {
1218     mpValue = pValue;
1219 }
1220 
getValue() const1221 OOXMLValue::Pointer_t OOXMLFastContextHandlerValue::getValue() const
1222 {
1223     return mpValue;
1224 }
1225 
lcl_endFastElement(Token_t)1226 void OOXMLFastContextHandlerValue::lcl_endFastElement
1227 (Token_t /*Element*/)
1228 {
1229     sendPropertyToParent();
1230 
1231     endAction();
1232 }
1233 
setDefaultBooleanValue()1234 void OOXMLFastContextHandlerValue::setDefaultBooleanValue()
1235 {
1236     if (!mpValue)
1237     {
1238         OOXMLValue::Pointer_t pValue = OOXMLBooleanValue::Create(true);
1239         setValue(pValue);
1240     }
1241 }
1242 
setDefaultIntegerValue()1243 void OOXMLFastContextHandlerValue::setDefaultIntegerValue()
1244 {
1245     if (!mpValue)
1246     {
1247         OOXMLValue::Pointer_t pValue = OOXMLIntegerValue::Create(0);
1248         setValue(pValue);
1249     }
1250 }
1251 
setDefaultHexValue()1252 void OOXMLFastContextHandlerValue::setDefaultHexValue()
1253 {
1254     if (!mpValue)
1255     {
1256         OOXMLValue::Pointer_t pValue(new OOXMLHexValue(sal_uInt32(0)));
1257         setValue(pValue);
1258     }
1259 }
1260 
setDefaultStringValue()1261 void OOXMLFastContextHandlerValue::setDefaultStringValue()
1262 {
1263     if (!mpValue)
1264     {
1265         OOXMLValue::Pointer_t pValue(new OOXMLStringValue(OUString()));
1266         setValue(pValue);
1267     }
1268 }
1269 
1270 // ECMA-376-1:2016 17.3.2.8; https://www.unicode.org/reports/tr9/#Explicit_Directional_Embeddings
pushBiDiEmbedLevel()1271 void OOXMLFastContextHandlerValue::pushBiDiEmbedLevel()
1272 {
1273     const bool bRtl
1274         = mpValue && mpValue->getInt() == NS_ooxml::LN_Value_ST_Direction_rtl;
1275     OOXMLFactory::characters(this, bRtl ? OUString(u"\u202B") : OUString(u"\u202A")); // RLE / LRE
1276 }
1277 
popBiDiEmbedLevel()1278 void OOXMLFastContextHandlerValue::popBiDiEmbedLevel()
1279 {
1280     OOXMLFactory::characters(this, u"\u202C"); // PDF (POP DIRECTIONAL FORMATTING)
1281 }
1282 
handleGridAfter()1283 void OOXMLFastContextHandlerValue::handleGridAfter()
1284 {
1285     if (!getValue())
1286         return;
1287 
1288     if (OOXMLFastContextHandler* pTableRowProperties = getParent())
1289     {
1290         if (OOXMLFastContextHandler* pTableRow = pTableRowProperties->getParent())
1291             // Save the value into the table row context, so it can be handled
1292             // right before the end of the row.
1293             pTableRow->setGridAfter(getValue());
1294     }
1295 }
1296 
1297 /*
1298   class OOXMLFastContextHandlerTable
1299 */
1300 
OOXMLFastContextHandlerTable(OOXMLFastContextHandler * pContext)1301 OOXMLFastContextHandlerTable::OOXMLFastContextHandlerTable
1302 (OOXMLFastContextHandler * pContext)
1303 : OOXMLFastContextHandler(pContext)
1304 {
1305 }
1306 
~OOXMLFastContextHandlerTable()1307 OOXMLFastContextHandlerTable::~OOXMLFastContextHandlerTable()
1308 {
1309 }
1310 
1311 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
createFastChildContext(sal_Int32 Element,const uno::Reference<xml::sax::XFastAttributeList> & Attribs)1312 OOXMLFastContextHandlerTable::createFastChildContext
1313 (sal_Int32 Element,
1314  const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
1315 {
1316     addCurrentChild();
1317 
1318     mCurrentChild.set(OOXMLFastContextHandler::createFastChildContext(Element, Attribs));
1319 
1320     return mCurrentChild;
1321 }
1322 
lcl_endFastElement(Token_t)1323 void OOXMLFastContextHandlerTable::lcl_endFastElement
1324 (Token_t /*Element*/)
1325 {
1326     addCurrentChild();
1327 
1328     writerfilter::Reference<Table>::Pointer_t pTable(mTable.clone());
1329     if (isForwardEvents() && mId != 0x0)
1330     {
1331         mpStream->table(mId, pTable);
1332     }
1333 }
1334 
addCurrentChild()1335 void OOXMLFastContextHandlerTable::addCurrentChild()
1336 {
1337     OOXMLFastContextHandler * pHandler = dynamic_cast<OOXMLFastContextHandler*>(mCurrentChild.get());
1338     if (pHandler != nullptr)
1339     {
1340         OOXMLValue::Pointer_t pValue(pHandler->getValue());
1341 
1342         if (pValue)
1343         {
1344             OOXMLTable::ValuePointer_t pTmpVal(pValue->clone());
1345             mTable.add(pTmpVal);
1346         }
1347     }
1348 }
1349 
1350 /*
1351   class OOXMLFastContextHandlerXNote
1352  */
1353 
OOXMLFastContextHandlerXNote(OOXMLFastContextHandler * pContext)1354 OOXMLFastContextHandlerXNote::OOXMLFastContextHandlerXNote
1355     (OOXMLFastContextHandler * pContext)
1356     : OOXMLFastContextHandlerProperties(pContext)
1357     , mbForwardEventsSaved(false)
1358     , mnMyXNoteId(0)
1359     , mnMyXNoteType(0)
1360 {
1361 }
1362 
~OOXMLFastContextHandlerXNote()1363 OOXMLFastContextHandlerXNote::~OOXMLFastContextHandlerXNote()
1364 {
1365 }
1366 
lcl_startFastElement(Token_t,const uno::Reference<xml::sax::XFastAttributeList> &)1367 void OOXMLFastContextHandlerXNote::lcl_startFastElement
1368 (Token_t /*Element*/,
1369  const uno::Reference< xml::sax::XFastAttributeList > & /*Attribs*/)
1370 {
1371     mbForwardEventsSaved = isForwardEvents();
1372 
1373     // If this is the note we're looking for or this is the footnote separator one.
1374     if (mnMyXNoteId == getXNoteId() ||
1375             static_cast<sal_uInt32>(mnMyXNoteType) == NS_ooxml::LN_Value_doc_ST_FtnEdn_separator ||
1376             mpParserState->isStartFootnote())
1377         setForwardEvents(true);
1378     else
1379         setForwardEvents(false);
1380 
1381     startAction();
1382 }
1383 
lcl_endFastElement(Token_t Element)1384 void OOXMLFastContextHandlerXNote::lcl_endFastElement
1385 (Token_t Element)
1386 {
1387     endAction();
1388 
1389     OOXMLFastContextHandlerProperties::lcl_endFastElement(Element);
1390 
1391     setForwardEvents(mbForwardEventsSaved);
1392 }
1393 
checkId(const OOXMLValue::Pointer_t & pValue)1394 void OOXMLFastContextHandlerXNote::checkId(const OOXMLValue::Pointer_t& pValue)
1395 {
1396     mnMyXNoteId = sal_Int32(pValue->getInt());
1397 }
1398 
checkType(const OOXMLValue::Pointer_t & pValue)1399 void OOXMLFastContextHandlerXNote::checkType(const OOXMLValue::Pointer_t& pValue)
1400 {
1401     mnMyXNoteType = pValue->getInt();
1402 }
1403 
1404 /*
1405   class OOXMLFastContextHandlerTextTableCell
1406  */
1407 
OOXMLFastContextHandlerTextTableCell(OOXMLFastContextHandler * pContext)1408 OOXMLFastContextHandlerTextTableCell::OOXMLFastContextHandlerTextTableCell
1409 (OOXMLFastContextHandler * pContext)
1410 : OOXMLFastContextHandler(pContext)
1411 {
1412 }
1413 
~OOXMLFastContextHandlerTextTableCell()1414 OOXMLFastContextHandlerTextTableCell::~OOXMLFastContextHandlerTextTableCell()
1415 {
1416 }
1417 
startCell()1418 void OOXMLFastContextHandlerTextTableCell::startCell()
1419 {
1420     if (isForwardEvents())
1421     {
1422         OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
1423         {
1424             OOXMLValue::Pointer_t pVal = OOXMLBooleanValue::Create(mnTableDepth > 0);
1425             pProps->add(NS_ooxml::LN_tcStart, pVal, OOXMLProperty::SPRM);
1426         }
1427 
1428         mpStream->props(pProps.get());
1429     }
1430 }
1431 
endCell()1432 void OOXMLFastContextHandlerTextTableCell::endCell()
1433 {
1434     if (!isForwardEvents())
1435         return;
1436 
1437     OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
1438     {
1439         OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(mnTableDepth);
1440         pProps->add(NS_ooxml::LN_tblDepth, pVal, OOXMLProperty::SPRM);
1441     }
1442     {
1443         OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
1444         pProps->add(NS_ooxml::LN_inTbl, pVal, OOXMLProperty::SPRM);
1445     }
1446     {
1447         OOXMLValue::Pointer_t pVal = OOXMLBooleanValue::Create(mnTableDepth > 0);
1448         pProps->add(NS_ooxml::LN_tblCell, pVal, OOXMLProperty::SPRM);
1449     }
1450     {
1451         OOXMLValue::Pointer_t pVal = OOXMLBooleanValue::Create(mnTableDepth > 0);
1452         pProps->add(NS_ooxml::LN_tcEnd, pVal, OOXMLProperty::SPRM);
1453     }
1454 
1455     mpStream->props(pProps.get());
1456 }
1457 
1458 /*
1459   class OOXMLFastContextHandlerTextTableRow
1460  */
1461 
OOXMLFastContextHandlerTextTableRow(OOXMLFastContextHandler * pContext)1462 OOXMLFastContextHandlerTextTableRow::OOXMLFastContextHandlerTextTableRow
1463 (OOXMLFastContextHandler * pContext)
1464 : OOXMLFastContextHandler(pContext)
1465 {
1466 }
1467 
~OOXMLFastContextHandlerTextTableRow()1468 OOXMLFastContextHandlerTextTableRow::~OOXMLFastContextHandlerTextTableRow()
1469 {
1470 }
1471 
startRow()1472 void OOXMLFastContextHandlerTextTableRow::startRow()
1473 {
1474 }
1475 
endRow()1476 void OOXMLFastContextHandlerTextTableRow::endRow()
1477 {
1478     if (mpGridAfter)
1479     {
1480         // Grid after is the same as grid before, the empty cells are just
1481         // inserted after the real ones, not before.
1482         handleGridBefore(mpGridAfter);
1483         mpGridAfter = nullptr;
1484     }
1485 
1486     startParagraphGroup();
1487 
1488     if (isForwardEvents())
1489     {
1490         OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
1491         {
1492             OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(mnTableDepth);
1493             pProps->add(NS_ooxml::LN_tblDepth, pVal, OOXMLProperty::SPRM);
1494         }
1495         {
1496             OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
1497             pProps->add(NS_ooxml::LN_inTbl, pVal, OOXMLProperty::SPRM);
1498         }
1499         {
1500             OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
1501             pProps->add(NS_ooxml::LN_tblRow, pVal, OOXMLProperty::SPRM);
1502         }
1503 
1504         mpStream->props(pProps.get());
1505     }
1506 
1507     startCharacterGroup();
1508 
1509     if (isForwardEvents())
1510         mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uCR), 1);
1511 
1512     endCharacterGroup();
1513     endParagraphGroup();
1514 }
1515 
1516 namespace {
fakeNoBorder()1517 OOXMLValue::Pointer_t fakeNoBorder()
1518 {
1519     OOXMLPropertySet::Pointer_t pProps( new OOXMLPropertySet );
1520     OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(0);
1521     pProps->add(NS_ooxml::LN_CT_Border_val, pVal, OOXMLProperty::ATTRIBUTE);
1522     OOXMLValue::Pointer_t pValue( new OOXMLPropertySetValue( pProps ));
1523     return pValue;
1524 }
1525 }
1526 
1527 // Handle w:gridBefore here by faking necessary input that'll fake cells. I'm apparently
1528 // not insane enough to find out how to add cells in dmapper.
handleGridBefore(const OOXMLValue::Pointer_t & val)1529 void OOXMLFastContextHandlerTextTableRow::handleGridBefore( const OOXMLValue::Pointer_t& val )
1530 {
1531     // start removing: disable for w:gridBefore
1532     if (!mpGridAfter)
1533         return;
1534 
1535     int count = val->getInt();
1536     for( int i = 0;
1537          i < count;
1538          ++i )
1539     {
1540         endOfParagraph();
1541 
1542         if (isForwardEvents())
1543         {
1544             // This whole part is OOXMLFastContextHandlerTextTableCell::endCell() .
1545             OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
1546             {
1547                 OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(mnTableDepth);
1548                 pProps->add(NS_ooxml::LN_tblDepth, pVal, OOXMLProperty::SPRM);
1549             }
1550             {
1551                 OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
1552                 pProps->add(NS_ooxml::LN_inTbl, pVal, OOXMLProperty::SPRM);
1553             }
1554             {
1555                 OOXMLValue::Pointer_t pVal = OOXMLBooleanValue::Create(mnTableDepth > 0);
1556                 pProps->add(NS_ooxml::LN_tblCell, pVal, OOXMLProperty::SPRM);
1557             }
1558 
1559             mpStream->props(pProps.get());
1560 
1561             // fake <w:tcBorders> with no border
1562             OOXMLPropertySet::Pointer_t pCellProps( new OOXMLPropertySet );
1563             {
1564                 OOXMLPropertySet::Pointer_t pBorderProps( new OOXMLPropertySet );
1565                 static Id borders[] = { NS_ooxml::LN_CT_TcBorders_top, NS_ooxml::LN_CT_TcBorders_bottom,
1566                     NS_ooxml::LN_CT_TcBorders_start, NS_ooxml::LN_CT_TcBorders_end };
1567                 for(sal_uInt32 border : borders)
1568                     pBorderProps->add(border, fakeNoBorder(), OOXMLProperty::SPRM);
1569                 OOXMLValue::Pointer_t pValue( new OOXMLPropertySetValue( pBorderProps ));
1570                 pCellProps->add(NS_ooxml::LN_CT_TcPrBase_tcBorders, pValue, OOXMLProperty::SPRM);
1571                 mpParserState->setCellProperties(pCellProps);
1572             }
1573         }
1574 
1575         sendCellProperties();
1576         endParagraphGroup();
1577     }
1578 }
1579 
1580 /*
1581   class OOXMLFastContextHandlerTextTable
1582  */
1583 
OOXMLFastContextHandlerTextTable(OOXMLFastContextHandler * pContext)1584 OOXMLFastContextHandlerTextTable::OOXMLFastContextHandlerTextTable
1585 (OOXMLFastContextHandler * pContext)
1586 : OOXMLFastContextHandler(pContext)
1587 {
1588 }
1589 
~OOXMLFastContextHandlerTextTable()1590 OOXMLFastContextHandlerTextTable::~OOXMLFastContextHandlerTextTable()
1591 {
1592     clearTableProps();
1593 }
1594 
lcl_startFastElement(Token_t,const uno::Reference<xml::sax::XFastAttributeList> &)1595 void OOXMLFastContextHandlerTextTable::lcl_startFastElement
1596 (Token_t /*Element*/,
1597  const uno::Reference< xml::sax::XFastAttributeList > & /*Attribs*/)
1598 {
1599     mpParserState->startTable();
1600     mnTableDepth++;
1601 
1602     OOXMLPropertySet::Pointer_t pProps( new OOXMLPropertySet );
1603     {
1604         OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(mnTableDepth);
1605         pProps->add(NS_ooxml::LN_tblStart, pVal, OOXMLProperty::SPRM);
1606     }
1607     mpParserState->setCharacterProperties(pProps);
1608 
1609     startAction();
1610 }
1611 
lcl_endFastElement(Token_t)1612 void OOXMLFastContextHandlerTextTable::lcl_endFastElement
1613 (Token_t /*Element*/)
1614 {
1615     endAction();
1616 
1617     OOXMLPropertySet::Pointer_t pProps( new OOXMLPropertySet );
1618     {
1619         OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(mnTableDepth);
1620         pProps->add(NS_ooxml::LN_tblEnd, pVal, OOXMLProperty::SPRM);
1621     }
1622     mpParserState->setCharacterProperties(pProps);
1623 
1624     mnTableDepth--;
1625     mpParserState->endTable();
1626 }
1627 
1628 // tdf#111550
start_P_Tbl()1629 void OOXMLFastContextHandlerTextTable::start_P_Tbl()
1630 {
1631     // Normally, when one paragraph ends, and another begins,
1632     // in OOXMLFactory_wml::endAction handler for <w:p>,
1633     // pHandler->endOfParagraph() is called, which (among other things)
1634     // calls TableManager::setHandle() to update current cell's starting point.
1635     // Then, in OOXMLFactory_wml::startAction for next <w:p>,
1636     // pHandler->startParagraphGroup() is called, which ends previous group,
1637     // and there, it pushes cells to row in TableManager::endParagraphGroup()
1638     // (cells have correct bounds defined by mCurHandle).
1639     // When a table is child of a <w:p>, that paragraph doesn't end before nested
1640     // paragraph begins. So, pHandler->endOfParagraph() was not (and should not be)
1641     // called. But as next paragraph starts, is the previous group is closed, then
1642     // cells will have wrong boundings. Here, we know that we *are* in paragraph
1643     // group, but it should not be finished.
1644     mpParserState->setInParagraphGroup(false);
1645 }
1646 
1647 /*
1648   class OOXMLFastContextHandlerShape
1649  */
1650 
OOXMLFastContextHandlerShape(OOXMLFastContextHandler * pContext)1651 OOXMLFastContextHandlerShape::OOXMLFastContextHandlerShape
1652 (OOXMLFastContextHandler * pContext)
1653 : OOXMLFastContextHandlerProperties(pContext), m_bShapeSent( false ),
1654     m_bShapeStarted(false), m_bShapeContextPushed(false)
1655 {
1656 }
1657 
~OOXMLFastContextHandlerShape()1658 OOXMLFastContextHandlerShape::~OOXMLFastContextHandlerShape()
1659 {
1660     if (m_bShapeContextPushed)
1661         getDocument()->popShapeContext();
1662 }
1663 
lcl_startFastElement(Token_t Element,const uno::Reference<xml::sax::XFastAttributeList> & Attribs)1664 void OOXMLFastContextHandlerShape::lcl_startFastElement
1665 (Token_t Element,
1666  const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
1667 {
1668     startAction();
1669 
1670     if (mrShapeContext.is())
1671     {
1672         mrShapeContext->startFastElement(Element, Attribs);
1673     }
1674 }
1675 
startUnknownElement(const OUString & Namespace,const OUString & Name,const uno::Reference<xml::sax::XFastAttributeList> & Attribs)1676 void SAL_CALL OOXMLFastContextHandlerShape::startUnknownElement
1677 (const OUString & Namespace,
1678  const OUString & Name,
1679  const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
1680 {
1681     if (mrShapeContext.is())
1682         mrShapeContext->startUnknownElement(Namespace, Name, Attribs);
1683 }
1684 
setToken(Token_t nToken)1685 void OOXMLFastContextHandlerShape::setToken(Token_t nToken)
1686 {
1687     if (nToken == Token_t(NMSP_wps | XML_wsp) || nToken == Token_t(NMSP_dmlPicture | XML_pic))
1688     {
1689         // drawingML shapes are independent, <wps:bodyPr> is not parsed after
1690         // shape contents without pushing/popping the stack.
1691         m_bShapeContextPushed = true;
1692         getDocument()->pushShapeContext();
1693     }
1694 
1695     mrShapeContext.set(getDocument()->getShapeContext());
1696     if (!mrShapeContext.is())
1697     {
1698         // Define the shape context for the whole document
1699         mrShapeContext = css::xml::sax::FastShapeContextHandler::create(getComponentContext());
1700         getDocument()->setShapeContext(mrShapeContext);
1701     }
1702 
1703     mrShapeContext->setModel(getDocument()->getModel());
1704     uno::Reference<document::XDocumentPropertiesSupplier> xDocSupplier(getDocument()->getModel(), uno::UNO_QUERY_THROW);
1705     mrShapeContext->setDocumentProperties(xDocSupplier->getDocumentProperties());
1706     mrShapeContext->setDrawPage(getDocument()->getDrawPage());
1707     mrShapeContext->setMediaDescriptor(getDocument()->getMediaDescriptor());
1708 
1709     mrShapeContext->setRelationFragmentPath(mpParserState->getTarget());
1710 
1711     auto xGraphicMapper = getDocument()->getGraphicMapper();
1712 
1713     if (xGraphicMapper.is())
1714         mrShapeContext->setGraphicMapper(xGraphicMapper);
1715 
1716     OOXMLFastContextHandler::setToken(nToken);
1717 
1718     if (mrShapeContext.is())
1719         mrShapeContext->setStartToken(nToken);
1720 }
1721 
sendShape(Token_t Element)1722 void OOXMLFastContextHandlerShape::sendShape( Token_t Element )
1723 {
1724     if ( !mrShapeContext.is() || m_bShapeSent )
1725         return;
1726 
1727     awt::Point aPosition = mpStream->getPositionOffset();
1728     mrShapeContext->setPosition(aPosition);
1729     uno::Reference<drawing::XShape> xShape(mrShapeContext->getShape());
1730     m_bShapeSent = true;
1731     if (!xShape.is())
1732         return;
1733 
1734     OOXMLValue::Pointer_t
1735         pValue(new OOXMLShapeValue(xShape));
1736     newProperty(NS_ooxml::LN_shape, pValue);
1737 
1738     bool bIsPicture = Element == ( NMSP_dmlPicture | XML_pic );
1739 
1740     //tdf#87569: Fix table layout with correcting anchoring
1741     //If anchored object is in table, Word calculates its position from cell border
1742     //instead of page (what is set in the sample document)
1743     uno::Reference<beans::XPropertySet> xShapePropSet(xShape, uno::UNO_QUERY);
1744     if (mnTableDepth > 0 && xShapePropSet.is() && mbIsVMLfound) //if we had a table
1745     {
1746         xShapePropSet->setPropertyValue(dmapper::getPropertyName(dmapper::PROP_FOLLOW_TEXT_FLOW),
1747                                         uno::makeAny(mbAllowInCell));
1748     }
1749     // Notify the dmapper that the shape is ready to use
1750     if ( !bIsPicture )
1751     {
1752         mpStream->startShape( xShape );
1753         m_bShapeStarted = true;
1754     }
1755 }
1756 
lcl_endFastElement(Token_t Element)1757 void OOXMLFastContextHandlerShape::lcl_endFastElement
1758 (Token_t Element)
1759 {
1760     if (!isForwardEvents())
1761         return;
1762 
1763     if (mrShapeContext.is())
1764     {
1765         mrShapeContext->endFastElement(Element);
1766         sendShape( Element );
1767     }
1768 
1769     OOXMLFastContextHandlerProperties::lcl_endFastElement(Element);
1770 
1771     // Ending the shape should be the last thing to do
1772     bool bIsPicture = Element == ( NMSP_dmlPicture | XML_pic );
1773     if ( !bIsPicture && m_bShapeStarted)
1774         mpStream->endShape( );
1775 }
1776 
endUnknownElement(const OUString & Namespace,const OUString & Name)1777 void SAL_CALL OOXMLFastContextHandlerShape::endUnknownElement
1778 (const OUString & Namespace,
1779  const OUString & Name)
1780 {
1781     if (mrShapeContext.is())
1782         mrShapeContext->endUnknownElement(Namespace, Name);
1783 }
1784 
1785 uno::Reference< xml::sax::XFastContextHandler >
lcl_createFastChildContext(Token_t Element,const uno::Reference<xml::sax::XFastAttributeList> & Attribs)1786 OOXMLFastContextHandlerShape::lcl_createFastChildContext
1787 (Token_t Element,
1788  const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
1789 {
1790     uno::Reference< xml::sax::XFastContextHandler > xContextHandler;
1791 
1792     bool bGroupShape = Element == Token_t(NMSP_vml | XML_group);
1793     // drawingML version also counts as a group shape.
1794     bGroupShape |= mrShapeContext->getStartToken() == Token_t(NMSP_wpg | XML_wgp);
1795     mbIsVMLfound = (getNamespace(Element) == NMSP_vmlOffice) || (getNamespace(Element) == NMSP_vml);
1796     switch (oox::getNamespace(Element))
1797     {
1798         case NMSP_doc:
1799         case NMSP_vmlWord:
1800         case NMSP_vmlOffice:
1801             if (!bGroupShape)
1802                 xContextHandler.set(OOXMLFactory::createFastChildContextFromStart(this, Element));
1803             [[fallthrough]];
1804         default:
1805             if (!xContextHandler.is())
1806             {
1807                 if (mrShapeContext.is())
1808                 {
1809                     uno::Reference<XFastContextHandler> pChildContext =
1810                         mrShapeContext->createFastChildContext(Element, Attribs);
1811 
1812                     rtl::Reference<OOXMLFastContextHandlerWrapper> pWrapper =
1813                         new OOXMLFastContextHandlerWrapper(this,
1814                                                            pChildContext,
1815                                                            this);
1816 
1817                     //tdf129888 store allowincell attribute of the VML shape
1818                     if (Attribs->hasAttribute(NMSP_vmlOffice | XML_allowincell))
1819                         mbAllowInCell
1820                             = !(Attribs->getValue(NMSP_vmlOffice | XML_allowincell) == "f");
1821 
1822                     if (!bGroupShape)
1823                     {
1824                         pWrapper->addNamespace(NMSP_doc);
1825                         pWrapper->addNamespace(NMSP_vmlWord);
1826                         pWrapper->addNamespace(NMSP_vmlOffice);
1827                         pWrapper->addToken( NMSP_vml|XML_textbox );
1828                     }
1829                     xContextHandler.set(pWrapper);
1830                 }
1831                 else
1832                     xContextHandler.set(this);
1833             }
1834             break;
1835     }
1836 
1837     // VML import of shape text is already handled by
1838     // OOXMLFastContextHandlerWrapper::lcl_createFastChildContext(), here we
1839     // handle the WPS import of shape text, as there the parent context is a
1840     // Shape one, so a different situation.
1841     if (Element == static_cast<sal_Int32>(NMSP_wps | XML_txbx) ||
1842         Element == static_cast<sal_Int32>(NMSP_wps | XML_linkedTxbx) )
1843         sendShape(Element);
1844 
1845     return xContextHandler;
1846 }
1847 
1848 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
createUnknownChildContext(const OUString & Namespace,const OUString & Name,const uno::Reference<xml::sax::XFastAttributeList> & Attribs)1849 OOXMLFastContextHandlerShape::createUnknownChildContext
1850 (const OUString & Namespace,
1851  const OUString & Name,
1852  const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
1853 {
1854     uno::Reference< xml::sax::XFastContextHandler > xResult;
1855 
1856     if (mrShapeContext.is())
1857         xResult.set(mrShapeContext->createUnknownChildContext
1858             (Namespace, Name, Attribs));
1859 
1860     return xResult;
1861 }
1862 
lcl_characters(const OUString & aChars)1863 void OOXMLFastContextHandlerShape::lcl_characters
1864 (const OUString & aChars)
1865 {
1866     if (mrShapeContext.is())
1867         mrShapeContext->characters(aChars);
1868 }
1869 
1870 /*
1871   class OOXMLFastContextHandlerWrapper
1872 */
1873 
OOXMLFastContextHandlerWrapper(OOXMLFastContextHandler * pParent,uno::Reference<XFastContextHandler> const & xContext,rtl::Reference<OOXMLFastContextHandlerShape> const & xShapeHandler)1874 OOXMLFastContextHandlerWrapper::OOXMLFastContextHandlerWrapper
1875 (OOXMLFastContextHandler * pParent,
1876  uno::Reference<XFastContextHandler> const & xContext,
1877  rtl::Reference<OOXMLFastContextHandlerShape> const & xShapeHandler)
1878     : OOXMLFastContextHandler(pParent),
1879       mxWrappedContext(xContext),
1880       mxShapeHandler(xShapeHandler)
1881 {
1882     setId(pParent->getId());
1883     setToken(pParent->getToken());
1884     setPropertySet(pParent->getPropertySet());
1885 }
1886 
~OOXMLFastContextHandlerWrapper()1887 OOXMLFastContextHandlerWrapper::~OOXMLFastContextHandlerWrapper()
1888 {
1889 }
1890 
startUnknownElement(const OUString & Namespace,const OUString & Name,const uno::Reference<xml::sax::XFastAttributeList> & Attribs)1891 void SAL_CALL OOXMLFastContextHandlerWrapper::startUnknownElement
1892 (const OUString & Namespace,
1893  const OUString & Name,
1894  const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
1895 {
1896     if (mxWrappedContext.is())
1897         mxWrappedContext->startUnknownElement(Namespace, Name, Attribs);
1898 }
1899 
endUnknownElement(const OUString & Namespace,const OUString & Name)1900 void SAL_CALL OOXMLFastContextHandlerWrapper::endUnknownElement
1901 (const OUString & Namespace,
1902  const OUString & Name)
1903 {
1904     if (mxWrappedContext.is())
1905         mxWrappedContext->endUnknownElement(Namespace, Name);
1906 }
1907 
1908 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
createUnknownChildContext(const OUString & Namespace,const OUString & Name,const uno::Reference<xml::sax::XFastAttributeList> & Attribs)1909 OOXMLFastContextHandlerWrapper::createUnknownChildContext
1910 (const OUString & Namespace,
1911  const OUString & Name,
1912  const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
1913 {
1914     uno::Reference< xml::sax::XFastContextHandler > xResult;
1915 
1916     if (mxWrappedContext.is())
1917         xResult = mxWrappedContext->createUnknownChildContext
1918             (Namespace, Name, Attribs);
1919     else
1920         xResult.set(this);
1921 
1922     return xResult;
1923 }
1924 
attributes(const uno::Reference<xml::sax::XFastAttributeList> & Attribs)1925 void OOXMLFastContextHandlerWrapper::attributes
1926 (const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
1927 {
1928     if (mxWrappedContext.is())
1929     {
1930         OOXMLFastContextHandler * pHandler = getFastContextHandler();
1931         if (pHandler != nullptr)
1932             pHandler->attributes(Attribs);
1933     }
1934 }
1935 
1936 OOXMLFastContextHandler::ResourceEnum_t
getResource() const1937 OOXMLFastContextHandlerWrapper::getResource() const
1938 {
1939     return UNKNOWN;
1940 }
1941 
addNamespace(Id nId)1942 void OOXMLFastContextHandlerWrapper::addNamespace(Id nId)
1943 {
1944     mMyNamespaces.insert(nId);
1945 }
1946 
addToken(Token_t Token)1947 void OOXMLFastContextHandlerWrapper::addToken( Token_t Token )
1948 {
1949     mMyTokens.insert( Token );
1950 }
1951 
lcl_startFastElement(Token_t Element,const uno::Reference<xml::sax::XFastAttributeList> & Attribs)1952 void OOXMLFastContextHandlerWrapper::lcl_startFastElement
1953 (Token_t Element,
1954  const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
1955 {
1956     if (mxWrappedContext.is())
1957         mxWrappedContext->startFastElement(Element, Attribs);
1958 }
1959 
lcl_endFastElement(Token_t Element)1960 void OOXMLFastContextHandlerWrapper::lcl_endFastElement
1961 (Token_t Element)
1962 {
1963     if (mxWrappedContext.is())
1964         mxWrappedContext->endFastElement(Element);
1965 }
1966 
1967 uno::Reference< xml::sax::XFastContextHandler >
lcl_createFastChildContext(Token_t Element,const uno::Reference<xml::sax::XFastAttributeList> & Attribs)1968 OOXMLFastContextHandlerWrapper::lcl_createFastChildContext
1969 (Token_t Element,
1970  const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
1971 {
1972     uno::Reference< xml::sax::XFastContextHandler > xResult;
1973 
1974     bool bInNamespaces = mMyNamespaces.find(oox::getNamespace(Element)) != mMyNamespaces.end();
1975     bool bInTokens = mMyTokens.find( Element ) != mMyTokens.end( );
1976 
1977     // We have methods to _add_ individual tokens or whole namespaces to be
1978     // processed by writerfilter (instead of oox), but we have no method to
1979     // filter out a single token. Just hardwire the 'wrap' and 'signatureline' tokens
1980     // here until we need a more generic solution.
1981     bool bIsWrap = Element == static_cast<sal_Int32>(NMSP_vmlWord | XML_wrap);
1982     bool bIsSignatureLine = Element == static_cast<sal_Int32>(NMSP_vmlOffice | XML_signatureline);
1983     bool bSkipImages = getDocument()->IsSkipImages() && oox::getNamespace(Element) == NMSP_dml &&
1984         (oox::getBaseToken(Element) != XML_linkedTxbx) && (oox::getBaseToken(Element) != XML_txbx);
1985 
1986     if ( bInNamespaces && ((!bIsWrap && !bIsSignatureLine)
1987                            || mxShapeHandler->isShapeSent()) )
1988     {
1989         xResult.set(OOXMLFactory::createFastChildContextFromStart(this, Element));
1990     }
1991     else if (mxWrappedContext.is()  && !bSkipImages)
1992     {
1993         rtl::Reference<OOXMLFastContextHandlerWrapper> pWrapper =
1994             new OOXMLFastContextHandlerWrapper
1995             (this, mxWrappedContext->createFastChildContext(Element, Attribs),
1996              mxShapeHandler);
1997         pWrapper->mMyNamespaces = mMyNamespaces;
1998         pWrapper->mMyTokens = mMyTokens;
1999         pWrapper->setPropertySet(getPropertySet());
2000         xResult.set(pWrapper);
2001     }
2002     else
2003     {
2004         xResult.set(this);
2005     }
2006 
2007     if ( bInTokens )
2008         mxShapeHandler->sendShape( Element );
2009 
2010     return xResult;
2011 }
2012 
lcl_characters(const OUString & aChars)2013 void OOXMLFastContextHandlerWrapper::lcl_characters
2014 (const OUString & aChars)
2015 {
2016     if (mxWrappedContext.is())
2017         mxWrappedContext->characters(aChars);
2018 }
2019 
2020 OOXMLFastContextHandler *
getFastContextHandler() const2021 OOXMLFastContextHandlerWrapper::getFastContextHandler() const
2022 {
2023     if (mxWrappedContext.is())
2024         return dynamic_cast<OOXMLFastContextHandler *>(mxWrappedContext.get());
2025 
2026     return nullptr;
2027 }
2028 
newProperty(Id nId,const OOXMLValue::Pointer_t & pVal)2029 void OOXMLFastContextHandlerWrapper::newProperty
2030 (Id nId, const OOXMLValue::Pointer_t& pVal)
2031 {
2032     if (mxWrappedContext.is())
2033     {
2034         OOXMLFastContextHandler * pHandler = getFastContextHandler();
2035         if (pHandler != nullptr)
2036             pHandler->newProperty(nId, pVal);
2037     }
2038 }
2039 
setPropertySet(const OOXMLPropertySet::Pointer_t & pPropertySet)2040 void OOXMLFastContextHandlerWrapper::setPropertySet
2041 (const OOXMLPropertySet::Pointer_t& pPropertySet)
2042 {
2043     if (mxWrappedContext.is())
2044     {
2045         OOXMLFastContextHandler * pHandler = getFastContextHandler();
2046         if (pHandler != nullptr)
2047             pHandler->setPropertySet(pPropertySet);
2048     }
2049 
2050     mpPropertySet = pPropertySet;
2051 }
2052 
getPropertySet() const2053 OOXMLPropertySet::Pointer_t OOXMLFastContextHandlerWrapper::getPropertySet()
2054     const
2055 {
2056     OOXMLPropertySet::Pointer_t pResult(mpPropertySet);
2057 
2058     if (mxWrappedContext.is())
2059     {
2060         OOXMLFastContextHandler * pHandler = getFastContextHandler();
2061         if (pHandler != nullptr)
2062             pResult = pHandler->getPropertySet();
2063     }
2064 
2065     return pResult;
2066 }
2067 
getType() const2068 string OOXMLFastContextHandlerWrapper::getType() const
2069 {
2070     string sResult = "Wrapper(";
2071 
2072     if (mxWrappedContext.is())
2073     {
2074         OOXMLFastContextHandler * pHandler = getFastContextHandler();
2075         if (pHandler != nullptr)
2076             sResult += pHandler->getType();
2077     }
2078 
2079     sResult += ")";
2080 
2081     return sResult;
2082 }
2083 
setId(Id rId)2084 void OOXMLFastContextHandlerWrapper::setId(Id rId)
2085 {
2086     OOXMLFastContextHandler::setId(rId);
2087 
2088     if (mxWrappedContext.is())
2089     {
2090         OOXMLFastContextHandler * pHandler = getFastContextHandler();
2091         if (pHandler != nullptr)
2092             pHandler->setId(rId);
2093     }
2094 }
2095 
getId() const2096 Id OOXMLFastContextHandlerWrapper::getId() const
2097 {
2098     Id nResult = OOXMLFastContextHandler::getId();
2099 
2100     if (mxWrappedContext.is())
2101     {
2102         OOXMLFastContextHandler * pHandler = getFastContextHandler();
2103         if (pHandler != nullptr && pHandler->getId() != 0)
2104             nResult = pHandler->getId();
2105     }
2106 
2107     return nResult;
2108 }
2109 
setToken(Token_t nToken)2110 void OOXMLFastContextHandlerWrapper::setToken(Token_t nToken)
2111 {
2112     OOXMLFastContextHandler::setToken(nToken);
2113 
2114     if (mxWrappedContext.is())
2115     {
2116         OOXMLFastContextHandler * pHandler = getFastContextHandler();
2117         if (pHandler != nullptr)
2118             pHandler->setToken(nToken);
2119     }
2120 }
2121 
getToken() const2122 Token_t OOXMLFastContextHandlerWrapper::getToken() const
2123 {
2124     Token_t nResult = OOXMLFastContextHandler::getToken();
2125 
2126     if (mxWrappedContext.is())
2127     {
2128         OOXMLFastContextHandler * pHandler = getFastContextHandler();
2129         if (pHandler != nullptr)
2130             nResult = pHandler->getToken();
2131     }
2132 
2133     return nResult;
2134 }
2135 
2136 
2137 /*
2138   class OOXMLFastContextHandlerLinear
2139  */
2140 
OOXMLFastContextHandlerLinear(OOXMLFastContextHandler * pContext)2141 OOXMLFastContextHandlerLinear::OOXMLFastContextHandlerLinear(OOXMLFastContextHandler* pContext)
2142     : OOXMLFastContextHandlerProperties(pContext)
2143     , depthCount( 0 )
2144 {
2145 }
2146 
lcl_startFastElement(Token_t Element,const uno::Reference<xml::sax::XFastAttributeList> & Attribs)2147 void OOXMLFastContextHandlerLinear::lcl_startFastElement(Token_t Element,
2148     const uno::Reference< xml::sax::XFastAttributeList >& Attribs)
2149 {
2150     buffer.appendOpeningTag( Element, Attribs );
2151     ++depthCount;
2152 }
2153 
lcl_endFastElement(Token_t Element)2154 void OOXMLFastContextHandlerLinear::lcl_endFastElement(Token_t Element)
2155 {
2156     buffer.appendClosingTag( Element );
2157     if( --depthCount == 0 )
2158         process();
2159 }
2160 
2161 uno::Reference< xml::sax::XFastContextHandler >
lcl_createFastChildContext(Token_t,const uno::Reference<xml::sax::XFastAttributeList> &)2162 OOXMLFastContextHandlerLinear::lcl_createFastChildContext(Token_t,
2163     const uno::Reference< xml::sax::XFastAttributeList >&)
2164 {
2165     uno::Reference< xml::sax::XFastContextHandler > xContextHandler;
2166     xContextHandler.set( this );
2167     return xContextHandler;
2168 }
2169 
lcl_characters(const OUString & aChars)2170 void OOXMLFastContextHandlerLinear::lcl_characters(const OUString& aChars)
2171 {
2172     buffer.appendCharacters( aChars );
2173 }
2174 
2175 /*
2176   class OOXMLFastContextHandlerLinear
2177  */
2178 
OOXMLFastContextHandlerMath(OOXMLFastContextHandler * pContext)2179 OOXMLFastContextHandlerMath::OOXMLFastContextHandlerMath(OOXMLFastContextHandler* pContext)
2180     : OOXMLFastContextHandlerLinear(pContext)
2181 {
2182 }
2183 
process()2184 void OOXMLFastContextHandlerMath::process()
2185 {
2186     SvGlobalName name( SO3_SM_CLASSID );
2187     comphelper::EmbeddedObjectContainer container;
2188     OUString aName;
2189     uno::Sequence<beans::PropertyValue> objArgs(1);
2190     objArgs[0].Name = "DefaultParentBaseURL";
2191     objArgs[0].Value <<= getDocument()->GetDocumentBaseURL();
2192     uno::Reference<embed::XEmbeddedObject> ref =
2193         container.CreateEmbeddedObject(name.GetByteSequence(), objArgs, aName);
2194     assert(ref.is());
2195     if (!ref.is())
2196         return;
2197     uno::Reference< uno::XInterface > component(ref->getComponent(), uno::UNO_QUERY_THROW);
2198 // gcc4.4 (and 4.3 and possibly older) have a problem with dynamic_cast directly to the target class,
2199 // so help it with an intermediate cast. I'm not sure what exactly the problem is, seems to be unrelated
2200 // to RTLD_GLOBAL, so most probably a gcc bug.
2201     oox::FormulaImportBase& import = dynamic_cast<oox::FormulaImportBase&>(dynamic_cast<SfxBaseModel&>(*component));
2202     import.readFormulaOoxml(buffer);
2203     if (!isForwardEvents())
2204         return;
2205 
2206     OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
2207     OOXMLValue::Pointer_t pVal( new OOXMLStarMathValue( ref ));
2208     if (mbIsMathPara)
2209     {
2210         switch (mnMathJcVal)
2211         {
2212             case eMathParaJc::CENTER:
2213                 pProps->add(NS_ooxml::LN_Value_math_ST_Jc_centerGroup, pVal,
2214                             OOXMLProperty::ATTRIBUTE);
2215                 break;
2216             case eMathParaJc::LEFT:
2217                 pProps->add(NS_ooxml::LN_Value_math_ST_Jc_left, pVal,
2218                             OOXMLProperty::ATTRIBUTE);
2219                 break;
2220             case eMathParaJc::RIGHT:
2221                 pProps->add(NS_ooxml::LN_Value_math_ST_Jc_right, pVal,
2222                             OOXMLProperty::ATTRIBUTE);
2223                 break;
2224             default:
2225                 break;
2226         }
2227     }
2228     else
2229         pProps->add(NS_ooxml::LN_starmath, pVal, OOXMLProperty::ATTRIBUTE);
2230     mpStream->props( pProps.get() );
2231 }
2232 
OOXMLFastContextHandlerCommentEx(OOXMLFastContextHandler * pContext)2233 OOXMLFastContextHandlerCommentEx::OOXMLFastContextHandlerCommentEx(
2234     OOXMLFastContextHandler* pContext)
2235     : OOXMLFastContextHandler(pContext)
2236 {
2237 }
2238 
lcl_endFastElement(Token_t)2239 void OOXMLFastContextHandlerCommentEx::lcl_endFastElement(Token_t /*Element*/)
2240 {
2241     mpStream->commentProps(m_sParaId, { m_bDone });
2242 }
2243 
att_paraId(const OOXMLValue::Pointer_t & pValue)2244 void OOXMLFastContextHandlerCommentEx::att_paraId(const OOXMLValue::Pointer_t& pValue)
2245 {
2246     m_sParaId = pValue->getString();
2247 }
2248 
att_done(const OOXMLValue::Pointer_t & pValue)2249 void OOXMLFastContextHandlerCommentEx::att_done(const OOXMLValue::Pointer_t& pValue)
2250 {
2251     if (pValue->getInt())
2252         m_bDone = true;
2253 }
2254 
2255 }
2256 
2257 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2258