LibreOffice Module writerfilter (master) 1
OOXMLFastContextHandler.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#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/SAXException.hpp>
24#include <ooxml/resourceids.hxx>
26#include <oox/token/namespaces.hxx>
28#include <sal/log.hxx>
32#include <tools/globname.hxx>
34#include <sfx2/sfxbasemodel.hxx>
36#include "OOXMLFactory.hxx"
37#include "Handler.hxx"
42#include "OOXMLPropertySet.hxx"
44
45const sal_Unicode uCR = 0xd;
48const sal_Unicode uFtnSep = 0x5;
49const sal_Unicode uTab = 0x9;
50const sal_Unicode uPgNum = 0x0;
53
55
56namespace writerfilter::ooxml
57{
58using namespace ::com::sun::star;
59using namespace oox;
60using namespace ::com::sun::star::xml::sax;
61
62/*
63 class OOXMLFastContextHandler
64 */
65
67(uno::Reference< uno::XComponentContext > const & context)
68: mpParent(nullptr),
69 mId(0),
70 mnDefine(0),
71 mnToken(oox::XML_TOKEN_COUNT),
72 mnMathJcVal(0),
73 mbIsMathPara(false),
74 mpStream(nullptr),
75 mnTableDepth(0),
76 m_inPositionV(false),
77 mbAllowInCell(true),
78 mbIsVMLfound(false),
79 m_xContext(context),
80 m_bDiscardChildren(false),
81 m_bTookChoice(false)
82{
83 if (!mpParserState)
84 mpParserState = new OOXMLParserState();
85
86 mpParserState->incContextCount();
87}
88
90: mpParent(pContext),
91 mId(0),
92 mnDefine(0),
93 mnToken(oox::XML_TOKEN_COUNT),
94 mnMathJcVal(pContext->mnMathJcVal),
95 mbIsMathPara(pContext->mbIsMathPara),
96 mpStream(pContext->mpStream),
97 mpParserState(pContext->mpParserState),
98 mnTableDepth(pContext->mnTableDepth),
99 m_inPositionV(pContext->m_inPositionV),
100 mbAllowInCell(pContext->mbAllowInCell),
101 mbIsVMLfound(pContext->mbIsVMLfound),
102 m_xContext(pContext->m_xContext),
103 m_bDiscardChildren(pContext->m_bDiscardChildren),
104 m_bTookChoice(pContext->m_bTookChoice)
105{
106 if (!mpParserState)
108
109 mpParserState->incContextCount();
110}
111
113{
114}
115
117{
118 switch (oox::getBaseToken(nElement))
119 {
120 case XML_AlternateContent:
121 {
122 SavedAlternateState aState;
124 m_bDiscardChildren = false;
126 m_bTookChoice = false;
127 mpParserState->getSavedAlternateStates().push_back(aState);
128 }
129 break;
130 case XML_Choice:
131 {
132 OUString aRequires = rAttribs->getOptionalValue(XML_Requires);
133 static const char* aFeatures[] = {
134 "wps",
135 "wpg",
136 "w14",
137 };
138 for (const char *p : aFeatures)
139 {
140 if (aRequires.equalsAscii(p))
141 {
142 m_bTookChoice = true;
143 return false;
144 }
145 }
146 return true;
147 }
148 break;
149 case XML_Fallback:
150 // If Choice is already taken, then let's ignore the Fallback.
151 return m_bTookChoice;
152 default:
153 SAL_WARN("writerfilter", "OOXMLFastContextHandler::prepareMceContext: unhandled element:" << oox::getBaseToken(nElement));
154 break;
155 }
156 return false;
157}
158
159// xml::sax::XFastContextHandler:
161(sal_Int32 Element,
163{
164 // Set xml:space value early, to allow child contexts use it when dealing with strings.
165 if (Attribs && Attribs->hasAttribute(oox::NMSP_xml | oox::XML_space))
166 {
167 mbPreserveSpace = Attribs->getValue(oox::NMSP_xml | oox::XML_space) == "preserve";
168 mbPreserveSpaceSet = true;
169 }
170 if (Element == W_TOKEN(footnote) || Element == W_TOKEN(endnote))
171 {
172 // send uFtnSep to sign new footnote content, but skip footnote separators
173 if (!Attribs->hasAttribute(W_TOKEN(type)) ||
174 ( Attribs->getValue(W_TOKEN(type)) != "separator" &&
175 Attribs->getValue(W_TOKEN(type)) != "continuationSeparator" &&
176 Attribs->getValue(W_TOKEN(type)) != "continuationNotice" ))
177 {
178 mpParserState->setStartFootnote(true);
179 }
180 }
181 else if (Element == (NMSP_officeMath | XML_oMathPara))
182 {
183 mnMathJcVal = eMathParaJc::CENTER;
184 mbIsMathPara = true;
185 }
186 else if (Element == (NMSP_officeMath | XML_jc) && mpParent && mpParent->mpParent )
187 {
188 mbIsMathPara = true;
189 auto aAttrLst = Attribs->getFastAttributes();
190 if (aAttrLst[0].Value == "center") mpParent->mpParent->mnMathJcVal = eMathParaJc::CENTER;
191 if (aAttrLst[0].Value == "left") mpParent->mpParent->mnMathJcVal = eMathParaJc::LEFT;
192 if (aAttrLst[0].Value == "right") mpParent->mpParent->mnMathJcVal = eMathParaJc::RIGHT;
193 }
194
195 if (oox::getNamespace(Element) == NMSP_mce)
196 m_bDiscardChildren = prepareMceContext(Element, Attribs);
197
198 else if (!m_bDiscardChildren)
199 {
200 attributes(Attribs);
201 lcl_startFastElement(Element, Attribs);
202 }
203}
204
206(const OUString & /*Namespace*/, const OUString & /*Name*/,
208{
209}
210
211void SAL_CALL OOXMLFastContextHandler::endFastElement(sal_Int32 Element)
212{
213 if (Element == (NMSP_mce | XML_Choice) || Element == (NMSP_mce | XML_Fallback))
214 m_bDiscardChildren = false;
215 else if (Element == (NMSP_mce | XML_AlternateContent))
216 {
217 SavedAlternateState aState(mpParserState->getSavedAlternateStates().back());
218 mpParserState->getSavedAlternateStates().pop_back();
221 }
222 else if (!m_bDiscardChildren)
223 lcl_endFastElement(Element);
224}
225
227(Token_t Element,
229{
231 if( Element == (NMSP_dmlWordDr|XML_positionV) )
232 m_inPositionV = true;
233 else if( Element == (NMSP_dmlWordDr|XML_positionH) )
234 m_inPositionV = false;
235}
236
238(Token_t /*Element*/)
239{
241}
242
244(const OUString & , const OUString & )
245{
246}
247
250(sal_Int32 Element,
252{
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
264(Token_t Element,
266{
267 return OOXMLFactory::createFastChildContext(this, Element);
268}
269
272(const OUString &,
273 const OUString &,
275{
277 (new OOXMLFastContextHandler(*const_cast<const OOXMLFastContextHandler *>(this)));
278}
279
281(const OUString & aChars)
282{
283 lcl_characters(aChars);
284}
285
287(const OUString & rString)
288{
290 OOXMLFactory::characters(this, rString);
291}
292
294{
295 mpStream = pStream;
296}
297
299{
300 return OOXMLValue::Pointer_t();
301}
302
305{
306 OOXMLFactory::attributes(this, Attribs);
307}
308
310{
312}
313
315{
317}
318
320{
321 mId = rId;
322}
323
325{
326 return mId;
327}
328
330{
331 mnDefine = nDefine;
332}
333
334
336{
337 mnToken = nToken;
338}
339
341{
342 return mnToken;
343}
344
346{
347 if (mnTableDepth <= 0)
348 return;
349
351 {
353 pProps->add(NS_ooxml::LN_tblDepth, pVal, OOXMLProperty::SPRM);
354 }
355 {
357 pProps->add(NS_ooxml::LN_inTbl, pVal, OOXMLProperty::SPRM);
358 }
359
360 mpStream->props(pProps.get());
361}
362
364{
365 mpParserState->setHandle();
366 mpStream->info(mpParserState->getHandle());
367}
368
370{
371 if (!isForwardEvents())
372 return;
373
374 if (mpParserState->isInCharacterGroup())
376
377 if (! mpParserState->isInParagraphGroup())
379
380 if (! mpParserState->isInCharacterGroup())
381 {
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
398{
399 if (isForwardEvents() && mpParserState->isInCharacterGroup())
400 {
402 mpParserState->setInCharacterGroup(false);
403 }
404}
405
407
409
411{
412 if (!isForwardEvents())
413 return;
414
415 if (mpParserState->GetFloatingTableEnded())
416 {
417 mpParserState->SetFloatingTableEnded(false);
418 }
419
420 if (mpParserState->isInParagraphGroup())
422
423 if (! mpParserState->isInSectionGroup())
425
426 if ( mpParserState->isInParagraphGroup())
427 return;
428
430 mpParserState->setInParagraphGroup(true);
431
432 if (const auto& pPropSet = getPropertySet())
433 {
434 OOXMLPropertySetEntryToString aHandler(NS_ooxml::LN_AG_Parids_paraId);
435 pPropSet->resolve(aHandler);
436 if (const OUString& sText = aHandler.getString(); !sText.isEmpty())
437 {
440 pPropertySet->add(NS_ooxml::LN_AG_Parids_paraId, pVal, OOXMLProperty::ATTRIBUTE);
441 mpStream->props(pPropertySet.get());
442 }
443 }
444}
445
447{
448 if (isForwardEvents())
449 {
450 if (mpParserState->isInCharacterGroup())
452
453 if (mpParserState->isInParagraphGroup())
454 {
456 mpParserState->setInParagraphGroup(false);
457 }
458 }
459}
460
462{
465 pProps->add(NS_ooxml::LN_CT_SdtBlock_sdtContent, pVal, OOXMLProperty::ATTRIBUTE);
466 mpStream->props(pProps.get());
467}
468
470{
473 pProps->add(NS_ooxml::LN_CT_SdtBlock_sdtEndContent, pVal, OOXMLProperty::ATTRIBUTE);
474 mpStream->props(pProps.get());
475}
476
478{
481 pProps->add(NS_ooxml::LN_CT_SdtRun_sdtContent, pVal, OOXMLProperty::ATTRIBUTE);
482 mpStream->props(pProps.get());
483}
484
486{
489 pProps->add(NS_ooxml::LN_CT_SdtRun_sdtEndContent, pVal, OOXMLProperty::ATTRIBUTE);
490 mpStream->props(pProps.get());
491}
492
494{
495 if (isForwardEvents())
496 {
497 if (mpParserState->isInSectionGroup())
499
500 if (! mpParserState->isInSectionGroup())
501 {
502 mpStream->info(mpParserState->getHandle());
504 mpParserState->setInSectionGroup(true);
505 }
506 }
507}
508
510{
511 if (isForwardEvents())
512 {
513 if (mpParserState->isInParagraphGroup())
515
516 if (mpParserState->isInSectionGroup())
517 {
519 mpParserState->setInSectionGroup(false);
520 }
521 }
522}
523
525{
526 mpParserState->setLastParagraphInSection(true);
528}
529
531{
533}
534
536(Id /*nId*/, const OOXMLValue::Pointer_t& /*pVal*/)
537{
538}
539
541(const OOXMLPropertySet::Pointer_t& /* pPropertySet */)
542{
543}
544
546{
548}
549
551{
553 if (isForwardEvents())
556}
557
559{
561 if (isForwardEvents())
562 mpStream->text(&cFieldSep, 1);
564}
565
567{
569 if (isForwardEvents())
570 mpStream->text(&cFieldEnd, 1);
572}
573
575{
577 if (isForwardEvents())
580}
581
583{
584 if (isForwardEvents())
585 mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uFtnEdnRef), 1);
586}
587
589{
590 if (isForwardEvents())
591 mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uFtnEdnSep), 1);
592}
593
595{
596 if (isForwardEvents())
598}
599
601{
602 if (isForwardEvents())
603 mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uPgNum), 1);
604}
605
607{
608 if (isForwardEvents())
609 mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uTab), 1);
610}
611
613{
614 if (isForwardEvents())
615 sendPropertiesWithId(NS_ooxml::LN_EG_RunInnerContent_sym);
616}
617
619{
620 if (isForwardEvents())
621 mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uCR), 1);
622}
623
625{
626 if (isForwardEvents())
627 mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uNoBreakHyphen), 1);
628}
629
631{
632 if (isForwardEvents())
633 mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uSoftHyphen), 1);
634}
635
637{
638 if (mpParserState->isLastParagraphInSection())
639 {
640 mpParserState->setLastParagraphInSection(false);
642 }
643}
644
646{
647 if (! mpParserState->isInCharacterGroup())
649 if (isForwardEvents())
650 mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uCR), 1);
651
652 mpParserState->getDocument()->incrementProgress();
653}
654
656{
657/*
658 This usually means there are recursive <w:p> elements, and the ones
659 inside and outside of w:txbxContent should not interfere (e.g.
660 the lastParagraphInSection setting). So save the whole state
661 and possibly start new groups for the nested content (not section
662 group though, as that'd cause the txbxContent to be moved onto
663 another page, I'm not sure how that should work exactly).
664*/
665 mpParserState->startTxbxContent();
667}
668
670{
672 mpParserState->endTxbxContent();
673}
674
675namespace {
676// XML schema defines white space as one of four characters:
677// #x9 (tab), #xA (line feed), #xD (carriage return), and #x20 (space)
678bool IsXMLWhitespace(sal_Unicode cChar)
679{
680 return cChar == 0x9 || cChar == 0xA || cChar == 0xD || cChar == 0x20;
681}
682
683OUString TrimXMLWhitespace(const OUString & sText)
684{
685 sal_Int32 nTrimmedStart = 0;
686 const sal_Int32 nLen = sText.getLength();
687 sal_Int32 nTrimmedEnd = nLen - 1;
688 while (nTrimmedStart < nLen && IsXMLWhitespace(sText[nTrimmedStart]))
689 ++nTrimmedStart;
690 while (nTrimmedStart <= nTrimmedEnd && IsXMLWhitespace(sText[nTrimmedEnd]))
691 --nTrimmedEnd;
692 if ((nTrimmedStart == 0) && (nTrimmedEnd == nLen - 1))
693 return sText;
694 else if (nTrimmedStart > nTrimmedEnd)
695 return OUString();
696 else
697 return sText.copy(nTrimmedStart, nTrimmedEnd-nTrimmedStart+1);
698}
699}
700
701void OOXMLFastContextHandler::text(const OUString & sText)
702{
703 if (!isForwardEvents())
704 return;
705
706 // tdf#108806: CRLFs in XML were converted to \n before this point.
707 // These must be converted to spaces before further processing.
708 OUString sNormalizedText = sText.replaceAll("\n", " ");
709 // tdf#108995: by default, leading and trailing white space is ignored;
710 // tabs are converted to spaces
711 if (!IsPreserveSpace())
712 {
713 sNormalizedText = TrimXMLWhitespace(sNormalizedText).replaceAll("\t", " ");
714 }
715 mpStream->utext(reinterpret_cast < const sal_uInt8 * >
716 (sNormalizedText.getStr()),
717 sNormalizedText.getLength());
718}
719
721{
722 if (isForwardEvents())
724}
725
727{
728}
729
730void OOXMLFastContextHandler::alignH(const OUString& rText)
731{
732 if (isForwardEvents())
733 mpStream->align(rText, /*bVertical=*/false);
734}
735
736void OOXMLFastContextHandler::alignV(const OUString& rText)
737{
738 if (isForwardEvents())
739 mpStream->align(rText, /*bVertical=*/true);
740}
741
743{
744 if (isForwardEvents())
746}
747
749{
750 if (isForwardEvents())
752}
753
755{
756 if (isForwardEvents())
758}
759
761{
762 mpParserState->setCharacterProperties(getPropertySet());
763}
764
766{
767 mpParserState->setCellProperties(getPropertySet());
768}
769
771{
772 mpParserState->setRowProperties(getPropertySet());
773}
774
776{
778
779 mpParserState->setTableProperties(pProps);
780}
781
783{
784 mpParserState->resolveCellProperties(*mpStream);
785}
786
788{
789 mpParserState->resolveRowProperties(*mpStream);
790}
791
793{
794 mpParserState->resolveTableProperties(*mpStream);
795}
796
798{
799 mpParserState->setTableProperties(new OOXMLPropertySet());
800}
801
803{
806
807 pPropertySet->add(nId, pValue, OOXMLProperty::SPRM);
808 mpStream->props(pPropertySet.get());
809}
810
812{
814}
815
817{
818}
819
821{
822}
823
825{
826}
827
829{
830}
831
833{
834 mpParserState->setDocument(pDocument);
835}
836
838{
839 return mpParserState->getDocument();
840}
841
843{
844 mpParserState->setForwardEvents(bForwardEvents);
845}
846
848{
849 return mpParserState->isForwardEvents();
850}
851
852void OOXMLFastContextHandler::setXNoteId(const sal_Int32 nId)
853{
854 mpParserState->setXNoteId(nId);
855}
856
858{
859 mpParserState->setXNoteId(sal_Int32(pValue->getInt()));
860}
861
863{
864 return mpParserState->getXNoteId();
865}
866
868(const sal_Int32 nId)
869{
870 mpParserState->getDocument()->resolveFootnote
871 (*mpStream, 0, nId);
872}
873
875{
876 mpParserState->getDocument()->resolveEndnote
877 (*mpStream, 0, nId);
878}
879
881{
882 mpParserState->getDocument()->resolveComment(*mpStream, nId);
883}
884
886{
887 mpParserState->getDocument()->resolvePicture(*mpStream, rId);
888}
889
891(const sal_Int32 type, const OUString & rId)
892{
893 mpParserState->getDocument()->resolveHeader(*mpStream, type, rId);
894}
895
897(const sal_Int32 type, const OUString & rId)
898{
899 mpParserState->getDocument()->resolveFooter(*mpStream, type, rId);
900}
901
902// Add the data pointed to by the reference as another property.
903void OOXMLFastContextHandler::resolveData(const OUString & rId)
904{
905 OOXMLDocument * objDocument = getDocument();
906 SAL_WARN_IF(!objDocument, "writerfilter", "no document to resolveData");
907 if (!objDocument)
908 return;
909
911 (objDocument->getInputStreamForId(rId));
912
913 OOXMLValue::Pointer_t aValue(new OOXMLInputStreamValue(xInputStream));
914
915 newProperty(NS_ooxml::LN_inputstream, aValue);
916}
917
919(const OUString & rId)
920{
921 return mpParserState->getDocument()->getTargetForId(rId);
922}
923
925{
926 if (mpParent != nullptr)
927 {
929
930 if (pProps)
931 {
932 pProps->add(mId, getValue(), OOXMLProperty::SPRM);
933 }
934 }
935}
936
938{
939 if (mpParent == nullptr)
940 return;
941
943
944 if (!pParentProps)
945 return;
946
948
949 if (pProps)
950 {
953
954 pParentProps->add(getId(), pValue, OOXMLProperty::SPRM);
955
956 }
957}
958
960{
961 // xml:space attribute applies to all elements within the content of the element where it is specified,
962 // unless overridden with another instance of the xml:space attribute
964 return mbPreserveSpace;
965 if (mpParent)
966 return mpParent->IsPreserveSpace();
967 return false; // default value
968}
969
970/*
971 class OOXMLFastContextHandlerStream
972 */
973
975(OOXMLFastContextHandler * pContext)
976: OOXMLFastContextHandler(pContext),
977 mpPropertySetAttrs(new OOXMLPropertySet)
978{
979}
980
982{
983}
984
986 const OOXMLValue::Pointer_t& pVal)
987{
988 if (nId != 0x0)
989 {
991 }
992}
993
995{
997 getPropertySetAttrs()->resolve(aHandler);
998 const OUString & sText = aHandler.getString();
999 mpStream->utext(reinterpret_cast < const sal_uInt8 * >
1000 (sText.getStr()),
1001 sText.getLength());
1002}
1003
1004
1006 const
1007{
1008 return getPropertySetAttrs();
1009}
1010
1012{
1013 OOXMLHyperlinkHandler aHyperlinkHandler(this);
1014 getPropertySetAttrs()->resolve(aHyperlinkHandler);
1015 aHyperlinkHandler.writetext();
1016}
1017
1018/*
1019 class OOXMLFastContextHandlerProperties
1020 */
1022(OOXMLFastContextHandler * pContext)
1023: OOXMLFastContextHandler(pContext), mpPropertySet(new OOXMLPropertySet),
1024 mbResolve(false)
1025{
1026 if (pContext->getResource() == STREAM)
1027 mbResolve = true;
1028}
1029
1031{
1032}
1033
1035(Token_t /*Element*/)
1036{
1037 try
1038 {
1039 endAction();
1040
1041 if (mbResolve)
1042 {
1043 if (isForwardEvents())
1044 {
1046 }
1047 }
1048 else
1049 {
1051 }
1052 }
1053 catch (const uno::RuntimeException&)
1054 {
1055 throw;
1056 }
1057 catch (const xml::sax::SAXException&)
1058 {
1059 throw;
1060 }
1061 catch (const uno::Exception& e)
1062 {
1063 auto a = cppu::getCaughtException();
1064 throw lang::WrappedTargetRuntimeException(e.Message, e.Context, a);
1065 }
1066}
1067
1069{
1071}
1072
1074(Id nId, const OOXMLValue::Pointer_t& pVal)
1075{
1076 if (nId != 0x0)
1077 {
1079 }
1080}
1081
1083{
1084 switch (mnToken)
1085 {
1086 case W_TOKEN(footnoteReference):
1087 {
1088 OOXMLFootnoteHandler aFootnoteHandler(this);
1089 mpPropertySet->resolve(aFootnoteHandler);
1090 }
1091 break;
1092 case W_TOKEN(endnoteReference):
1093 {
1094 OOXMLEndnoteHandler aEndnoteHandler(this);
1095 mpPropertySet->resolve(aEndnoteHandler);
1096 }
1097 break;
1098 default:
1099 break;
1100 }
1101}
1102
1104{
1105 switch (mnToken)
1106 {
1107 case W_TOKEN(footerReference):
1108 {
1109 OOXMLFooterHandler aFooterHandler(this);
1110 mpPropertySet->resolve(aFooterHandler);
1111 aFooterHandler.finalize();
1112 }
1113 break;
1114 case W_TOKEN(headerReference):
1115 {
1116 OOXMLHeaderHandler aHeaderHandler(this);
1117 mpPropertySet->resolve(aHeaderHandler);
1118 aHeaderHandler.finalize();
1119 }
1120 break;
1121 default:
1122 break;
1123 }
1124}
1125
1127{
1128 OOXMLCommentHandler aCommentHandler(this);
1129 getPropertySet()->resolve(aCommentHandler);
1130}
1131
1133{
1134 OOXMLPictureHandler aPictureHandler(this);
1135 getPropertySet()->resolve(aPictureHandler);
1136}
1137
1139{
1140 if(isForwardEvents())
1141 {
1142 OOXMLBreakHandler aBreakHandler(this, *mpStream);
1143 getPropertySet()->resolve(aBreakHandler);
1144 }
1145}
1146
1147// tdf#108714 : allow <w:br> at block level (despite this is illegal according to ECMA-376-1:2016)
1149{
1150 if(isForwardEvents())
1151 {
1152 mpParserState->setPostponedBreak(getPropertySet());
1153 }
1154}
1155
1157{
1158 OOXMLOLEHandler aOLEHandler(this);
1159 getPropertySet()->resolve(aOLEHandler);
1160}
1161
1163{
1164 OOXMLEmbeddedFontHandler handler(this);
1165 getPropertySet()->resolve(handler);
1166}
1167
1169 OOXMLHyperlinkURLHandler aHyperlinkURLHandler(this);
1170 getPropertySet()->resolve(aHyperlinkURLHandler);
1171}
1172
1174{
1175 OOXMLAltChunkHandler aHandler(this);
1176 getPropertySet()->resolve(aHandler);
1177}
1178
1180(const OOXMLPropertySet::Pointer_t& pPropertySet)
1181{
1182 if (pPropertySet)
1183 mpPropertySet = pPropertySet;
1184}
1185
1188{
1189 return mpPropertySet;
1190}
1191
1192/*
1193 * class OOXMLFasContextHandlerPropertyTable
1194 */
1195
1197(OOXMLFastContextHandler * pContext)
1199{
1200}
1201
1203{
1204}
1205
1207(Token_t /*Element*/)
1208{
1209 OOXMLPropertySet::Pointer_t pPropSet(mpPropertySet->clone());
1211 (new OOXMLPropertySetValue(pPropSet));
1212
1213 mTable.add(pTmpVal);
1214
1216
1217 mpStream->table(mId, pTable);
1218
1219 endAction();
1220}
1221
1222/*
1223 class OOXMLFastContextHandlerValue
1224*/
1225
1227(OOXMLFastContextHandler * pContext)
1228: OOXMLFastContextHandler(pContext)
1229{
1230}
1231
1233{
1234}
1235
1237{
1238 mpValue = pValue;
1239}
1240
1242{
1243 return mpValue;
1244}
1245
1247(Token_t /*Element*/)
1248{
1250
1251 endAction();
1252}
1253
1255{
1256 if (!mpValue)
1257 {
1259 setValue(pValue);
1260 }
1261}
1262
1264{
1265 if (!mpValue)
1266 {
1268 setValue(pValue);
1269 }
1270}
1271
1273{
1274 if (!mpValue)
1275 {
1276 OOXMLValue::Pointer_t pValue(new OOXMLHexValue(sal_uInt32(0)));
1277 setValue(pValue);
1278 }
1279}
1280
1282{
1283 if (!mpValue)
1284 {
1285 OOXMLValue::Pointer_t pValue(new OOXMLStringValue(OUString()));
1286 setValue(pValue);
1287 }
1288}
1289
1290// ECMA-376-1:2016 17.3.2.8; https://www.unicode.org/reports/tr9/#Explicit_Directional_Embeddings
1292{
1293 const bool bRtl
1294 = mpValue && mpValue->getInt() == NS_ooxml::LN_Value_ST_Direction_rtl;
1295 OOXMLFactory::characters(this, bRtl ? OUString(u"\u202B") : OUString(u"\u202A")); // RLE / LRE
1296}
1297
1299{
1300 OOXMLFactory::characters(this, u"\u202C"); // PDF (POP DIRECTIONAL FORMATTING)
1301}
1302
1304{
1305 if (!getValue())
1306 return;
1307
1308 if (OOXMLFastContextHandler* pTableRowProperties = getParent())
1309 {
1310 if (OOXMLFastContextHandler* pTableRow = pTableRowProperties->getParent())
1311 // Save the value into the table row context, so it can be handled
1312 // right before the end of the row.
1313 pTableRow->setGridAfter(getValue());
1314 }
1315}
1316
1317/*
1318 class OOXMLFastContextHandlerTable
1319*/
1320
1322(OOXMLFastContextHandler * pContext)
1323: OOXMLFastContextHandler(pContext)
1324{
1325}
1326
1328{
1329}
1330
1333(sal_Int32 Element,
1335{
1337
1339
1340 return mCurrentChild;
1341}
1342
1344(Token_t /*Element*/)
1345{
1347
1349 if (isForwardEvents() && mId != 0x0)
1350 {
1351 mpStream->table(mId, pTable);
1352 }
1353}
1354
1356{
1357 OOXMLFastContextHandler * pHandler = dynamic_cast<OOXMLFastContextHandler*>(mCurrentChild.get());
1358 if (pHandler != nullptr)
1359 {
1360 OOXMLValue::Pointer_t pValue(pHandler->getValue());
1361
1362 if (pValue)
1363 {
1364 OOXMLTable::ValuePointer_t pTmpVal(pValue->clone());
1365 mTable.add(pTmpVal);
1366 }
1367 }
1368}
1369
1370/*
1371 class OOXMLFastContextHandlerXNote
1372 */
1373
1375 (OOXMLFastContextHandler * pContext)
1377 , mbForwardEventsSaved(false)
1378 , mnMyXNoteId(0)
1379 , mnMyXNoteType(0)
1380{
1381}
1382
1384{
1385}
1386
1388(Token_t /*Element*/,
1390{
1392
1393 // If this is the note we're looking for or this is the footnote separator one.
1394 if (mnMyXNoteId == getXNoteId() ||
1395 static_cast<sal_uInt32>(mnMyXNoteType) == NS_ooxml::LN_Value_doc_ST_FtnEdn_separator ||
1396 mpParserState->isStartFootnote())
1397 setForwardEvents(true);
1398 else
1399 setForwardEvents(false);
1400
1401 startAction();
1402}
1403
1405(Token_t Element)
1406{
1407 endAction();
1408
1410
1412}
1413
1415{
1416 mnMyXNoteId = sal_Int32(pValue->getInt());
1418}
1419
1421{
1422 mnMyXNoteType = pValue->getInt();
1423}
1424
1425/*
1426 class OOXMLFastContextHandlerTextTableCell
1427 */
1428
1430(OOXMLFastContextHandler * pContext)
1431: OOXMLFastContextHandler(pContext)
1432{
1433}
1434
1436{
1437}
1438
1440{
1441 if (isForwardEvents())
1442 {
1444 {
1446 pProps->add(NS_ooxml::LN_tcStart, pVal, OOXMLProperty::SPRM);
1447 }
1448
1449 mpStream->props(pProps.get());
1450 }
1451}
1452
1454{
1455 if (!isForwardEvents())
1456 return;
1457
1459 {
1461 pProps->add(NS_ooxml::LN_tblDepth, pVal, OOXMLProperty::SPRM);
1462 }
1463 {
1465 pProps->add(NS_ooxml::LN_inTbl, pVal, OOXMLProperty::SPRM);
1466 }
1467 {
1469 pProps->add(NS_ooxml::LN_tblCell, pVal, OOXMLProperty::SPRM);
1470 }
1471 {
1473 pProps->add(NS_ooxml::LN_tcEnd, pVal, OOXMLProperty::SPRM);
1474 }
1475
1476 mpStream->props(pProps.get());
1477}
1478
1479/*
1480 class OOXMLFastContextHandlerTextTableRow
1481 */
1482
1484(OOXMLFastContextHandler * pContext)
1485: OOXMLFastContextHandler(pContext)
1486{
1487}
1488
1490{
1491}
1492
1494{
1495}
1496
1498{
1499 if (mpGridAfter)
1500 {
1501 // Grid after is the same as grid before, the empty cells are just
1502 // inserted after the real ones, not before.
1504 mpGridAfter = nullptr;
1505 }
1506
1508
1509 if (isForwardEvents())
1510 {
1512 {
1514 pProps->add(NS_ooxml::LN_tblDepth, pVal, OOXMLProperty::SPRM);
1515 }
1516 {
1518 pProps->add(NS_ooxml::LN_inTbl, pVal, OOXMLProperty::SPRM);
1519 }
1520 {
1522 pProps->add(NS_ooxml::LN_tblRow, pVal, OOXMLProperty::SPRM);
1523 }
1524
1525 mpStream->props(pProps.get());
1526 }
1527
1529
1530 if (isForwardEvents())
1531 mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uCR), 1);
1532
1535}
1536
1537namespace {
1538OOXMLValue::Pointer_t fakeNoBorder()
1539{
1542 pProps->add(NS_ooxml::LN_CT_Border_val, pVal, OOXMLProperty::ATTRIBUTE);
1543 OOXMLValue::Pointer_t pValue( new OOXMLPropertySetValue( pProps ));
1544 return pValue;
1545}
1546}
1547
1548// Handle w:gridBefore here by faking necessary input that'll fake cells. I'm apparently
1549// not insane enough to find out how to add cells in dmapper.
1551{
1552 // start removing: disable for w:gridBefore
1553 if (!mpGridAfter)
1554 return;
1555
1556 int count = val->getInt();
1557 for( int i = 0;
1558 i < count;
1559 ++i )
1560 {
1562
1563 if (isForwardEvents())
1564 {
1565 // This whole part is OOXMLFastContextHandlerTextTableCell::endCell() .
1567 {
1569 pProps->add(NS_ooxml::LN_tblDepth, pVal, OOXMLProperty::SPRM);
1570 }
1571 {
1573 pProps->add(NS_ooxml::LN_inTbl, pVal, OOXMLProperty::SPRM);
1574 }
1575 {
1577 pProps->add(NS_ooxml::LN_tblCell, pVal, OOXMLProperty::SPRM);
1578 }
1579
1580 mpStream->props(pProps.get());
1581
1582 // fake <w:tcBorders> with no border
1584 {
1586 static Id borders[] = { NS_ooxml::LN_CT_TcBorders_top, NS_ooxml::LN_CT_TcBorders_bottom,
1587 NS_ooxml::LN_CT_TcBorders_start, NS_ooxml::LN_CT_TcBorders_end };
1588 for(sal_uInt32 border : borders)
1589 pBorderProps->add(border, fakeNoBorder(), OOXMLProperty::SPRM);
1590 OOXMLValue::Pointer_t pValue( new OOXMLPropertySetValue( pBorderProps ));
1591 pCellProps->add(NS_ooxml::LN_CT_TcPrBase_tcBorders, pValue, OOXMLProperty::SPRM);
1592 mpParserState->setCellProperties(pCellProps);
1593 }
1594 }
1595
1598 }
1599}
1600
1601/*
1602 class OOXMLFastContextHandlerTextTable
1603 */
1604
1606(OOXMLFastContextHandler * pContext)
1607: OOXMLFastContextHandler(pContext)
1608{
1609}
1610
1612{
1614}
1615
1617(Token_t /*Element*/,
1619{
1620 if (mpParserState->GetFloatingTableEnded())
1621 {
1622 // We're starting a new table, but the previous table was floating. Insert a dummy paragraph
1623 // to ensure that the floating table has a suitable anchor.
1626 }
1627
1628 mpParserState->startTable();
1629 mnTableDepth++;
1630
1632 {
1634 pProps->add(NS_ooxml::LN_tblStart, pVal, OOXMLProperty::SPRM);
1635 }
1636 mpParserState->setCharacterProperties(pProps);
1637
1638 startAction();
1639}
1640
1642(Token_t /*Element*/)
1643{
1644 endAction();
1645
1647 {
1649 pProps->add(NS_ooxml::LN_tblEnd, pVal, OOXMLProperty::SPRM);
1650 }
1651 mpParserState->setCharacterProperties(pProps);
1652
1653 mnTableDepth--;
1654
1655 OOXMLPropertySet::Pointer_t pTableProps = mpParserState->GetTableProperties();
1656 if (pTableProps)
1657 {
1658 for (const auto& rTableProp : *pTableProps)
1659 {
1660 if (rTableProp->getId() == NS_ooxml::LN_CT_TblPrBase_tblpPr)
1661 {
1662 mpParserState->SetFloatingTableEnded(true);
1663 break;
1664 }
1665 }
1666 }
1667
1668 mpParserState->endTable();
1669}
1670
1671// tdf#111550
1673{
1674 // Normally, when one paragraph ends, and another begins,
1675 // in OOXMLFactory_wml::endAction handler for <w:p>,
1676 // pHandler->endOfParagraph() is called, which (among other things)
1677 // calls TableManager::setHandle() to update current cell's starting point.
1678 // Then, in OOXMLFactory_wml::startAction for next <w:p>,
1679 // pHandler->startParagraphGroup() is called, which ends previous group,
1680 // and there, it pushes cells to row in TableManager::endParagraphGroup()
1681 // (cells have correct bounds defined by mCurHandle).
1682 // When a table is child of a <w:p>, that paragraph doesn't end before nested
1683 // paragraph begins. So, pHandler->endOfParagraph() was not (and should not be)
1684 // called. But as next paragraph starts, is the previous group is closed, then
1685 // cells will have wrong boundings. Here, we know that we *are* in paragraph
1686 // group, but it should not be finished.
1687 mpParserState->setInParagraphGroup(false);
1688}
1689
1690/*
1691 class OOXMLFastContextHandlerShape
1692 */
1693
1695(OOXMLFastContextHandler * pContext)
1696: OOXMLFastContextHandlerProperties(pContext), m_bShapeSent( false ),
1697 m_bShapeStarted(false), m_bShapeContextPushed(false)
1698{
1699}
1700
1702{
1705}
1706
1708(Token_t Element,
1710{
1711 startAction();
1712
1713 if (mrShapeContext.is())
1714 {
1715 if (Element == DGM_TOKEN(relIds))
1716 {
1717 // It is a SmartArt. Make size available for generated group.
1718 // Search for PropertySet in parents
1719 OOXMLFastContextHandler* pHandler = getParent();
1720 while (pHandler && pHandler->getId() != NS_ooxml::LN_anchor_anchor
1721 && pHandler->getId() != NS_ooxml::LN_inline_inline)
1722 {
1723 pHandler = pHandler->getParent();
1724 }
1725 // Search for extent
1726 if (pHandler)
1727 {
1728 if (const OOXMLPropertySet::Pointer_t pPropSet = pHandler->getPropertySet())
1729 {
1730 auto aIt = pPropSet->begin();
1731 auto aItEnd = pPropSet->end();
1732 while (aIt != aItEnd && (*aIt)->getId() != NS_ooxml::LN_CT_Inline_extent
1733 && (*aIt)->getId() != NS_ooxml::LN_CT_Anchor_extent)
1734 {
1735 ++aIt;
1736 }
1737 if (aIt != aItEnd)
1738 {
1739 writerfilter::Reference<Properties>::Pointer_t pProperties = (*aIt)->getProps();
1740 if (pProperties)
1741 {
1743 pProperties->resolve(*pExtentHandler);
1744 mrShapeContext->setSize(pExtentHandler->getExtent());
1745 }
1746 }
1747 }
1748 }
1749 }
1750 mrShapeContext->startFastElement(Element, Attribs);
1751 }
1752}
1753
1755(const OUString & Namespace,
1756 const OUString & Name,
1758{
1759 if (mrShapeContext.is())
1760 mrShapeContext->startUnknownElement(Namespace, Name, Attribs);
1761}
1762
1764{
1765 if (nToken == Token_t(NMSP_wps | XML_wsp) || nToken == Token_t(NMSP_dmlPicture | XML_pic))
1766 {
1767 // drawingML shapes are independent, <wps:bodyPr> is not parsed after
1768 // shape contents without pushing/popping the stack.
1769 m_bShapeContextPushed = true;
1771 }
1772
1774 if (!mrShapeContext.is())
1775 {
1776 // Define the shape context for the whole document
1777 mrShapeContext = new oox::shape::ShapeContextHandler(getDocument()->getShapeFilterBase());
1779 auto pThemePtr = getDocument()->getTheme();
1780 if (pThemePtr)
1781 mrShapeContext->setTheme(pThemePtr);
1782 }
1783
1784 mrShapeContext->setModel(getDocument()->getModel());
1785 uno::Reference<document::XDocumentPropertiesSupplier> xDocSupplier(getDocument()->getModel(), uno::UNO_QUERY_THROW);
1786 mrShapeContext->setDocumentProperties(xDocSupplier->getDocumentProperties());
1787 mrShapeContext->setDrawPage(getDocument()->getDrawPage());
1788 mrShapeContext->setMediaDescriptor(getDocument()->getMediaDescriptor());
1789
1790 mrShapeContext->setRelationFragmentPath(mpParserState->getTarget());
1791
1792 // Floating tables (table inside a textframe) have issues with fullWPG,
1793 // so disable the fullWPGsupport in tables until that issue is not fixed.
1794 mrShapeContext->setFullWPGSupport(!mnTableDepth);
1795
1796 auto xGraphicMapper = getDocument()->getGraphicMapper();
1797
1798 if (xGraphicMapper.is())
1799 mrShapeContext->setGraphicMapper(xGraphicMapper);
1800
1802
1803 if (mrShapeContext.is())
1804 mrShapeContext->pushStartToken(nToken);
1805}
1806
1808{
1809 if ( !mrShapeContext.is() || m_bShapeSent )
1810 return;
1811
1812 awt::Point aPosition = mpStream->getPositionOffset();
1813 mrShapeContext->setPosition(aPosition);
1815 m_bShapeSent = true;
1816 if (!xShape.is())
1817 return;
1818
1820 pValue(new OOXMLShapeValue(xShape));
1821 newProperty(NS_ooxml::LN_shape, pValue);
1822
1823 bool bIsPicture = Element == ( NMSP_dmlPicture | XML_pic );
1824
1825 //tdf#87569: Fix table layout with correcting anchoring
1826 //If anchored object is in table, Word calculates its position from cell border
1827 //instead of page (what is set in the sample document)
1828 uno::Reference<beans::XPropertySet> xShapePropSet(xShape, uno::UNO_QUERY);
1829 if (mnTableDepth > 0 && xShapePropSet.is() && mbIsVMLfound) //if we had a table
1830 {
1831 xShapePropSet->setPropertyValue(dmapper::getPropertyName(dmapper::PROP_FOLLOW_TEXT_FLOW),
1833 }
1834 // Notify the dmapper that the shape is ready to use
1835 if ( !bIsPicture )
1836 {
1837 mpStream->startShape( xShape );
1838 m_bShapeStarted = true;
1839 }
1840}
1841
1843{
1844 return (mrShapeContext->getFullWPGSupport() && mrShapeContext->isWordProcessingGroupShape());
1845};
1846
1848(Token_t Element)
1849{
1850 if (!isForwardEvents())
1851 return;
1852
1853 if (mrShapeContext.is())
1854 {
1855 mrShapeContext->endFastElement(Element);
1856 sendShape( Element );
1857 }
1858
1860
1861 // Ending the shape should be the last thing to do
1862 bool bIsPicture = Element == ( NMSP_dmlPicture | XML_pic );
1863 if ( !bIsPicture && m_bShapeStarted)
1864 mpStream->endShape( );
1865}
1866
1868(const OUString & Namespace,
1869 const OUString & Name)
1870{
1871 if (mrShapeContext.is())
1872 mrShapeContext->endUnknownElement(Namespace, Name);
1873}
1874
1877(Token_t Element,
1879{
1880 // we need to share a single theme across all the shapes, but we parse it
1881 // in ShapeContextHandler. So if it has been parsed there, propagate it to
1882 // the document.
1883 if (mrShapeContext && mrShapeContext->getTheme() && !getDocument()->getTheme())
1884 {
1885 auto pThemePtr = mrShapeContext->getTheme();
1886 getDocument()->setTheme(pThemePtr);
1887 }
1888
1890
1891 bool bGroupShape = Element == Token_t(NMSP_vml | XML_group);
1892 // drawingML version also counts as a group shape.
1893 if (!mrShapeContext->getFullWPGSupport())
1894 bGroupShape |= mrShapeContext->getStartToken() == Token_t(NMSP_wpg | XML_wgp);
1895 mbIsVMLfound = (getNamespace(Element) == NMSP_vmlOffice) || (getNamespace(Element) == NMSP_vml);
1896 switch (oox::getNamespace(Element))
1897 {
1898 case NMSP_doc:
1899 case NMSP_vmlWord:
1900 case NMSP_vmlOffice:
1901 if (!bGroupShape)
1902 xContextHandler.set(OOXMLFactory::createFastChildContextFromStart(this, Element));
1903 [[fallthrough]];
1904 default:
1905 if (!xContextHandler.is())
1906 {
1907 if (mrShapeContext.is())
1908 {
1910 mrShapeContext->createFastChildContext(Element, Attribs);
1911
1914 pChildContext,
1915 this);
1916
1917 //tdf129888 store allowincell attribute of the VML shape
1918 if (Attribs->hasAttribute(NMSP_vmlOffice | XML_allowincell))
1920 = !(Attribs->getValue(NMSP_vmlOffice | XML_allowincell) == "f");
1921
1922 if (!bGroupShape)
1923 {
1924 pWrapper->addNamespace(NMSP_doc);
1925 pWrapper->addNamespace(NMSP_vmlWord);
1926 pWrapper->addNamespace(NMSP_vmlOffice);
1927 pWrapper->addToken( NMSP_vml|XML_textbox );
1928 }
1929 xContextHandler.set(pWrapper);
1930 }
1931 else
1932 xContextHandler.set(this);
1933 }
1934 break;
1935 }
1936
1937 // VML import of shape text is already handled by
1938 // OOXMLFastContextHandlerWrapper::lcl_createFastChildContext(), here we
1939 // handle the WPS import of shape text, as there the parent context is a
1940 // Shape one, so a different situation.
1941 if (Element == static_cast<sal_Int32>(NMSP_wps | XML_txbx) ||
1942 Element == static_cast<sal_Int32>(NMSP_wps | XML_linkedTxbx) )
1943 sendShape(Element);
1944
1945 return xContextHandler;
1946}
1947
1950(const OUString & Namespace,
1951 const OUString & Name,
1953{
1955
1956 if (mrShapeContext.is())
1957 xResult.set(mrShapeContext->createUnknownChildContext
1958 (Namespace, Name, Attribs));
1959
1960 return xResult;
1961}
1962
1964(const OUString & aChars)
1965{
1966 if (mrShapeContext.is())
1967 mrShapeContext->characters(aChars);
1968}
1969
1970/*
1971 class OOXMLFastContextHandlerWrapper
1972*/
1973
1975(OOXMLFastContextHandler * pParent,
1976 uno::Reference<XFastContextHandler> const & xContext,
1978 : OOXMLFastContextHandler(pParent),
1979 mxWrappedContext(xContext),
1980 mxShapeHandler(xShapeHandler)
1981{
1982 setId(pParent->getId());
1983 setToken(pParent->getToken());
1984 setPropertySet(pParent->getPropertySet());
1985}
1986
1988{
1989}
1990
1992(const OUString & Namespace,
1993 const OUString & Name,
1995{
1996 if (mxWrappedContext.is())
1997 mxWrappedContext->startUnknownElement(Namespace, Name, Attribs);
1998}
1999
2001(const OUString & Namespace,
2002 const OUString & Name)
2003{
2004 if (mxWrappedContext.is())
2005 mxWrappedContext->endUnknownElement(Namespace, Name);
2006}
2007
2010(const OUString & Namespace,
2011 const OUString & Name,
2013{
2015
2016 if (mxWrappedContext.is())
2017 xResult = mxWrappedContext->createUnknownChildContext
2018 (Namespace, Name, Attribs);
2019 else
2020 xResult.set(this);
2021
2022 return xResult;
2023}
2024
2027{
2028 if (mxWrappedContext.is())
2029 {
2031 if (pHandler != nullptr)
2032 pHandler->attributes(Attribs);
2033 }
2034}
2035
2038{
2039 return UNKNOWN;
2040}
2041
2043{
2044 mMyNamespaces.insert(nId);
2045}
2046
2048{
2049 mMyTokens.insert( Token );
2050}
2051
2053(Token_t Element,
2055{
2056 if (mxWrappedContext.is())
2057 mxWrappedContext->startFastElement(Element, Attribs);
2058
2059 if (mxShapeHandler->isDMLGroupShape()
2060 && (Element == Token_t(NMSP_wps | XML_txbx)
2061 || Element == Token_t(NMSP_wps | XML_linkedTxbx)))
2062 {
2064 }
2065}
2066
2068(Token_t Element)
2069{
2070 if (mxWrappedContext.is())
2071 mxWrappedContext->endFastElement(Element);
2072
2073 if (mxShapeHandler->isDMLGroupShape()
2074 && (Element == Token_t(NMSP_wps | XML_txbx)
2075 || Element == Token_t(NMSP_wps | XML_linkedTxbx)))
2076 {
2078 }
2079}
2080
2083(Token_t Element,
2085{
2087
2088 bool bInNamespaces = mMyNamespaces.find(oox::getNamespace(Element)) != mMyNamespaces.end();
2089 bool bInTokens = mMyTokens.find( Element ) != mMyTokens.end( );
2090
2091 // We have methods to _add_ individual tokens or whole namespaces to be
2092 // processed by writerfilter (instead of oox), but we have no method to
2093 // filter out a single token. Just hardwire the 'wrap' and 'signatureline' tokens
2094 // here until we need a more generic solution.
2095 bool bIsWrap = Element == static_cast<sal_Int32>(NMSP_vmlWord | XML_wrap);
2096 bool bIsSignatureLine = Element == static_cast<sal_Int32>(NMSP_vmlOffice | XML_signatureline);
2097 bool bSkipImages = getDocument()->IsSkipImages() && oox::getNamespace(Element) == NMSP_dml &&
2098 (oox::getBaseToken(Element) != XML_linkedTxbx) && (oox::getBaseToken(Element) != XML_txbx);
2099
2100 if ( bInNamespaces && ((!bIsWrap && !bIsSignatureLine)
2101 || mxShapeHandler->isShapeSent()) )
2102 {
2103 xResult.set(OOXMLFactory::createFastChildContextFromStart(this, Element));
2104 }
2105 else if (mxWrappedContext.is() && !bSkipImages)
2106 {
2109 (this, mxWrappedContext->createFastChildContext(Element, Attribs),
2111 pWrapper->mMyNamespaces = mMyNamespaces;
2112 pWrapper->mMyTokens = mMyTokens;
2113 pWrapper->setPropertySet(getPropertySet());
2114 xResult.set(pWrapper);
2115 }
2116 else
2117 {
2118 xResult.set(this);
2119 }
2120
2121 if ( bInTokens )
2122 mxShapeHandler->sendShape( Element );
2123
2124 return xResult;
2125}
2126
2128(const OUString & aChars)
2129{
2130 if (mxWrappedContext.is())
2131 mxWrappedContext->characters(aChars);
2132}
2133
2136{
2137 if (mxWrappedContext.is())
2138 return dynamic_cast<OOXMLFastContextHandler *>(mxWrappedContext.get());
2139
2140 return nullptr;
2141}
2142
2144(Id nId, const OOXMLValue::Pointer_t& pVal)
2145{
2146 if (mxWrappedContext.is())
2147 {
2149 if (pHandler != nullptr)
2150 pHandler->newProperty(nId, pVal);
2151 }
2152}
2153
2155(const OOXMLPropertySet::Pointer_t& pPropertySet)
2156{
2157 if (mxWrappedContext.is())
2158 {
2160 if (pHandler != nullptr)
2161 pHandler->setPropertySet(pPropertySet);
2162 }
2163
2164 mpPropertySet = pPropertySet;
2165}
2166
2168 const
2169{
2171
2172 if (mxWrappedContext.is())
2173 {
2175 if (pHandler != nullptr)
2176 pResult = pHandler->getPropertySet();
2177 }
2178
2179 return pResult;
2180}
2181
2183{
2184 std::string sResult = "Wrapper(";
2185
2186 if (mxWrappedContext.is())
2187 {
2189 if (pHandler != nullptr)
2190 sResult += pHandler->getType();
2191 }
2192
2193 sResult += ")";
2194
2195 return sResult;
2196}
2197
2199{
2201
2202 if (mxWrappedContext.is())
2203 {
2205 if (pHandler != nullptr)
2206 pHandler->setId(rId);
2207 }
2208}
2209
2211{
2213
2214 if (mxWrappedContext.is())
2215 {
2217 if (pHandler != nullptr && pHandler->getId() != 0)
2218 nResult = pHandler->getId();
2219 }
2220
2221 return nResult;
2222}
2223
2225{
2227
2228 if (mxWrappedContext.is())
2229 {
2231 if (pHandler != nullptr)
2232 pHandler->setToken(nToken);
2233 }
2234}
2235
2237{
2239
2240 if (mxWrappedContext.is())
2241 {
2243 if (pHandler != nullptr)
2244 nResult = pHandler->getToken();
2245 }
2246
2247 return nResult;
2248}
2249
2250
2251/*
2252 class OOXMLFastContextHandlerLinear
2253 */
2254
2257 , m_depthCount( 0 )
2258{
2259}
2260
2263{
2264 m_buffer.appendOpeningTag( Element, Attribs );
2265 ++m_depthCount;
2266}
2267
2269{
2270 m_buffer.appendClosingTag( Element );
2271 if( --m_depthCount == 0 )
2272 process();
2273}
2274
2278{
2280 xContextHandler.set( this );
2281 return xContextHandler;
2282}
2283
2285{
2286 m_buffer.appendCharacters( aChars );
2287}
2288
2289/*
2290 class OOXMLFastContextHandlerLinear
2291 */
2292
2295{
2296}
2297
2299{
2302 OUString aName;
2304 "DefaultParentBaseURL", getDocument()->GetDocumentBaseURL()) };
2306 container.CreateEmbeddedObject(name.GetByteSequence(), objArgs, aName);
2307 assert(ref.is());
2308 if (!ref.is())
2309 return;
2310 uno::Reference< uno::XInterface > component(ref->getComponent(), uno::UNO_QUERY_THROW);
2311 if( oox::FormulaImExportBase* import
2312 = dynamic_cast< oox::FormulaImExportBase* >( component.get()))
2313 import->readFormulaOoxml( m_buffer );
2314 if (!isForwardEvents())
2315 return;
2316
2318 OOXMLValue::Pointer_t pVal( new OOXMLStarMathValue( ref ));
2319 if (mbIsMathPara)
2320 {
2321 switch (mnMathJcVal)
2322 {
2323 case eMathParaJc::CENTER:
2324 pProps->add(NS_ooxml::LN_Value_math_ST_Jc_centerGroup, pVal,
2326 break;
2327 case eMathParaJc::LEFT:
2328 pProps->add(NS_ooxml::LN_Value_math_ST_Jc_left, pVal,
2330 break;
2331 case eMathParaJc::RIGHT:
2332 pProps->add(NS_ooxml::LN_Value_math_ST_Jc_right, pVal,
2334 break;
2335 default:
2336 break;
2337 }
2338 }
2339 else
2340 pProps->add(NS_ooxml::LN_starmath, pVal, OOXMLProperty::ATTRIBUTE);
2341 mpStream->props( pProps.get() );
2342}
2343
2345 OOXMLFastContextHandler* pContext)
2346 : OOXMLFastContextHandler(pContext)
2347{
2348}
2349
2351{
2353}
2354
2356{
2357 m_sParaId = pValue->getString();
2358}
2359
2361{
2362 if (pValue->getInt())
2363 m_bDone = true;
2364}
2365
2367{
2368 m_sParentId = pValue->getString();
2369}
2370
2371}
2372
2373/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const sal_Unicode uFtnEdnSep
const sal_Unicode uCR
const sal_Unicode uFtnSep
const sal_Unicode uPgNum
const sal_Unicode uFtnEdnRef
const sal_Unicode uSoftHyphen
const sal_uInt8 cFtnEdnCont
const sal_Unicode uNoBreakHyphen
const sal_Unicode uTab
Reference< XComponentContext > m_xContext
css::uno::Reference< css::embed::XEmbeddedObject > CreateEmbeddedObject(const css::uno::Sequence< sal_Int8 > &, OUString &, OUString const *pBaseURL=nullptr)
#define SO3_SM_CLASSID
void appendOpeningTag(int token, const css::uno::Reference< css::xml::sax::XFastAttributeList > &attributes=css::uno::Reference< css::xml::sax::XFastAttributeList >())
void appendCharacters(std::u16string_view characters)
T * get() const
Handler for a stream.
virtual void checkId(const sal_Int32 nId)=0
Receives identifier for node entry.
virtual void endGlossaryEntry()=0
Receives end mark for glossary document entry.
virtual void endParagraphGroup()=0
Receives end mark for group with the same paragraph properties.
virtual void endCharacterGroup()=0
Receives end mark for group with the same character properties.
virtual void props(writerfilter::Reference< Properties >::Pointer_t ref)=0
Receives properties of the current run of text.
virtual void markLastSectionGroup()
The current section is the last one in this body text.
virtual void startGlossaryEntry()=0
Receives start mark for glossary document entry.
virtual void startSectionGroup()=0
Receives start mark for group with the same section properties.
virtual void endTextBoxContent()=0
virtual void endSectionGroup()=0
Receives end mark for group with the same section properties.
virtual void align(const OUString &rText, bool bVertical)=0
Horizontal and vertical alignment for a shape.
virtual void info(const std::string &info)=0
Debugging: Receives information about current point in stream.
virtual void startParagraphGroup()=0
Receives start mark for group with the same paragraph properties.
virtual void text(const sal_uInt8 *data, size_t len)=0
Receives 8-bit per character text.
virtual void startTextBoxContent()=0
Receives a text-box-content.
virtual void positivePercentage(const OUString &rText)=0
virtual void startShape(css::uno::Reference< css::drawing::XShape > const &xShape)=0
Receives a shape.
virtual void startCharacterGroup()=0
Receives start mark for group with the same character properties.
virtual css::awt::Point getPositionOffset()=0
Returns the last set offsets of a shape in HMM.
virtual void markLastParagraphInSection()
virtual void table(Id name, writerfilter::Reference< Table >::Pointer_t ref)=0
Receives table.
virtual void commentProps(const OUString &, const CommentProperties &)
virtual void positionOffset(const OUString &rText, bool bVertical)=0
Offset in EMUs for a shape.
virtual void utext(const sal_uInt8 *data, size_t len)=0
Receives 16-bit per character text.
virtual void endShape()=0
Looks up the stream name for a '<w:altChunk r:id="..."/>' reference.
Definition: Handler.hxx:166
static OOXMLValue::Pointer_t const & Create(bool bValue)
virtual void setShapeContext(rtl::Reference< oox::shape::ShapeContextHandler > xContext) override
virtual rtl::Reference< oox::shape::ShapeContextHandler > getShapeContext() override
void setTheme(const oox::drawingml::ThemePtr &pTheme)
void popShapeContext() override
Pop context of a previously pushed drawingML shape.
virtual const oox::drawingml::ThemePtr & getTheme() const override
const css::uno::Reference< css::graphic::XGraphicMapper > & getGraphicMapper() const
void pushShapeContext() override
Push context of drawingML shapes, so nested shapes are handled separately.
virtual css::uno::Reference< css::io::XInputStream > getInputStreamForId(const OUString &rId)=0
static css::uno::Reference< css::xml::sax::XFastContextHandler > createFastChildContextFromStart(OOXMLFastContextHandler *pHandler, Token_t Element)
static void attributes(OOXMLFastContextHandler *pHandler, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs)
static void characters(OOXMLFastContextHandler *pHandler, const OUString &rString)
static void startAction(OOXMLFastContextHandler *pHandler)
static void endAction(OOXMLFastContextHandler *pHandler)
static css::uno::Reference< css::xml::sax::XFastContextHandler > createFastChildContext(OOXMLFastContextHandler *pHandler, Token_t Element)
void att_paraIdParent(const OOXMLValue::Pointer_t &pValue)
A class that converts from XFastParser/XFastContextHandler usage to a liner XML stream of data.
virtual void lcl_startFastElement(Token_t Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual void lcl_characters(const OUString &aChars) override
virtual void process()=0
Called when the tokens for the element, its content and sub-elements have been linearized and should ...
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > lcl_createFastChildContext(Token_t Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual void lcl_endFastElement(Token_t Element) override
OOXMLFastContextHandlerLinear(OOXMLFastContextHandler *pContext)
OOXMLFastContextHandlerMath(OOXMLFastContextHandler *pContext)
virtual void process() override
Called when the tokens for the element, its content and sub-elements have been linearized and should ...
OOXMLPropertySet::Pointer_t mpPropertySet
the properties
virtual OOXMLValue::Pointer_t getValue() const override
Return value of this context(element).
virtual void setPropertySet(const OOXMLPropertySet::Pointer_t &pPropertySet) override
virtual OOXMLPropertySet::Pointer_t getPropertySet() const override
virtual void newProperty(Id nId, const OOXMLValue::Pointer_t &pVal) override
virtual void SAL_CALL endUnknownElement(const OUString &Namespace, const OUString &Name) override
OOXMLFastContextHandlerShape(OOXMLFastContextHandler *pContext)
virtual void SAL_CALL startUnknownElement(const OUString &Namespace, const OUString &Name, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
rtl::Reference< oox::shape::ShapeContextHandler > mrShapeContext
virtual void lcl_startFastElement(Token_t Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createUnknownChildContext(const OUString &Namespace, const OUString &Name, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual void lcl_characters(const OUString &aChars) override
virtual void lcl_endFastElement(Token_t Element) override
bool m_bShapeContextPushed
Is it necessary to pop the stack in the dtor?
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > lcl_createFastChildContext(Token_t Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual OOXMLPropertySet::Pointer_t getPropertySet() const override
virtual void newProperty(Id aId, const OOXMLValue::Pointer_t &pVal) override
const OOXMLPropertySet::Pointer_t & getPropertySetAttrs() const
OOXMLFastContextHandlerStream(OOXMLFastContextHandler *pContext)
OOXMLFastContextHandlerTable(OOXMLFastContextHandler *pContext)
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
css::uno::Reference< css::xml::sax::XFastContextHandler > mCurrentChild
virtual void lcl_endFastElement(Token_t Element) override
virtual void lcl_startFastElement(Token_t Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual void lcl_endFastElement(Token_t Element) override
OOXMLFastContextHandlerValue(OOXMLFastContextHandler *pContext)
void setValue(const OOXMLValue::Pointer_t &pValue)
virtual OOXMLValue::Pointer_t getValue() const override
Return value of this context(element).
OOXMLFastContextHandlerWrapper wraps an OOXMLFastContextHandler.
rtl::Reference< OOXMLFastContextHandlerShape > mxShapeHandler
virtual void lcl_characters(const OUString &aChars) override
virtual OOXMLPropertySet::Pointer_t getPropertySet() const override
virtual void attributes(const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual void SAL_CALL startUnknownElement(const OUString &Namespace, const OUString &Name, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual std::string getType() const override
Returns a string describing the type of the context.
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createUnknownChildContext(const OUString &Namespace, const OUString &Name, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > lcl_createFastChildContext(Token_t Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual void newProperty(Id nId, const OOXMLValue::Pointer_t &pVal) override
virtual void SAL_CALL endUnknownElement(const OUString &Namespace, const OUString &Name) override
virtual void lcl_endFastElement(Token_t Element) override
OOXMLFastContextHandlerWrapper(OOXMLFastContextHandler *pParent, css::uno::Reference< css::xml::sax::XFastContextHandler > const &xContext, rtl::Reference< OOXMLFastContextHandlerShape > const &xShapeHandler)
virtual void lcl_startFastElement(Token_t Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
css::uno::Reference< css::xml::sax::XFastContextHandler > mxWrappedContext
virtual void setPropertySet(const OOXMLPropertySet::Pointer_t &pPropertySet) override
void checkType(const OOXMLValue::Pointer_t &pValue)
OOXMLFastContextHandlerXNote(OOXMLFastContextHandler *pContext)
virtual void lcl_startFastElement(Token_t Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual void lcl_endFastElement(Token_t Element) override
void checkId(const OOXMLValue::Pointer_t &pValue)
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual void setPropertySet(const OOXMLPropertySet::Pointer_t &pPropertySet)
virtual void SAL_CALL characters(const OUString &aChars) override
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createUnknownChildContext(const OUString &Namespace, const OUString &Name, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > lcl_createFastChildContext(Token_t Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs)
void resolveHeader(const sal_Int32 type, const OUString &rId)
virtual void newProperty(Id aId, const OOXMLValue::Pointer_t &pVal)
virtual void SAL_CALL startFastElement(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override final
virtual OOXMLValue::Pointer_t getValue() const
Return value of this context(element).
virtual void SAL_CALL startUnknownElement(const OUString &Namespace, const OUString &Name, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
virtual void SAL_CALL endUnknownElement(const OUString &Namespace, const OUString &Name) override
virtual void lcl_characters(const OUString &aChars)
bool m_bTookChoice
Did we take the Choice or want Fallback instead?
virtual void attributes(const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs)
virtual void SAL_CALL endFastElement(sal_Int32 Element) override
void resolveFooter(const sal_Int32 type, const OUString &rId)
virtual OOXMLPropertySet::Pointer_t getPropertySet() const
bool prepareMceContext(Token_t nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs)
Handles AlternateContent. Returns true, if children of the current element should be ignored.
void setXNoteId(const OOXMLValue::Pointer_t &pValue)
virtual void lcl_startFastElement(Token_t Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs)
virtual std::string getType() const
Returns a string describing the type of the context.
OOXMLFastContextHandler(css::uno::Reference< css::uno::XComponentContext > const &context)
static OOXMLValue::Pointer_t Create(sal_Int32 nValue)
tools::SvRef< OOXMLPropertySet > Pointer_t
void add(const ValuePointer_t &pPropertySet)
tools::SvRef< OOXMLValue > Pointer_t
RegionData_Impl * mpParent
float u
const char * name
OUString aName
void * p
uno_Any a
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
Any SAL_CALL getCaughtException()
int i
OUString getPropertyName(PropertyIds eId)
sal_Int32 Token_t
const sal_uInt8 cFieldSep
const sal_uInt8 cFieldStart
const sal_uInt8 cFieldEnd
const sal_uInt8 cFieldLock
sal_Int16 nId
DefTokenId nToken
sal_uInt32 Id
Struct to store our 'alternate state'.
bool m_bTookChoice
Did we take the Choice or want Fallback instead?
OUString Name
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
ResultType type