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 "xmlstyli.hxx"
21 #include <xmloff/xmlnamespace.hxx>
22 #include <xmloff/xmlimppr.hxx>
23 #include <xmloff/families.hxx>
24 #include <xmloff/xmlnumfi.hxx>
25 #include <xmloff/XMLGraphicsDefaultStyle.hxx>
26 #include <xmloff/xmltoken.hxx>
27 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
28 #include <com/sun/star/table/BorderLine2.hpp>
29 #include <comphelper/extract.hxx>
30 #include <xmloff/xmlprcon.hxx>
31 #include "XMLTableHeaderFooterContext.hxx"
32 #include "XMLConverter.hxx"
33 #include "XMLTableShapeImportHelper.hxx"
34 #include <sheetdata.hxx>
35 #include "xmlannoi.hxx"
36 #include <textuno.hxx>
37 #include <cellsuno.hxx>
38 #include "xmlstyle.hxx"
39 
40 #include <docuno.hxx>
41 #include <unonames.hxx>
42 #include <document.hxx>
43 #include <conditio.hxx>
44 #include <rangelst.hxx>
45 
46 #define XML_LINE_LEFT 0
47 #define XML_LINE_RIGHT 1
48 #define XML_LINE_TOP 2
49 #define XML_LINE_BOTTOM 3
50 
51 #define XML_LINE_TLBR 0
52 #define XML_LINE_BLTR 1
53 
54 using namespace ::com::sun::star;
55 using namespace ::com::sun::star::xml::sax;
56 using namespace ::com::sun::star::style;
57 using namespace ::com::sun::star::beans;
58 using namespace ::com::sun::star::container;
59 using namespace xmloff::token;
60 using namespace ::formula;
61 
62 using com::sun::star::uno::UNO_QUERY;
ScXMLCellImportPropertyMapper(const rtl::Reference<XMLPropertySetMapper> & rMapper,SvXMLImport & rImportP)63 ScXMLCellImportPropertyMapper::ScXMLCellImportPropertyMapper(
64         const rtl::Reference< XMLPropertySetMapper >& rMapper,
65         SvXMLImport& rImportP) :
66     SvXMLImportPropertyMapper( rMapper, rImportP )
67 {
68 }
69 
~ScXMLCellImportPropertyMapper()70 ScXMLCellImportPropertyMapper::~ScXMLCellImportPropertyMapper()
71 {
72 }
73 
finished(::std::vector<XMLPropertyState> & rProperties,sal_Int32 nStartIndex,sal_Int32 nEndIndex) const74 void ScXMLCellImportPropertyMapper::finished(::std::vector< XMLPropertyState >& rProperties, sal_Int32 nStartIndex, sal_Int32 nEndIndex ) const
75 {
76     static const sal_Int16 aPaddingCTF[4] = { CTF_SC_LEFTPADDING, CTF_SC_RIGHTPADDING,
77                                             CTF_SC_TOPPADDING, CTF_SC_BOTTOMPADDING };
78     static const sal_Int16 aBorderCTF[4] = { CTF_SC_LEFTBORDER, CTF_SC_RIGHTBORDER,
79                                             CTF_SC_TOPBORDER, CTF_SC_BOTTOMBORDER };
80 
81     SvXMLImportPropertyMapper::finished(rProperties, nStartIndex, nEndIndex);
82     XMLPropertyState* pAllPaddingProperty(nullptr);
83     XMLPropertyState* pPadding[4] = { nullptr, nullptr, nullptr, nullptr };
84     XMLPropertyState* pNewPadding[4] = { nullptr, nullptr, nullptr, nullptr };
85     XMLPropertyState* pAllBorderProperty = nullptr;
86     XMLPropertyState* pBorders[4] = { nullptr, nullptr, nullptr, nullptr };
87     XMLPropertyState* pNewBorders[4] = { nullptr, nullptr, nullptr, nullptr };
88     XMLPropertyState* pAllBorderWidthProperty = nullptr;
89     XMLPropertyState* pBorderWidths[4] = { nullptr, nullptr, nullptr, nullptr };
90     XMLPropertyState* pDiagBorders[2] = { nullptr };
91     XMLPropertyState* pOldDiagBorderWidths[2] = { nullptr };      // old attribute names without "s"
92     XMLPropertyState* pDiagBorderWidths[2] = { nullptr };
93 
94     for (auto& rProperty : rProperties)
95     {
96         XMLPropertyState*property = &rProperty;
97         if (property->mnIndex != -1)
98         {
99             sal_Int16 nContextID = getPropertySetMapper()->GetEntryContextId(property->mnIndex);
100             switch (nContextID)
101             {
102                 case CTF_SC_ALLPADDING                  : pAllPaddingProperty = property; break;
103                 case CTF_SC_LEFTPADDING                 : pPadding[XML_LINE_LEFT] = property; break;
104                 case CTF_SC_RIGHTPADDING                : pPadding[XML_LINE_RIGHT] = property; break;
105                 case CTF_SC_TOPPADDING                  : pPadding[XML_LINE_TOP] = property; break;
106                 case CTF_SC_BOTTOMPADDING               : pPadding[XML_LINE_BOTTOM] = property; break;
107                 case CTF_SC_ALLBORDER                   : pAllBorderProperty = property; break;
108                 case CTF_SC_LEFTBORDER                  : pBorders[XML_LINE_LEFT] = property; break;
109                 case CTF_SC_RIGHTBORDER                 : pBorders[XML_LINE_RIGHT] = property; break;
110                 case CTF_SC_TOPBORDER                   : pBorders[XML_LINE_TOP] = property; break;
111                 case CTF_SC_BOTTOMBORDER                : pBorders[XML_LINE_BOTTOM] = property; break;
112                 case CTF_SC_ALLBORDERWIDTH              : pAllBorderWidthProperty = property; break;
113                 case CTF_SC_LEFTBORDERWIDTH             : pBorderWidths[XML_LINE_LEFT] = property; break;
114                 case CTF_SC_RIGHTBORDERWIDTH            : pBorderWidths[XML_LINE_RIGHT] = property; break;
115                 case CTF_SC_TOPBORDERWIDTH              : pBorderWidths[XML_LINE_TOP] = property; break;
116                 case CTF_SC_BOTTOMBORDERWIDTH           : pBorderWidths[XML_LINE_BOTTOM] = property; break;
117                 case CTF_SC_DIAGONALTLBR                : pDiagBorders[XML_LINE_TLBR] = property; break;
118                 case CTF_SC_DIAGONALBLTR                : pDiagBorders[XML_LINE_BLTR] = property; break;
119                 case CTF_SC_DIAGONALTLBRWIDTH           : pOldDiagBorderWidths[XML_LINE_TLBR] = property; break;
120                 case CTF_SC_DIAGONALTLBRWIDTHS          : pDiagBorderWidths[XML_LINE_TLBR] = property; break;
121                 case CTF_SC_DIAGONALBLTRWIDTH           : pOldDiagBorderWidths[XML_LINE_BLTR] = property; break;
122                 case CTF_SC_DIAGONALBLTRWIDTHS          : pDiagBorderWidths[XML_LINE_BLTR] = property; break;
123             }
124         }
125     }
126     sal_uInt16 i;
127 
128     // #i27594#; copy Value, but don't insert
129     if (pAllBorderWidthProperty)
130         pAllBorderWidthProperty->mnIndex = -1;
131     if (pAllBorderProperty)
132         pAllBorderProperty->mnIndex = -1;
133     if (pAllPaddingProperty)
134         pAllPaddingProperty->mnIndex = -1;
135 
136     for (i = 0; i < 4; ++i)
137     {
138         if (pAllPaddingProperty && !pPadding[i])
139             pNewPadding[i] = new XMLPropertyState(maPropMapper->FindEntryIndex(aPaddingCTF[i]), pAllPaddingProperty->maValue);
140         if (pAllBorderProperty && !pBorders[i])
141         {
142             pNewBorders[i] = new XMLPropertyState(maPropMapper->FindEntryIndex(aBorderCTF[i]), pAllBorderProperty->maValue);
143             pBorders[i] = pNewBorders[i];
144         }
145         if( !pBorderWidths[i] )
146             pBorderWidths[i] = pAllBorderWidthProperty;
147         else
148             pBorderWidths[i]->mnIndex = -1;
149         if( pBorders[i] )
150         {
151             table::BorderLine2 aBorderLine;
152             pBorders[i]->maValue >>= aBorderLine;
153             if( pBorderWidths[i] )
154             {
155                 // Merge style:border-line-width values to fo:border values. Do
156                 // not override fo:border line width or line style with an
157                 // empty value!
158                 table::BorderLine2 aBorderLineWidth;
159                 pBorderWidths[i]->maValue >>= aBorderLineWidth;
160                 aBorderLine.OuterLineWidth = aBorderLineWidth.OuterLineWidth;
161                 aBorderLine.InnerLineWidth = aBorderLineWidth.InnerLineWidth;
162                 aBorderLine.LineDistance = aBorderLineWidth.LineDistance;
163                 pBorders[i]->maValue <<= aBorderLine;
164             }
165         }
166     }
167     for( i = 0; i < 2; ++i )
168     {
169         if( pDiagBorders[i] && ( pDiagBorderWidths[i] || pOldDiagBorderWidths[i] ) )
170         {
171             table::BorderLine2 aBorderLine;
172             pDiagBorders[i]->maValue >>= aBorderLine;
173             table::BorderLine2 aBorderLineWidth;
174             if (pDiagBorderWidths[i])
175                 pDiagBorderWidths[i]->maValue >>= aBorderLineWidth;     // prefer new attribute
176             else
177                 pOldDiagBorderWidths[i]->maValue >>= aBorderLineWidth;
178             aBorderLine.OuterLineWidth = aBorderLineWidth.OuterLineWidth;
179             aBorderLine.InnerLineWidth = aBorderLineWidth.InnerLineWidth;
180             aBorderLine.LineDistance = aBorderLineWidth.LineDistance;
181             pDiagBorders[i]->maValue <<= aBorderLine;
182             if (pDiagBorderWidths[i])
183                 pDiagBorderWidths[i]->mnIndex = -1;
184             if (pOldDiagBorderWidths[i])
185                 pOldDiagBorderWidths[i]->mnIndex = -1;      // reset mnIndex for old and new attribute if both are present
186         }
187     }
188 
189     for (i = 0; i < 4; ++i)
190     {
191         if (pNewPadding[i])
192         {
193             rProperties.push_back(*pNewPadding[i]);
194             delete pNewPadding[i];
195         }
196         if (pNewBorders[i])
197         {
198             rProperties.push_back(*pNewBorders[i]);
199             delete pNewBorders[i];
200         }
201     }
202 }
203 
ScXMLRowImportPropertyMapper(const rtl::Reference<XMLPropertySetMapper> & rMapper,SvXMLImport & rImportP)204 ScXMLRowImportPropertyMapper::ScXMLRowImportPropertyMapper(
205         const rtl::Reference< XMLPropertySetMapper >& rMapper,
206         SvXMLImport& rImportP) :
207     SvXMLImportPropertyMapper( rMapper, rImportP )
208 {
209 }
210 
~ScXMLRowImportPropertyMapper()211 ScXMLRowImportPropertyMapper::~ScXMLRowImportPropertyMapper()
212 {
213 }
214 
finished(::std::vector<XMLPropertyState> & rProperties,sal_Int32 nStartIndex,sal_Int32 nEndIndex) const215 void ScXMLRowImportPropertyMapper::finished(::std::vector< XMLPropertyState >& rProperties, sal_Int32 nStartIndex, sal_Int32 nEndIndex ) const
216 {
217     SvXMLImportPropertyMapper::finished(rProperties, nStartIndex, nEndIndex);
218     XMLPropertyState* pHeight(nullptr);
219     XMLPropertyState* pOptimalHeight(nullptr);
220     XMLPropertyState* pPageBreak(nullptr);
221     for (auto& rProperty : rProperties)
222     {
223         XMLPropertyState* property = &rProperty;
224         if (property->mnIndex != -1)
225         {
226             sal_Int16 nContextID = getPropertySetMapper()->GetEntryContextId(property->mnIndex);
227             switch (nContextID)
228             {
229                 case CTF_SC_ROWHEIGHT                   : pHeight = property; break;
230                 case CTF_SC_ROWOPTIMALHEIGHT            : pOptimalHeight = property; break;
231                 case CTF_SC_ROWBREAKBEFORE              : pPageBreak = property; break;
232             }
233         }
234     }
235     if (pPageBreak)
236     {
237         if(!(::cppu::any2bool(pPageBreak->maValue)))
238             pPageBreak->mnIndex = -1;
239     }
240     if (pOptimalHeight)
241     {
242         if (::cppu::any2bool(pOptimalHeight->maValue))
243         {
244             if (pHeight)
245             {
246                 // set the stored height, but keep "optimal" flag:
247                 // pass the height value as OptimalHeight property (only allowed while loading!)
248                 pOptimalHeight->maValue = pHeight->maValue;
249                 pHeight->mnIndex = -1;
250             }
251             else
252                 pOptimalHeight->mnIndex = -1;
253         }
254     }
255     else if (pHeight)
256     {
257         rProperties.emplace_back(maPropMapper->FindEntryIndex(CTF_SC_ROWOPTIMALHEIGHT), css::uno::Any(false));
258     }
259     // don't access pointers to rProperties elements after push_back!
260 }
261 
262 namespace {
263 
264 class XMLTableCellPropsContext : public SvXMLPropertySetContext
265 {
266     public:
267         XMLTableCellPropsContext(
268              SvXMLImport& rImport, sal_Int32 nElement,
269              const uno::Reference< xml::sax::XFastAttributeList >& xAttrList,
270              sal_uInt32 nFamily,
271              ::std::vector< XMLPropertyState > &rProps,
272              const rtl::Reference < SvXMLImportPropertyMapper > &rMap);
273 
274     using SvXMLPropertySetContext::createFastChildContext;
275     virtual css::uno::Reference< css::xml::sax::XFastContextHandler > createFastChildContext(
276         sal_Int32 nElement,
277         const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList,
278         ::std::vector< XMLPropertyState > &rProperties,
279         const XMLPropertyState& rProp ) override;
280 };
281 
282 }
283 
XMLTableCellPropsContext(SvXMLImport & rImport,sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList,sal_uInt32 nFamily,::std::vector<XMLPropertyState> & rProps,const rtl::Reference<SvXMLImportPropertyMapper> & rMap)284 XMLTableCellPropsContext::XMLTableCellPropsContext(
285              SvXMLImport& rImport, sal_Int32 nElement,
286              const uno::Reference< xml::sax::XFastAttributeList >& xAttrList,
287              sal_uInt32 nFamily,
288              ::std::vector< XMLPropertyState > &rProps,
289              const rtl::Reference < SvXMLImportPropertyMapper > &rMap)
290           : SvXMLPropertySetContext( rImport, nElement, xAttrList, nFamily,
291                rProps, rMap )
292 {
293 }
294 
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,::std::vector<XMLPropertyState> & rProperties,const XMLPropertyState & rProp)295 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTableCellPropsContext::createFastChildContext(
296     sal_Int32 nElement,
297     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList,
298     ::std::vector< XMLPropertyState > &rProperties,
299     const XMLPropertyState& rProp )
300 {
301     // no need for a custom context or indeed a SvXMLTokenMap to grab just the
302     // single attribute ( href ) that we are interested in.
303     // still though, we will check namespaces etc.
304     if (nElement == XML_ELEMENT(STYLE, XML_HYPERLINK) ||
305         nElement == XML_ELEMENT(LO_EXT, XML_HYPERLINK) )
306     {
307         OUString sURL;
308         for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
309         {
310             if ( aIter.getToken() == XML_ELEMENT(XLINK, XML_HREF) )
311                 sURL = aIter.toString();
312             else
313                 XMLOFF_WARN_UNKNOWN("sc", aIter);
314         }
315         if ( !sURL.isEmpty() )
316         {
317             XMLPropertyState aProp( rProp );
318             aProp.maValue <<=  sURL;
319             rProperties.push_back( aProp );
320         }
321     }
322     return SvXMLPropertySetContext::createFastChildContext( nElement, xAttrList, rProperties, rProp );
323 }
324 
325 namespace {
326 
327 class ScXMLMapContext : public SvXMLImportContext
328 {
329     OUString msApplyStyle;
330     OUString msCondition;
331     OUString msBaseCell;
332 
GetScImport()333     ScXMLImport& GetScImport() { return static_cast<ScXMLImport&>(GetImport()); }
334 public:
335 
336     ScXMLMapContext(
337             SvXMLImport& rImport, sal_Int32 nElement,
338             const uno::Reference< xml::sax::XFastAttributeList > & xAttrList );
339 
340     ScCondFormatEntry* CreateConditionEntry();
341 };
342 
343 }
344 
ScXMLMapContext(SvXMLImport & rImport,sal_Int32,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)345 ScXMLMapContext::ScXMLMapContext(SvXMLImport& rImport, sal_Int32 /*nElement*/,
346             const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
347     : SvXMLImportContext( rImport )
348 {
349     for( auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ) )
350     {
351         OUString sValue = aIter.toString();
352         switch (aIter.getToken())
353         {
354             case XML_ELEMENT(STYLE, XML_CONDITION):
355                 msCondition = sValue;
356                 break;
357             case XML_ELEMENT(STYLE, XML_APPLY_STYLE_NAME):
358                 msApplyStyle = GetImport().GetStyleDisplayName( XmlStyleFamily::TABLE_CELL, sValue);
359                 break;
360             case XML_ELEMENT(STYLE, XML_BASE_CELL_ADDRESS):
361                 msBaseCell = sValue;
362                 break;
363             default:
364                 XMLOFF_WARN_UNKNOWN("sc", aIter);
365         }
366     }
367 }
368 
CreateConditionEntry()369 ScCondFormatEntry* ScXMLMapContext::CreateConditionEntry()
370 {
371     OUString aCondition, aConditionNmsp;
372     FormulaGrammar::Grammar eGrammar = FormulaGrammar::GRAM_UNSPECIFIED;
373     GetScImport().ExtractFormulaNamespaceGrammar( aCondition, aConditionNmsp, eGrammar, msCondition );
374     bool bHasNmsp = aCondition.getLength() < msCondition.getLength();
375 
376     // parse a condition from the attribute string
377     ScXMLConditionParseResult aParseResult;
378     ScXMLConditionHelper::parseCondition( aParseResult, aCondition, 0 );
379 
380     if( !bHasNmsp )
381     {
382         // the attribute does not contain a namespace: try to find a namespace of an external grammar
383         FormulaGrammar::Grammar eNewGrammar = FormulaGrammar::GRAM_UNSPECIFIED;
384         GetScImport().ExtractFormulaNamespaceGrammar( aCondition, aConditionNmsp, eNewGrammar, aCondition, true );
385         if( eNewGrammar != FormulaGrammar::GRAM_EXTERNAL )
386             eGrammar = eNewGrammar;
387     }
388 
389     ScConditionMode eMode = ScConditionEntry::GetModeFromApi(aParseResult.meOperator);
390     ScDocument* pDoc = GetScImport().GetDocument();
391 
392     ScCondFormatEntry* pEntry =  new ScCondFormatEntry(eMode, aParseResult.maOperand1, aParseResult.maOperand2, *pDoc, ScAddress(), msApplyStyle,
393                                                     OUString(), OUString(), eGrammar, eGrammar);
394 
395     pEntry->SetSrcString(msBaseCell);
396     return pEntry;
397 }
398 
SetAttribute(sal_Int32 nElement,const OUString & rValue)399 void XMLTableStyleContext::SetAttribute( sal_Int32 nElement,
400                                         const OUString& rValue )
401 {
402     switch(nElement & TOKEN_MASK)
403     {
404         case XML_DATA_STYLE_NAME:
405             sDataStyleName = rValue;
406             break;
407         case XML_MASTER_PAGE_NAME:
408             sPageStyle = rValue;
409             break;
410         default:
411             XMLPropStyleContext::SetAttribute( nElement, rValue );
412     }
413 }
414 
415 
XMLTableStyleContext(ScXMLImport & rImport,SvXMLStylesContext & rStyles,XmlStyleFamily nFamily,bool bDefaultStyle)416 XMLTableStyleContext::XMLTableStyleContext( ScXMLImport& rImport,
417         SvXMLStylesContext& rStyles, XmlStyleFamily nFamily, bool bDefaultStyle ) :
418     XMLPropStyleContext( rImport, rStyles, nFamily, bDefaultStyle ),
419     sDataStyleName(),
420     pStyles(&rStyles),
421     nNumberFormat(-1),
422     nLastSheet(-1),
423     bParentSet(false),
424     mpCondFormat(nullptr),
425     mbDeleteCondFormat(true)
426 {
427 }
428 
~XMLTableStyleContext()429 XMLTableStyleContext::~XMLTableStyleContext()
430 {
431     if(mbDeleteCondFormat)
432         delete mpCondFormat;
433 }
434 
createFastChildContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList)435 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTableStyleContext::createFastChildContext(
436     sal_Int32 nElement,
437     const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
438 {
439     css::uno::Reference< css::xml::sax::XFastContextHandler > xContext;
440 
441     if( nElement == XML_ELEMENT(STYLE, XML_MAP) )
442     {
443         if(!mpCondFormat)
444             mpCondFormat = new ScConditionalFormat( 0, GetScImport().GetDocument() );
445         ScXMLMapContext* pMapContext = new ScXMLMapContext(GetImport(), nElement, xAttrList);
446         xContext = pMapContext;
447         mpCondFormat->AddEntry(pMapContext->CreateConditionEntry());
448     }
449     else if ( nElement == XML_ELEMENT(STYLE, XML_TABLE_CELL_PROPERTIES) )
450     {
451         rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
452             GetStyles()->GetImportPropertyMapper(
453                 GetFamily() );
454         if( xImpPrMap.is() )
455             xContext = new XMLTableCellPropsContext( GetImport(), nElement,
456                 xAttrList,
457                 XML_TYPE_PROP_TABLE_CELL,
458                 GetProperties(),
459                 xImpPrMap );
460     }
461 
462     if (!xContext)
463         xContext = XMLPropStyleContext::createFastChildContext( nElement, xAttrList );
464     return xContext;
465 }
466 
ApplyCondFormat(const uno::Sequence<table::CellRangeAddress> & xCellRanges)467 void XMLTableStyleContext::ApplyCondFormat( const uno::Sequence<table::CellRangeAddress>& xCellRanges )
468 {
469     if(!mpCondFormat || GetScImport().HasNewCondFormatData())
470         return;
471 
472     ScRangeList aRangeList;
473     for(const table::CellRangeAddress& aAddress : xCellRanges)
474     {
475         ScRange aRange( aAddress.StartColumn, aAddress.StartRow, aAddress.Sheet, aAddress.EndColumn, aAddress.EndRow, aAddress.Sheet );
476         aRangeList.Join( aRange );
477     }
478 
479     ScDocument* pDoc = GetScImport().GetDocument();
480     SCTAB nTab = GetScImport().GetTables().GetCurrentSheet();
481     ScConditionalFormatList* pFormatList = pDoc->GetCondFormList(nTab);
482     auto itr = std::find_if(pFormatList->begin(), pFormatList->end(),
483         [this](const std::unique_ptr<ScConditionalFormat>& rxFormat) { return rxFormat->EqualEntries(*mpCondFormat); });
484     if (itr != pFormatList->end())
485     {
486         ScRangeList& rRangeList = (*itr)->GetRangeList();
487         sal_uInt32 nCondId = (*itr)->GetKey();
488         size_t n = aRangeList.size();
489         for(size_t i = 0; i < n; ++i)
490         {
491             const ScRange & rRange = aRangeList[i];
492             rRangeList.Join(rRange);
493         }
494 
495         pDoc->AddCondFormatData( aRangeList, nTab, nCondId );
496         return;
497     }
498 
499     if(mpCondFormat && mbDeleteCondFormat)
500     {
501         sal_uLong nIndex = pDoc->AddCondFormat(std::unique_ptr<ScConditionalFormat>(mpCondFormat), nTab );
502         mpCondFormat->SetKey(nIndex);
503         mpCondFormat->SetRange(aRangeList);
504 
505         pDoc->AddCondFormatData( aRangeList, nTab, nIndex );
506         mbDeleteCondFormat = false;
507     }
508 
509 }
510 
FillPropertySet(const uno::Reference<XPropertySet> & rPropSet)511 void XMLTableStyleContext::FillPropertySet(
512     const uno::Reference< XPropertySet > & rPropSet )
513 {
514     if (!IsDefaultStyle())
515     {
516         if (GetFamily() == XmlStyleFamily::TABLE_CELL)
517         {
518             if (!bParentSet)
519             {
520                 AddProperty(CTF_SC_CELLSTYLE, uno::makeAny(GetImport().GetStyleDisplayName( XmlStyleFamily::TABLE_CELL, GetParentName() )));
521                 bParentSet = true;
522             }
523             sal_Int32 nNumFmt = GetNumberFormat();
524             if (nNumFmt >= 0)
525                 AddProperty(CTF_SC_NUMBERFORMAT, uno::makeAny(nNumFmt));
526         }
527         else if (GetFamily() == XmlStyleFamily::TABLE_TABLE)
528         {
529             if (!sPageStyle.isEmpty())
530                 AddProperty(CTF_SC_MASTERPAGENAME, uno::makeAny(GetImport().GetStyleDisplayName( XmlStyleFamily::MASTER_PAGE, sPageStyle )));
531         }
532     }
533     XMLPropStyleContext::FillPropertySet(rPropSet);
534 }
535 
SetDefaults()536 void XMLTableStyleContext::SetDefaults()
537 {
538     if ((GetFamily() == XmlStyleFamily::TABLE_CELL) && GetImport().GetModel().is())
539     {
540         uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetImport().GetModel(), uno::UNO_QUERY);
541         if (xMultiServiceFactory.is())
542         {
543             uno::Reference <beans::XPropertySet> xProperties(xMultiServiceFactory->createInstance("com.sun.star.sheet.Defaults"), uno::UNO_QUERY);
544             if (xProperties.is())
545                 FillPropertySet(xProperties);
546         }
547     }
548 }
549 
AddProperty(const sal_Int16 nContextID,const uno::Any & rValue)550 void XMLTableStyleContext::AddProperty(const sal_Int16 nContextID, const uno::Any& rValue)
551 {
552     XMLPropertyState* property = FindProperty(nContextID);
553     if (property)
554         property->mnIndex = -1; // #i46996# remove old property, so it isn't double
555     sal_Int32 nIndex(static_cast<XMLTableStylesContext *>(pStyles)->GetIndex(nContextID));
556     OSL_ENSURE(nIndex != -1, "Property not found in Map");
557     XMLPropertyState aPropState(nIndex, rValue);
558     GetProperties().push_back(aPropState); // has to be inserted in a sort order later
559 }
560 
FindProperty(const sal_Int16 nContextID)561 XMLPropertyState* XMLTableStyleContext::FindProperty(const sal_Int16 nContextID)
562 {
563     XMLPropertyState* pRet = nullptr;
564     rtl::Reference < XMLPropertySetMapper > xPrMap;
565     rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
566         pStyles->GetImportPropertyMapper( GetFamily() );
567     OSL_ENSURE( xImpPrMap.is(), "There is the import prop mapper" );
568     if( xImpPrMap.is() )
569         xPrMap = xImpPrMap->getPropertySetMapper();
570     if( xPrMap.is() )
571     {
572         auto aIter = std::find_if(GetProperties().begin(), GetProperties().end(),
573             [&xPrMap, &nContextID](const XMLPropertyState& rProp) {
574                 return rProp.mnIndex != -1 && xPrMap->GetEntryContextId(rProp.mnIndex) == nContextID;
575             });
576         if (aIter != GetProperties().end())
577             pRet = &(*aIter);
578     }
579     return pRet;
580 }
581 
GetNumberFormat()582 sal_Int32 XMLTableStyleContext::GetNumberFormat()
583 {
584     if (nNumberFormat < 0 && !sDataStyleName.isEmpty())
585     {
586         const SvXMLNumFormatContext* pStyle = static_cast<const SvXMLNumFormatContext*>(
587             pStyles->FindStyleChildContext(XmlStyleFamily::DATA_STYLE, sDataStyleName, true));
588 
589         if (!pStyle)
590         {
591             XMLTableStylesContext* pMyStyles = static_cast<XMLTableStylesContext*>(GetScImport().GetStyles());
592             if (pMyStyles)
593                 pStyle = static_cast<const SvXMLNumFormatContext*>(
594                     pMyStyles->FindStyleChildContext(XmlStyleFamily::DATA_STYLE, sDataStyleName, true));
595             else
596             {
597                 OSL_FAIL("not possible to get style");
598             }
599         }
600         if (pStyle)
601             nNumberFormat = const_cast<SvXMLNumFormatContext*>(pStyle)->GetKey();
602     }
603     return nNumberFormat;
604 }
605 
CreateStyleStyleChildContext(XmlStyleFamily nFamily,sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)606 SvXMLStyleContext *XMLTableStylesContext::CreateStyleStyleChildContext(
607         XmlStyleFamily nFamily, sal_Int32 nElement,
608         const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
609 {
610     SvXMLStyleContext *pStyle;
611     // use own wrapper for text and paragraph, to record style usage
612     if (nFamily == XmlStyleFamily::TEXT_PARAGRAPH || nFamily == XmlStyleFamily::TEXT_TEXT)
613         pStyle = new  ScCellTextStyleContext( GetImport(),*this, nFamily );
614     else
615         pStyle = SvXMLStylesContext::CreateStyleStyleChildContext(
616                     nFamily, nElement, xAttrList );
617 
618     if (!pStyle)
619     {
620         switch( nFamily )
621         {
622         case XmlStyleFamily::TABLE_CELL:
623         case XmlStyleFamily::TABLE_COLUMN:
624         case XmlStyleFamily::TABLE_ROW:
625         case XmlStyleFamily::TABLE_TABLE:
626             pStyle = new XMLTableStyleContext( GetScImport(), *this, nFamily );
627             break;
628         default: break;
629         }
630     }
631 
632     return pStyle;
633 }
634 
CreateDefaultStyleStyleChildContext(XmlStyleFamily nFamily,sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)635 SvXMLStyleContext *XMLTableStylesContext::CreateDefaultStyleStyleChildContext(
636         XmlStyleFamily nFamily, sal_Int32 nElement,
637         const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
638 {
639     SvXMLStyleContext *pStyle(SvXMLStylesContext::CreateDefaultStyleStyleChildContext( nFamily, nElement,
640                                                             xAttrList ));
641     if (!pStyle)
642     {
643         switch( nFamily )
644         {
645             case XmlStyleFamily::TABLE_CELL:
646                 pStyle = new XMLTableStyleContext( GetScImport(), *this, nFamily, true);
647             break;
648             case XmlStyleFamily::SD_GRAPHICS_ID:
649                 pStyle = new XMLGraphicsDefaultStyle( GetScImport(), *this);
650             break;
651             default: break;
652         }
653     }
654 
655     return pStyle;
656 }
657 
658 constexpr OUStringLiteral gsCellStyleServiceName(u"com.sun.star.style.CellStyle");
659 constexpr OUStringLiteral gsColumnStyleServiceName(u"" XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_NAME);
660 constexpr OUStringLiteral gsRowStyleServiceName(u"" XML_STYLE_FAMILY_TABLE_ROW_STYLES_NAME);
661 constexpr OUStringLiteral gsTableStyleServiceName(u"" XML_STYLE_FAMILY_TABLE_TABLE_STYLES_NAME);
662 
XMLTableStylesContext(SvXMLImport & rImport,const bool bTempAutoStyles)663 XMLTableStylesContext::XMLTableStylesContext( SvXMLImport& rImport,
664         const bool bTempAutoStyles )
665     : SvXMLStylesContext( rImport )
666     , nNumberFormatIndex(-1)
667     , nConditionalFormatIndex(-1)
668     , nCellStyleIndex(-1)
669     , nMasterPageNameIndex(-1)
670     , bAutoStyles(bTempAutoStyles)
671 {
672 }
673 
~XMLTableStylesContext()674 XMLTableStylesContext::~XMLTableStylesContext()
675 {
676 }
677 
endFastElement(sal_Int32)678 void XMLTableStylesContext::endFastElement(sal_Int32 )
679 {
680     if (bAutoStyles)
681         GetImport().GetTextImport()->SetAutoStyles( this );
682     else
683         GetScImport().InsertStyles();
684 }
685 
686 rtl::Reference < SvXMLImportPropertyMapper >
GetImportPropertyMapper(XmlStyleFamily nFamily) const687     XMLTableStylesContext::GetImportPropertyMapper(
688                     XmlStyleFamily nFamily ) const
689 {
690     rtl::Reference < SvXMLImportPropertyMapper > xMapper(SvXMLStylesContext::GetImportPropertyMapper(nFamily));
691 
692     if (!xMapper.is())
693     {
694         switch( nFamily )
695         {
696             case XmlStyleFamily::TABLE_CELL:
697             {
698                 if( !xCellImpPropMapper.is() )
699                 {
700                     const_cast<XMLTableStylesContext *>(this)->xCellImpPropMapper =
701                         new ScXMLCellImportPropertyMapper( GetScImport().GetCellStylesPropertySetMapper(), const_cast<SvXMLImport&>(GetImport()) );
702                     xCellImpPropMapper->ChainImportMapper(XMLTextImportHelper::CreateParaExtPropMapper(const_cast<SvXMLImport&>(GetImport())));
703                 }
704                 xMapper = xCellImpPropMapper;
705             }
706             break;
707             case XmlStyleFamily::TABLE_COLUMN:
708             {
709                 if( !xColumnImpPropMapper.is() )
710                     const_cast<XMLTableStylesContext *>(this)->xColumnImpPropMapper =
711                         new SvXMLImportPropertyMapper( GetScImport().GetColumnStylesPropertySetMapper(), const_cast<SvXMLImport&>(GetImport()) );
712                 xMapper = xColumnImpPropMapper;
713             }
714              break;
715             case XmlStyleFamily::TABLE_ROW:
716             {
717                 if( !xRowImpPropMapper.is() )
718                     const_cast<XMLTableStylesContext *>(this)->xRowImpPropMapper =
719                         new ScXMLRowImportPropertyMapper( GetScImport().GetRowStylesPropertySetMapper(), const_cast<SvXMLImport&>(GetImport()) );
720                 xMapper = xRowImpPropMapper;
721             }
722              break;
723             case XmlStyleFamily::TABLE_TABLE:
724             {
725                 if( !xTableImpPropMapper.is() )
726                     const_cast<XMLTableStylesContext *>(this)->xTableImpPropMapper =
727                         new SvXMLImportPropertyMapper( GetScImport().GetTableStylesPropertySetMapper(), const_cast<SvXMLImport&>(GetImport()) );
728                 xMapper = xTableImpPropMapper;
729             }
730              break;
731             default: break;
732         }
733     }
734 
735     return xMapper;
736 }
737 
738 uno::Reference < XNameContainer >
GetStylesContainer(XmlStyleFamily nFamily) const739         XMLTableStylesContext::GetStylesContainer( XmlStyleFamily nFamily ) const
740 {
741     uno::Reference < XNameContainer > xStyles(SvXMLStylesContext::GetStylesContainer(nFamily));
742     if (!xStyles.is())
743     {
744         OUString sName;
745         switch( nFamily )
746         {
747             case XmlStyleFamily::TABLE_TABLE:
748             {
749                 if( xTableStyles.is() )
750                     xStyles.set(xTableStyles);
751                 else
752                     sName = "TableStyles";
753             }
754             break;
755             case XmlStyleFamily::TABLE_CELL:
756             {
757                 if( xCellStyles.is() )
758                     xStyles.set(xCellStyles);
759                 else
760                     sName = "CellStyles";
761             }
762             break;
763             case XmlStyleFamily::TABLE_COLUMN:
764             {
765                 if( xColumnStyles.is() )
766                     xStyles.set(xColumnStyles);
767                 else
768                     sName = "ColumnStyles";
769             }
770             break;
771             case XmlStyleFamily::TABLE_ROW:
772             {
773                 if( xRowStyles.is() )
774                     xStyles.set(xRowStyles);
775                 else
776                     sName = "RowStyles";
777             }
778             break;
779             default: break;
780         }
781         if( !xStyles.is() && !sName.isEmpty() && GetScImport().GetModel().is() )
782         {
783             uno::Reference< XStyleFamiliesSupplier > xFamiliesSupp(
784                                             GetScImport().GetModel(), UNO_QUERY );
785             if (xFamiliesSupp.is())
786             {
787                 uno::Reference< XNameAccess > xFamilies(xFamiliesSupp->getStyleFamilies());
788 
789                 try
790                 {
791                     xStyles.set(xFamilies->getByName( sName ), uno::UNO_QUERY);
792                 }
793                 catch ( uno::Exception& )
794                 {
795                     // #i97680# Named table/column/row styles aren't supported, getByName will throw an exception.
796                     // For better interoperability, these styles should then be handled as automatic styles.
797                     // For now, NULL is returned (and the style is ignored).
798                 }
799                 switch( nFamily )
800                 {
801                 case XmlStyleFamily::TABLE_TABLE:
802                     const_cast<XMLTableStylesContext *>(this)->xTableStyles.set(xStyles);
803                     break;
804                 case XmlStyleFamily::TABLE_CELL:
805                     const_cast<XMLTableStylesContext *>(this)->xCellStyles.set(xStyles);
806                     break;
807                 case XmlStyleFamily::TABLE_COLUMN:
808                     const_cast<XMLTableStylesContext *>(this)->xColumnStyles.set(xStyles);
809                     break;
810                 case XmlStyleFamily::TABLE_ROW:
811                     const_cast<XMLTableStylesContext *>(this)->xRowStyles.set(xStyles);
812                     break;
813                 default: break;
814                 }
815             }
816         }
817     }
818 
819     return xStyles;
820 }
821 
GetServiceName(XmlStyleFamily nFamily) const822 OUString XMLTableStylesContext::GetServiceName( XmlStyleFamily nFamily ) const
823 {
824     OUString sServiceName(SvXMLStylesContext::GetServiceName(nFamily));
825     if (sServiceName.isEmpty())
826     {
827         switch( nFamily )
828         {
829         case XmlStyleFamily::TABLE_COLUMN:
830             sServiceName = gsColumnStyleServiceName;
831             break;
832         case XmlStyleFamily::TABLE_ROW:
833             sServiceName = gsRowStyleServiceName;
834             break;
835         case XmlStyleFamily::TABLE_CELL:
836             sServiceName = gsCellStyleServiceName;
837             break;
838         case XmlStyleFamily::TABLE_TABLE:
839             sServiceName = gsTableStyleServiceName;
840             break;
841         default: break;
842         }
843     }
844     return sServiceName;
845 }
846 
GetIndex(const sal_Int16 nContextID)847 sal_Int32 XMLTableStylesContext::GetIndex(const sal_Int16 nContextID)
848 {
849     if (nContextID == CTF_SC_CELLSTYLE)
850     {
851         if (nCellStyleIndex == -1)
852             nCellStyleIndex =
853                 GetImportPropertyMapper(XmlStyleFamily::TABLE_CELL)->getPropertySetMapper()->FindEntryIndex(nContextID);
854         return nCellStyleIndex;
855     }
856     else if (nContextID == CTF_SC_NUMBERFORMAT)
857     {
858         if (nNumberFormatIndex == -1)
859             nNumberFormatIndex =
860                 GetImportPropertyMapper(XmlStyleFamily::TABLE_CELL)->getPropertySetMapper()->FindEntryIndex(nContextID);
861         return nNumberFormatIndex;
862     }
863     else if (nContextID == CTF_SC_IMPORT_MAP)
864     {
865         if (nConditionalFormatIndex == -1)
866             nConditionalFormatIndex =
867                 GetImportPropertyMapper(XmlStyleFamily::TABLE_CELL)->getPropertySetMapper()->FindEntryIndex(nContextID);
868         return nConditionalFormatIndex;
869     }
870     else if (nContextID == CTF_SC_MASTERPAGENAME)
871     {
872         if (nMasterPageNameIndex == -1)
873                 nMasterPageNameIndex =
874                 GetImportPropertyMapper(XmlStyleFamily::TABLE_TABLE)->getPropertySetMapper()->FindEntryIndex(nContextID);
875         return nMasterPageNameIndex;
876     }
877     else
878         return -1;
879 }
880 
881 
InsertStyleFamily(XmlStyleFamily) const882 bool ScXMLMasterStylesContext::InsertStyleFamily( XmlStyleFamily ) const
883 {
884     return true;
885 }
886 
ScXMLMasterStylesContext(SvXMLImport & rImport)887 ScXMLMasterStylesContext::ScXMLMasterStylesContext( SvXMLImport& rImport ) :
888     SvXMLStylesContext( rImport )
889 {
890 }
891 
~ScXMLMasterStylesContext()892 ScXMLMasterStylesContext::~ScXMLMasterStylesContext()
893 {
894 }
895 
CreateStyleChildContext(sal_Int32 nElement,const uno::Reference<XFastAttributeList> & xAttrList)896 SvXMLStyleContext *ScXMLMasterStylesContext::CreateStyleChildContext(
897         sal_Int32 nElement,
898         const uno::Reference< XFastAttributeList > & xAttrList )
899 {
900     SvXMLStyleContext *pContext(nullptr);
901 
902     if( nElement == XML_ELEMENT(STYLE, XML_MASTER_PAGE) &&
903          InsertStyleFamily( XmlStyleFamily::MASTER_PAGE ) )
904         pContext = new ScMasterPageContext(
905                         GetImport(), nElement, xAttrList,
906                         !GetImport().GetTextImport()->IsInsertMode() );
907 
908     // any other style will be ignored here!
909 
910     return pContext;
911 }
912 
CreateStyleStyleChildContext(XmlStyleFamily,sal_Int32,const uno::Reference<XFastAttributeList> &)913 SvXMLStyleContext *ScXMLMasterStylesContext::CreateStyleStyleChildContext(
914         XmlStyleFamily /* nFamily */,
915         sal_Int32 /* nElement */,
916         const uno::Reference< XFastAttributeList > & /* xAttrList */ )
917 {
918     return nullptr;
919 }
920 
endFastElement(sal_Int32)921 void ScXMLMasterStylesContext::endFastElement(sal_Int32 )
922 {
923     FinishStyles(true);
924 }
925 
926 
ScMasterPageContext(SvXMLImport & rImport,sal_Int32 nElement,const uno::Reference<XFastAttributeList> & xAttrList,bool bOverwrite)927 ScMasterPageContext::ScMasterPageContext( SvXMLImport& rImport,
928         sal_Int32 nElement,
929         const uno::Reference< XFastAttributeList > & xAttrList,
930         bool bOverwrite ) :
931     XMLTextMasterPageContext( rImport, nElement, xAttrList, bOverwrite ),
932     bContainsRightHeader(false),
933     bContainsRightFooter(false)
934 {
935 }
936 
~ScMasterPageContext()937 ScMasterPageContext::~ScMasterPageContext()
938 {
939 }
940 
CreateHeaderFooterContext(sal_Int32 nElement,const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList,const bool bFooter,const bool bLeft,const bool bFirst)941 SvXMLImportContext *ScMasterPageContext::CreateHeaderFooterContext(
942             sal_Int32 nElement,
943             const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
944             const bool bFooter,
945             const bool bLeft,
946             const bool bFirst )
947 {
948     if (!bLeft)
949     {
950         if (bFooter)
951             bContainsRightFooter = true;
952         else
953             bContainsRightHeader = true;
954     }
955     if (!xPropSet.is())
956         xPropSet.set(GetStyle(), UNO_QUERY );
957     return new XMLTableHeaderFooterContext( GetImport(),
958                                                 nElement,
959                                                 xAttrList,
960                                                 xPropSet,
961                                                 bFooter, bLeft, bFirst );
962 }
963 
ClearContent(const OUString & rContent)964 void ScMasterPageContext::ClearContent(const OUString& rContent)
965 {
966     if (!xPropSet.is())
967         xPropSet.set(GetStyle(), UNO_QUERY );
968 
969     if (xPropSet.is())
970     {
971         uno::Reference < sheet::XHeaderFooterContent > xHeaderFooterContent(xPropSet->getPropertyValue( rContent ), uno::UNO_QUERY);
972         if (xHeaderFooterContent.is())
973         {
974             xHeaderFooterContent->getLeftText()->setString("");
975             xHeaderFooterContent->getCenterText()->setString("");
976             xHeaderFooterContent->getRightText()->setString("");
977             xPropSet->setPropertyValue( rContent, uno::makeAny(xHeaderFooterContent) );
978         }
979     }
980 }
981 
Finish(bool bOverwrite)982 void ScMasterPageContext::Finish( bool bOverwrite )
983 {
984     XMLTextMasterPageContext::Finish(bOverwrite);
985     if (!bContainsRightFooter)
986         ClearContent(SC_UNO_PAGE_RIGHTFTRCON);
987     if (!bContainsRightHeader)
988         ClearContent(SC_UNO_PAGE_RIGHTHDRCON);
989 }
990 
ScCellTextStyleContext(SvXMLImport & rImport,SvXMLStylesContext & rStyles,XmlStyleFamily nFamily)991 ScCellTextStyleContext::ScCellTextStyleContext( SvXMLImport& rImport,
992             SvXMLStylesContext& rStyles, XmlStyleFamily nFamily ) :
993     XMLTextStyleContext( rImport, rStyles, nFamily, false/*bDefaultStyle*/ ),
994     nLastSheet(-1)
995 {
996 }
997 
~ScCellTextStyleContext()998 ScCellTextStyleContext::~ScCellTextStyleContext()
999 {
1000 }
1001 
FillPropertySet(const uno::Reference<beans::XPropertySet> & xPropSet)1002 void ScCellTextStyleContext::FillPropertySet( const uno::Reference<beans::XPropertySet>& xPropSet )
1003 {
1004     XMLTextStyleContext::FillPropertySet( xPropSet );
1005 
1006     ScXMLImport& rXMLImport = GetScImport();
1007 
1008     ScCellTextCursor* pCellImp = comphelper::getUnoTunnelImplementation<ScCellTextCursor>( xPropSet );
1009     if (pCellImp)
1010     {
1011         ScAddress aPos = pCellImp->GetCellObj().GetPosition();
1012         if ( aPos.Tab() != nLastSheet )
1013         {
1014             ESelection aSel = pCellImp->GetSelection();
1015 
1016             ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(GetImport().GetModel())->GetSheetSaveData();
1017             pSheetData->AddTextStyle( GetName(), aPos, aSel );
1018 
1019             nLastSheet = aPos.Tab();
1020         }
1021     }
1022     else if ( rXMLImport.GetTables().GetCurrentSheet() != nLastSheet )
1023     {
1024         ScDrawTextCursor* pDrawImp = comphelper::getUnoTunnelImplementation<ScDrawTextCursor>( xPropSet );
1025         if (pDrawImp)
1026         {
1027             XMLTableShapeImportHelper* pTableShapeImport = static_cast<XMLTableShapeImportHelper*>(GetScImport().GetShapeImport().get());
1028             ScXMLAnnotationContext* pAnnotationContext = pTableShapeImport->GetAnnotationContext();
1029             if (pAnnotationContext)
1030             {
1031                 pAnnotationContext->AddContentStyle( GetFamily(), GetName(), pDrawImp->GetSelection() );
1032                 nLastSheet = rXMLImport.GetTables().GetCurrentSheet();
1033             }
1034         }
1035 
1036         // if it's a different shape, BlockSheet is called from XMLTableShapeImportHelper::finishShape
1037         // formatted text in page headers/footers can be ignored
1038     }
1039 }
1040 
1041 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1042