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 <memory>
21 #include <optional>
22 #include <tuple>
23 #include <vector>
24 
25 #include <com/sun/star/container/XEnumerationAccess.hpp>
26 #include <com/sun/star/frame/XModel.hpp>
27 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
29 #include <com/sun/star/text/ReferenceFieldSource.hpp>
30 #include <com/sun/star/text/XChapterNumberingSupplier.hpp>
31 #include <com/sun/star/text/XTextFrame.hpp>
32 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
33 #include <com/sun/star/text/XTextFramesSupplier.hpp>
34 #include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
35 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
36 #include <com/sun/star/text/XFormField.hpp>
37 #include <com/sun/star/ucb/XAnyCompareFactory.hpp>
38 #include <com/sun/star/container/XNamed.hpp>
39 #include <com/sun/star/style/XStyle.hpp>
40 #include <xmloff/xmlnamespace.hxx>
41 #include <xmloff/txtstyli.hxx>
42 #include <xmloff/xmlnumi.hxx>
43 #include <xmloff/maptype.hxx>
44 
45 #include <sal/log.hxx>
46 #include "txtparai.hxx"
47 #include <xmloff/txtprmap.hxx>
48 #include <xmloff/txtimppr.hxx>
49 #include <xmloff/xmlimp.hxx>
50 #include <txtvfldi.hxx>
51 #include <xmloff/i18nmap.hxx>
52 #include "XMLTextListItemContext.hxx"
53 #include "XMLTextListBlockContext.hxx"
54 #include "XMLTextFrameContext.hxx"
55 #include "XMLTextFrameHyperlinkContext.hxx"
56 #include "XMLSectionImportContext.hxx"
57 #include "XMLIndexTOCContext.hxx"
58 #include <xmloff/XMLEventsImportContext.hxx>
59 #include "XMLTrackedChangesImportContext.hxx"
60 #include "XMLChangeImportContext.hxx"
61 #include "XMLAutoMarkFileContext.hxx"
62 #include <xmloff/ProgressBarHelper.hxx>
63 
64 #include "XMLCalculationSettingsContext.hxx"
65 #include <XMLNumberStylesImport.hxx>
66 #include <PageMasterStyleMap.hxx>
67 #include <PageMasterPropHdlFactory.hxx>
68 #include <PageMasterPropMapper.hxx>
69 // XML import: reconstruction of assignment of paragraph style to outline levels (#i69629#)
70 #include <com/sun/star/beans/XPropertyState.hpp>
71 #include <txtlists.hxx>
72 #include <xmloff/odffields.hxx>
73 #include <comphelper/attributelist.hxx>
74 
75 using ::com::sun::star::ucb::XAnyCompare;
76 
77 using namespace ::std;
78 using namespace ::com::sun::star;
79 using namespace ::com::sun::star::uno;
80 using namespace ::com::sun::star::beans;
81 using namespace ::com::sun::star::text;
82 using namespace ::com::sun::star::frame;
83 using namespace ::com::sun::star::style;
84 using namespace ::com::sun::star::container;
85 using namespace ::com::sun::star::drawing;
86 using namespace ::com::sun::star::xml::sax;
87 using namespace ::com::sun::star::lang;
88 using namespace ::xmloff::token;
89 using namespace ::com::sun::star::ucb;
90 
91 
92 // maximum allowed length of combined characters field
93 #define MAX_COMBINED_CHARACTERS 6
94 
95 struct XMLTextImportHelper::Impl
96 {
97     std::optional< std::vector<OUString> > m_xPrevFrmNames;
98     std::optional< std::vector<OUString> > m_xNextFrmNames;
99     std::unique_ptr<XMLTextListsHelper> m_xTextListsHelper;
100 
101     rtl::Reference<SvXMLStylesContext> m_xAutoStyles;
102 
103     rtl::Reference< SvXMLImportPropertyMapper > m_xParaImpPrMap;
104     rtl::Reference< SvXMLImportPropertyMapper > m_xTextImpPrMap;
105     rtl::Reference< SvXMLImportPropertyMapper > m_xFrameImpPrMap;
106     rtl::Reference< SvXMLImportPropertyMapper > m_xSectionImpPrMap;
107     rtl::Reference< SvXMLImportPropertyMapper > m_xRubyImpPrMap;
108 
109     std::unique_ptr<SvI18NMap> m_xRenameMap;
110 
111     /* Change and extend data structure:
112        - data structure contains candidates of paragraph styles, which
113          will be assigned to the outline style
114        - data structure contains more than one candidate for each list level
115          of the outline style (#i69629#)
116     */
117     std::unique_ptr< std::vector< OUString > []>
118         m_xOutlineStylesCandidates;
119 
120     // start range, xml:id, RDFa stuff
121     typedef std::tuple<
122         uno::Reference<text::XTextRange>, OUString,
123         std::shared_ptr< ::xmloff::ParsedRDFaAttributes > >
124             BookmarkMapEntry_t;
125     /// start ranges for open bookmarks
126     std::map< OUString, BookmarkMapEntry_t > m_BookmarkStartRanges;
127 
128     std::vector< OUString > m_BookmarkVector;
129 
130     /// name of the last 'open' redline that started between paragraphs
131     OUString m_sOpenRedlineIdentifier;
132 
133     // Used for frame deduplication, the name of the last frame imported directly before the current one
134     OUString msLastImportedFrameName;
135 
136     std::map< OUString, bool > m_bBookmarkHidden;
137     std::map< OUString, OUString > m_sBookmarkCondition;
138 
139     uno::Reference<text::XText> m_xText;
140     uno::Reference<text::XTextCursor> m_xCursor;
141     uno::Reference<text::XTextRange> m_xCursorAsRange;
142     uno::Reference<container::XNameContainer> m_xParaStyles;
143     uno::Reference<container::XNameContainer> m_xTextStyles;
144     uno::Reference<container::XNameContainer> m_xNumStyles;
145     uno::Reference<container::XNameContainer> m_xFrameStyles;
146     uno::Reference<container::XNameContainer> m_xPageStyles;
147     uno::Reference<container::XNameContainer> m_xCellStyles;
148     uno::Reference<container::XIndexReplace> m_xChapterNumbering;
149     uno::Reference<container::XNameAccess> m_xTextFrames;
150     uno::Reference<container::XNameAccess> m_xGraphics;
151     uno::Reference<container::XNameAccess> m_xObjects;
152     uno::Reference<lang::XMultiServiceFactory> m_xServiceFactory;
153 
154     SvXMLImport & m_rSvXMLImport;
155 
156     bool m_bInsertMode : 1;
157     bool m_bStylesOnlyMode : 1;
158     bool m_bBlockMode : 1;
159     bool m_bProgress : 1;
160     bool m_bOrganizerMode : 1;
161     bool m_bBodyContentStarted : 1;
162 
163     /// Are we inside a <text:deletion> element (deleted redline section)
164     bool m_bInsideDeleteContext : 1;
165 
166     typedef ::std::pair< OUString, OUString> field_name_type_t;
167     typedef ::std::pair< OUString, OUString > field_param_t;
168     typedef ::std::vector< field_param_t > field_params_t;
169     typedef ::std::tuple<field_name_type_t, field_params_t, uno::Reference<text::XFormField>> field_stack_item_t;
170     typedef ::std::stack< field_stack_item_t > field_stack_t;
171 
172     field_stack_t m_FieldStack;
173 
174     OUString m_sCellParaStyleDefault;
175 
176     std::optional<std::map<OUString, OUString>> m_xCrossRefHeadingBookmarkMap;
177 
ImplXMLTextImportHelper::Impl178     Impl(       uno::Reference<frame::XModel> const& rModel,
179                 SvXMLImport & rImport,
180                 bool const bInsertMode, bool const bStylesOnlyMode,
181                 bool const bProgress, bool const bBlockMode,
182                 bool const bOrganizerMode)
183         :   m_xTextListsHelper( new XMLTextListsHelper() )
184         // XML import: reconstruction of assignment of paragraph style to outline levels (#i69629#)
185         ,   m_xServiceFactory( rModel, UNO_QUERY )
186         ,   m_rSvXMLImport( rImport )
187         ,   m_bInsertMode( bInsertMode )
188         ,   m_bStylesOnlyMode( bStylesOnlyMode )
189         ,   m_bBlockMode( bBlockMode )
190         ,   m_bProgress( bProgress )
191         ,   m_bOrganizerMode( bOrganizerMode )
192         ,   m_bBodyContentStarted( true )
193         ,   m_bInsideDeleteContext( false )
194     {
195     }
196     Impl(const Impl&) = delete;
197     Impl& operator=(const Impl&) = delete;
198 
InitOutlineStylesCandidatesXMLTextImportHelper::Impl199     void InitOutlineStylesCandidates()
200     {
201         if (!m_xOutlineStylesCandidates)
202         {
203             size_t const size(m_xChapterNumbering->getCount());
204             m_xOutlineStylesCandidates.reset(
205                 new ::std::vector< OUString >[size] );
206         }
207     }
208 
209 };
210 
211 
GetText()212 uno::Reference< text::XText > & XMLTextImportHelper::GetText()
213 {
214     return m_xImpl->m_xText;
215 }
216 
GetCursor()217 uno::Reference< text::XTextCursor > & XMLTextImportHelper::GetCursor()
218 {
219     return m_xImpl->m_xCursor;
220 }
221 
GetCursorAsRange()222 uno::Reference< text::XTextRange > & XMLTextImportHelper::GetCursorAsRange()
223 {
224     return m_xImpl->m_xCursorAsRange;
225 }
226 
IsInsertMode() const227 bool XMLTextImportHelper::IsInsertMode() const
228 {
229     return m_xImpl->m_bInsertMode;
230 }
231 
IsStylesOnlyMode() const232 bool XMLTextImportHelper::IsStylesOnlyMode() const
233 {
234     return m_xImpl->m_bStylesOnlyMode;
235 }
236 
IsBlockMode() const237 bool XMLTextImportHelper::IsBlockMode() const
238 {
239     return m_xImpl->m_bBlockMode;
240 }
241 
IsOrganizerMode() const242 bool XMLTextImportHelper::IsOrganizerMode() const
243 {
244     return m_xImpl->m_bOrganizerMode;
245 }
246 
IsProgress() const247 bool XMLTextImportHelper::IsProgress() const
248 {
249     return m_xImpl->m_bProgress;
250 }
251 
252 uno::Reference<container::XNameContainer> const&
GetParaStyles() const253 XMLTextImportHelper::GetParaStyles() const
254 {
255     return m_xImpl->m_xParaStyles;
256 }
257 
258 uno::Reference<container::XNameContainer> const&
GetTextStyles() const259 XMLTextImportHelper::GetTextStyles() const
260 {
261     return m_xImpl->m_xTextStyles;
262 }
263 
264 uno::Reference<container::XNameContainer> const&
GetNumberingStyles() const265 XMLTextImportHelper::GetNumberingStyles() const
266 {
267     return m_xImpl->m_xNumStyles;
268 }
269 
270 uno::Reference<container::XNameContainer> const&
GetFrameStyles() const271 XMLTextImportHelper::GetFrameStyles() const
272 {
273     return m_xImpl->m_xFrameStyles;
274 }
275 
276 uno::Reference<container::XNameContainer> const&
GetPageStyles() const277 XMLTextImportHelper::GetPageStyles() const
278 {
279     return m_xImpl->m_xPageStyles;
280 }
281 
282 uno::Reference<container::XNameContainer> const&
GetCellStyles() const283 XMLTextImportHelper::GetCellStyles() const
284 {
285     return m_xImpl->m_xCellStyles;
286 }
287 
288 uno::Reference<container::XIndexReplace> const&
GetChapterNumbering() const289 XMLTextImportHelper::GetChapterNumbering() const
290 {
291     return m_xImpl->m_xChapterNumbering;
292 }
293 
294 rtl::Reference< SvXMLImportPropertyMapper > const&
GetParaImportPropertySetMapper() const295 XMLTextImportHelper::GetParaImportPropertySetMapper() const
296 {
297     return m_xImpl->m_xParaImpPrMap;
298 }
299 
300 rtl::Reference< SvXMLImportPropertyMapper > const&
GetTextImportPropertySetMapper() const301 XMLTextImportHelper::GetTextImportPropertySetMapper() const
302 {
303     return m_xImpl->m_xTextImpPrMap;
304 }
305 
306 rtl::Reference< SvXMLImportPropertyMapper > const&
GetSectionImportPropertySetMapper() const307 XMLTextImportHelper::GetSectionImportPropertySetMapper() const
308 {
309     return m_xImpl->m_xSectionImpPrMap;
310 }
311 
312 rtl::Reference< SvXMLImportPropertyMapper > const&
GetRubyImportPropertySetMapper() const313 XMLTextImportHelper::GetRubyImportPropertySetMapper() const
314 {
315     return m_xImpl->m_xRubyImpPrMap;
316 }
317 
SetInsideDeleteContext(bool const bNew)318 void XMLTextImportHelper::SetInsideDeleteContext(bool const bNew)
319 {
320     m_xImpl->m_bInsideDeleteContext = bNew;
321 }
322 
IsInsideDeleteContext() const323 bool XMLTextImportHelper::IsInsideDeleteContext() const
324 {
325     return m_xImpl->m_bInsideDeleteContext;
326 }
327 
GetXMLImport()328 SvXMLImport & XMLTextImportHelper::GetXMLImport()
329 {
330     return m_xImpl->m_rSvXMLImport;
331 }
332 
GetTextListHelper()333 XMLTextListsHelper & XMLTextImportHelper::GetTextListHelper()
334 {
335     return *m_xImpl->m_xTextListsHelper;
336 }
337 
338 namespace
339 {
340     class FieldParamImporter
341     {
342         public:
343             typedef pair<OUString,OUString> field_param_t;
344             typedef vector<field_param_t> field_params_t;
FieldParamImporter(const field_params_t * const pInParams,Reference<XNameContainer> const & xOutParams)345             FieldParamImporter(const field_params_t* const pInParams, Reference<XNameContainer> const & xOutParams)
346                 : m_pInParams(pInParams)
347                 , m_xOutParams(xOutParams)
348             { };
349             void Import();
350 
351         private:
352             const field_params_t* const m_pInParams;
353             Reference<XNameContainer> m_xOutParams;
354     };
355 
Import()356     void FieldParamImporter::Import()
357     {
358         ::std::vector<OUString> vListEntries;
359         ::std::map<OUString, Any> vOutParams;
360         for(const auto& rCurrent : *m_pInParams)
361         {
362             if(rCurrent.first == ODF_FORMDROPDOWN_RESULT)
363             {
364                 // sal_Int32
365                 vOutParams[rCurrent.first] <<= rCurrent.second.toInt32();
366             }
367             else if(rCurrent.first == ODF_FORMCHECKBOX_RESULT)
368             {
369                 // bool
370                 vOutParams[rCurrent.first] <<= rCurrent.second.toBoolean();
371             }
372             else if(rCurrent.first == ODF_FORMDROPDOWN_LISTENTRY)
373             {
374                 // sequence
375                 vListEntries.push_back(rCurrent.second);
376             }
377             else
378                 vOutParams[rCurrent.first] <<= rCurrent.second;
379         }
380         if(!vListEntries.empty())
381         {
382             Sequence<OUString> vListEntriesSeq(vListEntries.size());
383             copy(vListEntries.begin(), vListEntries.end(), vListEntriesSeq.begin());
384             vOutParams[OUString(ODF_FORMDROPDOWN_LISTENTRY)] <<= vListEntriesSeq;
385         }
386         for(const auto& rCurrent : vOutParams)
387         {
388             try
389             {
390                 m_xOutParams->insertByName(rCurrent.first, rCurrent.second);
391             }
392             catch(const ElementExistException&)
393             {
394                 SAL_INFO("xmloff.text", "duplicate fieldmark param");
395             }
396         }
397     }
398 }
399 
XMLTextImportHelper(uno::Reference<frame::XModel> const & rModel,SvXMLImport & rImport,bool const bInsertMode,bool const bStylesOnlyMode,bool const bProgress,bool const bBlockMode,bool const bOrganizerMode)400 XMLTextImportHelper::XMLTextImportHelper(
401         uno::Reference<frame::XModel> const& rModel,
402         SvXMLImport& rImport,
403         bool const bInsertMode, bool const bStylesOnlyMode,
404         bool const bProgress, bool const bBlockMode,
405         bool const bOrganizerMode)
406     : m_xImpl( new Impl(rModel, rImport, bInsertMode, bStylesOnlyMode,
407                     bProgress, bBlockMode, bOrganizerMode) )
408     , m_xBackpatcherImpl( MakeBackpatcherImpl() )
409 {
410     static constexpr OUStringLiteral s_PropNameDefaultListId = u"DefaultListId";
411 
412     Reference< XChapterNumberingSupplier > xCNSupplier( rModel, UNO_QUERY );
413 
414     if (xCNSupplier.is())
415     {
416         // note: m_xChapterNumbering is accessed to import some fields
417         m_xImpl->m_xChapterNumbering = xCNSupplier->getChapterNumberingRules();
418         // the AutoCorrect document doesn't have a proper outline numbering
419         if (!IsBlockMode() && m_xImpl->m_xChapterNumbering.is())
420         {
421             Reference< XPropertySet > const xNumRuleProps(
422                 m_xImpl->m_xChapterNumbering, UNO_QUERY);
423             if ( xNumRuleProps.is() )
424             {
425                 Reference< XPropertySetInfo > xNumRulePropSetInfo(
426                                             xNumRuleProps->getPropertySetInfo());
427                 if (xNumRulePropSetInfo.is() &&
428                     xNumRulePropSetInfo->hasPropertyByName(
429                          s_PropNameDefaultListId))
430                 {
431                     OUString sListId;
432                     xNumRuleProps->getPropertyValue(s_PropNameDefaultListId)
433                         >>= sListId;
434                     assert( !sListId.isEmpty() &&
435                                 "no default list id found at chapter numbering rules instance. Serious defect." );
436                     if ( !sListId.isEmpty() )
437                     {
438                         Reference< XNamed > const xChapterNumNamed(
439                             m_xImpl->m_xChapterNumbering, UNO_QUERY);
440                         if ( xChapterNumNamed.is() )
441                         {
442                             m_xImpl->m_xTextListsHelper->KeepListAsProcessed(
443                                                     sListId,
444                                                     xChapterNumNamed->getName(),
445                                                     OUString() );
446                         }
447                     }
448                 }
449             }
450         }
451     }
452 
453     Reference< XStyleFamiliesSupplier > xFamiliesSupp( rModel, UNO_QUERY );
454 //  SAL_WARN_IF( !xFamiliesSupp.is(), "xmloff", "no chapter numbering supplier" ); for clipboard there may be documents without styles
455 
456     if( xFamiliesSupp.is() )
457     {
458         Reference< XNameAccess > xFamilies(xFamiliesSupp->getStyleFamilies());
459 
460         static const OUStringLiteral aParaStyles(u"ParagraphStyles");
461         if( xFamilies->hasByName( aParaStyles ) )
462         {
463             m_xImpl->m_xParaStyles.set(xFamilies->getByName(aParaStyles),
464                 UNO_QUERY);
465         }
466 
467         static const OUStringLiteral aCharStyles(u"CharacterStyles");
468         if( xFamilies->hasByName( aCharStyles ) )
469         {
470             m_xImpl->m_xTextStyles.set(xFamilies->getByName(aCharStyles),
471                 UNO_QUERY);
472         }
473 
474         static const OUStringLiteral aNumStyles(u"NumberingStyles");
475         if( xFamilies->hasByName( aNumStyles ) )
476         {
477             m_xImpl->m_xNumStyles.set(xFamilies->getByName(aNumStyles),
478                 UNO_QUERY);
479         }
480 
481         static const OUStringLiteral aFrameStyles(u"FrameStyles");
482         if( xFamilies->hasByName( aFrameStyles ) )
483         {
484             m_xImpl->m_xFrameStyles.set(xFamilies->getByName(aFrameStyles),
485                 UNO_QUERY);
486         }
487 
488         static const OUStringLiteral aPageStyles(u"PageStyles");
489         if( xFamilies->hasByName( aPageStyles ) )
490         {
491             m_xImpl->m_xPageStyles.set(xFamilies->getByName(aPageStyles),
492                 UNO_QUERY);
493         }
494 
495         static const OUStringLiteral aCellStyles(u"CellStyles");
496         if( xFamilies->hasByName( aCellStyles ) )
497         {
498             m_xImpl->m_xCellStyles.set(xFamilies->getByName(aCellStyles),
499                 UNO_QUERY);
500         }
501     }
502 
503     Reference < XTextFramesSupplier > xTFS( rModel, UNO_QUERY );
504     if( xTFS.is() )
505     {
506         m_xImpl->m_xTextFrames.set(xTFS->getTextFrames());
507     }
508 
509     Reference < XTextGraphicObjectsSupplier > xTGOS( rModel, UNO_QUERY );
510     if( xTGOS.is() )
511     {
512         m_xImpl->m_xGraphics.set(xTGOS->getGraphicObjects());
513     }
514 
515     Reference < XTextEmbeddedObjectsSupplier > xTEOS( rModel, UNO_QUERY );
516     if( xTEOS.is() )
517     {
518         m_xImpl->m_xObjects.set(xTEOS->getEmbeddedObjects());
519     }
520 
521     XMLPropertySetMapper *pPropMapper =
522             new XMLTextPropertySetMapper( TextPropMap::PARA, false );
523     m_xImpl->m_xParaImpPrMap =
524         new XMLTextImportPropertyMapper( pPropMapper, rImport );
525 
526     pPropMapper = new XMLTextPropertySetMapper( TextPropMap::TEXT, false );
527     m_xImpl->m_xTextImpPrMap =
528         new XMLTextImportPropertyMapper( pPropMapper, rImport );
529 
530     pPropMapper = new XMLTextPropertySetMapper( TextPropMap::FRAME, false );
531     m_xImpl->m_xFrameImpPrMap =
532         new XMLTextImportPropertyMapper( pPropMapper, rImport );
533 
534     pPropMapper = new XMLTextPropertySetMapper( TextPropMap::SECTION, false );
535     m_xImpl->m_xSectionImpPrMap =
536         new XMLTextImportPropertyMapper( pPropMapper, rImport );
537 
538     pPropMapper = new XMLTextPropertySetMapper( TextPropMap::RUBY, false );
539     m_xImpl->m_xRubyImpPrMap =
540         new SvXMLImportPropertyMapper( pPropMapper, rImport );
541 }
542 
~XMLTextImportHelper()543 XMLTextImportHelper::~XMLTextImportHelper()
544 {
545 }
546 
dispose()547 void XMLTextImportHelper::dispose()
548 {
549     if (m_xImpl->m_xAutoStyles)
550         m_xImpl->m_xAutoStyles->dispose();
551 }
552 
CreateShapeExtPropMapper(SvXMLImport & rImport)553 SvXMLImportPropertyMapper *XMLTextImportHelper::CreateShapeExtPropMapper(SvXMLImport& rImport)
554 {
555     XMLPropertySetMapper *pPropMapper =
556         new XMLTextPropertySetMapper( TextPropMap::FRAME, false );
557     return new XMLTextImportPropertyMapper( pPropMapper, rImport );
558 }
559 
CreateParaExtPropMapper(SvXMLImport & rImport)560 SvXMLImportPropertyMapper *XMLTextImportHelper::CreateParaExtPropMapper(SvXMLImport& rImport)
561 {
562     XMLPropertySetMapper *pPropMapper =
563         new XMLTextPropertySetMapper( TextPropMap::SHAPE_PARA, false );
564     return new XMLTextImportPropertyMapper( pPropMapper, rImport );
565 }
566 
CreateParaDefaultExtPropMapper(SvXMLImport & rImport)567 SvXMLImportPropertyMapper *XMLTextImportHelper::CreateParaDefaultExtPropMapper(SvXMLImport& rImport)
568 {
569     XMLPropertySetMapper* pPropMapper =
570         new XMLTextPropertySetMapper( TextPropMap::SHAPE_PARA, false );
571     SvXMLImportPropertyMapper* pImportMapper = new XMLTextImportPropertyMapper( pPropMapper, rImport );
572 
573     pPropMapper =
574         new XMLTextPropertySetMapper( TextPropMap::TEXT_ADDITIONAL_DEFAULTS, false );
575     pImportMapper->ChainImportMapper( new XMLTextImportPropertyMapper( pPropMapper, rImport ) );
576 
577     return pImportMapper;
578 }
579 
580 SvXMLImportPropertyMapper*
CreateTableDefaultExtPropMapper(SvXMLImport & rImport)581     XMLTextImportHelper::CreateTableDefaultExtPropMapper(
582         SvXMLImport& rImport )
583 {
584     XMLPropertySetMapper *pPropMapper =
585         new XMLTextPropertySetMapper( TextPropMap::TABLE_DEFAULTS, false );
586     return new SvXMLImportPropertyMapper( pPropMapper, rImport );
587 }
588 
589 SvXMLImportPropertyMapper*
CreateTableRowDefaultExtPropMapper(SvXMLImport & rImport)590     XMLTextImportHelper::CreateTableRowDefaultExtPropMapper(
591         SvXMLImport& rImport )
592 {
593     XMLPropertySetMapper *pPropMapper =
594         new XMLTextPropertySetMapper( TextPropMap::TABLE_ROW_DEFAULTS, false );
595     return new SvXMLImportPropertyMapper( pPropMapper, rImport );
596 }
597 
598 SvXMLImportPropertyMapper*
CreateTableCellExtPropMapper(SvXMLImport & rImport)599     XMLTextImportHelper::CreateTableCellExtPropMapper(
600         SvXMLImport& rImport )
601 {
602     XMLPropertySetMapper *pPropMapper =
603         new XMLTextPropertySetMapper( TextPropMap::CELL, false );
604     return new XMLTextImportPropertyMapper( pPropMapper, rImport );
605 }
606 
607 SvXMLImportPropertyMapper*
CreateDrawingPageExtPropMapper(SvXMLImport & rImport)608 XMLTextImportHelper::CreateDrawingPageExtPropMapper(SvXMLImport& rImport)
609 {
610     rtl::Reference<XMLPropertyHandlerFactory> const pFactory(new XMLPageMasterPropHdlFactory);
611     XMLPropertySetMapper *const pPropMapper(
612         new XMLPropertySetMapper(g_XMLPageMasterDrawingPageStyleMap, pFactory, false));
613     return new SvXMLImportPropertyMapper(pPropMapper, rImport);
614 }
615 
SetCursor(const Reference<XTextCursor> & rCursor)616 void XMLTextImportHelper::SetCursor( const Reference < XTextCursor > & rCursor )
617 {
618     m_xImpl->m_xCursor.set(rCursor);
619     m_xImpl->m_xText.set(rCursor->getText());
620     m_xImpl->m_xCursorAsRange = rCursor;
621 }
622 
ResetCursor()623 void XMLTextImportHelper::ResetCursor()
624 {
625     m_xImpl->m_xCursor.set(nullptr);
626     m_xImpl->m_xText.set(nullptr);
627     m_xImpl->m_xCursorAsRange.set(nullptr);
628 }
629 
630 
HasFrameByName(const OUString & rName) const631 bool XMLTextImportHelper::HasFrameByName( const OUString& rName ) const
632 {
633     return (m_xImpl->m_xTextFrames.is() &&
634             m_xImpl->m_xTextFrames->hasByName(rName))
635         || (m_xImpl->m_xGraphics.is() &&
636             m_xImpl->m_xGraphics->hasByName(rName))
637         || (m_xImpl->m_xObjects.is() &&
638             m_xImpl->m_xObjects->hasByName(rName));
639 }
640 
IsDuplicateFrame(const OUString & sName,sal_Int32 nX,sal_Int32 nY,sal_Int32 nWidth,sal_Int32 nHeight) const641 bool XMLTextImportHelper::IsDuplicateFrame(const OUString& sName, sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight) const
642 {
643     if (HasFrameByName(sName))
644     {
645         uno::Reference<beans::XPropertySet> xOtherFrame;
646         if(m_xImpl->m_xTextFrames.is() && m_xImpl->m_xTextFrames->hasByName(sName))
647             xOtherFrame.set(m_xImpl->m_xTextFrames->getByName(sName), uno::UNO_QUERY);
648         else if(m_xImpl->m_xGraphics.is() && m_xImpl->m_xGraphics->hasByName(sName))
649             xOtherFrame.set(m_xImpl->m_xGraphics->getByName(sName), uno::UNO_QUERY);
650         else if (m_xImpl->m_xObjects.is() && m_xImpl->m_xObjects->hasByName(sName))
651             xOtherFrame.set(m_xImpl->m_xObjects->getByName(sName), uno::UNO_QUERY);
652 
653         Reference< XPropertySetInfo > xPropSetInfo = xOtherFrame->getPropertySetInfo();
654         if(xPropSetInfo->hasPropertyByName("Width"))
655         {
656             sal_Int32 nOtherWidth = 0;
657             xOtherFrame->getPropertyValue("Width") >>= nOtherWidth;
658             if(nWidth != nOtherWidth)
659                 return false;
660         }
661 
662         if (xPropSetInfo->hasPropertyByName("Height"))
663         {
664             sal_Int32 nOtherHeight = 0;
665             xOtherFrame->getPropertyValue("Height") >>= nOtherHeight;
666             if (nHeight != nOtherHeight)
667                 return false;
668         }
669 
670         if (xPropSetInfo->hasPropertyByName("HoriOrientPosition"))
671         {
672             sal_Int32 nOtherX = 0;
673             xOtherFrame->getPropertyValue("HoriOrientPosition") >>= nOtherX;
674             if (nX != nOtherX)
675                 return false;
676         }
677 
678         if (xPropSetInfo->hasPropertyByName("VertOrientPosition"))
679         {
680             sal_Int32 nOtherY = 0;
681             xOtherFrame->getPropertyValue("VertOrientPosition") >>= nOtherY;
682             if (nY != nOtherY)
683                 return false;
684         }
685 
686         // In some case, position is not defined for frames, so check whether the two frames follow each other (are anchored to the same position)
687         return m_xImpl->msLastImportedFrameName == sName;
688     }
689     return false;
690 }
691 
StoreLastImportedFrameName(const OUString & rName)692 void XMLTextImportHelper::StoreLastImportedFrameName(const OUString& rName)
693 {
694     m_xImpl->msLastImportedFrameName = rName;
695 }
696 
ClearLastImportedTextFrameName()697 void XMLTextImportHelper::ClearLastImportedTextFrameName()
698 {
699     m_xImpl->msLastImportedFrameName.clear();
700 }
701 
InsertString(const OUString & rChars)702 void XMLTextImportHelper::InsertString( const OUString& rChars )
703 {
704     assert(m_xImpl->m_xText.is());
705     assert(m_xImpl->m_xCursorAsRange.is());
706     if (m_xImpl->m_xText.is())
707     {
708         m_xImpl->m_xText->insertString(m_xImpl->m_xCursorAsRange,
709             rChars, false);
710     }
711 }
712 
InsertString(const OUString & rChars,bool & rIgnoreLeadingSpace)713 void XMLTextImportHelper::InsertString( const OUString& rChars,
714                                         bool& rIgnoreLeadingSpace )
715 {
716     assert(m_xImpl->m_xText.is());
717     assert(m_xImpl->m_xCursorAsRange.is());
718     if (m_xImpl->m_xText.is())
719     {
720         sal_Int32 nLen = rChars.getLength();
721         OUStringBuffer sChars( nLen );
722 
723         for( sal_Int32 i=0; i < nLen; i++ )
724         {
725             sal_Unicode c = rChars[i];
726             switch( c )
727             {
728                 case 0x20:
729                 case 0x09:
730                 case 0x0a:
731                 case 0x0d:
732                     if( !rIgnoreLeadingSpace )
733                         sChars.append( u' ' );
734                     rIgnoreLeadingSpace = true;
735                     break;
736                 default:
737                     rIgnoreLeadingSpace = false;
738                     sChars.append( c );
739                     break;
740             }
741         }
742         m_xImpl->m_xText->insertString(m_xImpl->m_xCursorAsRange,
743                                        sChars.makeStringAndClear(), false);
744     }
745 }
746 
InsertControlCharacter(sal_Int16 nControl)747 void XMLTextImportHelper::InsertControlCharacter( sal_Int16 nControl )
748 {
749     assert(m_xImpl->m_xText.is());
750     assert(m_xImpl->m_xCursorAsRange.is());
751     if (m_xImpl->m_xText.is())
752     {
753         m_xImpl->m_xText->insertControlCharacter(
754             m_xImpl->m_xCursorAsRange, nControl, false);
755     }
756 }
757 
InsertTextContent(Reference<XTextContent> const & xContent)758 void XMLTextImportHelper::InsertTextContent(
759     Reference < XTextContent > const & xContent )
760 {
761     assert(m_xImpl->m_xText.is());
762     assert(m_xImpl->m_xCursorAsRange.is());
763     if (m_xImpl->m_xText.is())
764     {
765         // note: this may throw IllegalArgumentException and callers handle it
766         m_xImpl->m_xText->insertTextContent( m_xImpl->m_xCursorAsRange, xContent, false);
767     }
768 }
769 
DeleteParagraph()770 void XMLTextImportHelper::DeleteParagraph()
771 {
772     assert(m_xImpl->m_xText.is());
773     assert(m_xImpl->m_xCursor.is());
774     assert(m_xImpl->m_xCursorAsRange.is());
775 
776     bool bDelete = true;
777     Reference < XEnumerationAccess > const xEnumAccess(
778         m_xImpl->m_xCursor, UNO_QUERY);
779     if( xEnumAccess.is() )
780     {
781         Reference < XEnumeration > xEnum(xEnumAccess->createEnumeration());
782         SAL_WARN_IF(!xEnum->hasMoreElements(), "xmloff.text",
783                 "empty text enumeration");
784         if( xEnum->hasMoreElements() )
785         {
786             Reference < XComponent > xComp( xEnum->nextElement(), UNO_QUERY );
787             assert(xComp.is());
788             if( xComp.is() )
789             {
790                 xComp->dispose();
791                 bDelete = false;
792             }
793         }
794     }
795     if( bDelete )
796     {
797         if (m_xImpl->m_xCursor->goLeft( 1, true ))
798         {
799             m_xImpl->m_xText->insertString(m_xImpl->m_xCursorAsRange,
800                                            "", true);
801         }
802     }
803 }
804 
ConvertStarFonts(const OUString & rChars,const OUString & rStyleName,sal_uInt8 & rFlags,bool bPara,SvXMLImport & rImport) const805 OUString XMLTextImportHelper::ConvertStarFonts( const OUString& rChars,
806                                                 const OUString& rStyleName,
807                                                 sal_uInt8& rFlags,
808                                                 bool bPara,
809                                                 SvXMLImport& rImport ) const
810 {
811     OUStringBuffer sChars( rChars );
812     bool bConverted = false;
813     for( sal_Int32 j=0; j<rChars.getLength(); j++ )
814     {
815         sal_Unicode c = rChars[j];
816         if( c >= 0xf000 && c <= 0xf0ff )
817         {
818             if( (rFlags & CONV_STAR_FONT_FLAGS_VALID) == 0 )
819             {
820                 XMLTextStyleContext *pStyle = nullptr;
821                 XmlStyleFamily nFamily = bPara ? XmlStyleFamily::TEXT_PARAGRAPH
822                                                : XmlStyleFamily::TEXT_TEXT;
823                 if (!rStyleName.isEmpty() && m_xImpl->m_xAutoStyles.is())
824                 {
825                     const SvXMLStyleContext* pTempStyle =
826                         m_xImpl->m_xAutoStyles->
827                                 FindStyleChildContext( nFamily, rStyleName,
828                                                        true );
829                     pStyle = const_cast<XMLTextStyleContext*>( dynamic_cast< const XMLTextStyleContext* >(pTempStyle));
830                 }
831 
832                 if( pStyle )
833                 {
834                     sal_Int32 nCount = pStyle->GetProperties_().size();
835                     if( nCount )
836                     {
837                         rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
838                             m_xImpl->m_xAutoStyles->GetImportPropertyMapper(nFamily);
839                         if( xImpPrMap.is() )
840                         {
841                             rtl::Reference<XMLPropertySetMapper> rPropMapper =
842                                 xImpPrMap->getPropertySetMapper();
843                             for( sal_Int32 i=0; i < nCount; i++ )
844                             {
845                                 const XMLPropertyState& rProp = pStyle->GetProperties_()[i];
846                                 sal_Int32 nIdx = rProp.mnIndex;
847                                 sal_uInt32 nContextId = rPropMapper->GetEntryContextId(nIdx);
848                                 if( CTF_FONTFAMILYNAME == nContextId )
849                                 {
850                                     rFlags &= ~(CONV_FROM_STAR_BATS|CONV_FROM_STAR_MATH);
851                                     OUString sFontName;
852                                     rProp.maValue >>= sFontName;
853                                     if( sFontName.equalsIgnoreAsciiCase( "StarBats"  ) )
854                                         rFlags |= CONV_FROM_STAR_BATS;
855                                     else if( sFontName.equalsIgnoreAsciiCase( "StarMath" ) )
856                                         rFlags |= CONV_FROM_STAR_MATH;
857                                     break;
858                                 }
859                             }
860                         }
861                     }
862 
863                 }
864 
865                 rFlags |= CONV_STAR_FONT_FLAGS_VALID;
866             }
867             if( (rFlags & CONV_FROM_STAR_BATS ) != 0 )
868             {
869                 sChars[j] = rImport.ConvStarBatsCharToStarSymbol( c );
870                 bConverted = true;
871             }
872             else if( (rFlags & CONV_FROM_STAR_MATH ) != 0 )
873             {
874                 sChars[j] = rImport.ConvStarMathCharToStarSymbol( c );
875                 bConverted = true;
876             }
877         }
878     }
879 
880     return bConverted ? sChars.makeStringAndClear() : rChars;
881 }
882 
883 /* Helper method to determine, if a paragraph style has a list style (inclusive
884    an empty one) inherits a list style (inclusive an empty one) from one of its parents (#i69629#)
885 */
886 /* Apply special case, that found list style equals the chapter numbering, also
887    to the found list styles of the parent styles. (#i73973#)
888 */
lcl_HasListStyle(const OUString & sStyleName,const Reference<XNameContainer> & xParaStyles,SvXMLImport const & rImport,const OUString & sNumberingStyleName,std::u16string_view sOutlineStyleName)889 static bool lcl_HasListStyle( const OUString& sStyleName,
890                               const Reference < XNameContainer >& xParaStyles,
891                               SvXMLImport const & rImport,
892                               const OUString& sNumberingStyleName,
893                               std::u16string_view sOutlineStyleName )
894 {
895     bool bRet( false );
896 
897     if ( !xParaStyles->hasByName( sStyleName ) )
898     {
899         // error case
900         return true;
901     }
902 
903     Reference< XPropertyState > xPropState( xParaStyles->getByName( sStyleName ),
904                                             UNO_QUERY );
905     if ( !xPropState.is() )
906     {
907         // error case
908         return false;
909     }
910 
911     if ( xPropState->getPropertyState( sNumberingStyleName ) == PropertyState_DIRECT_VALUE )
912     {
913         // list style found
914         bRet = true;
915         // special case: the set list style equals the chapter numbering
916         Reference< XPropertySet > xPropSet( xPropState, UNO_QUERY );
917         if ( xPropSet.is() )
918         {
919             OUString sListStyle;
920             xPropSet->getPropertyValue( sNumberingStyleName ) >>= sListStyle;
921             if ( !sListStyle.isEmpty() &&
922                  sListStyle == sOutlineStyleName )
923             {
924                 bRet = false;
925             }
926         }
927     }
928     else
929     {
930         // Tools.Outline settings lost on Save (#i77708#)
931         sal_Int32 nUPD( 0 );
932         sal_Int32 nBuild( 0 );
933         // Don't use UPD for versioning: xmloff/source/text/txtstyli.cxx and txtimp.cxx (#i86058#)
934         const bool bBuildIdFound = rImport.getBuildIds( nUPD, nBuild );
935         // search list style at parent
936         Reference<XStyle> xStyle( xPropState, UNO_QUERY );
937         while ( xStyle.is() )
938         {
939             OUString aParentStyle( xStyle->getParentStyle() );
940             if ( !aParentStyle.isEmpty() )
941             {
942                 aParentStyle =
943                     rImport.GetStyleDisplayName( XmlStyleFamily::TEXT_PARAGRAPH,
944                                                  aParentStyle );
945             }
946             if ( aParentStyle.isEmpty() || !xParaStyles->hasByName( aParentStyle ) )
947             {
948                 // no list style found
949                 break;
950             }
951             else
952             {
953                 xPropState.set( xParaStyles->getByName( aParentStyle ),
954                                 UNO_QUERY );
955                 if ( !xPropState.is() )
956                 {
957                     // error case
958                     return true;
959                 }
960                 if ( xPropState->getPropertyState( sNumberingStyleName ) == PropertyState_DIRECT_VALUE )
961                 {
962                     // list style found
963                     bRet = true;
964                     // Special case: the found list style equals the chapter numbering (#i73973#)
965                     Reference< XPropertySet > xPropSet( xPropState, UNO_QUERY );
966                     if ( xPropSet.is() )
967                     {
968                         OUString sListStyle;
969                         xPropSet->getPropertyValue( sNumberingStyleName ) >>= sListStyle;
970                         if ( !sListStyle.isEmpty() &&
971                              sListStyle == sOutlineStyleName )
972                         {
973                             bRet = false;
974                         }
975                         // Special handling for text documents from OOo version prior OOo 2.4 (#i77708#)
976                         /* Check explicitly on certain versions and on import of
977                            text documents in OpenOffice.org file format (#i86058#)
978                         */
979                         else if ( sListStyle.isEmpty() &&
980                                   ( rImport.IsTextDocInOOoFileFormat() ||
981                                     ( bBuildIdFound &&
982                                       ( ( nUPD == 641 ) || ( nUPD == 645 ) || // prior OOo 2.0
983                                         ( nUPD == 680 && nBuild <= 9238 ) ) ) ) ) // OOo 2.0 - OOo 2.3.1
984                         {
985                             bRet = false;
986                         }
987                     }
988                     break;
989                 }
990                 else
991                 {
992                     // search list style at parent
993                     Reference<XStyle> xParentStyle(xPropState, UNO_QUERY);
994                     if (xStyle == xParentStyle)
995                     {
996                         // error case
997                         return true;
998                     }
999                     xStyle = xParentStyle;
1000                 }
1001             }
1002         }
1003     }
1004 
1005     return bRet;
1006 }
SetStyleAndAttrs(SvXMLImport const & rImport,const Reference<XTextCursor> & rCursor,const OUString & rStyleName,bool bPara,bool bOutlineLevelAttrFound,sal_Int8 nOutlineLevel,bool bSetListAttrs,bool bOutlineContentVisible)1007 OUString XMLTextImportHelper::SetStyleAndAttrs(
1008         SvXMLImport const & rImport,
1009         const Reference < XTextCursor >& rCursor,
1010         const OUString& rStyleName,
1011         bool bPara,
1012         bool bOutlineLevelAttrFound,
1013         sal_Int8 nOutlineLevel,
1014         // Numberings/Bullets in table not visible after save/reload (#i80724#)
1015         bool bSetListAttrs,
1016         bool bOutlineContentVisible)
1017 {
1018     static constexpr OUStringLiteral s_NumberingRules = u"NumberingRules";
1019     static constexpr OUStringLiteral s_NumberingIsNumber = u"NumberingIsNumber";
1020     static constexpr OUStringLiteral s_NumberingLevel = u"NumberingLevel";
1021     static constexpr OUStringLiteral s_ParaIsNumberingRestart = u"ParaIsNumberingRestart";
1022     static constexpr OUStringLiteral s_NumberingStartValue = u"NumberingStartValue";
1023     static constexpr OUStringLiteral s_PropNameListId = u"ListId";
1024     static constexpr OUStringLiteral s_PageDescName = u"PageDescName";
1025     static constexpr OUStringLiteral s_OutlineLevel = u"OutlineLevel";
1026 
1027     const XmlStyleFamily nFamily = bPara ? XmlStyleFamily::TEXT_PARAGRAPH
1028                                          : XmlStyleFamily::TEXT_TEXT;
1029     XMLTextStyleContext *pStyle = nullptr;
1030     OUString sStyleName( rStyleName );
1031     if (!sStyleName.isEmpty() && m_xImpl->m_xAutoStyles.is())
1032     {
1033         const SvXMLStyleContext* pTempStyle =
1034             m_xImpl->m_xAutoStyles->FindStyleChildContext( nFamily, sStyleName, true );
1035         pStyle = const_cast<XMLTextStyleContext*>(dynamic_cast< const XMLTextStyleContext* >(pTempStyle));
1036     }
1037     if( pStyle )
1038         sStyleName = pStyle->GetParentName();
1039 
1040     Reference < XPropertySet > xPropSet( rCursor, UNO_QUERY );
1041     Reference< XPropertySetInfo > xPropSetInfo(
1042         xPropSet->getPropertySetInfo());
1043 
1044     // style
1045     if( !sStyleName.isEmpty() )
1046     {
1047         sStyleName = rImport.GetStyleDisplayName( nFamily, sStyleName );
1048         const OUString rPropName = bPara ? OUString("ParaStyleName") : OUString("CharStyleName");
1049         const Reference < XNameContainer > & rStyles = bPara
1050             ? m_xImpl->m_xParaStyles
1051             : m_xImpl->m_xTextStyles;
1052         if( rStyles.is() &&
1053             xPropSetInfo->hasPropertyByName( rPropName ) &&
1054             rStyles->hasByName( sStyleName ) )
1055         {
1056             xPropSet->setPropertyValue( rPropName, makeAny(sStyleName) );
1057         }
1058         else
1059             sStyleName.clear();
1060     }
1061 
1062     /* The outline level needs to be only applied as list level, if the heading
1063        is not inside a list and if it by default applies the outline style. (#i70748#)
1064     */
1065     bool bApplyOutlineLevelAsListLevel( false );
1066     // Numberings/Bullets in table not visible after save/reload (#i80724#)
1067     if (bSetListAttrs && bPara
1068         && xPropSetInfo->hasPropertyByName( s_NumberingRules))
1069     {
1070         // Set numbering rules
1071         Reference< XIndexReplace > const xNumRules(
1072                 xPropSet->getPropertyValue(s_NumberingRules), UNO_QUERY);
1073 
1074         XMLTextListBlockContext * pListBlock(nullptr);
1075         XMLTextListItemContext  * pListItem(nullptr);
1076         XMLNumberedParaContext  * pNumberedParagraph(nullptr);
1077         GetTextListHelper().ListContextTop(
1078             pListBlock, pListItem, pNumberedParagraph);
1079 
1080         assert(!(pListBlock && pNumberedParagraph) && "XMLTextImportHelper::"
1081             "SetStyleAndAttrs: both list and numbered-paragraph???");
1082 
1083         Reference < XIndexReplace > xNewNumRules;
1084         sal_Int8 nLevel(-1);
1085         OUString sListId;
1086         sal_Int16 nStartValue(-1);
1087         bool bNumberingIsNumber(true);
1088 
1089         if (pListBlock) {
1090 
1091             if (!pListItem) {
1092                 bNumberingIsNumber = false; // list-header
1093             }
1094             // consider text:style-override property of <text:list-item>
1095             xNewNumRules.set(
1096                 (pListItem != nullptr && pListItem->HasNumRulesOverride())
1097                     ? pListItem->GetNumRulesOverride()
1098                     : pListBlock->GetNumRules() );
1099             nLevel = static_cast<sal_Int8>(pListBlock->GetLevel());
1100 
1101             if ( pListItem && pListItem->HasStartValue() ) {
1102                nStartValue = pListItem->GetStartValue();
1103             }
1104 
1105             // Inconsistent behavior regarding lists (#i92811#)
1106             sListId = m_xImpl->m_xTextListsHelper->GetListIdForListBlock(
1107                             *pListBlock);
1108         }
1109         else if (pNumberedParagraph)
1110         {
1111             xNewNumRules.set(pNumberedParagraph->GetNumRules());
1112             nLevel = static_cast<sal_Int8>(pNumberedParagraph->GetLevel());
1113             sListId = pNumberedParagraph->GetListId();
1114             nStartValue = pNumberedParagraph->GetStartValue();
1115         }
1116 
1117 
1118         if (pListBlock || pNumberedParagraph)
1119         {
1120             // Assure that list style of automatic paragraph style is applied at paragraph. (#i101349#)
1121             bool bApplyNumRules = pStyle && pStyle->IsListStyleSet();
1122             if ( !bApplyNumRules )
1123             {
1124                 bool bSameNumRules = xNewNumRules == xNumRules;
1125                 if( !bSameNumRules && xNewNumRules.is() && xNumRules.is() )
1126                 {
1127                     // If the interface pointers are different, then this does
1128                     // not mean that the num rules are different. Further tests
1129                     // are required then. However, if only one num rule is
1130                     // set, no tests are required of course.
1131                     Reference< XNamed > xNewNamed( xNewNumRules, UNO_QUERY );
1132                     Reference< XNamed > xNamed( xNumRules, UNO_QUERY );
1133                     if( xNewNamed.is() && xNamed.is() )
1134                     {
1135                         bSameNumRules = xNewNamed->getName() == xNamed->getName();
1136                     }
1137                     else
1138                     {
1139                         Reference< XAnyCompare > xNumRuleCompare( xNumRules, UNO_QUERY );
1140                         if( xNumRuleCompare.is() )
1141                         {
1142                             bSameNumRules = (xNumRuleCompare->compare( Any(xNumRules), Any(xNewNumRules) ) == 0);
1143                         }
1144                     }
1145                 }
1146                 bApplyNumRules = !bSameNumRules;
1147             }
1148 
1149             if ( bApplyNumRules )
1150             {
1151                 // #102607# This may except when xNewNumRules contains
1152                 // a Writer-NumRule-Implementation bug gets applied to
1153                 // a shape. Since this may occur inside a document
1154                 // (e.g. when edited), this must be handled
1155                 // gracefully.
1156                 try
1157                 {
1158                     xPropSet->setPropertyValue(
1159                         s_NumberingRules, makeAny(xNewNumRules) );
1160                 }
1161                 catch(const Exception&)
1162                 {
1163                     ; // I would really like to use a warning here,
1164                       // but I can't access the XMLErrorHandler from
1165                       // here.
1166                 }
1167             }
1168 
1169             if (!bNumberingIsNumber &&
1170                 xPropSetInfo->hasPropertyByName(s_NumberingIsNumber))
1171             {
1172                 xPropSet->setPropertyValue(s_NumberingIsNumber, Any(false));
1173             }
1174 
1175             xPropSet->setPropertyValue( s_NumberingLevel, Any(nLevel) );
1176 
1177             if( pListBlock && pListBlock->IsRestartNumbering() )
1178             {
1179                 // TODO: property missing
1180                 if (xPropSetInfo->hasPropertyByName(s_ParaIsNumberingRestart))
1181                 {
1182                     xPropSet->setPropertyValue(s_ParaIsNumberingRestart,
1183                                                makeAny(true) );
1184                 }
1185                 pListBlock->ResetRestartNumbering();
1186             }
1187 
1188             if ( 0 <= nStartValue &&
1189                 xPropSetInfo->hasPropertyByName(s_NumberingStartValue))
1190             {
1191                 xPropSet->setPropertyValue(s_NumberingStartValue,
1192                                            makeAny(nStartValue));
1193             }
1194 
1195             if (xPropSetInfo->hasPropertyByName(s_PropNameListId))
1196             {
1197                 if (!sListId.isEmpty()) {
1198                     xPropSet->setPropertyValue(s_PropNameListId,
1199                         makeAny(sListId) );
1200                 }
1201             }
1202 
1203             GetTextListHelper().SetListItem( nullptr );
1204         }
1205         else
1206         {
1207             /* If the paragraph is not in a list but its style, remove it from
1208                the list. Do not remove it, if the list of the style is
1209                the chapter numbering rule.
1210             */
1211             if( xNumRules.is() )
1212             {
1213                 bool bRemove( true );
1214                 // Special handling for document from OOo 2.x (#i70748#)
1215                 sal_Int32 nUPD( 0 );
1216                 sal_Int32 nBuild( 0 );
1217                 const bool bBuildIdFound = rImport.getBuildIds( nUPD, nBuild );
1218                 if ( ( bBuildIdFound && nUPD == 680 ) ||
1219                      !pStyle || !pStyle->IsListStyleSet() )
1220                 {
1221                     if (m_xImpl->m_xChapterNumbering.is())
1222                     {
1223                         Reference< XNamed > xNumNamed( xNumRules, UNO_QUERY );
1224                         Reference< XNamed > const xChapterNumNamed (
1225                             m_xImpl->m_xChapterNumbering, UNO_QUERY);
1226                         if ( xNumNamed.is() && xChapterNumNamed.is() &&
1227                              xNumNamed->getName() == xChapterNumNamed->getName() )
1228                         {
1229                             bRemove = false;
1230                             // RFE: inserting headings into text documents (#i70748#)
1231                             bApplyOutlineLevelAsListLevel = true;
1232                         }
1233                     }
1234                 }
1235                 else
1236                 {
1237                     SAL_INFO_IF(!pStyle->GetListStyle().isEmpty(),
1238                         "xmloff.text",
1239                         "automatic paragraph style with list style name, but paragraph not in list???");
1240                 }
1241                 if ( bRemove )
1242                 {
1243                     xPropSet->setPropertyValue( s_NumberingRules, Any() );
1244                 }
1245             }
1246         }
1247     }
1248 
1249     // hard paragraph properties
1250     if( pStyle )
1251     {
1252         pStyle->FillPropertySet( xPropSet );
1253         if( bPara && pStyle->HasMasterPageName() &&
1254             xPropSetInfo->hasPropertyByName(s_PageDescName))
1255         {
1256             OUString sDisplayName(
1257                 rImport.GetStyleDisplayName(
1258                                 XmlStyleFamily::MASTER_PAGE,
1259                                 pStyle->GetMasterPageName()) );
1260             if( sDisplayName.isEmpty() ||
1261                 (m_xImpl->m_xPageStyles.is() &&
1262                  m_xImpl->m_xPageStyles->hasByName( sDisplayName)))
1263             {
1264                 xPropSet->setPropertyValue(s_PageDescName,
1265                         makeAny(sDisplayName));
1266             }
1267         }
1268         if( bPara && !pStyle->GetDropCapStyleName().isEmpty() &&
1269             m_xImpl->m_xTextStyles.is())
1270         {
1271             OUString sDisplayName(
1272                 rImport.GetStyleDisplayName(
1273                                 XmlStyleFamily::TEXT_TEXT,
1274                                 pStyle->GetDropCapStyleName()) );
1275             if (m_xImpl->m_xTextStyles->hasByName(sDisplayName) &&
1276                 xPropSetInfo->hasPropertyByName("DropCapCharStyleName"))
1277             {
1278                 xPropSet->setPropertyValue("DropCapCharStyleName", makeAny(sDisplayName));
1279             }
1280         }
1281 
1282         // combined characters special treatment
1283         if (!bPara && pStyle->HasCombinedCharactersLetter())
1284         {
1285             // insert combined characters text field
1286             if (m_xImpl->m_xServiceFactory.is())
1287             {
1288                 uno::Reference<beans::XPropertySet> const xTmp(
1289                     m_xImpl->m_xServiceFactory->createInstance(
1290                         "com.sun.star.text.TextField.CombinedCharacters"), UNO_QUERY);
1291                 if( xTmp.is() )
1292                 {
1293                     // fix cursor if larger than possible for
1294                     // combined characters field
1295                     if (rCursor->getString().getLength() >
1296                             MAX_COMBINED_CHARACTERS)
1297                     {
1298                         rCursor->gotoRange(rCursor->getStart(), false);
1299                         rCursor->goRight(MAX_COMBINED_CHARACTERS, true);
1300                     }
1301 
1302                     // set field value (the combined character string)
1303                     xTmp->setPropertyValue("Content",
1304                         makeAny(rCursor->getString()));
1305 
1306                     // insert the field over it's original text
1307                     Reference<XTextContent> xTextContent(xTmp, UNO_QUERY);
1308                     if (m_xImpl->m_xText.is() && rCursor.is())
1309                     {
1310                         // #i107225# the combined characters need to be inserted first
1311                         // the selected text has to be removed afterwards
1312                         m_xImpl->m_xText->insertTextContent( rCursor->getStart(), xTextContent, true );
1313 
1314                         if( !rCursor->getString().isEmpty() )
1315                         {
1316                             try
1317                             {
1318                                 uno::Reference< text::XTextCursor > xCrsr = rCursor->getText()->createTextCursorByRange( rCursor->getStart() );
1319                                 xCrsr->goLeft( 1, true );
1320                                 uno::Reference< beans::XPropertySet> xCrsrProperties( xCrsr, uno::UNO_QUERY_THROW );
1321                                 //the hard properties of the removed text need to be applied to the combined characters field
1322                                 pStyle->FillPropertySet( xCrsrProperties );
1323                                 xCrsr->collapseToEnd();
1324                                 xCrsr->gotoRange( rCursor->getEnd(), true );
1325                                 xCrsr->setString( OUString() );
1326                             }
1327                             catch(const uno::Exception&)
1328                             {
1329                             }
1330                         }
1331                     }
1332                 }
1333             }
1334         }
1335     }
1336 
1337     // outline level; set after list style has been set
1338     // Complete re-worked and corrected: (#i53198#)
1339     // - set outline level at paragraph
1340     // - set numbering level at paragraph, if none is already set
1341     // - assure that style is marked as an outline style for the corresponding
1342     //   outline level.
1343     // - DO NOT set type of numbering rule to outline.
1344     // - DO NOT set numbering rule directly at the paragraph.
1345 
1346     // Some minor rework and adjust access to paragraph styles (#i70748#)
1347     if ( bPara )
1348     {
1349         // Headings not numbered anymore in 3.1 (#i103817#)
1350         sal_Int16 nCurrentOutlineLevelInheritedFromParagraphStyle = 0;
1351         const bool bHasOutlineLevelProp(
1352             xPropSetInfo->hasPropertyByName(s_OutlineLevel));
1353         if ( bHasOutlineLevelProp )
1354         {
1355             xPropSet->getPropertyValue(s_OutlineLevel)
1356                 >>= nCurrentOutlineLevelInheritedFromParagraphStyle;
1357         }
1358         if ( nOutlineLevel > 0 )
1359         {
1360             if ( bHasOutlineLevelProp )
1361             {
1362                 // In case that the value equals the value of its paragraph style
1363                 // attribute outline level, the paragraph attribute value is left unset
1364                 if ( nCurrentOutlineLevelInheritedFromParagraphStyle != nOutlineLevel )
1365                 {
1366                     xPropSet->setPropertyValue( s_OutlineLevel,
1367                         makeAny( static_cast<sal_Int16>(nOutlineLevel) ) );
1368                 }
1369             }
1370             if (!bOutlineContentVisible)
1371             {
1372                 uno::Sequence<beans::PropertyValue> aGrabBag;
1373                 xPropSet->getPropertyValue("ParaInteropGrabBag") >>= aGrabBag;
1374                 sal_Int32 length = aGrabBag.getLength();
1375                 aGrabBag.realloc(length + 1);
1376                 aGrabBag[length].Name = "OutlineContentVisibleAttr";
1377                 aGrabBag[length].Value <<= bool(bOutlineContentVisible);
1378                 xPropSet->setPropertyValue("ParaInteropGrabBag", uno::makeAny(aGrabBag));
1379             }
1380             // RFE: inserting headings into text documents (#i70748#)
1381             if ( bApplyOutlineLevelAsListLevel )
1382             {
1383                 sal_Int16 nNumLevel = -1;
1384                 xPropSet->getPropertyValue( s_NumberingLevel ) >>= nNumLevel;
1385                 if ( nNumLevel == -1 ||
1386                      nNumLevel != (nOutlineLevel - 1) )
1387                 {
1388                     xPropSet->setPropertyValue( s_NumberingLevel,
1389                             makeAny( static_cast<sal_Int8>(nOutlineLevel - 1) ) );
1390                 }
1391             }
1392             /* Correction: (#i69629#)
1393                - for text document from version OOo 2.0.4/SO 8 PU4 and earlier
1394                  the paragraph style of a heading should be assigned to the
1395                  corresponding list level of the outline style.
1396                - for other text documents the paragraph style of a heading is only
1397                  a candidate for an assignment to the list level of the outline
1398                  style, if it has no direct list style property and (if exists) the
1399                  automatic paragraph style has also no direct list style set.
1400             */
1401             if (m_xImpl->m_xParaStyles.is() && m_xImpl->m_xParaStyles->hasByName(sStyleName))
1402             {
1403                 bool bOutlineStyleCandidate( false );
1404 
1405                 sal_Int32 nUPD( 0 );
1406                 sal_Int32 nBuild( 0 );
1407                 const bool bBuildIdFound = rImport.getBuildIds( nUPD, nBuild );
1408                 // Lost outline numbering in master document (#i73509#)
1409                 // Check explicitly on certain versions (#i86058#)
1410                 if ( rImport.IsTextDocInOOoFileFormat() ||
1411                      ( bBuildIdFound &&
1412                        ( nUPD == 645 || nUPD == 641 ) ) )
1413                 {
1414                     bOutlineStyleCandidate = true;
1415                 }
1416                 else if ( nUPD == 680 && nBuild <= 9073 ) /* BuildId of OOo 2.0.4/SO8 PU4 */
1417                 {
1418                     bOutlineStyleCandidate = bOutlineLevelAttrFound;
1419                 }
1420                 if ( bOutlineStyleCandidate )
1421                 {
1422                     AddOutlineStyleCandidate( nOutlineLevel, sStyleName );
1423                 }
1424                 // Assure that heading applies the outline style (#i103817#)
1425                 if ( ( !pStyle || !pStyle->IsListStyleSet() ) &&
1426                      !bOutlineStyleCandidate &&
1427                      m_xImpl->m_xChapterNumbering.is())
1428                 {
1429                     if ( !lcl_HasListStyle( sStyleName,
1430                                     m_xImpl->m_xParaStyles, GetXMLImport(),
1431                                     u"NumberingStyleName",
1432                                     u"" ) )
1433                     {
1434                         // heading not in a list --> apply outline style
1435                         xPropSet->setPropertyValue( s_NumberingRules,
1436                             makeAny(m_xImpl->m_xChapterNumbering) );
1437                         xPropSet->setPropertyValue( s_NumberingLevel,
1438                             makeAny(static_cast<sal_Int8>(nOutlineLevel - 1)));
1439                     }
1440                 }
1441             }
1442         }
1443         //handle for text:p,if the paragraphstyle outlinelevel is set to[1~10]
1444         else if( bHasOutlineLevelProp )
1445         {
1446             if ( nCurrentOutlineLevelInheritedFromParagraphStyle != 0 )
1447             {
1448                 xPropSet->setPropertyValue(s_OutlineLevel,
1449                     makeAny( sal_Int16(0) ));
1450             }
1451         }
1452     }
1453 
1454     return sStyleName;
1455 }
1456 
FindOutlineStyleName(OUString & rStyleName,sal_Int8 nOutlineLevel)1457 void XMLTextImportHelper::FindOutlineStyleName( OUString& rStyleName,
1458                                                 sal_Int8 nOutlineLevel )
1459 {
1460     // style name empty?
1461     if( rStyleName.isEmpty() )
1462     {
1463         // Empty? Then we need o do stuff. Let's do error checking first.
1464         if (m_xImpl->m_xChapterNumbering.is() &&
1465             ( nOutlineLevel > 0 ) &&
1466             (nOutlineLevel <= m_xImpl->m_xChapterNumbering->getCount()))
1467         {
1468             nOutlineLevel--;   // for the remainder, the level's are 0-based
1469 
1470             // empty style name: look-up previously used name
1471 
1472             // if we don't have a previously used name, we'll use the default
1473             m_xImpl->InitOutlineStylesCandidates();
1474             if (m_xImpl->m_xOutlineStylesCandidates[nOutlineLevel].empty())
1475             {
1476                 // no other name used previously? Then use default
1477 
1478                 // iterate over property value sequence to find the style name
1479                 Sequence<PropertyValue> aProperties;
1480                 m_xImpl->m_xChapterNumbering->getByIndex( nOutlineLevel )
1481                     >>= aProperties;
1482                 auto pProp = std::find_if(aProperties.begin(), aProperties.end(),
1483                     [](const PropertyValue& rProp) { return rProp.Name == "HeadingStyleName"; });
1484                 if (pProp != aProperties.end())
1485                 {
1486                     OUString aOutlineStyle;
1487                     pProp->Value >>= aOutlineStyle;
1488                     m_xImpl->m_xOutlineStylesCandidates[nOutlineLevel]
1489                         .push_back( aOutlineStyle );
1490                 }
1491             }
1492 
1493             // finally, we'll use the previously used style name for this
1494             // format (or the default we've just put into that style)
1495             // take last added one (#i71249#)
1496             rStyleName =
1497                 m_xImpl->m_xOutlineStylesCandidates[nOutlineLevel].back();
1498         }
1499         // else: nothing we can do, so we'll leave it empty
1500     }
1501     // else: we already had a style name, so we let it pass.
1502 }
1503 
AddOutlineStyleCandidate(const sal_Int8 nOutlineLevel,const OUString & rStyleName)1504 void XMLTextImportHelper::AddOutlineStyleCandidate( const sal_Int8 nOutlineLevel,
1505                                                     const OUString& rStyleName )
1506 {
1507     if (!rStyleName.isEmpty()
1508         && m_xImpl->m_xChapterNumbering.is()
1509         && (nOutlineLevel > 0)
1510         && (nOutlineLevel <= m_xImpl->m_xChapterNumbering->getCount()))
1511     {
1512         m_xImpl->InitOutlineStylesCandidates();
1513         m_xImpl->m_xOutlineStylesCandidates[nOutlineLevel-1].push_back(
1514             rStyleName);
1515     }
1516 }
1517 
SetOutlineStyles(bool bSetEmptyLevels)1518 void XMLTextImportHelper::SetOutlineStyles( bool bSetEmptyLevels )
1519 {
1520     if (!(m_xImpl->m_xOutlineStylesCandidates != nullptr || bSetEmptyLevels) ||
1521         !m_xImpl->m_xChapterNumbering.is() ||
1522         IsInsertMode())
1523         return;
1524 
1525     bool bChooseLastOne( false );
1526     {
1527         if ( GetXMLImport().IsTextDocInOOoFileFormat() )
1528         {
1529             bChooseLastOne = true;
1530         }
1531         else
1532         {
1533             sal_Int32 nUPD( 0 );
1534             sal_Int32 nBuild( 0 );
1535             if ( GetXMLImport().getBuildIds( nUPD, nBuild ) )
1536             {
1537                 // check explicitly on certain versions
1538                 bChooseLastOne = ( nUPD == 641 ) || ( nUPD == 645 ) ||  // prior OOo 2.0
1539                                  ( nUPD == 680 && nBuild <= 9073 ); // OOo 2.0 - OOo 2.0.4
1540             }
1541         }
1542     }
1543 
1544     OUString sOutlineStyleName;
1545     {
1546         Reference<XPropertySet> xChapterNumRule(
1547             m_xImpl->m_xChapterNumbering, UNO_QUERY);
1548         xChapterNumRule->getPropertyValue("Name") >>= sOutlineStyleName;
1549     }
1550 
1551     const sal_Int32 nCount = m_xImpl->m_xChapterNumbering->getCount();
1552     /* First collect all paragraph styles chosen for assignment to each
1553        list level of the outline style, then perform the intrinsic assignment.
1554        Reason: The assignment of a certain paragraph style to a list level
1555                of the outline style causes side effects on the children
1556                paragraph styles in Writer. (#i106218#)
1557     */
1558     ::std::vector<OUString> sChosenStyles(nCount);
1559     for( sal_Int32 i=0; i < nCount; ++i )
1560     {
1561         if ( bSetEmptyLevels ||
1562              (m_xImpl->m_xOutlineStylesCandidates &&
1563               !m_xImpl->m_xOutlineStylesCandidates[i].empty()))
1564         {
1565             // determine, which candidate is one to be assigned to the list
1566             // level of the outline style
1567             if (m_xImpl->m_xOutlineStylesCandidates &&
1568                 !m_xImpl->m_xOutlineStylesCandidates[i].empty())
1569             {
1570                 if ( bChooseLastOne )
1571                 {
1572                     sChosenStyles[i] =
1573                     m_xImpl->m_xOutlineStylesCandidates[i].back();
1574                 }
1575                 else
1576                 {
1577                     for (size_t j = 0;
1578                         j < m_xImpl->m_xOutlineStylesCandidates[i].size();
1579                         ++j)
1580                     {
1581                         if (!lcl_HasListStyle(
1582                                 m_xImpl->m_xOutlineStylesCandidates[i][j],
1583                                 m_xImpl->m_xParaStyles,
1584                                 GetXMLImport(),
1585                                 "NumberingStyleName",
1586                                 sOutlineStyleName))
1587                         {
1588                             sChosenStyles[i] =
1589                                 m_xImpl->m_xOutlineStylesCandidates[i][j];
1590                             break;
1591                         }
1592                     }
1593                 }
1594             }
1595         }
1596     }
1597     // Trashed outline numbering in ODF 1.1 text document created by OOo 3.x (#i106218#)
1598     Sequence < PropertyValue > aProps( 1 );
1599     PropertyValue *pProps = aProps.getArray();
1600     pProps->Name = "HeadingStyleName";
1601     for ( sal_Int32 i = 0; i < nCount; ++i )
1602     {
1603         // Paragraph style assignments in Outline of template lost from second level on (#i107610#)
1604         if ( bSetEmptyLevels || !sChosenStyles[i].isEmpty() )
1605         {
1606             pProps->Value <<= sChosenStyles[i];
1607             m_xImpl->m_xChapterNumbering->replaceByIndex(i,
1608                     makeAny( aProps ));
1609         }
1610     }
1611 
1612 }
1613 
SetHyperlink(SvXMLImport const & rImport,const Reference<XTextCursor> & rCursor,const OUString & rHRef,const OUString & rName,const OUString & rTargetFrameName,const OUString & rStyleName,const OUString & rVisitedStyleName,XMLEventsImportContext * pEvents)1614 void XMLTextImportHelper::SetHyperlink(
1615     SvXMLImport const & rImport,
1616     const Reference < XTextCursor >& rCursor,
1617     const OUString& rHRef,
1618     const OUString& rName,
1619     const OUString& rTargetFrameName,
1620     const OUString& rStyleName,
1621     const OUString& rVisitedStyleName,
1622     XMLEventsImportContext* pEvents)
1623 {
1624     static constexpr OUStringLiteral s_HyperLinkURL = u"HyperLinkURL";
1625     static constexpr OUStringLiteral s_HyperLinkName = u"HyperLinkName";
1626     static constexpr OUStringLiteral s_HyperLinkTarget = u"HyperLinkTarget";
1627     static constexpr OUStringLiteral s_UnvisitedCharStyleName = u"UnvisitedCharStyleName";
1628     static constexpr OUStringLiteral s_VisitedCharStyleName = u"VisitedCharStyleName";
1629     static constexpr OUStringLiteral s_HyperLinkEvents = u"HyperLinkEvents";
1630 
1631     Reference < XPropertySet > xPropSet( rCursor, UNO_QUERY );
1632     Reference < XPropertySetInfo > xPropSetInfo(
1633         xPropSet->getPropertySetInfo());
1634     if (!xPropSetInfo.is() || !xPropSetInfo->hasPropertyByName(s_HyperLinkURL))
1635         return;
1636 
1637     xPropSet->setPropertyValue(s_HyperLinkURL, makeAny(rHRef));
1638 
1639     if (xPropSetInfo->hasPropertyByName(s_HyperLinkName))
1640     {
1641         xPropSet->setPropertyValue(s_HyperLinkName, makeAny(rName));
1642     }
1643 
1644     if (xPropSetInfo->hasPropertyByName(s_HyperLinkTarget))
1645     {
1646         xPropSet->setPropertyValue(s_HyperLinkTarget,
1647             makeAny(rTargetFrameName));
1648     }
1649 
1650     if ( (pEvents != nullptr) &&
1651         xPropSetInfo->hasPropertyByName(s_HyperLinkEvents))
1652     {
1653         // The API treats events at hyperlinks differently from most
1654         // other properties: You have to set a name replace with the
1655         // events in it. The easiest way to do this is to 1) get
1656         // events, 2) set new ones, and 3) then put events back.
1657         uno::Reference<XNameReplace> const xReplace(
1658             xPropSet->getPropertyValue(s_HyperLinkEvents), UNO_QUERY);
1659         if (xReplace.is())
1660         {
1661             // set events
1662             pEvents->SetEvents(xReplace);
1663 
1664             // put events
1665             xPropSet->setPropertyValue(s_HyperLinkEvents, makeAny(xReplace));
1666         }
1667     }
1668 
1669     if (m_xImpl->m_xTextStyles.is())
1670     {
1671         OUString sDisplayName(
1672             rImport.GetStyleDisplayName(
1673                             XmlStyleFamily::TEXT_TEXT, rStyleName ) );
1674         if( !sDisplayName.isEmpty() &&
1675             xPropSetInfo->hasPropertyByName(s_UnvisitedCharStyleName) &&
1676             m_xImpl->m_xTextStyles->hasByName(sDisplayName))
1677         {
1678             xPropSet->setPropertyValue(s_UnvisitedCharStyleName,
1679                 makeAny(sDisplayName));
1680         }
1681 
1682         sDisplayName =
1683             rImport.GetStyleDisplayName(
1684                             XmlStyleFamily::TEXT_TEXT, rVisitedStyleName );
1685         if( !sDisplayName.isEmpty() &&
1686             xPropSetInfo->hasPropertyByName(s_VisitedCharStyleName) &&
1687             m_xImpl->m_xTextStyles->hasByName(sDisplayName))
1688         {
1689             xPropSet->setPropertyValue(s_VisitedCharStyleName,
1690                 makeAny(sDisplayName));
1691         }
1692     }
1693 }
1694 
SetRuby(SvXMLImport const & rImport,const Reference<XTextCursor> & rCursor,const OUString & rStyleName,const OUString & rTextStyleName,const OUString & rText)1695 void XMLTextImportHelper::SetRuby(
1696     SvXMLImport const & rImport,
1697     const Reference < XTextCursor >& rCursor,
1698     const OUString& rStyleName,
1699     const OUString& rTextStyleName,
1700     const OUString& rText )
1701 {
1702     Reference<XPropertySet> xPropSet(rCursor, UNO_QUERY);
1703 
1704     OUString sRubyText("RubyText");
1705 
1706     // if we have one Ruby property, we assume all of them are present
1707     if (xPropSet.is() &&
1708         xPropSet->getPropertySetInfo()->hasPropertyByName( sRubyText ))
1709     {
1710         // the ruby text
1711         xPropSet->setPropertyValue(sRubyText, makeAny(rText));
1712 
1713         // the ruby style (ruby-adjust)
1714         if (!rStyleName.isEmpty() && m_xImpl->m_xAutoStyles.is())
1715         {
1716             const SvXMLStyleContext* pTempStyle =
1717                 m_xImpl->m_xAutoStyles->FindStyleChildContext( XmlStyleFamily::TEXT_RUBY,
1718                                        rStyleName, true );
1719             XMLPropStyleContext *pStyle = const_cast<XMLPropStyleContext*>(dynamic_cast< const XMLPropStyleContext* >(pTempStyle));
1720 
1721             if (nullptr != pStyle)
1722                 pStyle->FillPropertySet( xPropSet );
1723         }
1724 
1725         // the ruby text character style
1726         if (m_xImpl->m_xTextStyles.is())
1727         {
1728             OUString sDisplayName(
1729                 rImport.GetStyleDisplayName(
1730                             XmlStyleFamily::TEXT_TEXT, rTextStyleName ) );
1731             if( (!sDisplayName.isEmpty()) &&
1732                 m_xImpl->m_xTextStyles->hasByName( sDisplayName ))
1733             {
1734                 xPropSet->setPropertyValue("RubyCharStyleName", makeAny(sDisplayName));
1735             }
1736         }
1737     }
1738 }
1739 
SetAutoStyles(SvXMLStylesContext * pStyles)1740 void XMLTextImportHelper::SetAutoStyles( SvXMLStylesContext *pStyles )
1741 {
1742     m_xImpl->m_xAutoStyles = pStyles;
1743 }
1744 
CreateTextChildContext(SvXMLImport & rImport,sal_Int32 nElement,const Reference<XFastAttributeList> & xAttrList,XMLTextType eType)1745 SvXMLImportContext *XMLTextImportHelper::CreateTextChildContext(
1746         SvXMLImport& rImport,
1747         sal_Int32 nElement,
1748         const Reference< XFastAttributeList > & xAttrList,
1749         XMLTextType eType )
1750 {
1751     SvXMLImportContext *pContext = nullptr;
1752 
1753     bool bContent = true;
1754     switch( nElement )
1755     {
1756     case XML_ELEMENT(TEXT, XML_H):
1757     case XML_ELEMENT(TEXT, XML_P):
1758     case XML_ELEMENT(LO_EXT, XML_P):
1759         pContext = new XMLParaContext( rImport,
1760                                        nElement,
1761                                        xAttrList );
1762         if (m_xImpl->m_bProgress && XMLTextType::Shape != eType)
1763         {
1764             rImport.GetProgressBarHelper()->Increment();
1765         }
1766         break;
1767     // #i52127#
1768     case XML_ELEMENT(TEXT, XML_NUMBERED_PARAGRAPH):
1769         pContext = new XMLNumberedParaContext(
1770                         rImport, nElement, xAttrList );
1771         break;
1772     case XML_ELEMENT(TEXT, XML_LIST):
1773         pContext = new XMLTextListBlockContext( rImport, *this,
1774                                                 xAttrList );
1775         break;
1776     case XML_ELEMENT(TABLE,XML_TABLE):
1777     case XML_ELEMENT(LO_EXT, XML_TABLE):
1778         if( XMLTextType::Body == eType ||
1779             XMLTextType::TextBox == eType ||
1780              XMLTextType::Section == eType ||
1781             XMLTextType::HeaderFooter == eType ||
1782             XMLTextType::ChangedRegion == eType ||
1783             XMLTextType::Cell == eType )
1784             pContext = CreateTableChildContext( rImport, nElement, xAttrList );
1785         break;
1786     case XML_ELEMENT(TEXT, XML_SEQUENCE_DECLS):
1787         if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted) ||
1788             XMLTextType::HeaderFooter == eType )
1789         {
1790             pContext = new XMLVariableDeclsImportContext(
1791                 rImport, *this, VarTypeSequence);
1792             bContent = false;
1793         }
1794         break;
1795     case XML_ELEMENT(TEXT, XML_VARIABLE_DECLS):
1796         if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted) ||
1797             XMLTextType::HeaderFooter == eType )
1798         {
1799             pContext = new XMLVariableDeclsImportContext(
1800                 rImport, *this, VarTypeSimple);
1801             bContent = false;
1802         }
1803         break;
1804     case XML_ELEMENT(TEXT, XML_USER_FIELD_DECLS):
1805         if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted)||
1806             XMLTextType::HeaderFooter == eType )
1807         {
1808             pContext = new XMLVariableDeclsImportContext(
1809                 rImport, *this, VarTypeUserField);
1810             bContent = false;
1811         }
1812         break;
1813     case XML_ELEMENT(TEXT, XML_DDE_CONNECTION_DECLS):
1814         if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted) ||
1815             XMLTextType::HeaderFooter == eType )
1816         {
1817             pContext = new XMLDdeFieldDeclsImportContext(rImport);
1818             bContent = false;
1819         }
1820         break;
1821     case XML_ELEMENT(DRAW, XML_FRAME):
1822         if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted) ||
1823             XMLTextType::TextBox == eType ||
1824             XMLTextType::ChangedRegion == eType )
1825         {
1826             TextContentAnchorType eAnchorType =
1827                 XMLTextType::TextBox == eType ? TextContentAnchorType_AT_FRAME
1828                                                : TextContentAnchorType_AT_PAGE;
1829             pContext = new XMLTextFrameContext( rImport, xAttrList,
1830                                                 eAnchorType );
1831             bContent = false;
1832         }
1833         break;
1834     case XML_ELEMENT(DRAW, XML_A):
1835         if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted) ||
1836             XMLTextType::TextBox == eType ||
1837              XMLTextType::ChangedRegion == eType)
1838         {
1839             TextContentAnchorType eAnchorType =
1840                 XMLTextType::TextBox == eType ? TextContentAnchorType_AT_FRAME
1841                                                : TextContentAnchorType_AT_PAGE;
1842             pContext = new XMLTextFrameHyperlinkContext( rImport, nElement,
1843                                                 xAttrList,
1844                                                 eAnchorType );
1845             bContent = false;
1846         }
1847         break;
1848     case XML_ELEMENT(TEXT, XML_INDEX_TITLE):
1849     case XML_ELEMENT(TEXT, XML_SECTION):
1850         pContext = new XMLSectionImportContext( rImport );
1851         break;
1852     case XML_ELEMENT(TEXT, XML_TABLE_OF_CONTENT):
1853     case XML_ELEMENT(TEXT, XML_OBJECT_INDEX):
1854     case XML_ELEMENT(TEXT, XML_TABLE_INDEX):
1855     case XML_ELEMENT(TEXT, XML_ILLUSTRATION_INDEX):
1856     case XML_ELEMENT(TEXT, XML_USER_INDEX):
1857     case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX):
1858     case XML_ELEMENT(TEXT, XML_BIBLIOGRAPHY):
1859         if( XMLTextType::Shape != eType )
1860             pContext = new XMLIndexTOCContext( rImport, nElement );
1861         break;
1862     case XML_ELEMENT(TEXT, XML_TRACKED_CHANGES):
1863         pContext = new XMLTrackedChangesImportContext( rImport );
1864         bContent = false;
1865         break;
1866     case XML_ELEMENT(TEXT, XML_CHANGE):
1867     case XML_ELEMENT(TEXT, XML_CHANGE_START):
1868     case XML_ELEMENT(TEXT, XML_CHANGE_END):
1869         pContext = new XMLChangeImportContext(
1870             rImport,
1871             ((nElement == XML_ELEMENT(TEXT, XML_CHANGE_END))
1872                 ? XMLChangeImportContext::Element::END
1873                 : (nElement == XML_ELEMENT(TEXT, XML_CHANGE_START))
1874                     ? XMLChangeImportContext::Element::START
1875                     : XMLChangeImportContext::Element::POINT),
1876             true);
1877         break;
1878     case XML_ELEMENT(OFFICE, XML_FORMS):
1879         pContext = xmloff::OFormLayerXMLImport::createOfficeFormsContext(rImport);
1880         bContent = false;
1881         break;
1882     case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_AUTO_MARK_FILE):
1883         if( XMLTextType::Body == eType )
1884         {
1885             pContext = new XMLAutoMarkFileContext(rImport);
1886         }
1887         bContent = false;
1888         break;
1889     case XML_ELEMENT(TABLE, XML_CALCULATION_SETTINGS):
1890         pContext = new XMLCalculationSettingsContext ( rImport, nElement, xAttrList);
1891         bContent = false;
1892         break;
1893 
1894     default:
1895         if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted) ||
1896             XMLTextType::TextBox == eType ||
1897              XMLTextType::ChangedRegion == eType )
1898         {
1899             Reference < XShapes > xShapes;
1900             pContext = XMLShapeImportHelper::CreateGroupChildContext(
1901                     rImport, nElement, xAttrList, xShapes );
1902             bContent = false;
1903         }
1904     }
1905 
1906     // handle open redlines
1907     if ( (XML_ELEMENT(TEXT, XML_CHANGE) != nElement) &&
1908          (XML_ELEMENT(TEXT, XML_CHANGE_END) != nElement) &&
1909          (XML_ELEMENT(TEXT, XML_CHANGE_START) != nElement) )
1910     {
1911 //      ResetOpenRedlineId();
1912     }
1913 
1914     if( XMLTextType::Body == eType && bContent )
1915     {
1916         m_xImpl->m_bBodyContentStarted = false;
1917     }
1918 
1919     if( nElement != XML_ELEMENT(DRAW, XML_FRAME) )
1920         ClearLastImportedTextFrameName();
1921 
1922     if (!pContext)
1923         XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
1924 
1925     return pContext;
1926 }
1927 
CreateTableChildContext(SvXMLImport &,sal_Int32,const Reference<XFastAttributeList> &)1928 SvXMLImportContext *XMLTextImportHelper::CreateTableChildContext(
1929         SvXMLImport&,
1930         sal_Int32 /*nElement*/,
1931         const Reference< XFastAttributeList > & )
1932 {
1933     return nullptr;
1934 }
1935 
1936 /// get data style key for use with NumberFormat property
GetDataStyleKey(const OUString & sStyleName,bool * pIsSystemLanguage)1937 sal_Int32 XMLTextImportHelper::GetDataStyleKey(const OUString& sStyleName,
1938                                                bool* pIsSystemLanguage )
1939 {
1940     if (!m_xImpl->m_xAutoStyles.is())
1941         return -1;
1942 
1943     const SvXMLStyleContext* pStyle =
1944         m_xImpl->m_xAutoStyles->FindStyleChildContext( XmlStyleFamily::DATA_STYLE,
1945                                               sStyleName, true );
1946 
1947     // get appropriate context
1948 
1949 
1950     // first check if it's an Impress and draw only number format
1951     // this is needed since it's also a SvXMLNumFormatContext,
1952     // that was needed to support them for controls in impress/draw also
1953     const SdXMLNumberFormatImportContext* pSdNumStyle = dynamic_cast<const SdXMLNumberFormatImportContext*>( pStyle  );
1954     if( pSdNumStyle )
1955     {
1956         return pSdNumStyle->GetDrawKey();
1957     }
1958     else
1959     {
1960         SvXMLNumFormatContext* pNumStyle = const_cast<SvXMLNumFormatContext*>(dynamic_cast<const SvXMLNumFormatContext*>( pStyle ) );
1961         if( pNumStyle )
1962         {
1963             if( pIsSystemLanguage != nullptr )
1964                 *pIsSystemLanguage = pNumStyle->IsSystemLanguage();
1965 
1966             // return key
1967             return pNumStyle->GetKey();
1968         }
1969     }
1970     return -1;
1971 }
1972 
FindAutoListStyle(const OUString & rName) const1973 const SvxXMLListStyleContext *XMLTextImportHelper::FindAutoListStyle( const OUString& rName ) const
1974 {
1975     const SvxXMLListStyleContext *pStyle = nullptr;
1976     if (m_xImpl->m_xAutoStyles.is())
1977     {
1978         const SvXMLStyleContext* pTempStyle =
1979             m_xImpl->m_xAutoStyles->FindStyleChildContext( XmlStyleFamily::TEXT_LIST, rName,
1980                                            true );
1981         pStyle = dynamic_cast< const SvxXMLListStyleContext* >(pTempStyle);
1982     }
1983 
1984     return pStyle;
1985 }
1986 
FindAutoFrameStyle(const OUString & rName) const1987 XMLPropStyleContext *XMLTextImportHelper::FindAutoFrameStyle( const OUString& rName ) const
1988 {
1989     XMLPropStyleContext *pStyle = nullptr;
1990     if (m_xImpl->m_xAutoStyles.is())
1991     {
1992         const SvXMLStyleContext* pTempStyle =
1993             m_xImpl->m_xAutoStyles->FindStyleChildContext( XmlStyleFamily::SD_GRAPHICS_ID, rName,
1994                                            true );
1995         pStyle = const_cast<XMLPropStyleContext*>(dynamic_cast< const XMLPropStyleContext* >(pTempStyle));
1996     }
1997 
1998     return pStyle;
1999 }
2000 
FindSectionStyle(const OUString & rName) const2001 XMLPropStyleContext* XMLTextImportHelper::FindSectionStyle(
2002     const OUString& rName ) const
2003 {
2004     XMLPropStyleContext* pStyle = nullptr;
2005     if (m_xImpl->m_xAutoStyles.is())
2006     {
2007         const SvXMLStyleContext* pTempStyle =
2008             m_xImpl->m_xAutoStyles->FindStyleChildContext(
2009                                XmlStyleFamily::TEXT_SECTION,
2010                                rName, true );
2011         pStyle = const_cast<XMLPropStyleContext*>(dynamic_cast< const XMLPropStyleContext* >(pTempStyle));
2012     }
2013 
2014     return pStyle;
2015 }
2016 
FindPageMaster(const OUString & rName) const2017 XMLPropStyleContext* XMLTextImportHelper::FindPageMaster(
2018     const OUString& rName ) const
2019 {
2020     XMLPropStyleContext* pStyle = nullptr;
2021     if (m_xImpl->m_xAutoStyles.is())
2022     {
2023         const SvXMLStyleContext* pTempStyle =
2024             m_xImpl->m_xAutoStyles->FindStyleChildContext(
2025                                XmlStyleFamily::PAGE_MASTER,
2026                                rName, true );
2027         pStyle = const_cast<XMLPropStyleContext*>(dynamic_cast< const XMLPropStyleContext* >(pTempStyle));
2028     }
2029 
2030     return pStyle;
2031 }
2032 
FindDrawingPage(OUString const & rName) const2033 XMLPropStyleContext * XMLTextImportHelper::FindDrawingPage(OUString const& rName) const
2034 {
2035     if (!m_xImpl->m_xAutoStyles.is())
2036     {
2037         return nullptr;
2038     }
2039     SvXMLStyleContext const* pStyle(
2040         m_xImpl->m_xAutoStyles->FindStyleChildContext(
2041                XmlStyleFamily::SD_DRAWINGPAGE_ID, rName, true));
2042     assert(pStyle == nullptr || dynamic_cast<XMLPropStyleContext const*>(pStyle) != nullptr);
2043     return const_cast<XMLPropStyleContext*>(static_cast<XMLPropStyleContext const*>(pStyle));
2044 }
2045 
PushListContext()2046 void XMLTextImportHelper::PushListContext()
2047 {
2048     GetTextListHelper().PushListContext(static_cast<XMLTextListBlockContext*>(nullptr));
2049 }
2050 
PopListContext()2051 void XMLTextImportHelper::PopListContext()
2052 {
2053     GetTextListHelper().PopListContext();
2054 }
2055 
2056 
GetRenameMap()2057 SvI18NMap& XMLTextImportHelper::GetRenameMap()
2058 {
2059     if (!m_xImpl->m_xRenameMap)
2060     {
2061         m_xImpl->m_xRenameMap.reset( new SvI18NMap );
2062     }
2063     return *m_xImpl->m_xRenameMap;
2064 }
2065 
InsertBookmarkStartRange(const OUString & sName,const Reference<XTextRange> & rRange,OUString const & i_rXmlId,std::shared_ptr<::xmloff::ParsedRDFaAttributes> & i_rpRDFaAttributes)2066 void XMLTextImportHelper::InsertBookmarkStartRange(
2067     const OUString & sName,
2068     const Reference<XTextRange> & rRange,
2069     OUString const& i_rXmlId,
2070     std::shared_ptr< ::xmloff::ParsedRDFaAttributes > & i_rpRDFaAttributes)
2071 {
2072     m_xImpl->m_BookmarkStartRanges[sName] =
2073         std::make_tuple(rRange, i_rXmlId, i_rpRDFaAttributes);
2074     m_xImpl->m_BookmarkVector.push_back(sName);
2075 }
2076 
FindAndRemoveBookmarkStartRange(const OUString & sName,Reference<XTextRange> & o_rRange,OUString & o_rXmlId,std::shared_ptr<::xmloff::ParsedRDFaAttributes> & o_rpRDFaAttributes)2077 bool XMLTextImportHelper::FindAndRemoveBookmarkStartRange(
2078     const OUString & sName,
2079     Reference<XTextRange> & o_rRange,
2080     OUString & o_rXmlId,
2081     std::shared_ptr< ::xmloff::ParsedRDFaAttributes > & o_rpRDFaAttributes)
2082 {
2083     if (m_xImpl->m_BookmarkStartRanges.count(sName))
2084     {
2085         Impl::BookmarkMapEntry_t & rEntry =
2086             (*m_xImpl->m_BookmarkStartRanges.find(sName)).second;
2087         o_rRange.set(std::get<0>(rEntry));
2088         o_rXmlId = std::get<1>(rEntry);
2089         o_rpRDFaAttributes = std::get<2>(rEntry);
2090         m_xImpl->m_BookmarkStartRanges.erase(sName);
2091         auto it = std::find(m_xImpl->m_BookmarkVector.begin(), m_xImpl->m_BookmarkVector.end(), sName);
2092         if (it!=m_xImpl->m_BookmarkVector.end())
2093         {
2094             m_xImpl->m_BookmarkVector.erase(it);
2095         }
2096         return true;
2097     }
2098     else
2099     {
2100         return false;
2101     }
2102 }
2103 
pushFieldCtx(const OUString & name,const OUString & type)2104 void XMLTextImportHelper::pushFieldCtx( const OUString& name, const OUString& type )
2105 {
2106     m_xImpl->m_FieldStack.push(Impl::field_stack_item_t(
2107         Impl::field_name_type_t(name, type), Impl::field_params_t(), uno::Reference<text::XFormField>{}));
2108 }
2109 
2110 uno::Reference<text::XFormField>
popFieldCtx()2111 XMLTextImportHelper::popFieldCtx()
2112 {
2113     uno::Reference<text::XFormField> xRet;
2114     if ( !m_xImpl->m_FieldStack.empty() )
2115     {
2116         xRet = std::get<2>(m_xImpl->m_FieldStack.top());
2117         m_xImpl->m_FieldStack.pop();
2118     }
2119     else
2120     {
2121         SAL_INFO("xmloff.text", "unexpected fieldmark end");
2122     }
2123     return xRet;
2124 }
2125 
addFieldParam(const OUString & name,const OUString & value)2126 void XMLTextImportHelper::addFieldParam( const OUString& name, const OUString& value )
2127 {
2128     assert(!m_xImpl->m_FieldStack.empty());
2129     if (!m_xImpl->m_FieldStack.empty()) {
2130         Impl::field_stack_item_t & FieldStackItem(m_xImpl->m_FieldStack.top());
2131         std::get<1>(FieldStackItem).emplace_back( name, value );
2132     }
2133 }
2134 
getCurrentFieldType()2135 OUString XMLTextImportHelper::getCurrentFieldType()
2136 {
2137     assert(!m_xImpl->m_FieldStack.empty());
2138     if (!m_xImpl->m_FieldStack.empty())
2139     {
2140         return std::get<0>(m_xImpl->m_FieldStack.top()).second;
2141     }
2142     else
2143     {
2144         return OUString();
2145     }
2146 }
2147 
hasCurrentFieldCtx() const2148 bool XMLTextImportHelper::hasCurrentFieldCtx() const
2149 {
2150     return !m_xImpl->m_FieldStack.empty();
2151 }
2152 
setCurrentFieldParamsTo(css::uno::Reference<css::text::XFormField> const & xFormField)2153 void XMLTextImportHelper::setCurrentFieldParamsTo(css::uno::Reference< css::text::XFormField> const &xFormField)
2154 {
2155     assert(!m_xImpl->m_FieldStack.empty());
2156     if (!m_xImpl->m_FieldStack.empty() && xFormField.is())
2157     {
2158         FieldParamImporter(&std::get<1>(m_xImpl->m_FieldStack.top()),
2159             xFormField->getParameters()).Import();
2160         std::get<2>(m_xImpl->m_FieldStack.top()) = xFormField;
2161     }
2162 }
2163 
2164 
ConnectFrameChains(const OUString & rFrmName,const OUString & rNextFrmName,const Reference<XPropertySet> & rFrmPropSet)2165 void XMLTextImportHelper::ConnectFrameChains(
2166         const OUString& rFrmName,
2167         const OUString& rNextFrmName,
2168         const Reference < XPropertySet >& rFrmPropSet )
2169 {
2170     if( rFrmName.isEmpty() )
2171         return;
2172 
2173     if( !rNextFrmName.isEmpty() )
2174     {
2175         OUString sNextFrmName(GetRenameMap().Get( XML_TEXT_RENAME_TYPE_FRAME,
2176                                                     rNextFrmName ));
2177         if (m_xImpl->m_xTextFrames.is()
2178             && m_xImpl->m_xTextFrames->hasByName(sNextFrmName))
2179         {
2180             rFrmPropSet->setPropertyValue("ChainNextName",
2181                 makeAny(sNextFrmName));
2182         }
2183         else
2184         {
2185             if (!m_xImpl->m_xPrevFrmNames)
2186             {
2187                 m_xImpl->m_xPrevFrmNames.emplace();
2188                 m_xImpl->m_xNextFrmNames.emplace();
2189             }
2190             m_xImpl->m_xPrevFrmNames->push_back(rFrmName);
2191             m_xImpl->m_xNextFrmNames->push_back(sNextFrmName);
2192         }
2193     }
2194     if (m_xImpl->m_xPrevFrmNames && !m_xImpl->m_xPrevFrmNames->empty())
2195     {
2196         for(std::vector<OUString>::iterator i = m_xImpl->m_xPrevFrmNames->begin(), j = m_xImpl->m_xNextFrmNames->begin(); i != m_xImpl->m_xPrevFrmNames->end() && j != m_xImpl->m_xNextFrmNames->end(); ++i, ++j)
2197         {
2198             if((*j) == rFrmName)
2199             {
2200                 // The previous frame must exist, because it existing than
2201                 // inserting the entry
2202                 rFrmPropSet->setPropertyValue("ChainPrevName", makeAny(*i));
2203 
2204                 i = m_xImpl->m_xPrevFrmNames->erase(i);
2205                 j = m_xImpl->m_xNextFrmNames->erase(j);
2206 
2207                 // There cannot be more than one previous frames
2208                 break;
2209             }
2210         }
2211     }
2212 }
2213 
IsInFrame() const2214 bool XMLTextImportHelper::IsInFrame() const
2215 {
2216     static constexpr OUStringLiteral s_TextFrame = u"TextFrame";
2217 
2218     bool bIsInFrame = false;
2219 
2220     // are we currently in a text frame? yes, if the cursor has a
2221     // TextFrame property and it's non-NULL
2222     Reference<XPropertySet> xPropSet(const_cast<XMLTextImportHelper*>(this)->GetCursor(), UNO_QUERY);
2223     if (xPropSet.is())
2224     {
2225         if (xPropSet->getPropertySetInfo()->hasPropertyByName(s_TextFrame))
2226         {
2227             uno::Reference<XTextFrame> const xFrame(
2228                 xPropSet->getPropertyValue(s_TextFrame), UNO_QUERY);
2229 
2230             if (xFrame.is())
2231             {
2232                 bIsInFrame = true;
2233             }
2234         }
2235     }
2236 
2237     return bIsInFrame;
2238 }
2239 
IsInHeaderFooter() const2240 bool XMLTextImportHelper::IsInHeaderFooter() const
2241 {
2242     return false;
2243 }
2244 
createAndInsertOLEObject(SvXMLImport &,const OUString &,const OUString &,const OUString &,sal_Int32,sal_Int32)2245 Reference< XPropertySet> XMLTextImportHelper::createAndInsertOLEObject(
2246                                         SvXMLImport&,
2247                                         const OUString& /*rHRef*/,
2248                                         const OUString& /*rStyleName*/,
2249                                         const OUString& /*rTblName*/,
2250                                         sal_Int32 /*nWidth*/, sal_Int32 /*nHeight*/ )
2251 {
2252     Reference< XPropertySet> xPropSet;
2253     return xPropSet;
2254 }
2255 
createAndInsertOOoLink(SvXMLImport &,const OUString &,const OUString &,const OUString &,sal_Int32,sal_Int32)2256 Reference< XPropertySet> XMLTextImportHelper::createAndInsertOOoLink(
2257                                         SvXMLImport&,
2258                                         const OUString& /*rHRef*/,
2259                                         const OUString& /*rStyleName*/,
2260                                         const OUString& /*rTblName*/,
2261                                         sal_Int32 /*nWidth*/, sal_Int32 /*nHeight*/ )
2262 {
2263     Reference< XPropertySet> xPropSet;
2264     return xPropSet;
2265 }
2266 
createAndInsertApplet(const OUString &,const OUString &,bool,const OUString &,sal_Int32,sal_Int32)2267 Reference< XPropertySet> XMLTextImportHelper::createAndInsertApplet(
2268                                         const OUString& /*rCode*/,
2269                                         const OUString& /*rName*/,
2270                                         bool /*bMayScript*/,
2271                                         const OUString& /*rHRef*/,
2272                                         sal_Int32 /*nWidth*/, sal_Int32 /*nHeight*/ )
2273 {
2274     Reference< XPropertySet> xPropSet;
2275     return xPropSet;
2276 }
createAndInsertPlugin(const OUString &,const OUString &,sal_Int32,sal_Int32)2277 Reference< XPropertySet> XMLTextImportHelper::createAndInsertPlugin(
2278                                         const OUString& /*rMimeType*/,
2279                                         const OUString& /*rHRef*/,
2280                                         sal_Int32 /*nWidth*/, sal_Int32 /*nHeight*/ )
2281 {
2282     Reference< XPropertySet> xPropSet;
2283     return xPropSet;
2284 }
createAndInsertFloatingFrame(const OUString &,const OUString &,const OUString &,sal_Int32,sal_Int32)2285 Reference< XPropertySet> XMLTextImportHelper::createAndInsertFloatingFrame(
2286                                         const OUString& /*rName*/,
2287                                         const OUString& /*rHRef*/,
2288                                         const OUString& /*rStyleName*/,
2289                                         sal_Int32 /*nWidth*/, sal_Int32 /*nHeight*/ )
2290 {
2291     Reference< XPropertySet> xPropSet;
2292     return xPropSet;
2293 }
2294 
endAppletOrPlugin(const Reference<XPropertySet> &,std::map<const OUString,OUString> &)2295 void XMLTextImportHelper::endAppletOrPlugin(
2296         const Reference < XPropertySet> &,
2297         std::map < const OUString, OUString > &)
2298 {
2299 }
2300 // redline helper: dummy implementation to be overridden in sw/filter/xml
RedlineAdd(const OUString &,const OUString &,const OUString &,const OUString &,const util::DateTime &,bool)2301 void XMLTextImportHelper::RedlineAdd( const OUString& /*rType*/,
2302                                       const OUString& /*rId*/,
2303                                       const OUString& /*rAuthor*/,
2304                                       const OUString& /*rComment*/,
2305                                       const util::DateTime& /*rDateTime*/,
2306                                       bool /*bMergeLastPara*/)
2307 {
2308     // dummy implementation: do nothing
2309 }
2310 
RedlineCreateText(Reference<XTextCursor> &,const OUString &)2311 Reference<XTextCursor> XMLTextImportHelper::RedlineCreateText(
2312     Reference<XTextCursor> & /*rOldCursor*/,
2313     const OUString& /*rId*/)
2314 {
2315     // dummy implementation: do nothing
2316     Reference<XTextCursor> xRet;
2317     return xRet;
2318 }
2319 
RedlineSetCursor(const OUString &,bool,bool)2320 void XMLTextImportHelper::RedlineSetCursor(
2321     const OUString& /*rId*/,
2322     bool /*bStart*/,
2323     bool /*bIsOutsideOfParagraph*/)
2324 {
2325     // dummy implementation: do nothing
2326 }
2327 
RedlineAdjustStartNodeCursor()2328 void XMLTextImportHelper::RedlineAdjustStartNodeCursor()
2329 {
2330     // dummy implementation: do nothing
2331 }
2332 
SetShowChanges(bool)2333 void XMLTextImportHelper::SetShowChanges( bool )
2334 {
2335     // dummy implementation: do nothing
2336 }
2337 
SetRecordChanges(bool)2338 void XMLTextImportHelper::SetRecordChanges( bool )
2339 {
2340     // dummy implementation: do nothing
2341 }
SetChangesProtectionKey(const Sequence<sal_Int8> &)2342 void XMLTextImportHelper::SetChangesProtectionKey(const Sequence<sal_Int8> &)
2343 {
2344     // dummy implementation: do nothing
2345 }
2346 
2347 
GetOpenRedlineId() const2348 OUString const & XMLTextImportHelper::GetOpenRedlineId() const
2349 {
2350     return m_xImpl->m_sOpenRedlineIdentifier;
2351 }
2352 
SetOpenRedlineId(OUString const & rId)2353 void XMLTextImportHelper::SetOpenRedlineId( OUString const & rId)
2354 {
2355     m_xImpl->m_sOpenRedlineIdentifier = rId;
2356 }
2357 
ResetOpenRedlineId()2358 void XMLTextImportHelper::ResetOpenRedlineId()
2359 {
2360     SetOpenRedlineId("");
2361 }
2362 
2363 void
SetCellParaStyleDefault(OUString const & rNewValue)2364 XMLTextImportHelper::SetCellParaStyleDefault(OUString const& rNewValue)
2365 {
2366     m_xImpl->m_sCellParaStyleDefault = rNewValue;
2367 }
2368 
GetCellParaStyleDefault() const2369 OUString const& XMLTextImportHelper::GetCellParaStyleDefault() const
2370 {
2371     return m_xImpl->m_sCellParaStyleDefault;
2372 }
2373 
AddCrossRefHeadingMapping(OUString const & rFrom,OUString const & rTo)2374 void XMLTextImportHelper::AddCrossRefHeadingMapping(OUString const& rFrom, OUString const& rTo)
2375 {
2376     if (!m_xImpl->m_xCrossRefHeadingBookmarkMap)
2377     {
2378         m_xImpl->m_xCrossRefHeadingBookmarkMap.emplace();
2379     }
2380     m_xImpl->m_xCrossRefHeadingBookmarkMap->insert(std::make_pair(rFrom, rTo));
2381 }
2382 
2383 // tdf#94804: hack to map cross reference fields that reference duplicate marks
2384 // note that we can't really check meta:generator for this since the file might
2385 // be round-tripped by different versions preserving duplicates => always map
MapCrossRefHeadingFieldsHorribly()2386 void XMLTextImportHelper::MapCrossRefHeadingFieldsHorribly()
2387 {
2388     if (!m_xImpl->m_xCrossRefHeadingBookmarkMap)
2389     {
2390         return;
2391     }
2392 
2393     uno::Reference<text::XTextFieldsSupplier> const xFieldsSupplier(
2394             m_xImpl->m_rSvXMLImport.GetModel(), uno::UNO_QUERY);
2395     if (!xFieldsSupplier.is())
2396     {
2397         return;
2398     }
2399     uno::Reference<container::XEnumerationAccess> const xFieldsEA(
2400             xFieldsSupplier->getTextFields());
2401     uno::Reference<container::XEnumeration> const xFields(
2402             xFieldsEA->createEnumeration());
2403     while (xFields->hasMoreElements())
2404     {
2405         uno::Reference<lang::XServiceInfo> const xFieldInfo(
2406                 xFields->nextElement(), uno::UNO_QUERY);
2407         if (!xFieldInfo->supportsService("com.sun.star.text.textfield.GetReference"))
2408         {
2409             continue;
2410         }
2411         uno::Reference<beans::XPropertySet> const xField(
2412                 xFieldInfo, uno::UNO_QUERY);
2413         sal_uInt16 nType(0);
2414         xField->getPropertyValue("ReferenceFieldSource") >>= nType;
2415         if (text::ReferenceFieldSource::BOOKMARK != nType)
2416         {
2417             continue;
2418         }
2419         OUString name;
2420         xField->getPropertyValue("SourceName") >>= name;
2421         auto const iter(m_xImpl->m_xCrossRefHeadingBookmarkMap->find(name));
2422         if (iter == m_xImpl->m_xCrossRefHeadingBookmarkMap->end())
2423         {
2424             continue;
2425         }
2426         xField->setPropertyValue("SourceName", uno::makeAny(iter->second));
2427     }
2428 }
2429 
setBookmarkAttributes(OUString const & bookmark,bool hidden,OUString const & condition)2430 void XMLTextImportHelper::setBookmarkAttributes(OUString const& bookmark, bool hidden, OUString const& condition)
2431 {
2432     m_xImpl->m_bBookmarkHidden[bookmark] = hidden;
2433     m_xImpl->m_sBookmarkCondition[bookmark] = condition;
2434 }
2435 
getBookmarkHidden(OUString const & bookmark) const2436 bool XMLTextImportHelper::getBookmarkHidden(OUString const& bookmark) const
2437 {
2438     return m_xImpl->m_bBookmarkHidden[bookmark];
2439 }
2440 
getBookmarkCondition(OUString const & bookmark) const2441 const OUString& XMLTextImportHelper::getBookmarkCondition(OUString const& bookmark) const
2442 {
2443     return m_xImpl->m_sBookmarkCondition[bookmark];
2444 }
2445 
2446 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2447