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